dav/sync.c

changeset 526
e3c0440bd599
parent 525
26a1d5b9d9d2
child 527
d0e37224eba1
equal deleted inserted replaced
525:26a1d5b9d9d2 526:e3c0440bd599
31 #include <string.h> 31 #include <string.h>
32 #include <errno.h> 32 #include <errno.h>
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <signal.h> 34 #include <signal.h>
35 #include <time.h> 35 #include <time.h>
36 #include <utime.h>
36 #include <libxml/xmlerror.h> 37 #include <libxml/xmlerror.h>
37 #include <sys/types.h> 38 #include <sys/types.h>
38 #include <ucx/string.h> 39 #include <ucx/string.h>
39 #include <ucx/utils.h> 40 #include <ucx/utils.h>
40 #include <ucx/properties.h> 41 #include <ucx/properties.h>
497 locked = TRUE; 498 locked = TRUE;
498 locktokenfile = create_locktoken_file(dir->name, lock->token); 499 locktokenfile = create_locktoken_file(dir->name, lock->token);
499 } 500 }
500 501
501 int ret = 0; 502 int ret = 0;
502 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags from / with depth = infinity"); 503 DavResource *ls = dav_query(sn, "select D:getetag,idav:status,idav:tags,idav:finfo,idav:xattributes from / with depth = infinity");
503 if(!ls) { 504 if(!ls) {
504 print_resource_error(sn, "/"); 505 print_resource_error(sn, "/");
505 if(locked) { 506 if(locked) {
506 if(dav_unlock(root)) { 507 if(dav_unlock(root)) {
507 print_resource_error(sn, "/"); 508 print_resource_error(sn, "/");
547 UcxList *res_mkdir = NULL; 548 UcxList *res_mkdir = NULL;
548 UcxList *res_metadata = NULL; 549 UcxList *res_metadata = NULL;
549 UcxList *res_broken = NULL; 550 UcxList *res_broken = NULL;
550 UcxList *lres_removed = NULL; // list of LocalResource* 551 UcxList *lres_removed = NULL; // list of LocalResource*
551 552
552 UcxMap *svrres = ucx_map_new(db->resources->count); 553 //UcxMap *svrres = ucx_map_new(db->resources->count);
553 UcxMap *dbres = ucx_map_clone(db->resources, NULL, NULL); 554 UcxMap *dbres = ucx_map_clone(db->resources, NULL, NULL);
554 555
555 UcxList *statls = NULL; 556 UcxList *statls = NULL;
556 557
557 UcxList *stack = ucx_list_prepend(NULL, ls->children); 558 UcxList *stack = ucx_list_prepend(NULL, ls->children);
693 break; 694 break;
694 } 695 }
695 696
696 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); 697 LocalResource *local = ucx_map_cstr_get(db->resources, res->path);
697 if(local) { 698 if(local) {
699 printf("update: %s\n", res->path);
698 char *local_path = util_concat_path(dir->path, res->path); 700 char *local_path = util_concat_path(dir->path, res->path);
699 if(sync_store_tags(dir, local_path, local, res)) { 701 if(sync_store_metadata(dir, local_path, local, res)) {
700 fprintf(stderr, "Tag update failed: %s\n", res->path); 702 fprintf(stderr, "Metadata update failed: %s\n", res->path);
703 sync_error++;
704 } else {
705 struct stat s;
706 if(stat(local_path, &s)) {
707 fprintf(stderr, "Cannot stat file after update: %s\n", strerror(errno));
708 }
709 sync_set_metadata_from_stat(local, &s);
710 sync_success++;
701 } 711 }
702 free(local_path); 712 free(local_path);
703 } else { 713 } else {
704 // this should never happen but who knows 714 // this should never happen but who knows
705 fprintf(stderr, 715 fprintf(stderr,
817 if(sstrprefix(e, S("W/"))) { 827 if(sstrprefix(e, S("W/"))) {
818 e = sstrsubs(e, 2); 828 e = sstrsubs(e, 2);
819 } 829 }
820 if(!strcmp(e.ptr, local->etag)) { 830 if(!strcmp(e.ptr, local->etag)) {
821 // resource is already up-to-date on the client 831 // resource is already up-to-date on the client
822
823 // TODO: detect metadata update
824 //sync_store_tags(dir, local_path, local, res);
825 nochange = TRUE; 832 nochange = TRUE;
826 } 833 }
827 } 834 }
828 835
829 if(!nochange) { 836 if(!nochange) {
836 ret = type; 843 ret = type;
837 } else { 844 } else {
838 ret = REMOTE_CHANGE_NEW; 845 ret = REMOTE_CHANGE_NEW;
839 } 846 }
840 847
841 if(ret == REMOTE_NO_CHANGE) { 848 while(ret == REMOTE_NO_CHANGE && local) {
842 // check if tags have changed 849 // check if tags have changed
843 if(dir->tagconfig) { 850 if(dir->tagconfig) {
851 DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_NS, "tags");
852 UcxList *remote_tags = NULL;
853 if(tagsprop) {
854 remote_tags = parse_dav_xml_taglist(tagsprop);
855 }
856 char *remote_hash = create_tags_hash(remote_tags);
857 if(nullstrcmp(remote_hash, local->remote_tags_hash)) {
858 ret = REMOTE_CHANGE_METADATA;
859 }
860 if(remote_hash) {
861 free(remote_hash);
862 }
863 free_taglist(remote_tags);
844 864
845 } 865 if(ret == REMOTE_CHANGE_METADATA) {
846 866 break;
867 }
868 }
869
870 // check if extended attributes have changed
871 if(dir->metadata & FINFO_XATTR == FINFO_XATTR) {
872 DavXmlNode *xattr = dav_get_property_ns(res, DAV_NS, "xattributes");
873 char *xattr_hash = get_xattr_hash(xattr);
874 if(nullstrcmp(xattr_hash, local->xattr_hash)) {
875 ret = REMOTE_CHANGE_METADATA;
876 break;
877 }
878 }
879
880 // check if finfo has changed
881 DavXmlNode *finfo = dav_get_property_ns(res, DAV_NS, "finfo");
882 if(dir->metadata & FINFO_MODE == FINFO_MODE) {
883 FileInfo f;
884 finfo_get_values(finfo, &f);
885 if(f.mode_set && f.mode != local->mode) {
886 ret = REMOTE_CHANGE_METADATA;
887 break;
888 }
889 }
890
891 break;
847 } 892 }
848 893
849 free(local_path); 894 free(local_path);
850 return ret; 895 return ret;
896 }
897
898 void sync_set_metadata_from_stat(LocalResource *local, struct stat *s) {
899 local->last_modified = s->st_mtime;
900 local->mode = s->st_mode & 07777;
901 local->uid = s->st_uid;
902 local->gid = s->st_gid;
903 local->size = s->st_size;
851 } 904 }
852 905
853 int sync_get_resource( 906 int sync_get_resource(
854 CmdArgs *a, 907 CmdArgs *a,
855 SyncDirectory *dir, 908 SyncDirectory *dir,
885 } 938 }
886 fclose(out); 939 fclose(out);
887 940
888 if(ret == 0) { 941 if(ret == 0) {
889 (*counter)++; 942 (*counter)++;
943
944 if(sync_store_metadata(dir, tmp_path, local, res)) {
945 fprintf(stderr, "Cannot store metadata: %s\n", res->path);
946 }
890 947
891 if(dir->trash && dir->backuppull) { 948 if(dir->trash && dir->backuppull) {
892 move_to_trash(dir, local_path); 949 move_to_trash(dir, local_path);
893 } 950 }
894 if(sys_rename(tmp_path, local_path)) { 951 if(sys_rename(tmp_path, local_path)) {
916 } 973 }
917 974
918 if(local->etag) { 975 if(local->etag) {
919 free(local->etag); 976 free(local->etag);
920 } 977 }
978
921 // set metadata from stat 979 // set metadata from stat
922 local->etag = strdup(etag); 980 local->etag = strdup(etag);
923 local->last_modified = s.st_mtime; 981 sync_set_metadata_from_stat(local, &s);
924 local->size = s.st_size;
925 local->skipped = FALSE; 982 local->skipped = FALSE;
926
927 sync_store_tags(dir, tmp_path, local, res);
928 } else { 983 } else {
929 if(sys_unlink(tmp_path)) { 984 if(sys_unlink(tmp_path)) {
930 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); 985 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path);
931 } 986 }
932 } 987 }
1847 } 1902 }
1848 1903
1849 if(db_res->last_modified == res->last_modified && db_res->size == res->size) { 1904 if(db_res->last_modified == res->last_modified && db_res->size == res->size) {
1850 return 0; 1905 return 0;
1851 } 1906 }
1907 } else {
1908 res->tags_updated = 1;
1909 res->finfo_updated = 1;
1910 res->xattr_updated = 1;
1911 res->metadata_updated = 1;
1852 } 1912 }
1853 return 1; 1913 return 1;
1854 } 1914 }
1855 1915
1856 int remote_resource_is_changed( 1916 int remote_resource_is_changed(
1952 } 2012 }
1953 ucx_map_free(map1); 2013 ucx_map_free(map1);
1954 return equal; 2014 return equal;
1955 } 2015 }
1956 2016
2017 int sync_store_metadata(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) {
2018 int ret = 0;
2019
2020 DavXmlNode *fileinfo = dav_get_property_ns(res, DAV_NS, "finfo");
2021 if(fileinfo) {
2022 FileInfo f;
2023 finfo_get_values(fileinfo, &f);
2024 if(dir->metadata & FINFO_DATE == FINFO_DATE && f.date_set) {
2025 // set mtime
2026 struct utimbuf t;
2027 t.actime = f.last_modified;
2028 t.modtime = f.last_modified;
2029 if(utime(path, &t)) {
2030 fprintf(stderr, "utime failed for file: %s : %s\n", path, strerror(errno));
2031 ret = 1;
2032 }
2033 }
2034 if(dir->metadata & FINFO_MODE == FINFO_MODE && f.mode_set) {
2035 // set mode
2036 if(chmod(path, f.mode)) {
2037 fprintf(stderr, "chmod failed for file: %s : %s\n", path, strerror(errno));
2038 ret = 1;
2039 }
2040 }
2041 }
2042
2043 DavXmlNode *xattr_prop = dav_get_property_ns(res, DAV_NS, "xattributes");
2044 if(xattr_prop) {
2045 XAttributes *xattr = xml_get_attributes(xattr_prop);
2046 if(xattr) {
2047 if(!sync_store_xattr(dir, path, xattr)) {
2048 if(local->xattr_hash) {
2049 free(local->xattr_hash);
2050 }
2051 local->xattr_hash = xattr->hash;
2052 }
2053 }
2054 }
2055
2056 if(sync_store_tags(dir, path, local, res)) {
2057 ret = 1;
2058 }
2059
2060 return ret;
2061 }
2062
2063 int sync_store_xattr(SyncDirectory *dir, const char *path, XAttributes *xattr) {
2064 for(int i=0;i<xattr->nattr;i++) {
2065 sstr_t value = xattr->values[i];
2066 if(xattr_set(path, xattr->names[i], value.ptr, value.length)) {
2067 fprintf(
2068 stderr,
2069 "Cannot store xattr '%s' for file: %s\n",
2070 xattr->names[i],
2071 path);
2072 }
2073 }
2074 return 0;
2075 }
2076
1957 int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) { 2077 int sync_store_tags(SyncDirectory *dir, const char *path, LocalResource *local, DavResource *res) {
1958 if(!dir->tagconfig) { 2078 if(!dir->tagconfig) {
1959 return 0; 2079 return 0;
1960 } 2080 }
1961 2081
1971 DavBool store_tags = FALSE; 2091 DavBool store_tags = FALSE;
1972 DavBool tags_changed = FALSE; 2092 DavBool tags_changed = FALSE;
1973 UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed, NULL); 2093 UcxList *local_tags = sync_get_file_tags(dir, local, &tags_changed, NULL);
1974 if(tags_changed) { 2094 if(tags_changed) {
1975 switch(dir->tagconfig->conflict) { 2095 switch(dir->tagconfig->conflict) {
1976 case TAG_NO_CONFLICT: 2096 case TAG_NO_CONFLICT: {
2097 store_tags = TRUE;
2098 break;
2099 }
1977 case TAG_KEEP_LOCAL: { 2100 case TAG_KEEP_LOCAL: {
1978 store_tags = FALSE; 2101 store_tags = FALSE;
1979 break; 2102 break;
1980 } 2103 }
1981 case TAG_KEEP_REMOTE: { 2104 case TAG_KEEP_REMOTE: {
2034 if(data) { 2157 if(data) {
2035 char *data_hash = dav_create_hash(data->space, data->size); 2158 char *data_hash = dav_create_hash(data->space, data->size);
2036 int update = 1; 2159 int update = 1;
2037 if(local) { 2160 if(local) {
2038 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) { 2161 if(!local->tags_hash || strcmp(data_hash, local->tags_hash)) {
2039 printf("update: %s\n", local->path); 2162 //printf("update: %s\n", local->path);
2040 } else { 2163 } else {
2041 update = 0; 2164 update = 0;
2042 } 2165 }
2043 } 2166 }
2044 if(update) { 2167 if(update) {
2056 } else { 2179 } else {
2057 ret = -1; 2180 ret = -1;
2058 } 2181 }
2059 } else { 2182 } else {
2060 if(local) { 2183 if(local) {
2061 printf("update: %s\n", local->path); 2184 //printf("update: %s\n", local->path);
2062 } 2185 }
2063 ret = xattr_remove(path, dir->tagconfig->xattr_name); 2186 ret = xattr_remove(path, dir->tagconfig->xattr_name);
2064 } 2187 }
2065 } 2188 }
2066 2189

mercurial