dav/sync.c

changeset 611
a7c48e0dca88
parent 608
3e4c0285a868
child 613
f6072141f5ee
equal deleted inserted replaced
610:aa3baf1dd81b 611:a7c48e0dca88
134 return -1; 134 return -1;
135 } 135 }
136 136
137 xmlGenericErrorFunc fnc = xmlerrorfnc; 137 xmlGenericErrorFunc fnc = xmlerrorfnc;
138 initGenericErrorDefaultFunc(&fnc); 138 initGenericErrorDefaultFunc(&fnc);
139 sys_init();
139 ctx = dav_context_new(); 140 ctx = dav_context_new();
140 int cfgret = load_config(ctx) || load_sync_config(); 141 int cfgret = load_config(ctx) || load_sync_config();
141 142
142 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 143 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
143 pthread_mutex_lock(&mutex); 144 pthread_mutex_lock(&mutex);
210 free_sync_config(); 211 free_sync_config();
211 212
212 curl_global_cleanup(); 213 curl_global_cleanup();
213 xmlCleanupParser(); 214 xmlCleanupParser();
214 215
216 sys_uninit();
217
215 return ret; 218 return ret;
216 } 219 }
217 220
218 void print_usage(char *cmd) { 221 void print_usage(char *cmd) {
219 fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); 222 fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd);
714 // 717 //
715 718
716 // the first thing we need are all directories to put the files in 719 // the first thing we need are all directories to put the files in
717 UCX_FOREACH(elm, res_mkdir) { 720 UCX_FOREACH(elm, res_mkdir) {
718 DavResource *res = elm->data; 721 DavResource *res = elm->data;
722 char *res_path = resource_local_path(res);
719 char *local_path = create_local_path(dir, res->path); 723 char *local_path = create_local_path(dir, res->path);
724 free(res_path);
720 if(sys_mkdir(local_path) && errno != EEXIST) { 725 if(sys_mkdir(local_path) && errno != EEXIST) {
721 fprintf(stderr, 726 fprintf(stderr,
722 "Cannot create directory %s: %s", 727 "Cannot create directory %s: %s",
723 local_path, strerror(errno)); 728 local_path, strerror(errno));
724 } 729 }
725 free(local_path); 730 free(local_path);
731 // TODO: create localres for dir
726 } 732 }
727 733
728 // we need a map for all conflicts for fast lookups 734 // we need a map for all conflicts for fast lookups
729 UcxMap *conflicts = ucx_map_new(ucx_list_size(res_conflict)+16); 735 UcxMap *conflicts = ucx_map_new(ucx_list_size(res_conflict)+16);
730 UCX_FOREACH(elm, res_conflict) { 736 UCX_FOREACH(elm, res_conflict) {
755 LocalResource *local = ucx_map_cstr_get(hashes, hash); 761 LocalResource *local = ucx_map_cstr_get(hashes, hash);
756 if(!local) { 762 if(!local) {
757 continue; 763 continue;
758 } 764 }
759 765
760 char *local_path = util_concat_path(dir->path, local->path); 766 char *local_path = util_concat_path(dir->path, local_resource_path(local));
761 int staterr = sys_stat(local_path, &s); 767 int staterr = sys_stat(local_path, &s);
762 free(local_path); 768 free(local_path);
763 if(staterr) { 769 if(staterr) {
764 // origin doesn't exist or is inaccessible 770 // origin doesn't exist or is inaccessible
765 continue; 771 continue;
838 } 844 }
839 845
840 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); 846 LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
841 if(local) { 847 if(local) {
842 printf("update: %s\n", res->path); 848 printf("update: %s\n", res->path);
849 char *res_path = resource_local_path(res);
843 char *local_path = create_local_path(dir, res->path); 850 char *local_path = create_local_path(dir, res->path);
851 free(res_path);
844 if(sync_store_metadata(dir, local_path, local, res)) { 852 if(sync_store_metadata(dir, local_path, local, res)) {
845 fprintf(stderr, "Metadata update failed: %s\n", res->path); 853 fprintf(stderr, "Metadata update failed: %s\n", res->path);
846 sync_error++; 854 sync_error++;
847 } else { 855 } else {
848 SYS_STAT s; 856 SYS_STAT s;
1221 int *counter) 1229 int *counter)
1222 { 1230 {
1223 renamefunc fn = copy ? copy_file : sys_rename; 1231 renamefunc fn = copy ? copy_file : sys_rename;
1224 1232
1225 char *new_path = util_concat_path(dir->path, res->path); 1233 char *new_path = util_concat_path(dir->path, res->path);
1226 char *old_path = util_concat_path(dir->path, content->path); 1234 char *old_path = util_concat_path(dir->path, local_resource_path(content));
1227 1235
1228 printf("%s: %s -> %s\n", copy?"copy":"move", content->path, res->path); 1236 printf("%s: %s -> %s\n", copy?"copy":"move", content->path, res->path);
1229 if(fn(old_path, new_path)) { 1237 if(fn(old_path, new_path)) {
1230 free(new_path); 1238 free(new_path);
1231 free(old_path); 1239 free(old_path);
1285 const char *path, 1293 const char *path,
1286 DavResource *res, 1294 DavResource *res,
1287 SyncDatabase *db, 1295 SyncDatabase *db,
1288 int *counter) 1296 int *counter)
1289 { 1297 {
1290 LocalResource *local = ucx_map_cstr_get(db->resources, path);
1291 char *local_path = create_local_path(dir, path);
1292
1293 char *link = SYNC_SYMLINK(dir) ? 1298 char *link = SYNC_SYMLINK(dir) ?
1294 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; 1299 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL;
1300
1301 LocalResource *local = ucx_map_cstr_get(db->resources, path);
1302
1303 char *local_path;
1304 if(link) {
1305 char *res_path = resource_local_path(res);
1306 local_path = create_local_path(dir, res_path);
1307 free(res_path);
1308 } else {
1309 local_path = create_local_path(dir, path);
1310 }
1295 1311
1296 char *etag = dav_get_string_property(res, "D:getetag"); 1312 char *etag = dav_get_string_property(res, "D:getetag");
1297 SYS_STAT s; 1313 SYS_STAT s;
1298 memset(&s, 0, sizeof(SYS_STAT)); 1314 memset(&s, 0, sizeof(SYS_STAT));
1299 1315
1819 if(local->isdirectory || local->link_target) { 1835 if(local->isdirectory || local->link_target) {
1820 elm = elm->next; 1836 elm = elm->next;
1821 continue; 1837 continue;
1822 } 1838 }
1823 1839
1824 char *local_path = util_concat_path(dir->path, local->path); 1840 char *local_path = util_concat_path(dir->path, local_resource_path(local));
1825 char *hash = util_file_hash(local_path); 1841 char *hash = util_file_hash(local_path);
1826 local->hash = hash; 1842 local->hash = hash;
1827 // check if a file with this hash already exists 1843 // check if a file with this hash already exists
1828 LocalResource *origin = ucx_map_cstr_get(db_hashes, hash); 1844 LocalResource *origin = ucx_map_cstr_get(db_hashes, hash);
1829 if(origin) { 1845 if(origin) {
2502 } else { 2518 } else {
2503 res->path = util_concat_path(path, "/"); 2519 res->path = util_concat_path(path, "/");
2504 res->isdirectory = 1; 2520 res->isdirectory = 1;
2505 } 2521 }
2506 2522
2507 if(S_ISLNK(s.st_mode)) { 2523 if(SYS_ISLINK(file_path, s)) {
2508 off_t l_sz = s.st_size + 16; 2524 char *lnkbuf = sys_readlink(file_path, &s);
2509 size_t lnksize = l_sz > 256 ? l_sz : 256; 2525 #ifdef SYS_LINK_EXT
2510 char *lnkbuf = malloc(lnksize); 2526 // on Windows, we interpret .lnk files as links
2511 2527 // we dont want resource names with this extension
2512 ssize_t len = 0; 2528 // and possibly sync this to other operating systems
2513 for(int i=0;i<4;i++) { 2529 // therefore we remove the .lnk extension from the file name
2514 // we try to read the link at most 4 times 2530 // change res->path
2515 // only repeat if the buffer is too small 2531 // we only do this, if there isn't any other file with this name
2516 len = sys_readlink(file_path, lnkbuf, lnksize); 2532 sstr_t fpath = sstr(file_path);
2517 if(len != lnksize) { 2533 sstr_t rpath = sstr(path);
2518 break; 2534 // remove last 4 chars (.lnk)
2519 } 2535 sstr_t new_file_path = sstrdup(sstrsubsl(fpath, 0 , fpath.length-4));
2520 lnksize *= 2; 2536 // check if a file with this name exists
2521 lnkbuf = realloc(lnkbuf, lnksize); 2537 SYS_STAT nfp_s;
2522 } 2538 if(!sys_stat(new_file_path.ptr, &nfp_s)) {
2523 2539 // we can't upload the link without the file extension, because
2524 if(len > 0) { 2540 // there is another file with this name
2525 // readlink successful 2541 free(lnkbuf);
2526 lnkbuf[len] = 0; 2542 lnkbuf = NULL;
2527 2543 } else {
2544 sstr_t new_path = sstrdup(sstrsubsl(rpath, 0, rpath.length-4));
2545 res->local_path = res->path;
2546 res->path = new_path.ptr; // remove .lnk ext from resource path
2547 }
2548 free(new_file_path.ptr);
2549 #endif
2550
2551 if(lnkbuf) {
2552 // readlink successful
2528 char *normalized = NULL; 2553 char *normalized = NULL;
2529 if(lnkbuf[0] != '/') { 2554 if(!util_path_isabsolut(lnkbuf)) {
2530 char *link_parent = util_parent_path(res->path); 2555 char *link_parent = util_parent_path(res->path);
2531 char *abs_link_parent = util_concat_path(dir->path, link_parent); 2556 char *abs_link_parent = util_concat_path(dir->path, link_parent);
2532 char *link = util_concat_path(abs_link_parent, lnkbuf); 2557 char *link = util_concat_path(abs_link_parent, lnkbuf);
2533 normalized = util_path_normalize(link); 2558 normalized = util_path_normalize(link);
2534 free(abs_link_parent); 2559 free(abs_link_parent);
2536 free(link); 2561 free(link);
2537 } else { 2562 } else {
2538 normalized = util_path_normalize(lnkbuf); 2563 normalized = util_path_normalize(lnkbuf);
2539 } 2564 }
2540 2565
2541 if(util_path_isrelated(dir->path, normalized)) { 2566 char *dirpath = util_path_normalize(dir->path);
2567 if(util_path_isrelated(dirpath, normalized)) {
2542 // the link points to a file inside the syncdir 2568 // the link points to a file inside the syncdir
2543 char *rel = util_create_relative_path(normalized, file_path); 2569 char *rel = util_create_relative_path(normalized, file_path);
2544 res->link_target = rel; 2570 res->link_target = rel;
2545 } 2571 }
2572 free(dirpath);
2546 free(normalized); 2573 free(normalized);
2547 } 2574 free(lnkbuf);
2548 2575 }
2549 free(lnkbuf);
2550 } 2576 }
2551 2577
2552 free(file_path); 2578 free(file_path);
2553 2579
2554 return res; 2580 return res;
2581 }
2582
2583 char* local_resource_path(LocalResource *res) {
2584 return res->local_path ? res->local_path : res->path;
2555 } 2585 }
2556 2586
2557 int local_resource_is_changed( 2587 int local_resource_is_changed(
2558 SyncDirectory *dir, 2588 SyncDirectory *dir,
2559 SyncDatabase *db, 2589 SyncDatabase *db,
2710 } 2740 }
2711 } 2741 }
2712 return ret; 2742 return ret;
2713 } 2743 }
2714 2744
2745 char* resource_local_path(DavResource *res) {
2746 #ifdef SYS_LINK_EXT
2747 // on Windows, add .lnk extension to links
2748 if(dav_get_property_ns(res, DAV_PROPS_NS, "link")) {
2749 return ucx_sprintf("%s%s", res->path, SYS_LINK_EXT).ptr;
2750 } else {
2751 // not a link
2752 return strdup(res->path);
2753 }
2754 #else
2755 return strdup(res->path);
2756 #endif
2757 }
2758
2715 size_t resource_get_blocksize(SyncDirectory *dir, LocalResource *local, DavResource *res, off_t filesize) { 2759 size_t resource_get_blocksize(SyncDirectory *dir, LocalResource *local, DavResource *res, off_t filesize) {
2716 size_t local_blocksize = 0; 2760 size_t local_blocksize = 0;
2717 if(local->blocksize < 0) { 2761 if(local->blocksize < 0) {
2718 // file splitting disabled 2762 // file splitting disabled
2719 return 0; 2763 return 0;
3064 return res->cached_tags; 3108 return res->cached_tags;
3065 } 3109 }
3066 UcxBuffer *buf = NULL; 3110 UcxBuffer *buf = NULL;
3067 if(dir->tagconfig->store == TAG_STORE_XATTR) { 3111 if(dir->tagconfig->store == TAG_STORE_XATTR) {
3068 ssize_t tag_length = 0; 3112 ssize_t tag_length = 0;
3069 char *local_path = create_local_path(dir, res->path); 3113 char *local_path = create_local_path(dir, local_resource_path(res));
3070 char* tag_data = xattr_get( 3114 char* tag_data = xattr_get(
3071 local_path, 3115 local_path,
3072 dir->tagconfig->xattr_name, 3116 dir->tagconfig->xattr_name,
3073 &tag_length); 3117 &tag_length);
3074 free(local_path); 3118 free(local_path);
3558 SyncDirectory *dir, 3602 SyncDirectory *dir,
3559 DavResource *res, 3603 DavResource *res,
3560 LocalResource *local, 3604 LocalResource *local,
3561 int *counter) 3605 int *counter)
3562 { 3606 {
3563 char *local_path = create_local_path(dir, res->path); 3607 char *local_path = create_local_path(dir, local_resource_path(local));
3564 3608
3565 SYS_STAT s; 3609 SYS_STAT s;
3566 if(sys_stat(local_path, &s)) { 3610 if(sys_stat(local_path, &s)) {
3567 fprintf(stderr, "Cannot stat file: %s\n", local_path); 3611 fprintf(stderr, "Cannot stat file: %s\n", local_path);
3568 perror(""); 3612 perror("");

mercurial