Attempt to preserve timestamps mmanoncvs-timestamp-branch
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 10 Sep 2015 14:32:27 +0000 (10:32 -0400)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 10 Sep 2015 14:32:27 +0000 (10:32 -0400)
mmsoftware/mmanoncvs/mmanoncvs.c

index be103cc..d90b5b0 100644 (file)
 
 
 #include <sys/types.h>
+#include <sys/file.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include <sys/file.h>
+#include <sys/time.h>
 #include <unistd.h>
+#include <utime.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -104,6 +106,7 @@ struct cvsroot_file {
  */
 struct dir_node {
     pnode_t node;
+    struct utimbuf times;
     size_t size, namelen;
     int flags;
     char name[PATH_MAX];
@@ -166,7 +169,7 @@ static bool cvsroot_delete(const char *);
 static bool dir_valid(char *);
 static bool dir_make(const char *, const char *);
 static int dir_open(list_t *, const char *, bool);
-static void dir_close(list_t *);
+static void dir_close(list_t *, bool);
 static int tree_open(list_t *, const char *, bool);
 static int tree_open_r(list_t *, const char *, bool);
 static void tree_close(list_t *, bool);
@@ -919,7 +922,7 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
                    break;
                }
                (void) closedir(dptr);
-               dir_close(dir);
+               dir_close(dir, FALSE);
                return error;
            }
            (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d", dirpath,
@@ -929,7 +932,7 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
                (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.locl", dirpath);
                (void) rmdir(buf);
                (void) closedir(dptr);
-               dir_close(dir);
+               dir_close(dir, FALSE);
                return E_PERM;
            }
            (void) close(fd);
@@ -953,7 +956,7 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
                (void) fprintf(stderr, "dir_open(%s) - lstat(%s) - (%s)",
                               dirpath, buf, strerror(errno));
                (void) closedir(dptr);
-               dir_close(dir);
+               dir_close(dir, FALSE);
                if (locking) {
                    (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d",
                                    dirpath, (int)pid);
@@ -1022,7 +1025,7 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
                /* Release everything cleanly */
                (void) fprintf(stderr, "dir_open() - Out of memory\n");
                (void) closedir(dptr);
-               dir_close(dir);
+               dir_close(dir, FALSE);
                if (locking) {
                    (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d",
                                    dirpath, (int)pid);
@@ -1037,6 +1040,8 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
             * files already the value may in fact fit safely into an ssize_t.
             */
            dnode->size = (size_t)st.st_size;
+           dnode->times.actime = st.st_atime;
+           dnode->times.modtime = st.st_mtime;
            dnode->flags = flags;
            dnode->namelen = mm_strncpy(dnode->name, buf, PATH_MAX - 1);
            DLIST_APPEND(dir, (node_t *)dnode);
@@ -1054,7 +1059,7 @@ static int dir_open(list_t *dir, const char *dirpath, bool locking)
  * initialized. Safe to use on empty lists, as long as they at least have
  * previously been initialized once using DLIST_INIT().
  */
-static void dir_close(list_t *dir)
+static void dir_close(list_t *dir, bool timefix)
 {
     struct dir_node *dnode, *tmp;
 
@@ -1067,6 +1072,11 @@ static void dir_close(list_t *dir)
      */
     for (dnode = DLIST_TOP(dir); dnode != NULL; dnode = tmp) {
        tmp = DLIST_NEXT(dnode);
+       if (timefix) {
+               if (utime(dnode->name, &dnode->times) == -1)
+                       (void) fprintf(stderr, "dir_close() - utime(%s)\n",
+                           dnode->name);
+       }
        (void) pool_free((pnode_t *)dnode);
     }
     DLIST_INIT(dir);
@@ -1140,12 +1150,12 @@ static int tree_open_r(list_t *tree, const char *dirpath, bool locking)
                (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", dirpath);
                (void) rmdir(buf);
            }
-           dir_close(&dir);
+           dir_close(&dir, FALSE);
            tree_close(tree, locking);
            return E_NOMEM;
        }
     } else {
-       dir_close(&dir);
+       dir_close(&dir, FALSE);
        return error;
     }
 
@@ -1153,10 +1163,11 @@ static int tree_open_r(list_t *tree, const char *dirpath, bool locking)
 }
 
 
-/* Releases all successfully locked directories in the specified tree, as well
- * as all memory resources in use to cache it's filenames. The tree must
- * previously have been loaded using tree_open(). The tree_pool pool_t must
- * previously have been initialized.
+/* Releases all successfully locked directories in the specified tree, apply
+ * their timestamps to reflect the originals, and free all memory resources
+ * in use to cache their filenames.
+ * The tree must previously have been loaded using tree_open(). The tree_pool
+ * pool_t must previously have been initialized.
  */
 static void tree_close(list_t *tree, bool locking)
 {
@@ -1166,7 +1177,6 @@ static void tree_close(list_t *tree, bool locking)
     /* Can't use DLIST_FOREACH() as we're also freeing nodes */
     for (tnode = DLIST_TOP(tree); tnode != NULL; tnode = tmp) {
        tmp = DLIST_NEXT(tnode);
-       dir_close(&tnode->dir);
        if (locking) {
            (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.rfl.%d", tnode->name,
                            (int)pid);
@@ -1174,6 +1184,11 @@ static void tree_close(list_t *tree, bool locking)
            (void) snprintf(buf, PATH_MAX - 1, "%s/#cvs.lock", tnode->name);
            (void) rmdir(buf);
        }
+       /*
+        * We unfortunately need to update timestamps after unlocking the
+        * directory by the above deletions.
+        */
+       dir_close(&tnode->dir, TRUE);
        (void) pool_free((pnode_t *)tnode);
     }
     DLIST_INIT(tree);
@@ -1398,6 +1413,10 @@ static bool tree_delete(const char *dirpath)
        }
        if (newcnt == oldcnt) {
            /* There obviously is a problem here, stop iterating. */
+           if (newcnt != 0)
+               (void) fprintf(stderr,
+                   "tree_delete() - directory count %ld not decreasing\n",
+                   newcnt);
            break;
        }
     }