dav/sync.c

changeset 411
a182e503617b
parent 405
6b85d745e402
child 412
dc74f736aea1
equal deleted inserted replaced
410:0b9bea2d7283 411:a182e503617b
53 #include "error.h" 53 #include "error.h"
54 #include "assistant.h" 54 #include "assistant.h"
55 #include "libxattr.h" 55 #include "libxattr.h"
56 #include "tags.h" 56 #include "tags.h"
57 57
58 #include "system.h"
58 59
59 #include <pthread.h> 60 #include <pthread.h>
60 #include <ctype.h> 61 #include <ctype.h>
61 62
62 static DavContext *ctx; 63 static DavContext *ctx;
521 522
522 // stat all files with unknown lastmodified date 523 // stat all files with unknown lastmodified date
523 UCX_FOREACH(elm, statls) { 524 UCX_FOREACH(elm, statls) {
524 LocalResource *l = elm->data; 525 LocalResource *l = elm->data;
525 char *local_path = util_concat_path(dir->path, l->path); 526 char *local_path = util_concat_path(dir->path, l->path);
526 struct stat s; 527 SYS_STAT s;
527 if(!stat(local_path, &s)) { 528 if(!sys_stat(local_path, &s)) {
528 l->last_modified = s.st_mtime; 529 l->last_modified = s.st_mtime;
529 } 530 }
530 free(local_path); 531 free(local_path);
531 } 532 }
532 ucx_list_free(statls); 533 ucx_list_free(statls);
608 609
609 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); 610 LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
610 char *local_path = util_concat_path(dir->path, res->path); 611 char *local_path = util_concat_path(dir->path, res->path);
611 612
612 char *etag = dav_get_string_property(res, "D:getetag"); 613 char *etag = dav_get_string_property(res, "D:getetag");
613 struct stat s; 614 SYS_STAT s;
614 memset(&s, 0, sizeof(struct stat)); 615 memset(&s, 0, sizeof(SYS_STAT));
615 if(local && !res->iscollection) { 616 if(local && !res->iscollection) {
616 int exists = 1; 617 int exists = 1;
617 if(stat(local_path, &s)) { 618 if(sys_stat(local_path, &s)) {
618 // Ignore the fact, that the file is locally removed. If the 619 // Ignore the fact, that the file is locally removed. If the
619 // server has an updated version, we read the file or the 620 // server has an updated version, we read the file or the
620 // next push will delete it on the server. 621 // next push will delete it on the server.
621 if(errno != ENOENT) { 622 if(errno != ENOENT) {
622 fprintf(stderr, "Cannot stat file: %s\n", local_path); 623 fprintf(stderr, "Cannot stat file: %s\n", local_path);
643 if(cdt && exists && s.st_mtime != local->last_modified) { 644 if(cdt && exists && s.st_mtime != local->last_modified) {
644 // file modified on the server and on the client 645 // file modified on the server and on the client
645 rename_conflict_file(dir, db, local->path); 646 rename_conflict_file(dir, db, local->path);
646 } 647 }
647 } else { 648 } else {
648 if(stat(local_path, &s)) { 649 if(sys_stat(local_path, &s)) {
649 if(errno != ENOENT) { 650 if(errno != ENOENT) {
650 fprintf(stderr, "Cannot stat file: %s\n", local_path); 651 fprintf(stderr, "Cannot stat file: %s\n", local_path);
651 } 652 }
652 } else if(S_ISDIR(s.st_mode)) { 653 } else if(S_ISDIR(s.st_mode)) {
653 //fprintf(stderr, "Error: file %s is a directory\n", local_path); 654 //fprintf(stderr, "Error: file %s is a directory\n", local_path);
684 if(!tmp_path) { 685 if(!tmp_path) {
685 fprintf(stderr, "Cannot create tmp path for %s\n", local_path); 686 fprintf(stderr, "Cannot create tmp path for %s\n", local_path);
686 free(local_path); 687 free(local_path);
687 return -1; 688 return -1;
688 } 689 }
689 FILE *out = fopen(tmp_path, "wb"); 690 FILE *out = sys_fopen(tmp_path, "wb");
690 if(!out) { 691 if(!out) {
691 fprintf(stderr, "Cannot open output file: %s\n", local_path); 692 fprintf(stderr, "Cannot open output file: %s\n", local_path);
692 free(local_path); 693 free(local_path);
693 free(tmp_path); 694 free(tmp_path);
694 return -1; 695 return -1;
705 (*counter)++; 706 (*counter)++;
706 707
707 if(dir->trash && dir->backuppull) { 708 if(dir->trash && dir->backuppull) {
708 move_to_trash(dir, local_path); 709 move_to_trash(dir, local_path);
709 } 710 }
710 if(rename(tmp_path, local_path)) { 711 if(sys_rename(tmp_path, local_path)) {
711 fprintf( 712 fprintf(
712 stderr, 713 stderr,
713 "Cannot rename file %s to %s\n", 714 "Cannot rename file %s to %s\n",
714 tmp_path, 715 tmp_path,
715 local_path); 716 local_path);
717 free(tmp_path); 718 free(tmp_path);
718 free(local_path); 719 free(local_path);
719 return -1; 720 return -1;
720 } 721 }
721 722
722 if(stat(local_path, &s)) { 723 if(sys_stat(local_path, &s)) {
723 fprintf(stderr, "Cannot stat file: %s\n", local_path); 724 fprintf(stderr, "Cannot stat file: %s\n", local_path);
724 perror(""); 725 perror("");
725 } 726 }
726 727
727 if(!local) { 728 if(!local) {
751 return ret; 752 return ret;
752 } 753 }
753 754
754 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { 755 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) {
755 char *local_path = util_concat_path(dir->path, res->path); 756 char *local_path = util_concat_path(dir->path, res->path);
756 struct stat s; 757 SYS_STAT s;
757 if(stat(local_path, &s)) { 758 if(sys_stat(local_path, &s)) {
758 free(local_path); 759 free(local_path);
759 return -2; 760 return -2;
760 } 761 }
761 762
762 if(S_ISDIR(s.st_mode)) { 763 if(S_ISDIR(s.st_mode)) {
797 void rename_conflict_file(SyncDirectory *dir, SyncDatabase *db, char *path) { 798 void rename_conflict_file(SyncDirectory *dir, SyncDatabase *db, char *path) {
798 char *local_path = util_concat_path(dir->path, path); 799 char *local_path = util_concat_path(dir->path, path);
799 char *parent = util_parent_path(local_path); 800 char *parent = util_parent_path(local_path);
800 801
801 int rev = 0; 802 int rev = 0;
802 struct stat s; 803 SYS_STAT s;
803 int loop = 1; 804 int loop = 1;
804 do { 805 do {
805 char *res_parent = util_parent_path(path); 806 char *res_parent = util_parent_path(path);
806 char *res_name = util_resource_name(path); 807 char *res_name = util_resource_name(path);
807 808
815 res_parent, 816 res_parent,
816 rev, 817 rev,
817 res_name); 818 res_name);
818 819
819 820
820 if(stat(new_path.ptr, &s)) { 821 if(sys_stat(new_path.ptr, &s)) {
821 if(errno == ENOENT) { 822 if(errno == ENOENT) {
822 loop = 0; 823 loop = 0;
823 printf("conflict: %s\n", local_path); 824 printf("conflict: %s\n", local_path);
824 if(rename(local_path, new_path.ptr)) { 825 if(sys_rename(local_path, new_path.ptr)) {
825 //printf("errno: %d\n", errno); 826 //printf("errno: %d\n", errno);
826 fprintf( 827 fprintf(
827 stderr, 828 stderr,
828 "Cannot rename file %s to %s\n", 829 "Cannot rename file %s to %s\n",
829 local_path, 830 local_path,
854 "%sdownload%d-%s", 855 "%sdownload%d-%s",
855 parent, 856 parent,
856 i, 857 i,
857 util_resource_name(path)); 858 util_resource_name(path));
858 859
859 struct stat s; 860 SYS_STAT s;
860 if(stat(np.ptr, &s)) { 861 if(sys_stat(np.ptr, &s)) {
861 if(errno == ENOENT) { 862 if(errno == ENOENT) {
862 new_path = np.ptr; 863 new_path = np.ptr;
863 } 864 }
864 break; 865 break;
865 } 866 }
878 "%s%d-%s", 879 "%s%d-%s",
879 dir->trash, 880 dir->trash,
880 i, 881 i,
881 util_resource_name(path)); 882 util_resource_name(path));
882 883
883 struct stat s; 884 SYS_STAT s;
884 if(stat(np.ptr, &s)) { 885 if(sys_stat(np.ptr, &s)) {
885 if(errno == ENOENT) { 886 if(errno == ENOENT) {
886 new_path = np.ptr; 887 new_path = np.ptr;
887 } 888 }
888 break; 889 break;
889 } 890 }
893 if(!new_path) { 894 if(!new_path) {
894 fprintf(stderr, "Cannot move file %s to trash.\n", path); 895 fprintf(stderr, "Cannot move file %s to trash.\n", path);
895 return; 896 return;
896 } 897 }
897 898
898 if(rename(path, new_path)) { 899 if(sys_rename(path, new_path)) {
899 //printf("errno: %d\n", errno); 900 //printf("errno: %d\n", errno);
900 fprintf( 901 fprintf(
901 stderr, 902 stderr,
902 "Cannot rename file %s to %s\n", 903 "Cannot rename file %s to %s\n",
903 path, 904 path,
1201 // if an entry is a directory, put it on the stack 1202 // if an entry is a directory, put it on the stack
1202 1203
1203 char *p = stack->data; 1204 char *p = stack->data;
1204 stack = ucx_list_remove(stack, stack); 1205 stack = ucx_list_remove(stack, stack);
1205 char *local_path = util_concat_path(dir->path, p); 1206 char *local_path = util_concat_path(dir->path, p);
1206 DIR *local_dir = opendir(local_path); 1207 SYS_DIR local_dir = sys_opendir(local_path);
1207 1208
1208 if(!local_dir) { 1209 if(!local_dir) {
1209 fprintf(stderr, "Cannot open directory %s\n", local_path); 1210 fprintf(stderr, "Cannot open directory %s\n", local_path);
1210 } else { 1211 } else {
1211 struct dirent *ent; 1212 SysDirEnt *ent;
1212 while((ent = readdir(local_dir)) != NULL) { 1213 while((ent = sys_readdir(local_dir)) != NULL) {
1213 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { 1214 if(!strcmp(ent->name, ".") || !strcmp(ent->name, "..")) {
1214 continue; 1215 continue;
1215 } 1216 }
1216 1217
1217 char *new_path = util_concat_path(p, ent->d_name); 1218 char *new_path = util_concat_path(p, ent->name);
1218 int isdir; 1219 int isdir;
1219 LocalResource *res = local_resource_new(dir, db, new_path, &isdir); 1220 LocalResource *res = local_resource_new(dir, db, new_path, &isdir);
1220 if(isdir) { 1221 if(isdir) {
1221 resources = ucx_list_append(resources, res); 1222 resources = ucx_list_append(resources, res);
1222 stack = ucx_list_prepend(stack, new_path); 1223 stack = ucx_list_prepend(stack, new_path);
1225 free(new_path); 1226 free(new_path);
1226 } else { 1227 } else {
1227 free(new_path); 1228 free(new_path);
1228 } 1229 }
1229 } 1230 }
1230 closedir(local_dir); 1231 sys_closedir(local_dir);
1231 1232
1232 } 1233 }
1233 free(local_path); 1234 free(local_path);
1234 free(p); 1235 free(p);
1235 } 1236 }
1283 return resources; 1284 return resources;
1284 } 1285 }
1285 1286
1286 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) { 1287 LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path, int *isdir) {
1287 char *file_path = util_concat_path(dir->path, path); 1288 char *file_path = util_concat_path(dir->path, path);
1288 struct stat s; 1289 SYS_STAT s;
1289 if(stat(file_path, &s)) { 1290 if(sys_stat(file_path, &s)) {
1290 fprintf(stderr, "Cannot stat file %s\n", file_path); 1291 fprintf(stderr, "Cannot stat file %s\n", file_path);
1291 free(file_path); 1292 free(file_path);
1292 return NULL; 1293 return NULL;
1293 } 1294 }
1294 free(file_path); 1295 free(file_path);
1681 LocalResource *local, 1682 LocalResource *local,
1682 int *counter) 1683 int *counter)
1683 { 1684 {
1684 char *local_path = util_concat_path(dir->path, res->path); 1685 char *local_path = util_concat_path(dir->path, res->path);
1685 1686
1686 struct stat s; 1687 SYS_STAT s;
1687 if(stat(local_path, &s)) { 1688 if(sys_stat(local_path, &s)) {
1688 fprintf(stderr, "cannot stat file: %s\n", local_path); 1689 fprintf(stderr, "cannot stat file: %s\n", local_path);
1689 perror(""); 1690 perror("");
1690 free(local_path); 1691 free(local_path);
1691 return -1; 1692 return -1;
1692 } 1693 }
1693 1694
1694 FILE *in = fopen(local_path, "rb"); 1695 FILE *in = sys_fopen(local_path, "rb");
1695 if(!in) { 1696 if(!in) {
1696 fprintf(stderr, "Cannot open file %s\n", local_path); 1697 fprintf(stderr, "Cannot open file %s\n", local_path);
1697 free(local_path); 1698 free(local_path);
1698 return -1; 1699 return -1;
1699 } 1700 }
1875 1876
1876 UcxMapIterator i = ucx_map_iterator(db->conflict); 1877 UcxMapIterator i = ucx_map_iterator(db->conflict);
1877 LocalResource *res; 1878 LocalResource *res;
1878 UCX_MAP_FOREACH(key, res, i) { 1879 UCX_MAP_FOREACH(key, res, i) {
1879 char *path = util_concat_path(dir->path, res->path); 1880 char *path = util_concat_path(dir->path, res->path);
1880 struct stat s; 1881 SYS_STAT s;
1881 if(stat(path, &s)) { 1882 if(sys_stat(path, &s)) {
1882 if(errno == ENOENT) { 1883 if(errno == ENOENT) {
1883 dc[numdc] = res->path; 1884 dc[numdc] = res->path;
1884 numdc++; 1885 numdc++;
1885 } else { 1886 } else {
1886 fprintf(stderr, "Cannot stat file: %s\n", path); 1887 fprintf(stderr, "Cannot stat file: %s\n", path);
2118 if(!syncdir->trash) { 2119 if(!syncdir->trash) {
2119 printf("trash not configured for %s\n", syncdir->name); 2120 printf("trash not configured for %s\n", syncdir->name);
2120 return 0; 2121 return 0;
2121 } 2122 }
2122 2123
2123 DIR *dir = opendir(syncdir->trash); 2124 SYS_DIR dir = sys_opendir(syncdir->trash);
2124 if(!dir) { 2125 if(!dir) {
2125 fprintf(stderr, "cannot open trash directory: %s\n", syncdir->trash); 2126 fprintf(stderr, "cannot open trash directory: %s\n", syncdir->trash);
2126 perror("opendir"); 2127 perror("opendir");
2127 return -1; 2128 return -1;
2128 } 2129 }
2129 2130
2130 uint64_t trashsize = 0; 2131 uint64_t trashsize = 0;
2131 int count = 0; 2132 int count = 0;
2132 struct dirent *ent; 2133 SysDirEnt *ent;
2133 while((ent = readdir(dir)) != NULL) { 2134 while((ent = sys_readdir(dir)) != NULL) {
2134 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { 2135 if(!strcmp(ent->name, ".") || !strcmp(ent->name, "..")) {
2135 continue; 2136 continue;
2136 } 2137 }
2137 2138
2138 char *path = util_concat_path(syncdir->trash, ent->d_name); 2139 char *path = util_concat_path(syncdir->trash, ent->name);
2139 2140
2140 struct stat s; 2141 SYS_STAT s;
2141 if(stat(path, &s)) { 2142 if(sys_stat(path, &s)) {
2142 perror("stat"); 2143 perror("stat");
2143 } else { 2144 } else {
2144 trashsize += s.st_size; 2145 trashsize += s.st_size;
2145 } 2146 }
2146 count++; 2147 count++;
2147 2148
2148 free(path); 2149 free(path);
2149 } 2150 }
2150 closedir(dir); 2151 sys_closedir(dir);
2151 2152
2152 printf("path: %s\n", syncdir->trash); 2153 printf("path: %s\n", syncdir->trash);
2153 printf("%d %s\n", count, count == 1 ? "file" : "files"); 2154 printf("%d %s\n", count, count == 1 ? "file" : "files");
2154 char *sizestr = size_str(trashsize); 2155 char *sizestr = size_str(trashsize);
2155 printf("%s\n", sizestr); 2156 printf("%s\n", sizestr);
2174 if(!syncdir->trash) { 2175 if(!syncdir->trash) {
2175 fprintf(stderr, "trash not configured for %s\n", syncdir->name); 2176 fprintf(stderr, "trash not configured for %s\n", syncdir->name);
2176 return -1; 2177 return -1;
2177 } 2178 }
2178 2179
2179 DIR *dir = opendir(syncdir->trash); 2180 SYS_DIR dir = sys_opendir(syncdir->trash);
2180 if(!dir) { 2181 if(!dir) {
2181 fprintf(stderr, "cannot open trash directory: %s\n", syncdir->trash); 2182 fprintf(stderr, "cannot open trash directory: %s\n", syncdir->trash);
2182 perror("opendir"); 2183 perror("opendir");
2183 return -1; 2184 return -1;
2184 } 2185 }
2185 2186
2186 struct dirent *ent; 2187 SysDirEnt *ent;
2187 while((ent = readdir(dir)) != NULL) { 2188 while((ent = sys_readdir(dir)) != NULL) {
2188 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { 2189 if(!strcmp(ent->name, ".") || !strcmp(ent->name, "..")) {
2189 continue; 2190 continue;
2190 } 2191 }
2191 2192
2192 char *path = util_concat_path(syncdir->trash, ent->d_name); 2193 char *path = util_concat_path(syncdir->trash, ent->name);
2193 printf("delete: %s\n", path); 2194 printf("delete: %s\n", path);
2194 2195
2195 struct stat s; 2196 SYS_STAT s;
2196 if(stat(path, &s)) { 2197 if(sys_stat(path, &s)) {
2197 perror("stat"); 2198 perror("stat");
2198 free(path); 2199 free(path);
2199 continue; 2200 continue;
2200 } 2201 }
2201 if(S_ISDIR(s.st_mode)) { 2202 if(S_ISDIR(s.st_mode)) {
2208 } 2209 }
2209 } 2210 }
2210 2211
2211 free(path); 2212 free(path);
2212 } 2213 }
2213 closedir(dir); 2214 sys_closedir(dir);
2214 2215
2215 return 0; 2216 return 0;
2216 } 2217 }
2217 2218
2218 #define CMD_TAG_ADD 0 2219 #define CMD_TAG_ADD 0
2388 free(fullpath); 2389 free(fullpath);
2389 return 1; 2390 return 1;
2390 } 2391 }
2391 2392
2392 int sync_get_file(CmdArgs *args, const char *path, const char *dir, SyncFile *f) { 2393 int sync_get_file(CmdArgs *args, const char *path, const char *dir, SyncFile *f) {
2393 struct stat s; 2394 SYS_STAT s;
2394 if(stat(path, &s)) { 2395 if(sys_stat(path, &s)) {
2395 switch(errno) { 2396 switch(errno) {
2396 case EACCES: return 2; 2397 case EACCES: return 2;
2397 case ENOENT: return 1; 2398 case ENOENT: return 1;
2398 default: return 3; 2399 default: return 3;
2399 } 2400 }
2584 char* create_locktoken_file(const char *syncdirname, const char *locktoken) { 2585 char* create_locktoken_file(const char *syncdirname, const char *locktoken) {
2585 sstr_t fname = ucx_sprintf("locktoken-%s.txt", syncdirname); 2586 sstr_t fname = ucx_sprintf("locktoken-%s.txt", syncdirname);
2586 char *path = config_file_path(fname.ptr); 2587 char *path = config_file_path(fname.ptr);
2587 free(fname.ptr); 2588 free(fname.ptr);
2588 2589
2589 FILE *file = fopen(path, "w"); 2590 FILE *file = sys_fopen(path, "w");
2590 if(file) { 2591 if(file) {
2591 fprintf(file, "%s\n", locktoken); 2592 fprintf(file, "%s\n", locktoken);
2592 fclose(file); 2593 fclose(file);
2593 return path; 2594 return path;
2594 } else { 2595 } else {

mercurial