dav/sync.c

changeset 144
c2c02c9b3be4
parent 135
664aeaec8d25
child 145
82475dc12dd4
--- 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;i<dir->max_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;
 }

mercurial