This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository efm2.

View the commit online.

commit 98b6b2a72e2da4aea1ead63d9e3282d9872f88ce
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Sat Jun 8 17:21:59 2024 +0100

    move to a tmp subdir + artomic rename to keep thumbs valid
    
    so mv file to dest in a tmp dir (dst/.efm/.tmp/xxx) then if that works
    mov thumbs and meta over, then rename the tmp dir to the real dst path
    so when this happens the file appears "atomically" in whole with thumb
    file already there and valid. have to limit stat info for this to
    work. yes - it makes mv's of a lot of files and dirs slower with more
    io ops.... but its also safer as partly copied files are held in
    .efm/.tmp/ so you know anything left over there is not complete. this
    avoids thumb re-gen too on mving files abvout as the thumbs follow now.
---
 src/backends/default/mv.c | 105 ++++++++++++++++++++++++++++++++++++++++------
 src/shared/sha.c          |   8 ++--
 2 files changed, 96 insertions(+), 17 deletions(-)

diff --git a/src/backends/default/mv.c b/src/backends/default/mv.c
index d5c1194..16ded30 100644
--- a/src/backends/default/mv.c
+++ b/src/backends/default/mv.c
@@ -15,6 +15,7 @@
 #include "status.h"
 #include "fs.h"
 #include "esc.h"
+#include "sha.h"
 
 static const char *config_dir = NULL;
 
