diff -r aa3baf1dd81b -r a7c48e0dca88 dav/sync.c --- a/dav/sync.c Fri Aug 02 21:40:05 2019 +0200 +++ b/dav/sync.c Fri Aug 02 22:04:00 2019 +0200 @@ -136,6 +136,7 @@ xmlGenericErrorFunc fnc = xmlerrorfnc; initGenericErrorDefaultFunc(&fnc); + sys_init(); ctx = dav_context_new(); int cfgret = load_config(ctx) || load_sync_config(); @@ -212,6 +213,8 @@ curl_global_cleanup(); xmlCleanupParser(); + sys_uninit(); + return ret; } @@ -716,13 +719,16 @@ // the first thing we need are all directories to put the files in UCX_FOREACH(elm, res_mkdir) { DavResource *res = elm->data; + char *res_path = resource_local_path(res); char *local_path = create_local_path(dir, res->path); + free(res_path); if(sys_mkdir(local_path) && errno != EEXIST) { fprintf(stderr, "Cannot create directory %s: %s", local_path, strerror(errno)); } free(local_path); + // TODO: create localres for dir } // we need a map for all conflicts for fast lookups @@ -757,7 +763,7 @@ continue; } - char *local_path = util_concat_path(dir->path, local->path); + char *local_path = util_concat_path(dir->path, local_resource_path(local)); int staterr = sys_stat(local_path, &s); free(local_path); if(staterr) { @@ -840,7 +846,9 @@ LocalResource *local = ucx_map_cstr_get(db->resources, res->path); if(local) { printf("update: %s\n", res->path); + char *res_path = resource_local_path(res); char *local_path = create_local_path(dir, res->path); + free(res_path); if(sync_store_metadata(dir, local_path, local, res)) { fprintf(stderr, "Metadata update failed: %s\n", res->path); sync_error++; @@ -1223,7 +1231,7 @@ renamefunc fn = copy ? copy_file : sys_rename; char *new_path = util_concat_path(dir->path, res->path); - char *old_path = util_concat_path(dir->path, content->path); + char *old_path = util_concat_path(dir->path, local_resource_path(content)); printf("%s: %s -> %s\n", copy?"copy":"move", content->path, res->path); if(fn(old_path, new_path)) { @@ -1287,12 +1295,20 @@ SyncDatabase *db, int *counter) { - LocalResource *local = ucx_map_cstr_get(db->resources, path); - char *local_path = create_local_path(dir, path); - char *link = SYNC_SYMLINK(dir) ? dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; + LocalResource *local = ucx_map_cstr_get(db->resources, path); + + char *local_path; + if(link) { + char *res_path = resource_local_path(res); + local_path = create_local_path(dir, res_path); + free(res_path); + } else { + local_path = create_local_path(dir, path); + } + char *etag = dav_get_string_property(res, "D:getetag"); SYS_STAT s; memset(&s, 0, sizeof(SYS_STAT)); @@ -1821,7 +1837,7 @@ continue; } - char *local_path = util_concat_path(dir->path, local->path); + char *local_path = util_concat_path(dir->path, local_resource_path(local)); char *hash = util_file_hash(local_path); local->hash = hash; // check if a file with this hash already exists @@ -2504,29 +2520,38 @@ res->isdirectory = 1; } - if(S_ISLNK(s.st_mode)) { - off_t l_sz = s.st_size + 16; - size_t lnksize = l_sz > 256 ? l_sz : 256; - char *lnkbuf = malloc(lnksize); + if(SYS_ISLINK(file_path, s)) { + char *lnkbuf = sys_readlink(file_path, &s); +#ifdef SYS_LINK_EXT + // on Windows, we interpret .lnk files as links + // we dont want resource names with this extension + // and possibly sync this to other operating systems + // therefore we remove the .lnk extension from the file name + // change res->path + // we only do this, if there isn't any other file with this name + sstr_t fpath = sstr(file_path); + sstr_t rpath = sstr(path); + // remove last 4 chars (.lnk) + sstr_t new_file_path = sstrdup(sstrsubsl(fpath, 0 , fpath.length-4)); + // check if a file with this name exists + SYS_STAT nfp_s; + if(!sys_stat(new_file_path.ptr, &nfp_s)) { + // we can't upload the link without the file extension, because + // there is another file with this name + free(lnkbuf); + lnkbuf = NULL; + } else { + sstr_t new_path = sstrdup(sstrsubsl(rpath, 0, rpath.length-4)); + res->local_path = res->path; + res->path = new_path.ptr; // remove .lnk ext from resource path + } + free(new_file_path.ptr); +#endif - ssize_t len = 0; - for(int i=0;i<4;i++) { - // we try to read the link at most 4 times - // only repeat if the buffer is too small - len = sys_readlink(file_path, lnkbuf, lnksize); - if(len != lnksize) { - break; - } - lnksize *= 2; - lnkbuf = realloc(lnkbuf, lnksize); - } - - if(len > 0) { - // readlink successful - lnkbuf[len] = 0; - + if(lnkbuf) { + // readlink successful char *normalized = NULL; - if(lnkbuf[0] != '/') { + if(!util_path_isabsolut(lnkbuf)) { char *link_parent = util_parent_path(res->path); char *abs_link_parent = util_concat_path(dir->path, link_parent); char *link = util_concat_path(abs_link_parent, lnkbuf); @@ -2538,15 +2563,16 @@ normalized = util_path_normalize(lnkbuf); } - if(util_path_isrelated(dir->path, normalized)) { + char *dirpath = util_path_normalize(dir->path); + if(util_path_isrelated(dirpath, normalized)) { // the link points to a file inside the syncdir char *rel = util_create_relative_path(normalized, file_path); res->link_target = rel; } + free(dirpath); free(normalized); + free(lnkbuf); } - - free(lnkbuf); } free(file_path); @@ -2554,6 +2580,10 @@ return res; } +char* local_resource_path(LocalResource *res) { + return res->local_path ? res->local_path : res->path; +} + int local_resource_is_changed( SyncDirectory *dir, SyncDatabase *db, @@ -2712,6 +2742,20 @@ return ret; } +char* resource_local_path(DavResource *res) { +#ifdef SYS_LINK_EXT + // on Windows, add .lnk extension to links + if(dav_get_property_ns(res, DAV_PROPS_NS, "link")) { + return ucx_sprintf("%s%s", res->path, SYS_LINK_EXT).ptr; + } else { + // not a link + return strdup(res->path); + } +#else + return strdup(res->path); +#endif +} + size_t resource_get_blocksize(SyncDirectory *dir, LocalResource *local, DavResource *res, off_t filesize) { size_t local_blocksize = 0; if(local->blocksize < 0) { @@ -3066,7 +3110,7 @@ UcxBuffer *buf = NULL; if(dir->tagconfig->store == TAG_STORE_XATTR) { ssize_t tag_length = 0; - char *local_path = create_local_path(dir, res->path); + char *local_path = create_local_path(dir, local_resource_path(res)); char* tag_data = xattr_get( local_path, dir->tagconfig->xattr_name, @@ -3560,7 +3604,7 @@ LocalResource *local, int *counter) { - char *local_path = create_local_path(dir, res->path); + char *local_path = create_local_path(dir, local_resource_path(local)); SYS_STAT s; if(sys_stat(local_path, &s)) {