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); |
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) { |
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(""); |