adds content hash for splitted files

Thu, 28 Mar 2019 11:19:13 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 28 Mar 2019 11:19:13 +0100
changeset 541
e59a989d890d
parent 540
d18f92483945
child 542
060a8cda7f62

adds content hash for splitted files

dav/db.c file | annotate | diff | comparison | revisions
dav/db.h file | annotate | diff | comparison | revisions
dav/sync.c file | annotate | diff | comparison | revisions
--- a/dav/db.c	Tue Mar 26 18:28:37 2019 +0100
+++ b/dav/db.c	Thu Mar 28 11:19:13 2019 +0100
@@ -211,6 +211,8 @@
                 field = 9;
             } else if(xstreq(name, "blocksize")) {
                 field = 10;
+            } else if(xstreq(name, "hash")) {
+                field = 11;
             } else if(xstreq(name, "skipped")) {
                 res->skipped = TRUE;
             } else if(xstreq(name, "tags-updated")) {
@@ -300,6 +302,11 @@
                         }
                         res->blocksize = blsz;
                     }
+                    break;
+                }
+                case 11: {
+                    res->hash = strdup((char*)value);
+                    break;
                 }
             }
         } else if(XML_READER_TYPE_END_ELEMENT) {
@@ -401,6 +408,18 @@
                 return -1;
             }
         }
+        
+        if(res->hash) {
+            r = xmlTextWriterWriteElement(
+                    writer,
+                    BAD_CAST "hash",
+                    BAD_CAST res->hash);
+            if(r < 0) {
+                fprintf(stderr, "Cannot write hash: %s\n", res->hash);
+                xmlFreeTextWriter(writer);
+                return -1;
+            }
+        }
 
         r = xmlTextWriterWriteFormatElement(
                 writer,
--- a/dav/db.h	Tue Mar 26 18:28:37 2019 +0100
+++ b/dav/db.h	Thu Mar 28 11:19:13 2019 +0100
@@ -54,6 +54,7 @@
     char    *name;
     char    *path;
     char    *etag;
+    char    *hash;
     time_t  last_modified;
     mode_t  mode;
     uid_t   uid;
--- a/dav/sync.c	Tue Mar 26 18:28:37 2019 +0100
+++ b/dav/sync.c	Thu Mar 28 11:19:13 2019 +0100
@@ -80,6 +80,7 @@
     { DAV_NS, "finfo" },
     { DAV_NS, "tags" },
     { DAV_NS, "xattributes" },
+    { DAV_NS, "content-hash" },
     { DAV_NS, "split" }
 };
 static size_t numdefprops = 6;
@@ -2042,6 +2043,7 @@
         {"DAV:", "getetag"},
         {DAV_NS, "tags"},
         {DAV_NS, "version-collection"},
+        {DAV_NS, "content-hash"},
         {DAV_NS, "split" }
     };
     int err = dav_load_prop(remote, properties, 4);
@@ -2053,7 +2055,12 @@
     int ret = 0;
     if(err == 0) {
         char *etag = dav_get_string_property(remote, "D:getetag");
-        if(!res->etag) {
+        char *hash = dav_get_string_property(remote, "idav:content-hash");
+        if(hash || res->hash) {
+            if(!nullstrcmp(hash, res->hash)) {
+                ret = 1;
+            }
+        } else if(!res->etag) {
             // the resource is on the server and the client has no etag
             ret = 1;
         } else if(etag) {
@@ -2735,7 +2742,11 @@
     uint32_t session_flags = res->session->flags;
     res->session->flags ^= DAV_SESSION_ENCRYPT_NAME;
     
+    DAV_SHA_CTX *sha = dav_hash_init();
+    
     while((r = fread(buffer, 1, blocksize, in)) > 0) {
+        dav_hash_update(sha, buffer, r);
+        
         int upload_block = 0;
         char *block_hash = dav_create_hash(buffer, r);
         if(blockindex >= local->numparts) {
@@ -2796,6 +2807,15 @@
         return NULL;
     }
     
+    // set content-hash
+    char content_hash[DAV_SHA256_DIGEST_LENGTH];
+    dav_hash_final(sha, content_hash);
+    char *hash_hex = util_hexstr(content_hash, DAV_SHA256_DIGEST_LENGTH);
+    dav_set_string_property_ns(res, DAV_NS, "content-hash", hash_hex);
+    local->hash = hash_hex;
+    
+    // get etags from uploaded resources
+    // also delete everything, that is not part of the file
     UcxList *updated_parts = NULL;
     DavResource *parts = dav_query(res->session, "select D:getetag from %s order by name", res->path);
     if(!parts) {
@@ -2932,6 +2952,11 @@
         dav_set_content(res, in, (dav_read_func)myread, (dav_seek_func)file_seek);
         dav_set_content_length(res, s.st_size);
     } else {
+        // set split property
+        char blocksize_str[32];
+        snprintf(blocksize_str, 32, "%zu", split_blocksize);
+        dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str);
+        
         // splitted/partial upload
         parts = upload_parts(
                 local,

mercurial