dav/sync.c

changeset 686
ab159748055c
parent 685
487645580b5e
child 687
9922a349a61a
equal deleted inserted replaced
685:487645580b5e 686:ab159748055c
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 &&
1153 } 1182 }
1154 local_resource_set_etag(local, etag); 1183 local_resource_set_etag(local, etag);
1155 if(!local->hash) { 1184 if(!local->hash) {
1156 local->hash = update_hash; 1185 local->hash = update_hash;
1157 } // else: hash already updated 1186 } // else: hash already updated
1187 if(link) {
1188 nullfree(local->link_target);
1189 local->link_target = link;
1190 }
1158 } 1191 }
1159 1192
1160 free(local_path); 1193 free(local_path);
1161 return ret; 1194 return ret;
1162 } 1195 }
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;

mercurial