967 CmdArgs *a, |
967 CmdArgs *a, |
968 DavResource *res, |
968 DavResource *res, |
969 SyncDirectory *dir, |
969 SyncDirectory *dir, |
970 SyncDatabase *db) |
970 SyncDatabase *db) |
971 { |
971 { |
|
972 DavBool update_db = FALSE; |
|
973 |
972 char *etag = dav_get_string_property(res, "D:getetag"); |
974 char *etag = dav_get_string_property(res, "D:getetag"); |
973 if(!etag) { |
975 if(!etag) { |
974 fprintf(stderr, "Error: resource %s has no etag\n", res->path); |
976 fprintf(stderr, "Error: resource %s has no etag\n", res->path); |
975 return REMOTE_NO_CHANGE; |
977 return REMOTE_NO_CHANGE; |
976 } |
978 } |
1015 } else if(local) { |
1017 } else if(local) { |
1016 DavBool nochange = FALSE; |
1018 DavBool nochange = FALSE; |
1017 if(SYNC_SYMLINK(dir) && nullstrcmp(link, local->link_target)) { |
1019 if(SYNC_SYMLINK(dir) && nullstrcmp(link, local->link_target)) { |
1018 ret = REMOTE_CHANGE_LINK; |
1020 ret = REMOTE_CHANGE_LINK; |
1019 nochange = TRUE; |
1021 nochange = TRUE; |
|
1022 |
|
1023 if(local->link_target) { |
|
1024 LocalResource *local2 = local_resource_new(dir, db, local->path); |
|
1025 if(type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED && nullstrcmp(local->link_target, local2->link_target)) { |
|
1026 ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
|
1027 } |
|
1028 local_resource_free(local2); |
|
1029 |
|
1030 if(!nullstrcmp(link, local->link_target)) { |
|
1031 ret = REMOTE_NO_CHANGE; |
|
1032 update_db = TRUE; |
|
1033 } |
|
1034 } |
1020 } else if(issplit && local->hash && hash) { |
1035 } else if(issplit && local->hash && hash) { |
1021 if(!strcmp(local->hash, hash)) { |
1036 if(!strcmp(local->hash, hash)) { |
1022 // resource is already up-to-date on the client |
1037 // resource is already up-to-date on the client |
1023 nochange = TRUE; |
1038 nochange = TRUE; |
1024 } |
1039 } |
1038 type = REMOTE_CHANGE_MODIFIED; |
1053 type = REMOTE_CHANGE_MODIFIED; |
1039 } |
1054 } |
1040 ret = type; |
1055 ret = type; |
1041 } |
1056 } |
1042 } else if(link) { |
1057 } else if(link) { |
|
1058 // new file is a link |
|
1059 ret = REMOTE_CHANGE_LINK; |
|
1060 |
1043 if(exists && type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) { |
1061 if(exists && type == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) { |
1044 ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
1062 // a file with the same name already exists |
1045 } else { |
1063 // if it is a link, compare the targets |
1046 ret = REMOTE_CHANGE_LINK; |
1064 LocalResource *local2 = local_resource_new(dir, db, res->path); |
1047 } |
1065 if(local2) { |
|
1066 if(local2->link_target) { |
|
1067 if(strcmp(link, local2->link_target)) { |
|
1068 ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
|
1069 } |
|
1070 } else { |
|
1071 ret = REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
|
1072 } |
|
1073 |
|
1074 local_resource_free(local2); |
|
1075 } |
|
1076 } |
|
1077 |
1048 } else if(exists) { |
1078 } else if(exists) { |
1049 ret = type; |
1079 ret = type; |
1050 } else { |
1080 } else { |
1051 ret = REMOTE_CHANGE_NEW; |
1081 ret = REMOTE_CHANGE_NEW; |
1052 } |
1082 } |
1053 |
1083 |
1054 // if hashing is enabled we can compare the hash of the remote file |
1084 // if hashing is enabled we can compare the hash of the remote file |
1055 // with the local file to test if a file is really modified |
1085 // with the local file to test if a file is really modified |
1056 DavBool update_db = FALSE; |
|
1057 char *update_hash = NULL; |
1086 char *update_hash = NULL; |
1058 if (!iscollection && |
1087 if (!iscollection && |
1059 !link && |
1088 !link && |
1060 (ret == REMOTE_CHANGE_MODIFIED || ret == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) && |
1089 (ret == REMOTE_CHANGE_MODIFIED || ret == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) && |
1061 exists && |
1090 exists && |
2208 print_resource_error(sn, local_res->path); |
2241 print_resource_error(sn, local_res->path); |
2209 ret = -1; |
2242 ret = -1; |
2210 sync_error++; |
2243 sync_error++; |
2211 } else { |
2244 } else { |
2212 DavBool equal = FALSE; |
2245 DavBool equal = FALSE; |
|
2246 DavBool res_conflict = FALSE; |
2213 int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); |
2247 int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); |
2214 if(equal) { |
2248 if(equal) { |
2215 char *etag = dav_get_string_property(res, "D:getetag"); |
2249 char *etag = dav_get_string_property(res, "D:getetag"); |
2216 if(local_res->metadata_updated) { |
2250 if(local_res->metadata_updated) { |
2217 ls_update = ucx_list_prepend(ls_update, local_res); |
2251 ls_update = ucx_list_prepend(ls_update, local_res); |
2229 local_res->etag = NULL; |
2263 local_res->etag = NULL; |
2230 nullfree(local_res->hash); |
2264 nullfree(local_res->hash); |
2231 local_res->hash = NULL; |
2265 local_res->hash = NULL; |
2232 local_res->skipped = TRUE; |
2266 local_res->skipped = TRUE; |
2233 sync_conflict++; |
2267 sync_conflict++; |
|
2268 |
|
2269 if(local_res->link_target) { |
|
2270 free(local_res->link_target); |
|
2271 local_res->link_target = local_res->link_target_db; |
|
2272 local_res->link_target_db = NULL; |
|
2273 } |
|
2274 |
|
2275 res_conflict = TRUE; |
2234 } else { |
2276 } else { |
2235 if(local_res->link_target) { |
2277 if(local_res->link_target) { |
2236 printf( |
2278 printf( |
2237 "link: %s -> %s\n", |
2279 "link: %s -> %s\n", |
2238 local_res->path, |
2280 local_res->path, |
2250 } |
2292 } |
2251 } |
2293 } |
2252 |
2294 |
2253 if(!err) { |
2295 if(!err) { |
2254 LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); |
2296 LocalResource *dbres = ucx_map_cstr_remove(db->resources, local_res->path); |
2255 ucx_map_cstr_put(db->resources, local_res->path, local_res); |
2297 // in case of a conflict, don't store the resource |
|
2298 // in the db, if it is new |
|
2299 if(!res_conflict || dbres) { |
|
2300 ucx_map_cstr_put(db->resources, local_res->path, local_res); |
|
2301 } |
2256 } |
2302 } |
2257 } |
2303 } |
2258 |
2304 |
2259 dav_resource_free(res); |
2305 dav_resource_free(res); |
2260 } |
2306 } |
2844 if(db_res->xattr_hash) { |
2890 if(db_res->xattr_hash) { |
2845 res->xattr_hash = strdup(db_res->xattr_hash); |
2891 res->xattr_hash = strdup(db_res->xattr_hash); |
2846 } |
2892 } |
2847 if(db_res->hash) { |
2893 if(db_res->hash) { |
2848 res->prev_hash = strdup(db_res->hash); |
2894 res->prev_hash = strdup(db_res->hash); |
|
2895 } |
|
2896 if(db_res->link_target) { |
|
2897 res->link_target_db = db_res->link_target; |
2849 } |
2898 } |
2850 |
2899 |
2851 // if the resource is splitted, copy the part info to the new |
2900 // if the resource is splitted, copy the part info to the new |
2852 // LocalResource obj, because we need it later |
2901 // LocalResource obj, because we need it later |
2853 if(db_res->parts) { |
2902 if(db_res->parts) { |
3003 |
3052 |
3004 if(remote->iscollection && !res->parts) { |
3053 if(remote->iscollection && !res->parts) { |
3005 return 1; |
3054 return 1; |
3006 } |
3055 } |
3007 |
3056 |
|
3057 char *link = dav_get_string_property_ns(remote, DAV_PROPS_NS, "link"); |
|
3058 |
3008 int ret = 0; |
3059 int ret = 0; |
3009 if(err == 0) { |
3060 if(err == 0) { |
3010 char *etag = dav_get_string_property(remote, "D:getetag"); |
3061 char *etag = dav_get_string_property(remote, "D:getetag"); |
3011 char *hash = sync_get_content_hash(remote); |
3062 char *hash = sync_get_content_hash(remote); |
|
3063 |
|
3064 if(res->link_target_db || link) { |
|
3065 ret = nullstrcmp(res->link_target_db, link); |
|
3066 if(ret && equal) { |
|
3067 *equal = !nullstrcmp(res->link_target, link); |
|
3068 } |
|
3069 return ret; |
|
3070 } |
3012 |
3071 |
3013 if(hash && res->hash && equal) { |
3072 if(hash && res->hash && equal) { |
3014 // if requested, check if the local and remote res are equal |
3073 // if requested, check if the local and remote res are equal |
3015 if(!strcmp(hash, res->hash)) { |
3074 if(!strcmp(hash, res->hash)) { |
3016 *equal = TRUE; |
3075 *equal = TRUE; |