dav/sync.c

changeset 491
fdc2fb090cc7
parent 490
d94c4fd35c21
child 492
7bde663719dc
equal deleted inserted replaced
490:d94c4fd35c21 491:fdc2fb090cc7
1979 size_t myread(void *ptr, size_t size, size_t nmemb, FILE *f) { 1979 size_t myread(void *ptr, size_t size, size_t nmemb, FILE *f) {
1980 size_t ret = fread(ptr, size, nmemb, f); 1980 size_t ret = fread(ptr, size, nmemb, f);
1981 return ret; 1981 return ret;
1982 } 1982 }
1983 1983
1984 int gen_random_name(char *buf, size_t len) {
1985 char name_prefix[8];
1986 memset(name_prefix, 0, 8);
1987 dav_rand_bytes(name_prefix, 8);
1988 char *pre = util_hexstr(name_prefix, 8);
1989 int64_t ts = (int64_t)time(NULL);
1990 int w = snprintf(buf, len, "%s-%"PRId64"\0", pre, ts);
1991 free(pre);
1992 return w >= len;
1993 }
1994
1995 #define VBEGIN_ERROR_MKCOL 1
1996 #define VBEGIN_ERROR_MOVE 2
1997 #define VBEGIN_ERROR_PROPPATCH 3
1998 #define VBEGIN_ERROR_CHECKOUT 4
1999 int versioning_begin(SyncDirectory *dir, DavResource *res, int *exists) {
2000 int ret = 0;
2001
2002 if(dir->versioning->type == VERSIONING_SIMPLE) {
2003 DavResource *history_collection = dav_resource_new(
2004 res->session,
2005 dir->versioning->collection);
2006
2007 // get the path to the version history collection for this resource
2008 // if propfind fails we just assume that it doesn't exist
2009 // better error handling is done later (sync_put_resource)
2010 // if there is no history collection for this resource, we create a one
2011
2012 DavPropName prop;
2013 prop.ns = DAV_NS;
2014 prop.name = VERSION_PATH_PROPERTY;
2015 *exists = dav_load_prop(res, &prop, 1);
2016
2017 char *history_href = NULL;
2018 char *vcol_path = dav_get_string_property_ns(res, DAV_NS, VERSION_PATH_PROPERTY);
2019 if(!vcol_path) {
2020 DavResource *history_res = NULL;
2021
2022 // create a new collection for version history
2023 // the name is a combination of a random prefix and a timestamp
2024 while(!history_res) {
2025 char history_res_name[128];
2026 gen_random_name(history_res_name, 128);
2027
2028 history_res = dav_resource_new_child(
2029 res->session,
2030 history_collection,
2031 history_res_name);
2032 if(dav_exists(history_res)) {
2033 dav_resource_free(history_res);
2034 history_res = NULL;
2035 }
2036 }
2037
2038 history_res->iscollection = TRUE;
2039 if(dav_create(history_res)) {
2040 dav_resource_free(history_res);
2041 dav_resource_free(history_collection);
2042 return VBEGIN_ERROR_MKCOL;
2043 }
2044
2045 history_href = strdup(history_res->href);
2046
2047 dav_resource_free(history_res);
2048 } else {
2049 history_href = vcol_path;
2050 }
2051
2052 // find a free url and move 'res' to this location
2053 DavResource *version_res = NULL;
2054 while(!version_res) {
2055 char version_name[128];
2056 gen_random_name(version_name, 128);
2057
2058 char *href = util_concat_path(history_href, version_name);
2059 version_res = dav_resource_new_href(res->session, href);
2060 free(href);
2061
2062 char *dest = util_get_url(res->session, version_res->href);
2063 int err = dav_moveto(res, dest, FALSE);
2064 free(dest);
2065
2066 if(err) {
2067 dav_resource_free(version_res);
2068 version_res = NULL;
2069 if(res->session->error != DAV_PRECONDITION_FAILED) {
2070 ret = VBEGIN_ERROR_MOVE;
2071 break;
2072 }
2073 }
2074 }
2075
2076 if(!ret) {
2077 dav_set_string_property_ns(version_res, DAV_NS, "origin", res->href);
2078 if(dav_store(version_res)) {
2079 ret = VBEGIN_ERROR_PROPPATCH;
2080 }
2081 dav_resource_free(version_res);
2082
2083 // we can just set the property here and don't need dav_store
2084 // because sync_put_resource will call dav_store(res) later
2085 dav_set_string_property_ns(
2086 res,
2087 DAV_NS,
2088 VERSION_PATH_PROPERTY,
2089 history_href);
2090 }
2091
2092 if(vcol_path != history_href) {
2093 free(history_href);
2094 }
2095
2096 dav_resource_free(history_collection);
2097 } else {
2098 // Delta V is so much easier :)
2099 if(dav_checkout(res)) {
2100 ret = VBEGIN_ERROR_CHECKOUT;
2101 }
2102 }
2103
2104 return ret;
2105 }
2106
2107 int versioning_end(SyncDirectory *dir, DavResource *res) {
2108 if(dir->versioning->type == VERSIONING_DELTAV) {
2109 return dav_checkin(res);
2110 }
2111 }
2112
1984 int sync_put_resource( 2113 int sync_put_resource(
1985 SyncDirectory *dir, 2114 SyncDirectory *dir,
1986 DavResource *res, 2115 DavResource *res,
1987 LocalResource *local, 2116 LocalResource *local,
1988 int *counter) 2117 int *counter)
1989 { 2118 {
1990 char *local_path = util_concat_path(dir->path, res->path); 2119 char *local_path = util_concat_path(dir->path, res->path);
1991 2120
1992 SYS_STAT s; 2121 SYS_STAT s;
1993 if(sys_stat(local_path, &s)) { 2122 if(sys_stat(local_path, &s)) {
1994 fprintf(stderr, "cannot stat file: %s\n", local_path); 2123 fprintf(stderr, "Cannot stat file: %s\n", local_path);
1995 perror(""); 2124 perror("");
1996 free(local_path); 2125 free(local_path);
1997 return -1; 2126 return -1;
1998 } 2127 }
1999 2128
2012 DavXmlNode *prop = create_xml_taglist(tags); 2141 DavXmlNode *prop = create_xml_taglist(tags);
2013 if(prop) { 2142 if(prop) {
2014 dav_set_property_ns(res, DAV_NS, "tags", prop); 2143 dav_set_property_ns(res, DAV_NS, "tags", prop);
2015 } 2144 }
2016 } 2145 }
2017 2146
2147 int exists = dav_exists(res);
2148 if(dir->versioning && dir->versioning->always) {
2149 int err = versioning_begin(dir, res, &exists);
2150 if(err) {
2151 fprintf(stderr, "Cannot store version for resource: %s\n", res->href);
2152 free(local_path);
2153 return -1;
2154 }
2155 } else {
2156 exists = dav_exists(res);
2157 }
2158
2018 int ret = -1; 2159 int ret = -1;
2019 int created = 0;
2020 for(int i=0;i<=dir->max_retry;i++) { 2160 for(int i=0;i<=dir->max_retry;i++) {
2021 if(!created && dav_create(res)) { 2161 if(!exists && dav_create(res)) {
2022 continue; 2162 continue;
2023 } 2163 }
2024 created = 1; 2164 exists = 1;
2025 if(dav_store(res)) { 2165 if(dav_store(res)) {
2026 continue; 2166 continue;
2027 } 2167 }
2028 ret = 0; 2168 ret = 0;
2029 break; 2169 break;
2030 } 2170 }
2031 2171
2032 2172 if(dir->versioning && dir->versioning->always) {
2173 if(versioning_end(dir, res)) {
2174 fprintf(stderr, "Cannot checkin resource\n");
2175 ret = 1;
2176 }
2177 }
2033 2178
2034 if(ret == 0) { 2179 if(ret == 0) {
2035 (*counter)++; 2180 (*counter)++;
2036 2181
2037 // check contentlength and get new etag 2182 // check contentlength and get new etag

mercurial