696 } |
696 } |
697 } |
697 } |
698 cxListDestroy(stack); |
698 cxListDestroy(stack); |
699 } |
699 } |
700 |
700 |
|
701 static CxHashKey resource_path_key(DavResource *res) { |
|
702 CxHashKey key = { NULL, 0, 0 }; |
|
703 if(res && res->path) { |
|
704 cxstring res_path = cx_str(res->path); |
|
705 if(res_path.length > 0 && res_path.ptr[res_path.length-1] == '/') { |
|
706 res_path.length--; |
|
707 } |
|
708 key = cx_hash_key(res_path.ptr, res_path.length); |
|
709 } |
|
710 return key; |
|
711 } |
|
712 |
701 int cmd_pull(CmdArgs *a, DavBool incoming) { |
713 int cmd_pull(CmdArgs *a, DavBool incoming) { |
702 if(a->argc != 1) { |
714 if(a->argc != 1) { |
703 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
715 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
704 return -1; |
716 return -1; |
705 } |
717 } |
908 } |
920 } |
909 |
921 |
910 // remove every server resource from dbres |
922 // remove every server resource from dbres |
911 // all remaining elements are the resources that are removed |
923 // all remaining elements are the resources that are removed |
912 // on the server |
924 // on the server |
913 cxMapRemove(dbres, cx_hash_key_str(res->path)); |
925 cxMapRemove(dbres, resource_path_key(res)); |
914 |
926 |
915 if(!dav_get_property_ns(res, DAV_NS, "split") && res->children) { |
927 if(!dav_get_property_ns(res, DAV_NS, "split") && res->children) { |
916 cxListInsert(stack, 0, res->children); |
928 cxListInsert(stack, 0, res->children); |
917 } |
929 } |
918 res = res->next; |
930 res = res->next; |
1054 cx_foreach(DavResource *, res, i) { |
1066 cx_foreach(DavResource *, res, i) { |
1055 if(sync_shutdown) { |
1067 if(sync_shutdown) { |
1056 break; |
1068 break; |
1057 } |
1069 } |
1058 |
1070 |
1059 LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); |
1071 LocalResource *local = cxMapGet(db->resources, resource_path_key(res)); |
1060 if(local) { |
1072 if(local) { |
1061 log_printf("update: %s\n", res->path); |
1073 log_printf("update: %s\n", res->path); |
1062 char *res_path = resource_local_path(res); |
1074 char *res_path = resource_local_path(res); |
1063 char *local_path = create_local_path(dir, res->path); |
1075 char *local_path = create_local_path(dir, res->path); |
1064 free(res_path); |
1076 free(res_path); |
1179 DavBool iscollection = res->iscollection && !issplit; |
1190 DavBool iscollection = res->iscollection && !issplit; |
1180 |
1191 |
1181 RemoteChangeType type = cmd_getoption(a, "conflict") ? |
1192 RemoteChangeType type = cmd_getoption(a, "conflict") ? |
1182 REMOTE_CHANGE_MODIFIED : REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
1193 REMOTE_CHANGE_MODIFIED : REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED; |
1183 |
1194 |
1184 LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); |
1195 LocalResource *local = cxMapGet(db->resources, resource_path_key(res)); |
1185 char *local_path = create_local_path(dir, res->path); |
1196 char *local_path = create_local_path(dir, res->path); |
1186 |
1197 |
1187 char *link = SYNC_SYMLINK(dir) ? |
1198 char *link = SYNC_SYMLINK(dir) ? |
1188 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; |
1199 dav_get_string_property_ns(res, DAV_PROPS_NS, "link") : NULL; |
1189 |
1200 |
1804 CmdArgs *a, |
1815 CmdArgs *a, |
1805 SyncDirectory *dir, |
1816 SyncDirectory *dir, |
1806 DavResource *res, |
1817 DavResource *res, |
1807 SyncDatabase *db) |
1818 SyncDatabase *db) |
1808 { |
1819 { |
1809 char *res_path = resource_local_path(res); |
1820 cxstring res_path = cx_str(res->path); |
|
1821 if(res_path.length > 0 && res_path.ptr[res_path.length-1] == '/') { |
|
1822 res_path.length--; |
|
1823 } |
|
1824 |
|
1825 // TODO: use resource_local_path return value (necessary for creating links on windows) |
|
1826 //char *res_path = resource_local_path(res); |
1810 char *local_path = create_local_path(dir, res->path); |
1827 char *local_path = create_local_path(dir, res->path); |
1811 free(res_path); |
1828 //free(res_path); |
1812 |
1829 |
1813 log_printf("get: %s\n", res->path); |
1830 log_printf("get: %s\n", res->path); |
1814 // create directory |
1831 // create directory |
1815 // ignore error if it already exists |
1832 // ignore error if it already exists |
1816 if(sys_mkdir(local_path) && errno != EEXIST) { |
1833 if(sys_mkdir(local_path) && errno != EEXIST) { |
1828 free(local_path); |
1845 free(local_path); |
1829 return 1; |
1846 return 1; |
1830 } |
1847 } |
1831 |
1848 |
1832 // if it doesn't exist in the db, create an entry for the dir |
1849 // if it doesn't exist in the db, create an entry for the dir |
1833 LocalResource *local = cxMapGet(db->resources, cx_hash_key_str(res->path)); |
1850 LocalResource *local = cxMapGet(db->resources, cx_hash_key(res_path.ptr, res_path.length)); |
1834 if(!local) { |
1851 if(!local) { |
1835 local = calloc(1, sizeof(LocalResource)); |
1852 local = calloc(1, sizeof(LocalResource)); |
1836 local->path = strdup(res->path); |
1853 local->path = cx_strdup(res_path).ptr; |
1837 cxMapPut(db->resources, cx_hash_key_str(local->path), local); |
1854 cxMapPut(db->resources, cx_hash_key_str(local->path), local); |
1838 } |
1855 } |
1839 local->isdirectory = 1; |
1856 local->isdirectory = 1; |
1840 |
1857 |
1841 // cleanup LocalResource |
1858 // cleanup LocalResource |
3443 } |
3460 } |
3444 local->etag = cx_strdup(e).ptr; |
3461 local->etag = cx_strdup(e).ptr; |
3445 } |
3462 } |
3446 |
3463 |
3447 char* resource_local_path(DavResource *res) { |
3464 char* resource_local_path(DavResource *res) { |
|
3465 cxstring path = cx_str(res->path); |
|
3466 if(path.length > 0 && path.ptr[path.length-1] == '/') { |
|
3467 path.length--; |
|
3468 } |
3448 #ifdef SYS_LINK_EXT |
3469 #ifdef SYS_LINK_EXT |
3449 // on Windows, add .lnk extension to links |
3470 // on Windows, add .lnk extension to links |
3450 if(dav_get_property_ns(res, DAV_PROPS_NS, "link")) { |
3471 if(dav_get_property_ns(res, DAV_PROPS_NS, "link")) { |
3451 return cx_asprintf("%s%s", res->path, SYS_LINK_EXT).ptr; |
3472 return cx_asprintf("%.*s%s", (int)path.length, path.ptr, SYS_LINK_EXT).ptr; |
3452 } else { |
3473 } else { |
3453 // not a link |
3474 // not a link |
3454 return strdup(res->path); |
3475 return cx_strdup(path).ptr; |
3455 } |
3476 } |
3456 #else |
3477 #else |
3457 return strdup(res->path); |
3478 return cx_strdup(path).ptr; |
3458 #endif |
3479 #endif |
3459 } |
3480 } |
3460 |
3481 |
3461 size_t resource_get_blocksize(SyncDirectory *dir, LocalResource *local, DavResource *res, off_t filesize) { |
3482 size_t resource_get_blocksize(SyncDirectory *dir, LocalResource *local, DavResource *res, off_t filesize) { |
3462 size_t local_blocksize = 0; |
3483 size_t local_blocksize = 0; |