75 } |
75 } |
76 |
76 |
77 static DavPropName defprops[] = { |
77 static DavPropName defprops[] = { |
78 { "DAV:", "getetag" }, |
78 { "DAV:", "getetag" }, |
79 { DAV_NS, "status" }, |
79 { DAV_NS, "status" }, |
80 { DAV_NS, "finfo" }, |
|
81 { DAV_NS, "tags" }, |
|
82 { DAV_NS, "xattributes" }, |
|
83 { DAV_NS, "content-hash" }, |
80 { DAV_NS, "content-hash" }, |
84 { DAV_NS, "split" }, |
81 { DAV_NS, "split" }, |
85 { DAV_NS, "link" } |
82 { DAV_PROPS_NS, "finfo" }, |
|
83 { DAV_PROPS_NS, "tags" }, |
|
84 { DAV_PROPS_NS, "xattributes" }, |
|
85 { DAV_PROPS_NS, "link" } |
86 }; |
86 }; |
87 static size_t numdefprops = 8 ; |
87 static size_t numdefprops = 8 ; |
88 |
88 |
89 /* |
89 /* |
90 * strcmp version that works with NULL pointers |
90 * strcmp version that works with NULL pointers |
343 //} |
343 //} |
344 if(res->iscollection) { |
344 if(res->iscollection) { |
345 return 1; |
345 return 1; |
346 } |
346 } |
347 |
347 |
348 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
348 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); |
349 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
349 UcxList *res_tags = parse_dav_xml_taglist(tagsprop); |
350 |
350 |
351 int ret = matches_tagfilter(res_tags, tagfilter); |
351 int ret = matches_tagfilter(res_tags, tagfilter); |
352 |
352 |
353 ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); |
353 ucx_list_free_content(res_tags, (ucx_destructor) free_dav_tag); |
550 locked = TRUE; |
550 locked = TRUE; |
551 locktokenfile = create_locktoken_file(dir->name, lock->token); |
551 locktokenfile = create_locktoken_file(dir->name, lock->token); |
552 } |
552 } |
553 |
553 |
554 int ret = 0; |
554 int ret = 0; |
555 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes,idav:split,idav:link,`idav:content-hash` from / with depth = infinity"); |
555 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:split,`idav:content-hash`,idavprops:tags,idavprops:finfo,idavprops:xattributes,idavprops:link from / with depth = infinity"); |
556 if(!ls) { |
556 if(!ls) { |
557 print_resource_error(sn, "/"); |
557 print_resource_error(sn, "/"); |
558 if(locked) { |
558 if(locked) { |
559 if(dav_unlock(root)) { |
559 if(dav_unlock(root)) { |
560 print_resource_error(sn, "/"); |
560 print_resource_error(sn, "/"); |
956 |
956 |
957 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
957 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
958 char *local_path = create_local_path(dir, res->path); |
958 char *local_path = create_local_path(dir, res->path); |
959 |
959 |
960 char *link = SYNC_SYMLINK(dir) ? |
960 char *link = SYNC_SYMLINK(dir) ? |
961 dav_get_string_property_ns(res, DAV_NS, "link") : NULL; |
961 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; |
962 |
962 |
963 SYS_STAT s; |
963 SYS_STAT s; |
964 DavBool exists = 1; |
964 DavBool exists = 1; |
965 if(sys_stat(local_path, &s)) { |
965 if(sys_stat(local_path, &s)) { |
966 if(errno != ENOENT) { |
966 if(errno != ENOENT) { |
1017 } |
1017 } |
1018 |
1018 |
1019 while(ret == REMOTE_NO_CHANGE && local) { |
1019 while(ret == REMOTE_NO_CHANGE && local) { |
1020 // check if tags have changed |
1020 // check if tags have changed |
1021 if(dir->tagconfig) { |
1021 if(dir->tagconfig) { |
1022 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
1022 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); |
1023 UcxList *remote_tags = NULL; |
1023 UcxList *remote_tags = NULL; |
1024 if(tagsprop) { |
1024 if(tagsprop) { |
1025 remote_tags = parse_dav_xml_taglist(tagsprop); |
1025 remote_tags = parse_dav_xml_taglist(tagsprop); |
1026 } |
1026 } |
1027 char *remote_hash = create_tags_hash(remote_tags); |
1027 char *remote_hash = create_tags_hash(remote_tags); |
1038 } |
1038 } |
1039 } |
1039 } |
1040 |
1040 |
1041 // check if extended attributes have changed |
1041 // check if extended attributes have changed |
1042 if((dir->metadata & FINFO_XATTR) == FINFO_XATTR) { |
1042 if((dir->metadata & FINFO_XATTR) == FINFO_XATTR) { |
1043 DavXmlNode *xattr = dav_get_property_ns(res, DAV_NS, "xattributes"); |
1043 DavXmlNode *xattr = dav_get_property_ns(res, DAV_PROPS_NS, "xattributes"); |
1044 char *xattr_hash = get_xattr_hash(xattr); |
1044 char *xattr_hash = get_xattr_hash(xattr); |
1045 if(nullstrcmp(xattr_hash, local->xattr_hash)) { |
1045 if(nullstrcmp(xattr_hash, local->xattr_hash)) { |
1046 ret = REMOTE_CHANGE_METADATA; |
1046 ret = REMOTE_CHANGE_METADATA; |
1047 break; |
1047 break; |
1048 } |
1048 } |
1049 } |
1049 } |
1050 |
1050 |
1051 // check if finfo has changed |
1051 // check if finfo has changed |
1052 DavXmlNode *finfo = dav_get_property_ns(res, DAV_NS, "finfo"); |
1052 DavXmlNode *finfo = dav_get_property_ns(res, DAV_PROPS_NS, "finfo"); |
1053 if((dir->metadata & FINFO_MODE) == FINFO_MODE) { |
1053 if((dir->metadata & FINFO_MODE) == FINFO_MODE) { |
1054 FileInfo f; |
1054 FileInfo f; |
1055 finfo_get_values(finfo, &f); |
1055 finfo_get_values(finfo, &f); |
1056 if(f.mode_set && f.mode != local->mode) { |
1056 if(f.mode_set && f.mode != local->mode) { |
1057 ret = REMOTE_CHANGE_METADATA; |
1057 ret = REMOTE_CHANGE_METADATA; |
1289 { |
1289 { |
1290 LocalResource *local = ucx_map_cstr_get(db->resources, path); |
1290 LocalResource *local = ucx_map_cstr_get(db->resources, path); |
1291 char *local_path = create_local_path(dir, path); |
1291 char *local_path = create_local_path(dir, path); |
1292 |
1292 |
1293 char *link = SYNC_SYMLINK(dir) ? |
1293 char *link = SYNC_SYMLINK(dir) ? |
1294 dav_get_string_property_ns(res, DAV_NS, "link") : NULL; |
1294 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; |
1295 |
1295 |
1296 char *etag = dav_get_string_property(res, "D:getetag"); |
1296 char *etag = dav_get_string_property(res, "D:getetag"); |
1297 SYS_STAT s; |
1297 SYS_STAT s; |
1298 memset(&s, 0, sizeof(SYS_STAT)); |
1298 memset(&s, 0, sizeof(SYS_STAT)); |
1299 |
1299 |
2309 resources = ucx_list_sort(resources, (cmp_func)localres_cmp_path, NULL); |
2309 resources = ucx_list_sort(resources, (cmp_func)localres_cmp_path, NULL); |
2310 |
2310 |
2311 UCX_FOREACH(elm, resources) { |
2311 UCX_FOREACH(elm, resources) { |
2312 LocalResource *resource = elm->data; |
2312 LocalResource *resource = elm->data; |
2313 |
2313 |
2314 DavResource *res = dav_get(sn, resource->path, "D:getetag,idav:status,idav:version-collection,idav:finfo,idav:xattributes"); |
2314 DavResource *res = dav_get(sn, resource->path, "D:getetag,idav:status,idav:version-collection,idav:split,`idav:content-hash`,idavprops:tags,idavprops:finfo,idavprops:xattributes,idavprops:link"); |
2315 if(!res) { |
2315 if(!res) { |
2316 printf("skip: %s\n", resource->path); |
2316 printf("skip: %s\n", resource->path); |
2317 continue; |
2317 continue; |
2318 } |
2318 } |
2319 char *status = dav_get_string_property(res, "idav:status"); |
2319 char *status = dav_get_string_property(res, "idav:status"); |
2671 DavResource *remote, |
2671 DavResource *remote, |
2672 LocalResource *res) |
2672 LocalResource *res) |
2673 { |
2673 { |
2674 DavPropName properties[] = { |
2674 DavPropName properties[] = { |
2675 {"DAV:", "getetag"}, |
2675 {"DAV:", "getetag"}, |
2676 {DAV_NS, "tags"}, |
|
2677 {DAV_NS, "version-collection"}, |
2676 {DAV_NS, "version-collection"}, |
2678 {DAV_NS, "content-hash"}, |
2677 {DAV_NS, "content-hash"}, |
2679 {DAV_NS, "split" }, |
2678 {DAV_NS, "split" }, |
2680 {DAV_NS, "link" } |
2679 {DAV_PROPS_NS, "tags"}, |
|
2680 {DAV_PROPS_NS, "link" } |
2681 }; |
2681 }; |
2682 int err = dav_load_prop(remote, properties, 6); |
2682 int err = dav_load_prop(remote, properties, 6); |
2683 |
2683 |
2684 if(res->restore) { |
2684 if(res->restore) { |
2685 return 0; |
2685 return 0; |
2806 return ret; |
2806 return ret; |
2807 } |
2807 } |
2808 |
2808 |
2809 // TODO: remove code dup (main.c: find_version) |
2809 // TODO: remove code dup (main.c: find_version) |
2810 DavResource* versioning_deltav_find(DavResource *res, const char *version) { |
2810 DavResource* versioning_deltav_find(DavResource *res, const char *version) { |
2811 DavResource *list = dav_versiontree(res, "D:getetag,idav:status,idav:finfo,idav:xattributes,idav:tags"); |
2811 DavResource *list = dav_versiontree(res, "D:getetag,idav:status,idav:split,idavprops:link,idavprops:finfo,idavprops:xattributes,idavprops:tags"); |
2812 DavResource *ret = NULL; |
2812 DavResource *ret = NULL; |
2813 while(list) { |
2813 while(list) { |
2814 DavResource *next = list->next; |
2814 DavResource *next = list->next; |
2815 if(!ret) { |
2815 if(!ret) { |
2816 char *vname = dav_get_string_property(list, "D:version-name"); |
2816 char *vname = dav_get_string_property(list, "D:version-name"); |
2875 } |
2875 } |
2876 |
2876 |
2877 int sync_store_metadata(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { |
2877 int sync_store_metadata(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { |
2878 int ret = 0; |
2878 int ret = 0; |
2879 |
2879 |
2880 DavXmlNode *fileinfo = dav_get_property_ns(res, DAV_NS, "finfo"); |
2880 DavXmlNode *fileinfo = dav_get_property_ns(res, DAV_PROPS_NS, "finfo"); |
2881 if(fileinfo) { |
2881 if(fileinfo) { |
2882 FileInfo f; |
2882 FileInfo f; |
2883 finfo_get_values(fileinfo, &f); |
2883 finfo_get_values(fileinfo, &f); |
2884 if((dir->metadata & FINFO_DATE) == FINFO_DATE && f.date_set) { |
2884 if((dir->metadata & FINFO_DATE) == FINFO_DATE && f.date_set) { |
2885 // set mtime |
2885 // set mtime |
2898 ret = 1; |
2898 ret = 1; |
2899 } |
2899 } |
2900 } |
2900 } |
2901 } |
2901 } |
2902 |
2902 |
2903 DavXmlNode *xattr_prop = dav_get_property_ns(res, DAV_NS, "xattributes"); |
2903 DavXmlNode *xattr_prop = dav_get_property_ns(res, DAV_PROPS_NS, "xattributes"); |
2904 if(xattr_prop) { |
2904 if(xattr_prop) { |
2905 XAttributes *xattr = xml_get_attributes(xattr_prop); |
2905 XAttributes *xattr = xml_get_attributes(xattr_prop); |
2906 if(xattr) { |
2906 if(xattr) { |
2907 if(!sync_store_xattr(dir, path, xattr)) { |
2907 if(!sync_store_xattr(dir, path, xattr)) { |
2908 if(local->xattr_hash) { |
2908 if(local->xattr_hash) { |
3570 return -1; |
3570 return -1; |
3571 } |
3571 } |
3572 |
3572 |
3573 DavBool islink = local->link_target ? 1 : 0; |
3573 DavBool islink = local->link_target ? 1 : 0; |
3574 if(!local->link_target && local->link_updated) { |
3574 if(!local->link_target && local->link_updated) { |
3575 dav_remove_property_ns(res, DAV_NS, "link"); |
3575 dav_remove_property_ns(res, DAV_PROPS_NS, "link"); |
3576 } |
3576 } |
3577 |
3577 |
3578 size_t split_blocksize = resource_get_blocksize(dir, local, res, s.st_size); |
3578 size_t split_blocksize = resource_get_blocksize(dir, local, res, s.st_size); |
3579 |
3579 |
3580 FILE *in = sys_fopen(local_path, "rb"); |
3580 FILE *in = sys_fopen(local_path, "rb"); |
3588 int split_err = 0; |
3588 int split_err = 0; |
3589 UcxList *parts = NULL; |
3589 UcxList *parts = NULL; |
3590 uint64_t blockcount = 0; |
3590 uint64_t blockcount = 0; |
3591 |
3591 |
3592 if(islink) { |
3592 if(islink) { |
3593 dav_set_string_property_ns(res, DAV_NS, "link", local->link_target); |
3593 dav_set_string_property_ns(res, DAV_PROPS_NS, "link", local->link_target); |
3594 } else if(issplit) { |
3594 } else if(issplit) { |
3595 // set split property |
3595 // set split property |
3596 char blocksize_str[32]; |
3596 char blocksize_str[32]; |
3597 snprintf(blocksize_str, 32, "%zu", split_blocksize); |
3597 snprintf(blocksize_str, 32, "%zu", split_blocksize); |
3598 dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str); |
3598 dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str); |
3892 hashes.tags = tags_hash; |
3892 hashes.tags = tags_hash; |
3893 |
3893 |
3894 DavBool store_tags = TRUE; |
3894 DavBool store_tags = TRUE; |
3895 // get remote tags |
3895 // get remote tags |
3896 UcxList *remote_tags = NULL; |
3896 UcxList *remote_tags = NULL; |
3897 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags"); |
3897 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); |
3898 if(tagsprop) { |
3898 if(tagsprop) { |
3899 remote_tags = parse_dav_xml_taglist(tagsprop); |
3899 remote_tags = parse_dav_xml_taglist(tagsprop); |
3900 } |
3900 } |
3901 char *remote_hash = create_tags_hash(remote_tags); |
3901 char *remote_hash = create_tags_hash(remote_tags); |
3902 if(nullstrcmp(remote_hash, local->remote_tags_hash)) { |
3902 if(nullstrcmp(remote_hash, local->remote_tags_hash)) { |
3925 } |
3925 } |
3926 |
3926 |
3927 if(store_tags) { |
3927 if(store_tags) { |
3928 if(tags) { |
3928 if(tags) { |
3929 DavXmlNode *tagprop = create_xml_taglist(tags); |
3929 DavXmlNode *tagprop = create_xml_taglist(tags); |
3930 dav_set_property_ns(res, DAV_NS, "tags", tagprop); |
3930 dav_set_property_ns(res, DAV_PROPS_NS, "tags", tagprop); |
3931 } else { |
3931 } else { |
3932 dav_remove_property_ns(res, DAV_NS, "tags"); |
3932 dav_remove_property_ns(res, DAV_PROPS_NS, "tags"); |
3933 } |
3933 } |
3934 } |
3934 } |
3935 |
3935 |
3936 free_taglist(remote_tags); |
3936 free_taglist(remote_tags); |
3937 } else { |
3937 } else { |