543:2f85df8cd35e | 544:9e85e1ec1155 |
---|---|
271 pthread_mutex_unlock(mutex); | 271 pthread_mutex_unlock(mutex); |
272 void *data; | 272 void *data; |
273 pthread_join(tid, &data); | 273 pthread_join(tid, &data); |
274 } | 274 } |
275 | 275 |
276 static char* create_local_path(SyncDirectory *dir, const char *path) { | |
277 char *local_path = util_concat_path(dir->path, path); | |
278 size_t local_path_len = strlen(local_path); | |
279 if(local_path[local_path_len-1] == '/') { | |
280 local_path[local_path_len-1] = '\0'; | |
281 } | |
282 return local_path; | |
283 } | |
284 | |
276 static int res_matches_filter(SyncDirectory *dir, char *res_path) { | 285 static int res_matches_filter(SyncDirectory *dir, char *res_path) { |
277 // trash filter | 286 // trash filter |
278 if (dir->trash) { | 287 if (dir->trash) { |
279 sstr_t rpath = sstr(util_concat_path(dir->path, res_path)); | 288 sstr_t rpath = sstr(util_concat_path(dir->path, res_path)); |
280 if (sstrprefix(rpath, sstr(dir->trash))) { | 289 if (util_path_isrelated(dir->trash, rpath.ptr)) { |
281 free(rpath.ptr); | 290 free(rpath.ptr); |
282 return 1; | 291 return 1; |
283 } | 292 } |
284 free(rpath.ptr); | 293 free(rpath.ptr); |
285 } | 294 } |
522 locked = TRUE; | 531 locked = TRUE; |
523 locktokenfile = create_locktoken_file(dir->name, lock->token); | 532 locktokenfile = create_locktoken_file(dir->name, lock->token); |
524 } | 533 } |
525 | 534 |
526 int ret = 0; | 535 int ret = 0; |
527 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes,`idav:content-hash` from / with depth = infinity"); | 536 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes,idav:split,`idav:content-hash` from / with depth = infinity"); |
528 if(!ls) { | 537 if(!ls) { |
529 print_resource_error(sn, "/"); | 538 print_resource_error(sn, "/"); |
530 if(locked) { | 539 if(locked) { |
531 if(dav_unlock(root)) { | 540 if(dav_unlock(root)) { |
532 print_resource_error(sn, "/"); | 541 print_resource_error(sn, "/"); |
574 UcxList *res_broken = NULL; | 583 UcxList *res_broken = NULL; |
575 UcxList *lres_removed = NULL; // list of LocalResource* | 584 UcxList *lres_removed = NULL; // list of LocalResource* |
576 | 585 |
577 //UcxMap *svrres = ucx_map_new(db->resources->count); | 586 //UcxMap *svrres = ucx_map_new(db->resources->count); |
578 UcxMap *dbres = ucx_map_clone(db->resources, NULL, NULL); | 587 UcxMap *dbres = ucx_map_clone(db->resources, NULL, NULL); |
579 | |
580 UcxList *statls = NULL; | |
581 | 588 |
582 UcxList *stack = ucx_list_prepend(NULL, ls->children); | 589 UcxList *stack = ucx_list_prepend(NULL, ls->children); |
583 while(stack) { | 590 while(stack) { |
584 DavResource *res = stack->data; | 591 DavResource *res = stack->data; |
585 stack = ucx_list_remove(stack, stack); | 592 stack = ucx_list_remove(stack, stack); |
650 // remove every server resource from dbres | 657 // remove every server resource from dbres |
651 // all remaining elements are the resources that are removed | 658 // all remaining elements are the resources that are removed |
652 // on the server | 659 // on the server |
653 ucx_map_cstr_remove(dbres, res->path); | 660 ucx_map_cstr_remove(dbres, res->path); |
654 | 661 |
655 if(res->children) { | 662 if(!dav_get_property_ns(res, DAV_NS, "split") && res->children) { |
656 stack = ucx_list_prepend(stack, res->children); | 663 stack = ucx_list_prepend(stack, res->children); |
657 } | 664 } |
658 res = res->next; | 665 res = res->next; |
659 } | 666 } |
660 } | 667 } |
674 } | 681 } |
675 | 682 |
676 // the first thing we need are all directories to put the files in | 683 // the first thing we need are all directories to put the files in |
677 UCX_FOREACH(elm, res_mkdir) { | 684 UCX_FOREACH(elm, res_mkdir) { |
678 DavResource *res = elm->data; | 685 DavResource *res = elm->data; |
679 char *local_path = util_concat_path(dir->path, res->path); | 686 char *local_path = create_local_path(dir, res->path); |
680 if(sys_mkdir(local_path) && errno != EEXIST) { | 687 if(sys_mkdir(local_path) && errno != EEXIST) { |
681 fprintf(stderr, | 688 fprintf(stderr, |
682 "Cannot create directory %s: %s", | 689 "Cannot create directory %s: %s", |
683 local_path, strerror(errno)); | 690 local_path, strerror(errno)); |
684 } | 691 } |
699 DavResource *res = elm->data; | 706 DavResource *res = elm->data; |
700 if(sync_shutdown) { | 707 if(sync_shutdown) { |
701 break; | 708 break; |
702 } | 709 } |
703 | 710 |
711 DavBool issplit = dav_get_property_ns(res, DAV_NS, "split") ? 1 : 0; | |
704 if(ucx_map_cstr_get(conflicts, res->path)) { | 712 if(ucx_map_cstr_get(conflicts, res->path)) { |
705 rename_conflict_file(dir, db, res->path); | 713 rename_conflict_file(dir, db, res->path, issplit); |
706 } | 714 } |
707 | 715 |
708 // download the resource | 716 // download the resource |
709 if(sync_get_resource(a, dir, res->path, res, db, &sync_success)) { | 717 if(sync_get_resource(a, dir, res->path, res, db, &sync_success)) { |
710 fprintf(stderr, "resource download failed: %s\n", res->path); | 718 fprintf(stderr, "resource download failed: %s\n", res->path); |
719 } | 727 } |
720 | 728 |
721 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); | 729 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
722 if(local) { | 730 if(local) { |
723 printf("update: %s\n", res->path); | 731 printf("update: %s\n", res->path); |
724 char *local_path = util_concat_path(dir->path, res->path); | 732 char *local_path = create_local_path(dir, res->path); |
725 if(sync_store_metadata(dir, local_path, local, res)) { | 733 if(sync_store_metadata(dir, local_path, local, res)) { |
726 fprintf(stderr, "Metadata update failed: %s\n", res->path); | 734 fprintf(stderr, "Metadata update failed: %s\n", res->path); |
727 sync_error++; | 735 sync_error++; |
728 } else { | 736 } else { |
729 struct stat s; | 737 struct stat s; |
821 fprintf(stderr, "Error: resource %s has no etag\n", res->path); | 829 fprintf(stderr, "Error: resource %s has no etag\n", res->path); |
822 return REMOTE_NO_CHANGE; | 830 return REMOTE_NO_CHANGE; |
823 } | 831 } |
824 | 832 |
825 DavBool issplit = dav_get_property(res, "idav:split") ? TRUE : FALSE; | 833 DavBool issplit = dav_get_property(res, "idav:split") ? TRUE : FALSE; |
834 if(issplit) { | |
835 util_remove_trailing_pathseparator(res->path); | |
836 } | |
826 | 837 |
827 RemoteChangeType type = cmd_getoption(a, "conflict") ? | 838 RemoteChangeType type = cmd_getoption(a, "conflict") ? |
828 REMOTE_CHANGE_MODIFIED : REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; | 839 REMOTE_CHANGE_MODIFIED : REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
829 | 840 |
830 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); | 841 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
831 char *local_path = util_concat_path(dir->path, res->path); | 842 char *local_path = create_local_path(dir, res->path); |
832 | 843 |
833 SYS_STAT s; | 844 SYS_STAT s; |
834 DavBool exists = 1; | 845 DavBool exists = 1; |
835 if(sys_stat(local_path, &s)) { | 846 if(sys_stat(local_path, &s)) { |
836 if(errno != ENOENT) { | 847 if(errno != ENOENT) { |
932 local->mode = s->st_mode & 07777; | 943 local->mode = s->st_mode & 07777; |
933 local->uid = s->st_uid; | 944 local->uid = s->st_uid; |
934 local->gid = s->st_gid; | 945 local->gid = s->st_gid; |
935 local->size = s->st_size; | 946 local->size = s->st_size; |
936 } | 947 } |
948 | |
949 static UcxList* sync_download_changed_parts( | |
950 DavResource *res, | |
951 LocalResource *local, | |
952 FILE *out, | |
953 size_t blocksize, | |
954 uint64_t *blockcount, | |
955 int64_t *truncate_file, | |
956 int *err) | |
957 { | |
958 UcxList *updates = NULL; | |
959 | |
960 size_t local_numparts = local ? local->numparts : 0; | |
961 | |
962 int error = 0; | |
963 | |
964 UcxBuffer *buf = ucx_buffer_new(NULL, blocksize, 0); | |
965 | |
966 int64_t maxsize = -1; | |
967 | |
968 DavResource *part = res->children; | |
969 uint64_t i = 0; | |
970 while(part) { | |
971 char *res_name = part->name; | |
972 while(res_name[0] == '0' && res_name[1] != '\0') { | |
973 res_name++; | |
974 } | |
975 uint64_t partnum = 0; | |
976 if(util_strtouint(res_name, &partnum)) { | |
977 DavBool download_part = FALSE; | |
978 char *etag = dav_get_string_property_ns(part, "DAV:", "getetag"); | |
979 if(partnum >= local_numparts) { | |
980 // new part | |
981 download_part = TRUE; | |
982 } else { | |
983 FilePart p = local->parts[partnum]; // local is always non-null here | |
984 if(etag) { | |
985 if(nullstrcmp(etag, p.etag)) { | |
986 download_part = TRUE; | |
987 } | |
988 } | |
989 } | |
990 | |
991 uint64_t offset; | |
992 int mul_err = util_uint_mul(partnum, blocksize, &offset); | |
993 if(mul_err || offset >= INT64_MAX) { | |
994 error = 1; | |
995 fprintf(stderr, "Error: part number too high\n"); | |
996 break; | |
997 } | |
998 | |
999 if(download_part) { | |
1000 if(fseeko(out, offset, SEEK_SET)) { | |
1001 error = 1; | |
1002 fprintf(stderr, "Error: fseek failed: %s\n", strerror(errno)); | |
1003 break; | |
1004 } | |
1005 buf->pos = 0; | |
1006 buf->size = 0; | |
1007 if(dav_get_content(part, buf,(dav_write_func)ucx_buffer_write)) { | |
1008 fprintf(stderr, "Error: cannot download part: %s\n", part->name); | |
1009 error = 1; | |
1010 break; | |
1011 } | |
1012 printf("offset: %lu length: %lu\n", offset, (uint64_t)buf->size); | |
1013 if(fwrite(buf->space, 1, buf->size, out) == 0) { | |
1014 perror("write"); | |
1015 error = 1; | |
1016 break; | |
1017 } | |
1018 | |
1019 FilePart *update = calloc(1, sizeof(FilePart)); | |
1020 update->block = partnum; | |
1021 update->etag = etag ? strdup(etag) : NULL; | |
1022 update->hash = dav_create_hash(buf->space, buf->size); | |
1023 updates = ucx_list_append(updates, update); | |
1024 } | |
1025 | |
1026 | |
1027 | |
1028 i++; | |
1029 } // else: res is not a regular file part | |
1030 part = part->next; | |
1031 } | |
1032 | |
1033 ucx_buffer_free(buf); | |
1034 | |
1035 if(error) { | |
1036 *err = 1; | |
1037 ucx_list_free_content(updates, (ucx_destructor)filepart_free); | |
1038 return NULL; | |
1039 } | |
1040 | |
1041 *err = 0; | |
1042 *blockcount = i; | |
1043 *truncate_file = maxsize; | |
1044 return updates; | |
1045 } | |
1046 | |
1047 | |
937 | 1048 |
938 int sync_get_resource( | 1049 int sync_get_resource( |
939 CmdArgs *a, | 1050 CmdArgs *a, |
940 SyncDirectory *dir, | 1051 SyncDirectory *dir, |
941 const char *path, | 1052 const char *path, |
942 DavResource *res, | 1053 DavResource *res, |
943 SyncDatabase *db, | 1054 SyncDatabase *db, |
944 int *counter) | 1055 int *counter) |
945 { | 1056 { |
946 LocalResource *local = ucx_map_cstr_get(db->resources, path); | 1057 LocalResource *local = ucx_map_cstr_get(db->resources, path); |
947 char *local_path = util_concat_path(dir->path, path); | 1058 char *local_path = create_local_path(dir, path); |
948 | 1059 |
949 char *etag = dav_get_string_property(res, "D:getetag"); | 1060 char *etag = dav_get_string_property(res, "D:getetag"); |
950 SYS_STAT s; | 1061 SYS_STAT s; |
951 memset(&s, 0, sizeof(SYS_STAT)); | 1062 memset(&s, 0, sizeof(SYS_STAT)); |
1063 | |
1064 char *blocksize_str = dav_get_string_property_ns(res, DAV_NS, "split"); | |
1065 int64_t blocksize = 0; | |
1066 DavBool issplit = FALSE; | |
1067 if(blocksize_str) { | |
1068 if(!util_strtouint(blocksize_str, &blocksize)) { | |
1069 fprintf(stderr, "Error: split property does not contain an integer.\n"); | |
1070 return 1; | |
1071 } | |
1072 issplit = TRUE; | |
1073 } | |
1074 UcxList *part_updates = NULL; | |
1075 uint64_t blockcount = 0; | |
1076 | |
1077 if(res->iscollection && !issplit) { | |
1078 // why are we here? | |
1079 return 0; | |
1080 } | |
952 | 1081 |
953 int ret = 0; | 1082 int ret = 0; |
954 char *tmp_path = create_tmp_download_path(local_path); | 1083 |
955 | 1084 char *tmp_path = NULL; |
956 if(!tmp_path) { | 1085 FILE *out = NULL; |
957 fprintf(stderr, "Cannot create tmp path for %s\n", local_path); | 1086 if(!issplit) { |
958 free(local_path); | 1087 tmp_path = create_tmp_download_path(local_path); |
959 return -1; | 1088 if(!tmp_path) { |
960 } | 1089 fprintf(stderr, "Cannot create tmp path for %s\n", local_path); |
961 FILE *out = sys_fopen(tmp_path, "wb"); | 1090 free(local_path); |
1091 return -1; | |
1092 } | |
1093 out = sys_fopen(tmp_path , "wb"); | |
1094 } else { | |
1095 out = sys_fopen(local_path, "r+b"); | |
1096 if(!out && errno == ENOENT) { | |
1097 out = sys_fopen(local_path, "wb"); | |
1098 } | |
1099 } | |
962 if(!out) { | 1100 if(!out) { |
963 fprintf(stderr, "Cannot open output file: %s\n", local_path); | 1101 fprintf(stderr, "Cannot open output file: %s\n", local_path); |
964 free(local_path); | 1102 free(local_path); |
965 free(tmp_path); | 1103 if(tmp_path) { |
966 return -1; | 1104 free(tmp_path); |
967 } | 1105 } |
1106 return -1; | |
1107 } | |
1108 | |
1109 int64_t truncate_file = -1; | |
968 printf("get: %s\n", path); | 1110 printf("get: %s\n", path); |
969 if(dav_get_content(res, out, (dav_write_func)fwrite)) { | 1111 if(issplit) { |
970 ret = -1; | 1112 part_updates = sync_download_changed_parts(res, local, out, blocksize, &blockcount, &truncate_file, &ret); |
1113 } else { | |
1114 ret = dav_get_content(res, out, (dav_write_func)fwrite); | |
971 } | 1115 } |
972 fclose(out); | 1116 fclose(out); |
1117 if(truncate_file >= 0) { | |
1118 truncate(tmp_path, truncate_file); | |
1119 } | |
973 | 1120 |
974 if(ret == 0) { | 1121 if(ret == 0) { |
975 (*counter)++; | 1122 (*counter)++; |
976 | 1123 |
977 if(dir->trash && dir->backuppull) { | 1124 if(tmp_path) { |
978 move_to_trash(dir, local_path); | 1125 if(dir->trash && dir->backuppull) { |
979 } | 1126 move_to_trash(dir, local_path); |
980 if(sys_rename(tmp_path, local_path)) { | 1127 } |
981 fprintf( | 1128 if(sys_rename(tmp_path, local_path)) { |
982 stderr, | 1129 fprintf( |
983 "Cannot rename file %s to %s\n", | 1130 stderr, |
984 tmp_path, | 1131 "Cannot rename file %s to %s\n", |
985 local_path); | 1132 tmp_path, |
986 perror(""); | 1133 local_path); |
987 free(tmp_path); | 1134 perror(""); |
988 free(local_path); | 1135 free(tmp_path); |
989 return -1; | 1136 free(local_path); |
1137 return -1; | |
1138 } | |
990 } | 1139 } |
991 | 1140 |
992 if(sys_stat(local_path, &s)) { | 1141 if(sys_stat(local_path, &s)) { |
993 fprintf(stderr, | 1142 fprintf(stderr, |
994 "Cannot stat file %s: %s\n", local_path, strerror(errno)); | 1143 "Cannot stat file %s: %s\n", local_path, strerror(errno)); |
1007 | 1156 |
1008 if(local->etag) { | 1157 if(local->etag) { |
1009 free(local->etag); | 1158 free(local->etag); |
1010 } | 1159 } |
1011 | 1160 |
1161 update_parts(local, part_updates, blockcount); | |
1162 | |
1012 // set metadata from stat | 1163 // set metadata from stat |
1013 local->etag = strdup(etag); | 1164 local->etag = strdup(etag); |
1014 sync_set_metadata_from_stat(local, &s); | 1165 sync_set_metadata_from_stat(local, &s); |
1015 local->skipped = FALSE; | 1166 local->skipped = FALSE; |
1016 } else { | 1167 } else if(tmp_path) { |
1017 if(sys_unlink(tmp_path)) { | 1168 if(sys_unlink(tmp_path)) { |
1018 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); | 1169 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); |
1019 } | 1170 } |
1020 } | 1171 } |
1021 | 1172 |
1022 free(tmp_path); | 1173 if(tmp_path) { |
1174 free(tmp_path); | |
1175 } | |
1023 free(local_path); | 1176 free(local_path); |
1024 return ret; | 1177 return ret; |
1025 } | 1178 } |
1026 | 1179 |
1027 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { | 1180 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { |
1028 char *local_path = util_concat_path(dir->path, res->path); | 1181 char *local_path = create_local_path(dir, res->path); |
1029 SYS_STAT s; | 1182 SYS_STAT s; |
1030 if(sys_stat(local_path, &s)) { | 1183 if(sys_stat(local_path, &s)) { |
1031 free(local_path); | 1184 free(local_path); |
1032 return -2; | 1185 return -2; |
1033 } | 1186 } |
1055 return ret; | 1208 return ret; |
1056 } | 1209 } |
1057 | 1210 |
1058 int sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { | 1211 int sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { |
1059 int ret = 0; | 1212 int ret = 0; |
1060 char *local_path = util_concat_path(dir->path, res->path); | 1213 char *local_path = create_local_path(dir, res->path); |
1061 | 1214 |
1062 printf("delete: %s\n", res->path); | 1215 printf("delete: %s\n", res->path); |
1063 if(rmdir(local_path)) { | 1216 if(rmdir(local_path)) { |
1064 fprintf(stderr, "rmdir: %s : %s", local_path, strerror(errno)); | 1217 fprintf(stderr, "rmdir: %s : %s", local_path, strerror(errno)); |
1065 ret = 1; | 1218 ret = 1; |
1067 | 1220 |
1068 free(local_path); | 1221 free(local_path); |
1069 return ret; | 1222 return ret; |
1070 } | 1223 } |
1071 | 1224 |
1072 void rename_conflict_file(SyncDirectory *dir, SyncDatabase *db, char *path) { | 1225 int copy_file(const char *from, const char *to) { |
1073 char *local_path = util_concat_path(dir->path, path); | 1226 FILE *in = sys_fopen(from, "rb"); |
1227 if(!in) { | |
1228 return 1; | |
1229 } | |
1230 FILE *out = sys_fopen(to, "wb"); | |
1231 if(!out) { | |
1232 fclose(in); | |
1233 return 1; | |
1234 } | |
1235 | |
1236 ucx_stream_copy(in, out, (read_func)fread, (write_func)fwrite); | |
1237 fclose(in); | |
1238 fclose(out); | |
1239 } | |
1240 | |
1241 typedef int (*renamefunc)(const char*,const char*); | |
1242 | |
1243 void rename_conflict_file(SyncDirectory *dir, SyncDatabase *db, char *path, DavBool copy) { | |
1244 char *local_path = create_local_path(dir, path); | |
1074 char *parent = util_parent_path(local_path); | 1245 char *parent = util_parent_path(local_path); |
1246 | |
1247 renamefunc fn = copy ? copy_file : sys_rename; | |
1075 | 1248 |
1076 int rev = 0; | 1249 int rev = 0; |
1077 SYS_STAT s; | 1250 SYS_STAT s; |
1078 int loop = 1; | 1251 int loop = 1; |
1079 do { | 1252 do { |
1094 | 1267 |
1095 if(sys_stat(new_path.ptr, &s)) { | 1268 if(sys_stat(new_path.ptr, &s)) { |
1096 if(errno == ENOENT) { | 1269 if(errno == ENOENT) { |
1097 loop = 0; | 1270 loop = 0; |
1098 printf("conflict: %s\n", local_path); | 1271 printf("conflict: %s\n", local_path); |
1099 if(sys_rename(local_path, new_path.ptr)) { | 1272 if(fn(local_path, new_path.ptr)) { |
1100 //printf("errno: %d\n", errno); | 1273 //printf("errno: %d\n", errno); |
1101 fprintf( | 1274 fprintf( |
1102 stderr, | 1275 stderr, |
1103 "Cannot rename file %s to %s\n", | 1276 "Cannot rename file %s to %s\n", |
1104 local_path, | 1277 local_path, |
1635 if(!resource) { | 1808 if(!resource) { |
1636 continue; | 1809 continue; |
1637 } | 1810 } |
1638 } | 1811 } |
1639 | 1812 |
1640 char *file_path = util_concat_path(dir->path, resource->path); | 1813 char *file_path = create_local_path(dir, resource->path); |
1641 SYS_STAT s; | 1814 SYS_STAT s; |
1642 if(sys_stat(file_path, &s)) { | 1815 if(sys_stat(file_path, &s)) { |
1643 if(errno == ENOENT) { | 1816 if(errno == ENOENT) { |
1644 if(restore_removed) { | 1817 if(restore_removed) { |
1645 deleted = ucx_list_prepend(deleted, resource); | 1818 deleted = ucx_list_prepend(deleted, resource); |
1739 } | 1912 } |
1740 | 1913 |
1741 // download the resource | 1914 // download the resource |
1742 if(!sync_shutdown) { | 1915 if(!sync_shutdown) { |
1743 if(resource->isdirectory) { | 1916 if(resource->isdirectory) { |
1744 char *local_path = util_concat_path(dir->path, res->path); | 1917 char *local_path = create_local_path(dir, res->path); |
1745 if(sys_mkdir(local_path) && errno != EEXIST) { | 1918 if(sys_mkdir(local_path) && errno != EEXIST) { |
1746 fprintf(stderr, | 1919 fprintf(stderr, |
1747 "Cannot create directory %s: %s", | 1920 "Cannot create directory %s: %s", |
1748 local_path, strerror(errno)); | 1921 local_path, strerror(errno)); |
1749 } | 1922 } |
1801 // get a directory path from the stack and read all entries | 1974 // get a directory path from the stack and read all entries |
1802 // if an entry is a directory, put it on the stack | 1975 // if an entry is a directory, put it on the stack |
1803 | 1976 |
1804 char *p = stack->data; | 1977 char *p = stack->data; |
1805 stack = ucx_list_remove(stack, stack); | 1978 stack = ucx_list_remove(stack, stack); |
1806 char *local_path = util_concat_path(dir->path, p); | 1979 char *local_path = create_local_path(dir, p); |
1807 SYS_DIR local_dir = sys_opendir(local_path); | 1980 SYS_DIR local_dir = sys_opendir(local_path); |
1808 | 1981 |
1809 if(!local_dir) { | 1982 if(!local_dir) { |
1810 fprintf(stderr, "Cannot open directory %s\n", local_path); | 1983 fprintf(stderr, "Cannot open directory %s\n", local_path); |
1811 } else { | 1984 } else { |
1883 | 2056 |
1884 return resources; | 2057 return resources; |
1885 } | 2058 } |
1886 | 2059 |
1887 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { | 2060 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { |
1888 char *file_path = util_concat_path(dir->path, path); | 2061 char *file_path = create_local_path(dir, path); |
1889 SYS_STAT s; | 2062 SYS_STAT s; |
1890 if(sys_stat(file_path, &s)) { | 2063 if(sys_stat(file_path, &s)) { |
1891 fprintf(stderr, "Cannot stat file %s\n", file_path); | 2064 fprintf(stderr, "Cannot stat file %s\n", file_path); |
1892 free(file_path); | 2065 free(file_path); |
1893 return NULL; | 2066 return NULL; |
2009 res->metadata_updated = 1; | 2182 res->metadata_updated = 1; |
2010 } | 2183 } |
2011 } | 2184 } |
2012 | 2185 |
2013 if((dir->metadata & FINFO_XATTR) == FINFO_XATTR) { | 2186 if((dir->metadata & FINFO_XATTR) == FINFO_XATTR) { |
2014 char *path = util_concat_path(dir->path, db_res->path); | 2187 char *path = create_local_path(dir, db_res->path); |
2015 XAttributes *xattr = file_get_attributes(path); | 2188 XAttributes *xattr = file_get_attributes(path); |
2016 // test if xattr are added, removed or changed | 2189 // test if xattr are added, removed or changed |
2017 if((db_res->xattr_hash && !xattr) || | 2190 if((db_res->xattr_hash && !xattr) || |
2018 (!db_res->xattr_hash && xattr) || | 2191 (!db_res->xattr_hash && xattr) || |
2019 (xattr && db_res->xattr_hash && strcmp(xattr->hash, db_res->xattr_hash))) | 2192 (xattr && db_res->xattr_hash && strcmp(xattr->hash, db_res->xattr_hash))) |
2446 return res->cached_tags; | 2619 return res->cached_tags; |
2447 } | 2620 } |
2448 UcxBuffer *buf = NULL; | 2621 UcxBuffer *buf = NULL; |
2449 if(dir->tagconfig->store == TAG_STORE_XATTR) { | 2622 if(dir->tagconfig->store == TAG_STORE_XATTR) { |
2450 ssize_t tag_length = 0; | 2623 ssize_t tag_length = 0; |
2451 char *local_path = util_concat_path(dir->path, res->path); | 2624 char *local_path = create_local_path(dir, res->path); |
2452 char* tag_data = xattr_get( | 2625 char* tag_data = xattr_get( |
2453 local_path, | 2626 local_path, |
2454 dir->tagconfig->xattr_name, | 2627 dir->tagconfig->xattr_name, |
2455 &tag_length); | 2628 &tag_length); |
2456 free(local_path); | 2629 free(local_path); |
2884 | 3057 |
2885 *err = 0; | 3058 *err = 0; |
2886 return updated_parts; | 3059 return updated_parts; |
2887 } | 3060 } |
2888 | 3061 |
2889 static void update_parts(LocalResource *local, UcxList *updates, uint64_t numparts) { | 3062 void update_parts(LocalResource *local, UcxList *updates, uint64_t numparts) { |
2890 size_t old_num = local->numparts; | 3063 size_t old_num = local->numparts; |
2891 if(old_num > numparts) { | 3064 if(old_num > numparts) { |
2892 // free old parts | 3065 // free old parts |
2893 for(size_t i=numparts;i<old_num;i++) { | 3066 for(size_t i=numparts;i<old_num;i++) { |
2894 FilePart p = local->parts[i]; | 3067 FilePart p = local->parts[i]; |
2936 SyncDirectory *dir, | 3109 SyncDirectory *dir, |
2937 DavResource *res, | 3110 DavResource *res, |
2938 LocalResource *local, | 3111 LocalResource *local, |
2939 int *counter) | 3112 int *counter) |
2940 { | 3113 { |
2941 char *local_path = util_concat_path(dir->path, res->path); | 3114 char *local_path = create_local_path(dir, res->path); |
2942 | 3115 |
2943 SYS_STAT s; | 3116 SYS_STAT s; |
2944 if(sys_stat(local_path, &s)) { | 3117 if(sys_stat(local_path, &s)) { |
2945 fprintf(stderr, "Cannot stat file: %s\n", local_path); | 3118 fprintf(stderr, "Cannot stat file: %s\n", local_path); |
2946 perror(""); | 3119 perror(""); |
3263 int numdc = 0; | 3436 int numdc = 0; |
3264 | 3437 |
3265 UcxMapIterator i = ucx_map_iterator(db->conflict); | 3438 UcxMapIterator i = ucx_map_iterator(db->conflict); |
3266 LocalResource *res; | 3439 LocalResource *res; |
3267 UCX_MAP_FOREACH(key, res, i) { | 3440 UCX_MAP_FOREACH(key, res, i) { |
3268 char *path = util_concat_path(dir->path, res->path); | 3441 char *path = create_local_path(dir, res->path); |
3269 SYS_STAT s; | 3442 SYS_STAT s; |
3270 if(sys_stat(path, &s)) { | 3443 if(sys_stat(path, &s)) { |
3271 if(errno == ENOENT) { | 3444 if(errno == ENOENT) { |
3272 dc[numdc] = res->path; | 3445 dc[numdc] = res->path; |
3273 numdc++; | 3446 numdc++; |
3384 // delete all conflict files | 3557 // delete all conflict files |
3385 UcxMapIterator i = ucx_map_iterator(db->conflict); | 3558 UcxMapIterator i = ucx_map_iterator(db->conflict); |
3386 LocalResource *res; | 3559 LocalResource *res; |
3387 UCX_MAP_FOREACH(key, res, i) { | 3560 UCX_MAP_FOREACH(key, res, i) { |
3388 printf("delete: %s\n", res->path); | 3561 printf("delete: %s\n", res->path); |
3389 char *path = util_concat_path(dir->path, res->path); | 3562 char *path = create_local_path(dir, res->path); |
3390 if(sys_unlink(path)) { | 3563 if(sys_unlink(path)) { |
3391 if(errno != ENOENT) { | 3564 if(errno != ENOENT) { |
3392 perror("unlink"); | 3565 perror("unlink"); |
3393 num_err++; | 3566 num_err++; |
3394 } | 3567 } |