dav/sync.c

changeset 190
a76e43d89f55
parent 185
cd42cccee550
child 191
0e45b04236a7
equal deleted inserted replaced
189:0d04ccf6747b 190:a76e43d89f55
86 int ret = EXIT_FAILURE; 86 int ret = EXIT_FAILURE;
87 if(!strcmp(cmd, "pull")) { 87 if(!strcmp(cmd, "pull")) {
88 ret = cmd_pull(args); 88 ret = cmd_pull(args);
89 } else if(!strcmp(cmd, "push")) { 89 } else if(!strcmp(cmd, "push")) {
90 ret = cmd_push(args); 90 ret = cmd_push(args);
91 } else if(!strcasecmp(cmd, "version") || !strcasecmp(cmd, "-version") || !strcasecmp(cmd, "--version")) {
92 #ifdef DEBUG
93 fprintf(stderr, "dav-synv %s unstable\n", DAV_VERSION);
94 #else
95 fprintf(stderr, "dav-sync %s\n", DAV_VERSION);
96 #endif
91 } 97 }
92 98
93 // TODO: cleanup sync config (don't forget to call regfree for regex) 99 // TODO: cleanup sync config (don't forget to call regfree for regex)
94 100
95 return ret; 101 return ret;
234 } 240 }
235 241
236 // delete every remotely removed resource 242 // delete every remotely removed resource
237 UcxMapIterator i = ucx_map_iterator(db->resources); 243 UcxMapIterator i = ucx_map_iterator(db->resources);
238 LocalResource *local; 244 LocalResource *local;
245 UcxList *rmdirs = NULL;
239 UCX_MAP_FOREACH(key, local, i) { 246 UCX_MAP_FOREACH(key, local, i) {
240 if (res_matches_filter(dir, local->path)) { 247 if (res_matches_filter(dir, local->path)) {
241 continue; 248 continue;
242 } 249 }
243 // sync_remove_resource does all necessary tests 250 // sync_remove_resource does all necessary tests
244 sync_remove_local_resource(dir, local); 251 if(sync_remove_local_resource(dir, local)) {
252 rmdirs = ucx_list_append(rmdirs, local);
253 }
254 }
255 UCX_FOREACH(elm, rmdirs) {
256 LocalResource *local_dir = elm->data;
257 sync_remove_local_directory(dir, local_dir);
245 } 258 }
246 ucx_map_free(db->resources); 259 ucx_map_free(db->resources);
247 db->resources = svrres; 260 db->resources = svrres;
248 261
249 // TODO: cleanup - BUT DONT CLEANUP SYNC CONFIG (do this in main!) 262 // TODO: cleanup - BUT DONT CLEANUP SYNC CONFIG (do this in main!)
263 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); 276 LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
264 char *local_path = util_concat_path(dir->path, res->path); 277 char *local_path = util_concat_path(dir->path, res->path);
265 278
266 char *etag = dav_get_property(res, "D:getetag"); 279 char *etag = dav_get_property(res, "D:getetag");
267 struct stat s; 280 struct stat s;
268 if(local) { 281 if(local && !res->iscollection) {
269 int exists = 1; 282 int exists = 1;
270 if(stat(local_path, &s)) { 283 if(stat(local_path, &s)) {
271 // Ignore the fact, that the file is locally removed. If the 284 // Ignore the fact, that the file is locally removed. If the
272 // server has an updated version, we read the file or the 285 // server has an updated version, we read the file or the
273 // next push will delete it on the server. 286 // next push will delete it on the server.
313 if(res->iscollection) { 326 if(res->iscollection) {
314 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 327 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
315 if(util_mkdir(local_path, mode) && errno != EEXIST) { 328 if(util_mkdir(local_path, mode) && errno != EEXIST) {
316 ret = -1; 329 ret = -1;
317 } 330 }
331
332 if(ret == 0) {
333 if(!local) {
334 // new local resource
335 local = calloc(1, sizeof(LocalResource));
336 local->path = util_concat_path(res->path, "/");
337 local->last_modified = s.st_mtime;
338 ucx_map_cstr_put(db->resources, local->path, local);
339 }
340 }
318 } else { 341 } else {
319 if(!tmp_path) { 342 if(!tmp_path) {
320 fprintf(stderr, "Cannot create tmp path for %s\n", local_path); 343 fprintf(stderr, "Cannot create tmp path for %s\n", local_path);
321 free(local_path); 344 free(local_path);
322 return -1; 345 return -1;
379 free(tmp_path); 402 free(tmp_path);
380 free(local_path); 403 free(local_path);
381 return ret; 404 return ret;
382 } 405 }
383 406
384 void sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { 407 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) {
385 char *local_path = util_concat_path(dir->path, res->path); 408 char *local_path = util_concat_path(dir->path, res->path);
386 struct stat s; 409 struct stat s;
387 if(stat(local_path, &s)) { 410 if(stat(local_path, &s)) {
388 free(local_path); 411 free(local_path);
389 return; 412 return 0;
413 }
414
415 if(S_ISDIR(s.st_mode)) {
416 free(local_path);
417 return 1;
390 } 418 }
391 419
392 if(s.st_mtime != res->last_modified) { 420 if(s.st_mtime != res->last_modified) {
393 free(local_path); 421 free(local_path);
394 return; 422 return 0;
395 } 423 }
396 424
397 printf("delete: %s\n", res->path); 425 printf("delete: %s\n", res->path);
398 426
399 if(dir->trash) { 427 if(dir->trash) {
400 move_to_trash(dir, local_path); 428 move_to_trash(dir, local_path);
401 } else if(unlink(local_path)) { 429 } else if(unlink(local_path)) {
402 fprintf(stderr, "Cannot remove file %s\n", local_path); 430 fprintf(stderr, "Cannot remove file %s\n", local_path);
403 } 431 }
432 free(local_path);
433
434 return 0;
435 }
436
437 void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) {
438 char *local_path = util_concat_path(dir->path, res->path);
439
440 printf("delete: %s\n", res->path);
441 if(rmdir(local_path)) {
442 // TODO
443 }
444
404 free(local_path); 445 free(local_path);
405 } 446 }
406 447
407 void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) { 448 void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) {
408 char *local_path = util_concat_path(dir->path, path); 449 char *local_path = util_concat_path(dir->path, path);
547 UCX_FOREACH(elm, resources) { 588 UCX_FOREACH(elm, resources) {
548 LocalResource *local_res = elm->data; 589 LocalResource *local_res = elm->data;
549 if (!res_matches_filter(dir, local_res->path+1)) { 590 if (!res_matches_filter(dir, local_res->path+1)) {
550 // upload every changed file 591 // upload every changed file
551 if (local_resource_is_changed(dir, db, local_res)) { 592 if (local_resource_is_changed(dir, db, local_res)) {
552 printf("put: %s\n", local_res->path);
553 DavResource *res = dav_resource_new(sn, local_res->path); 593 DavResource *res = dav_resource_new(sn, local_res->path);
554 if(sync_put_resource(dir, res, local_res)) { 594
555 // TODO: I don't know what to do now 595 if(local_res->isdirectory) {
596 printf("mkcol: %s\n", local_res->path);
597 if(sync_mkdir(dir, res, local_res)) {
598 // TODO: I don't know what to do now
599 }
600 } else {
601 printf("put: %s\n", local_res->path);
602 if(sync_put_resource(dir, res, local_res)) {
603 // TODO: I don't know what to do now
604 }
556 } 605 }
557 dav_resource_free(res); 606 dav_resource_free(res);
558 } 607 }
559 608
560 // remove every locally available resource from db->resource 609 // remove every locally available resource from db->resource
614 663
615 char *new_path = util_concat_path(p, ent->d_name); 664 char *new_path = util_concat_path(p, ent->d_name);
616 int isdir; 665 int isdir;
617 LocalResource *res = local_resource_new(dir, db, new_path, &isdir); 666 LocalResource *res = local_resource_new(dir, db, new_path, &isdir);
618 if(isdir) { 667 if(isdir) {
668 resources = ucx_list_append(resources, res);
619 stack = ucx_list_prepend(stack, new_path); 669 stack = ucx_list_prepend(stack, new_path);
620 } else if(res) { 670 } else if(res) {
621 resources = ucx_list_append(resources, res); 671 resources = ucx_list_append(resources, res);
622 free(new_path); 672 free(new_path);
623 } else { 673 } else {
704 res->last_modified = s.st_mtime; 754 res->last_modified = s.st_mtime;
705 res->size = s.st_size; 755 res->size = s.st_size;
706 return res; 756 return res;
707 } else { 757 } else {
708 *isdir = 1; 758 *isdir = 1;
759 LocalResource *res = calloc(1, sizeof(LocalResource));
760 res->path = util_concat_path(path, "/");
761 res->last_modified = s.st_mtime;
762 res->isdirectory = 1;
763 return res;
709 } 764 }
710 return NULL; 765 return NULL;
711 } 766 }
712 767
713 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) { 768 int local_resource_is_changed(SyncDirectory *dir, SyncDatabase *db, LocalResource *res) {
820 free(local_path); 875 free(local_path);
821 876
822 return ret; 877 return ret;
823 } 878 }
824 879
880 int sync_mkdir(SyncDirectory *dir, DavResource *res, LocalResource *local) {
881 res->iscollection = 1;
882 int ret = -1;
883 for(int i=0;i<dir->max_retry;i++) {
884 if(dav_create(res)) {
885 continue;
886 }
887 ret = 0;
888 break;
889 }
890 return ret;
891 }
892
825 int sync_delete_remote_resource(DavSession *sn, LocalResource *local_res) { 893 int sync_delete_remote_resource(DavSession *sn, LocalResource *local_res) {
826 DavResource *res = dav_get(sn, local_res->path, "D:getetag"); 894 DavResource *res = dav_get(sn, local_res->path, "D:getetag");
827 if(!res) { 895 if(!res) {
828 return sn->error == DAV_NOT_FOUND ? 0 : 1; 896 return sn->error == DAV_NOT_FOUND ? 0 : 1;
829 } 897 }
830 898
831 char *etag = dav_get_property(res, "D:getetag");
832 if(etag) {
833 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') {
834 etag = etag + 2;
835 }
836 }
837
838 int ret = 0; 899 int ret = 0;
839 if(etag && !strcmp(etag, local_res->etag)) { 900 if(res->iscollection) {
840 // local resource metadata == remote resource metadata
841 // resource can be deleted
842 printf("delete: %s\n", res->path); 901 printf("delete: %s\n", res->path);
843 if(dav_delete(res)) { 902 if(dav_delete(res)) {
844 if(sn->error != DAV_NOT_FOUND) { 903 ret = 1;
845 fprintf(stderr, "Cannot delete resource %s\n", res->path); 904 fprintf(stderr, "Cannot delete resource %s\n", res->path);
846 }
847 } 905 }
848 } else { 906 } else {
849 ret = 1; 907 char *etag = dav_get_property(res, "D:getetag");
908 if(etag) {
909 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') {
910 etag = etag + 2;
911 }
912 }
913
914 if(etag && !strcmp(etag, local_res->etag)) {
915 // local resource metadata == remote resource metadata
916 // resource can be deleted
917 printf("delete: %s\n", res->path);
918 if(dav_delete(res)) {
919 if(sn->error != DAV_NOT_FOUND) {
920 fprintf(stderr, "Cannot delete resource %s\n", res->path);
921 }
922 }
923 } else {
924 ret = 1;
925 }
850 } 926 }
851 927
852 // cleanup 928 // cleanup
853 dav_resource_free(res); 929 dav_resource_free(res);
854 930

mercurial