107 if(!repo) { |
107 if(!repo) { |
108 fprintf(stderr, "Unkown repository %s\n", dir->name); |
108 fprintf(stderr, "Unkown repository %s\n", dir->name); |
109 return -1; |
109 return -1; |
110 } |
110 } |
111 |
111 |
112 UcxMap *db = load_db(dir->database); |
112 SyncDatabase *db = load_db(dir->database); |
113 if(!db) { |
113 if(!db) { |
114 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
114 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
115 return -1; |
115 return -1; |
116 } |
116 } |
117 |
117 |
132 |
132 |
133 if(!ls->children) { |
133 if(!ls->children) { |
134 // TODO: free |
134 // TODO: free |
135 return 0; // empty repository |
135 return 0; // empty repository |
136 } |
136 } |
137 |
137 |
138 UcxList *stack = ucx_list_prepend(NULL, ls->children); |
138 UcxList *stack = ucx_list_prepend(NULL, ls->children); |
139 while(stack) { |
139 while(stack) { |
140 DavResource *res = stack->data; |
140 DavResource *res = stack->data; |
141 stack = ucx_list_remove(stack, stack); |
141 stack = ucx_list_remove(stack, stack); |
142 |
142 |
143 while(res) { |
143 while(res) { |
144 if(sync_get_resource(dir, res, db)) { |
144 if(sync_get_resource(dir, res, db)) { |
145 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); |
145 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); |
146 } |
146 } |
147 |
147 |
161 } |
161 } |
162 |
162 |
163 return 0; |
163 return 0; |
164 } |
164 } |
165 |
165 |
166 int sync_get_resource(SyncDirectory *dir, DavResource *res, UcxMap *db) { |
166 int sync_get_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db) { |
167 LocalResource *local = ucx_map_cstr_get(db, res->path); |
167 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
|
168 char *local_path = util_concat_path(dir->path, res->path); |
|
169 |
168 char *etag = dav_get_property(res, "D:getetag"); |
170 char *etag = dav_get_property(res, "D:getetag"); |
|
171 struct stat s; |
169 if(local) { |
172 if(local) { |
|
173 if(stat(local_path, &s)) { |
|
174 if(errno == ENOENT) { |
|
175 printf("removed %s\n", res->path); |
|
176 // the file is in the database, but doesn't exists |
|
177 // mark the file as removed to delete it on next push |
|
178 ucx_map_cstr_remove(db->resources, local->path); |
|
179 ucx_map_cstr_put(db->remove, local->path, local); |
|
180 return 0; |
|
181 } else { |
|
182 fprintf(stderr, "stat failed: %s\n", local_path); |
|
183 free(local_path); |
|
184 return -1; |
|
185 } |
|
186 } |
|
187 |
170 if(local->etag) { |
188 if(local->etag) { |
171 sstr_t e = sstr(etag); |
189 sstr_t e = sstr(etag); |
172 if(sstrprefix(e, S("W/"))) { |
190 if(sstrprefix(e, S("W/"))) { |
173 e = sstrsubs(e, 2); |
191 e = sstrsubs(e, 2); |
174 } |
192 } |
177 return 0; |
195 return 0; |
178 } |
196 } |
179 } |
197 } |
180 } |
198 } |
181 |
199 |
182 char *local_path = util_concat_path(dir->path, res->path); |
|
183 int ret = 0; |
200 int ret = 0; |
184 if(res->iscollection) { |
201 if(res->iscollection) { |
185 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
202 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
186 //printf("mkdir %s\n", local_path); |
203 //printf("mkdir %s\n", local_path); |
187 if(util_mkdir(local_path, mode) && errno != EEXIST) { |
204 if(util_mkdir(local_path, mode) && errno != EEXIST) { |
199 ret = -1; |
216 ret = -1; |
200 } |
217 } |
201 fclose(out); |
218 fclose(out); |
202 |
219 |
203 if(ret == 0) { |
220 if(ret == 0) { |
204 // get file informations for db update |
|
205 struct stat s; |
|
206 if(stat(local_path, &s)) { |
|
207 fprintf(stderr, "stat failed: %s\n", local_path); |
|
208 ret = -1; |
|
209 } |
|
210 |
|
211 if(!local) { |
221 if(!local) { |
|
222 // new local resource |
212 local = calloc(1, sizeof(LocalResource)); |
223 local = calloc(1, sizeof(LocalResource)); |
213 local->path = strdup(res->path); |
224 local->path = strdup(res->path); |
214 ucx_map_cstr_put(db, local->path, local); |
225 ucx_map_cstr_put(db->resources, local->path, local); |
215 } |
226 } |
216 |
227 |
217 if(local->etag) { |
228 if(local->etag) { |
218 free(local->etag); |
229 free(local->etag); |
219 } |
230 } |
|
231 // set metadata from stat |
220 local->etag = etag; |
232 local->etag = etag; |
221 local->last_modified = s.st_mtim.tv_sec; |
233 local->last_modified = s.st_mtim.tv_sec; |
222 local->size = s.st_size; |
234 local->size = s.st_size; |
223 } |
235 } |
224 } |
236 } |
243 if(!repo) { |
255 if(!repo) { |
244 fprintf(stderr, "Unkown repository %s\n", dir->name); |
256 fprintf(stderr, "Unkown repository %s\n", dir->name); |
245 return -1; |
257 return -1; |
246 } |
258 } |
247 |
259 |
248 UcxMap *db = load_db(dir->database); |
260 SyncDatabase *db = load_db(dir->database); |
249 if(!db) { |
261 if(!db) { |
250 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
262 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
251 return -1; |
263 return -1; |
252 } |
264 } |
253 |
265 |
277 } |
289 } |
278 |
290 |
279 return 0; |
291 return 0; |
280 } |
292 } |
281 |
293 |
282 UcxList* local_scan(SyncDirectory *dir, UcxMap *db) { |
294 UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { |
283 UcxList *resources = NULL; |
295 UcxList *resources = NULL; |
284 |
296 |
285 char *path = strdup("/"); |
297 char *path = strdup("/"); |
286 UcxList *stack = ucx_list_prepend(NULL, path); |
298 UcxList *stack = ucx_list_prepend(NULL, path); |
287 while(stack) { |
299 while(stack) { |
320 free(file_path); |
332 free(file_path); |
321 |
333 |
322 if(S_ISDIR(s.st_mode)) { |
334 if(S_ISDIR(s.st_mode)) { |
323 stack = ucx_list_prepend(stack, new_path); |
335 stack = ucx_list_prepend(stack, new_path); |
324 } else { |
336 } else { |
325 LocalResource *res = ucx_map_cstr_get(db, new_path); |
337 LocalResource *res = ucx_map_cstr_get( |
|
338 db->resources, |
|
339 new_path); |
326 if(res) { |
340 if(res) { |
327 // the file is already in the database |
341 // the file is already in the database |
328 // compare length and lastmodified date |
342 // compare length and lastmodified date |
329 |
343 |
330 if(res->last_modified == s.st_mtim.tv_sec |
344 if(res->last_modified == s.st_mtim.tv_sec |
347 LocalResource *res = calloc(1, sizeof(LocalResource)); |
361 LocalResource *res = calloc(1, sizeof(LocalResource)); |
348 res->path = strdup(new_path); |
362 res->path = strdup(new_path); |
349 res->etag = NULL; |
363 res->etag = NULL; |
350 res->last_modified = s.st_mtim.tv_sec; |
364 res->last_modified = s.st_mtim.tv_sec; |
351 res->size = s.st_size; |
365 res->size = s.st_size; |
352 ucx_map_cstr_put(db, res->path, res); |
366 ucx_map_cstr_put(db->resources, res->path, res); |
353 resources = ucx_list_append(resources, new_path); |
367 resources = ucx_list_append(resources, new_path); |
354 } |
368 } |
355 } |
369 } |
356 } |
370 } |
357 closedir(local_dir); |
371 closedir(local_dir); |
362 } |
376 } |
363 |
377 |
364 return resources; |
378 return resources; |
365 } |
379 } |
366 |
380 |
367 int sync_put_resource(SyncDirectory *dir, DavResource *res, UcxMap *db) { |
381 int sync_put_resource(SyncDirectory *dir, DavResource *res, SyncDatabase *db) { |
368 char *local_path = util_concat_path(dir->path, res->path); |
382 char *local_path = util_concat_path(dir->path, res->path); |
369 FILE *in = fopen(local_path, "r"); |
383 FILE *in = fopen(local_path, "r"); |
370 if(!in) { |
384 if(!in) { |
371 fprintf(stderr, "Cannot open file %s\n", local_path); |
385 fprintf(stderr, "Cannot open file %s\n", local_path); |
372 free(local_path); |
386 free(local_path); |
387 ret = 0; |
401 ret = 0; |
388 break; |
402 break; |
389 } |
403 } |
390 |
404 |
391 if(ret == 0) { |
405 if(ret == 0) { |
392 LocalResource *local_res = ucx_map_cstr_get(db, res->path); |
406 LocalResource *local_res = ucx_map_cstr_get(db->resources, res->path); |
393 if(local_res->etag) { |
407 if(local_res->etag) { |
394 free(local_res->etag); |
408 free(local_res->etag); |
395 } |
409 } |
396 |
410 |
397 DavResource *up_res = dav_get(res->session, res->path, "D:getetag"); |
411 DavResource *up_res = dav_get(res->session, res->path, "D:getetag"); |
398 char *etag_str = dav_get_property(up_res, "D:getetag"); |
412 char *etag = dav_get_property(up_res, "D:getetag"); |
399 sstr_t etag; |
413 if(etag) { |
400 etag.ptr = NULL; |
414 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { |
401 if(etag_str) { |
415 etag = etag + 2; |
402 etag = sstr(etag_str); |
416 } |
403 } |
417 } |
404 if(sstrprefix(etag, S("W/"))) { |
418 |
405 etag = sstrsubs(etag, 2); |
419 |
406 } |
420 if(etag) { |
407 |
421 local_res->etag = strdup(etag); |
408 |
|
409 if(etag.ptr) { |
|
410 local_res->etag = strdup(etag.ptr); |
|
411 } else { |
422 } else { |
412 local_res->etag = NULL; |
423 local_res->etag = NULL; |
413 } |
424 } |
414 } |
425 } |
415 |
426 |