@@ -47,11 +48,16 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
 { // mv [src] [dstdir]
   const char  *fname, *home_dir;
   Eina_Strbuf *buf   = NULL;
+  Eina_Strbuf *buf2   = NULL;
   Eina_List   *files = NULL, *l;
   File_Set    *fs;
   size_t       sz;
   char        *src = "" *dst = NULL;
   char         sbuf[PATH_MAX + 256];
+  int          ret;
+  struct stat  st;
+  mode_t       prev_umask;
+  Eina_Bool    src_can_write, dst_can_write;
 
   eina_init();
   eet_init();
@@ -96,6 +102,8 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
 
   buf = eina_strbuf_new();
   if (!buf) goto err;
+  buf2 = eina_strbuf_new();
+  if (!buf2) goto err;
 
   status_begin();
   status_op("mv");
@@ -118,21 +126,57 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
     // when monitoring/watching a status file dst dst=xxx allows you to place
     // progress in the right dst dir
     status_dst(fs->dst);
+    ret = stat(fs->dst, &st);
+    if (ret != 0)
+      {
+        status_error(fs->src, fs->dst, "Cannot stat destination");
+        break;
+      }
+
+    src_can_write = meta_path_can_write(fs->src);
     eina_strbuf_reset(buf);
     eina_strbuf_append(buf, fs->dst);
     eina_strbuf_append(buf, "/");
     eina_strbuf_append(buf, fname);
+    dst_can_write = meta_path_can_write(eina_strbuf_string_get(buf));
+
+    eina_strbuf_reset(buf);
+    eina_strbuf_append(buf, fs->dst);
+    eina_strbuf_append(buf, "/.efm");
+    prev_umask = umask(0);
+    ret        = mkdir(eina_strbuf_string_get(buf), st.st_mode);
+    if ((ret != 0) && (errno != EEXIST))
+      {
+        status_error(fs->src, eina_strbuf_string_get(buf),
+                     "Cannot create directory");
+        break;
+      }
+    eina_strbuf_append(buf, "/.tmp");
+    ret = mkdir(eina_strbuf_string_get(buf), st.st_mode);
+    if ((ret != 0) && (errno != EEXIST))
+      {
+        status_error(fs->src, eina_strbuf_string_get(buf),
+                     "Cannot create directory");
+        break;
+      }
+    umask(prev_umask);
+
+    eina_strbuf_reset(buf);
+    eina_strbuf_append(buf, fs->dst);
+    eina_strbuf_append(buf, "/.efm/.tmp/");
+    eina_strbuf_append(buf, fname);
     // mv the file ...
     if (fs_mv(fs->src, eina_strbuf_string_get(buf), EINA_TRUE))
       { // it worked so deal with meta/thumbs
-        Eina_Bool   src_can_write, dst_can_write;
         const char *dstfile;
-        char       *src_meta, *dst_meta;
+        char       *src_meta, *dst_meta, *dstpath;
 
+        eina_strbuf_reset(buf);
+        eina_strbuf_append(buf, fs->dst);
+        eina_strbuf_append(buf, "/");
+        eina_strbuf_append(buf, fname);
         dstfile = eina_strbuf_string_get(buf);
-
-        src_can_write = meta_path_can_write(fs->src);
-        dst_can_write = meta_path_can_write(eina_strbuf_string_get(buf));
+        dstpath = strdup(dstfile);
 
         // metadata file for the base target file
         if (src_can_write) src_meta = meta_path_find(fs->src, "meta.efm");
@@ -163,16 +207,52 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
           {
             status_count(1, src_meta);
             fs_mv(src_meta, dst_meta, EINA_FALSE);
-            // XXX: we seem to have any open active re-gen thumbs here as
-            // opposed to use the thumb we mv'd across. we need to do something
-            // like block any thumbnailing while in progress andf tyhen the
-            // thumb has to have its statinfo replaced with valid statinfo
-            // from the new finished cp/mv'd file as its valid... also when
-            // the thumb is finished copying/updating/mvind we need active
-            // opens know to send updates to the views
+            // fix up the oprig stat info to match so thub is valid
+            eina_strbuf_reset(buf);
+            eina_strbuf_append(buf, fs->dst);
+            eina_strbuf_append(buf, "/.efm/.tmp/");
+            eina_strbuf_append(buf, fname);
+            // get stat info of new mv'd file
+            if (stat(eina_strbuf_string_get(buf), &st) == 0)
+              {
+                Eet_File *ef;
+                unsigned char statsha1[21];
+
+                // sha1 the stat info
+                statsha1[20] = 0;
+                sha1_stat(&st, statsha1);
+                // open the thumb for read+write
+                ef = eet_open(dst_meta, EET_FILE_MODE_READ_WRITE);
+                // update orig path just to be nice - not used for validity
+                eet_write(ef, "orig/path", dstpath, strlen(dstpath),
+                          EET_COMPRESSION_LOW);
+                // write new stat info so it's valid
+                eet_write(ef, "orig/stat/sha1", statsha1, 20,
+                          EET_COMPRESSION_NONE);
+                eet_close(ef);
+              }
           }
         free(src_meta);
         free(dst_meta);
+        free(dstpath);
+
+        // rename atomically the tmp mv'd file to its dest now thumb and meta
+        // are ok/valid
+        eina_strbuf_reset(buf);
+        eina_strbuf_append(buf, fs->dst);
+        eina_strbuf_append(buf, "/.efm/.tmp/");
+        eina_strbuf_append(buf, fname);
+        eina_strbuf_reset(buf2);
+        eina_strbuf_append(buf2, fs->dst);
+        eina_strbuf_append(buf2, "/");
+        eina_strbuf_append(buf2, fname);
+        ret = rename(eina_strbuf_string_get(buf), eina_strbuf_string_get(buf2));
+        if (ret != 0)
+          {
+            status_error(eina_strbuf_string_get(buf),
+                         eina_strbuf_string_get(buf2), "Cannot rename");
+            break;
+          }
       }
     else break;
   }
@@ -181,6 +261,7 @@ err2:
 
 err:
   if (buf) eina_strbuf_free(buf);
+  if (buf2) eina_strbuf_free(buf2);
   EINA_LIST_FREE(files, fs)
   {
     eina_stringshare_del(fs->src);
diff --git a/src/shared/sha.c b/src/shared/sha.c
index d3ad054..2e21462 100644
--- a/src/shared/sha.c
+++ b/src/shared/sha.c
@@ -23,12 +23,10 @@ sha1_stat(const struct stat *st, unsigned char dst[20])
 #define STAT_NSEC_CTIME(st) (unsigned long long)(0)
 #endif
 
-  snprintf(buf, sizeof(buf), "%llu %llu %llu %llu %llu %llu %llu %llu",
-           (unsigned long long)(st->st_mode), (unsigned long long)(st->st_uid),
-           (unsigned long long)(st->st_gid), (unsigned long long)(st->st_size),
+  snprintf(buf, sizeof(buf), "%llu %llu %llu",
+           (unsigned long long)(st->st_size),
            (unsigned long long)(st->st_mtime),
-           (unsigned long long)(st->st_ctime), STAT_NSEC_MTIME(st),
-           STAT_NSEC_CTIME(st));
+           STAT_NSEC_MTIME(st));
   eina_sha1((unsigned char *)buf, strlen(buf), dst);
 }
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to