dav/sync.c

changeset 544
9e85e1ec1155
parent 543
2f85df8cd35e
child 545
268157722a0e
equal deleted inserted replaced
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 }

mercurial