dav/sync.c

changeset 46
0542668d0f26
child 47
fbbbeed4ba8f
equal deleted inserted replaced
45:e3839719b079 46:0542668d0f26
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2013 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <time.h>
35 #include <libxml/xmlerror.h>
36 #include <sys/types.h>
37 #include <ucx/string.h>
38 #include <dirent.h>
39
40 #include <libidav/webdav.h>
41 #include <libidav/utils.h>
42
43 #include "config.h"
44 #include "scfg.h"
45 #include "sopt.h"
46 #include "db.h"
47
48 #include "sync.h"
49
50 static DavContext *ctx;
51
52 static void xmlerrorfnc(void * c, const char * msg, ... ) {
53 // nothing
54 }
55
56 int main(int argc, char **argv) {
57 if(argc < 2) {
58 fprintf(stderr, "Missing command\n");
59 print_usage(argv[0]);
60 return -1;
61 }
62
63 char *cmd = argv[1];
64 CmdArgs *args = cmd_parse_args(argc - 2, argv + 2);
65 if(!args) {
66 print_usage(argv[0]);
67 return -1;
68 }
69
70 xmlGenericErrorFunc fnc = xmlerrorfnc;
71 initGenericErrorDefaultFunc(&fnc);
72 ctx = dav_context_new();
73 load_config(ctx);
74 if(load_sync_config()) {
75 return EXIT_FAILURE;
76 }
77
78 int ret = EXIT_FAILURE;
79 if(!strcmp(cmd, "pull")) {
80 ret = cmd_pull(args);
81 } else if(!strcmp(cmd, "push")) {
82 ret = cmd_pull(args);
83 } else if(!strcmp(cmd, "sync")) {
84 ret = cmd_sync(args);
85 }
86
87 return ret;
88 }
89
90 void print_usage(char *cmd) {
91
92 }
93
94 int cmd_pull(CmdArgs *a) {
95 if(a->argc != 1) {
96 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");
97 return -1;
98 }
99
100 SyncDirectory *dir = scfg_get_dir(a->argv[0]);
101 if(!dir) {
102 fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]);
103 return -1;
104 }
105
106 Repository *repo = get_repository(sstr(dir->repository));
107 if(!repo) {
108 fprintf(stderr, "Unkown repository %s\n", dir->name);
109 return -1;
110 }
111
112 UcxMap *db = load_db(dir->database);
113 if(!db) {
114 fprintf(stderr, "Cannot load database file: %s\n", dir->database);
115 return -1;
116 }
117
118 DavSession *sn = dav_session_new_auth(
119 ctx,
120 repo->url,
121 repo->user,
122 repo->password);
123 dav_session_set_flags(sn, get_repository_flags(repo));
124 sn->key = dav_context_get_key(ctx, repo->default_key);
125
126 DavResource *ls = dav_query(sn, "get D:getetag from / where lastmodified > 0 with depth -1");
127 if(!ls) {
128 fprintf(stderr, "Error\n");
129 // TODO: free
130 return -1;
131 }
132
133 if(!ls->children) {
134 // TODO: free
135 return 0; // empty repository
136 }
137
138 UcxList *stack = ucx_list_prepend(NULL, ls->children);
139 while(stack) {
140 DavResource *res = stack->data;
141 stack = ucx_list_remove(stack, stack);
142
143 while(res) {
144 if(sync_get_resource(dir, res, db)) {
145 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path);
146 }
147
148 if(res->children) {
149 stack = ucx_list_prepend(stack, res->children);
150 }
151 res = res->next;
152 }
153 }
154
155 // store db
156
157
158 return 0;
159 }
160
161 int sync_get_resource(SyncDirectory *dir, DavResource *res, UcxMap *db) {
162 LocalResource *local = ucx_map_cstr_get(db, res->path);
163 char *etag = dav_get_property(res, "D:getetag");
164 if(local) {
165 if(local->etag && !strcmp(etag, local->etag)) {
166 // resource is already up-to-date on the client
167 return 0;
168 }
169 }
170
171 char *local_path = util_concat_path(dir->path, res->path);
172 int ret = 0;
173 if(res->iscollection) {
174 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
175 printf("mkdir %s\n", local_path);
176 if(util_mkdir(local_path, mode) && errno != EEXIST) {
177 ret = -1;
178 }
179 } else {
180 FILE *out = fopen(local_path, "w");
181 if(!out) {
182 fprintf(stderr, "cannot open output file: %s\n", local_path);
183 free(local_path);
184 return -1;
185 }
186 printf("get %s\n", res->path);
187 if(dav_get_content(res, out, (dav_write_func)fwrite)) {
188 ret = -1;
189 } else {
190 if(local) {
191 if(local->etag) {
192 free(local->etag);
193 }
194 local->etag = etag;
195 }
196 }
197 fclose(out);
198 }
199
200 free(local_path);
201 return ret;
202 }
203
204 int cmd_push(CmdArgs *a) {
205 return 0;
206 }
207
208 int cmd_sync(CmdArgs *a) {
209 return 0;
210 }
211

mercurial