diff -r d8b01bed3d83 -r c2c02c9b3be4 dav/sync.c --- a/dav/sync.c Sat Oct 03 00:09:23 2015 +0200 +++ b/dav/sync.c Sat Oct 03 13:33:15 2015 +0200 @@ -182,7 +182,7 @@ curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); } - DavResource *ls = dav_query(sn, "select D:getetag from / depth -1 where lastmodified > 0 with"); + DavResource *ls = dav_query(sn, "select D:getetag,idav:status from / with depth = infinity"); if(!ls) { fprintf(stderr, "Error\n"); // TODO: free @@ -207,6 +207,12 @@ continue; } + char *status = dav_get_property(res, "idav:status"); + if(status && !strcmp(status, "broken")) { + res = res->next; + continue; + } + // download the resource if(sync_get_resource(a, dir, res, db)) { fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); @@ -665,53 +671,99 @@ } +int sync_set_status(DavResource *res, char *status) { + DavResource *resource = dav_resource_new(res->session, res->path); + dav_set_property(resource, "idav:status", status); + int ret = dav_store(resource); + dav_resource_free(resource); + return ret; +} + +int sync_remove_status(DavResource *res) { + DavResource *resource = dav_resource_new(res->session, res->path); + dav_remove_property(resource, "idav:status"); + int ret = dav_store(resource); + dav_resource_free(resource); + return ret; +} + int sync_put_resource(SyncDirectory *dir, DavResource *res, LocalResource *local) { char *local_path = util_concat_path(dir->path, res->path); + + struct stat s; + if(stat(local_path, &s)) { + fprintf(stderr, "cannot stat file: %s\n", local_path); + perror(""); + free(local_path); + return -1; + } + FILE *in = fopen(local_path, "rb"); if(!in) { fprintf(stderr, "Cannot open file %s\n", local_path); free(local_path); return -1; } - free(local_path); dav_set_content(res, in, (dav_read_func)fread); int ret = -1; - for(;;) { - if(dav_create(res)) { - break; + int created = 0; + for(int i=0;imax_retry;i++) { + if(!created && dav_create(res)) { + continue; } + created = 1; if(dav_store(res)) { - break; + continue; } ret = 0; break; } + + if(ret == 0) { - // get new etag + // check contentlength and get new etag DavResource *up_res = dav_get(res->session, res->path, "D:getetag"); - char *etag = dav_get_property(up_res, "D:getetag"); - if(etag) { - if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { - etag = etag + 2; - } - } - if(local->etag) { - free(local->etag); + if(up_res) { + // the new content length must be equal or greater than the file size + if(up_res->contentlength < s.st_size) { + fprintf(stderr, "Incomplete Upload: %s", local_path); + ret = -1; + // try to set the resource status to 'broken' + sync_set_status(res, "broken"); + } else { + // everything seems fine, we can update the local resource + char *etag = dav_get_property(up_res, "D:getetag"); + if(etag) { + if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { + etag = etag + 2; + } + } + + if(local->etag) { + free(local->etag); + } + + if(etag) { + local->etag = strdup(etag); + } else { + local->etag = NULL; + } + dav_resource_free(up_res); + + sync_remove_status(res); + } } - - if(etag) { - local->etag = strdup(etag); - } else { - local->etag = NULL; - } - dav_resource_free(up_res); + } else { + ret = -1; + sync_set_status(res, "broken"); } fclose(in); + free(local_path); return ret; }