]> pd.if.org Git - zpackage/blobdiff - zpm-syncfs.c
add support for notes
[zpackage] / zpm-syncfs.c
index 935e71509f2591ae20cc3a9801c22548c0a53ae1..d2847cf2387f295b9e2d393e94dcd8e29189cbca 100644 (file)
@@ -40,11 +40,12 @@ struct nitem {
        gid_t gid;
        char *dest;
        char *path;
-       char *hash;
+       char *hash, *ohash;
        char *target;
        time_t mtime;
        mode_t mode;
        int ftype;
+       int configuration;
        struct timespec times[2];
 };
 
@@ -285,6 +286,7 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) {
        struct config *conf = f;
        char *dest;
        struct stat st;
+       int flags = 0;
 
        dest = COL("dest");
        if (!dest) return seterror(conf,"no file dest");
@@ -306,21 +308,22 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) {
        }
 
        if (S_ISDIR(st.st_mode)) {
-               if (conf->verbose) {
-                       fprintf(stderr, "rmdir(%s)\n", dest);
-               }
-               rmdir(dest);
-       } else if (S_ISREG(st.st_mode)) {
-               /* TODO conf to import before removal */
-               if (conf->verbose) {
-                       fprintf(stderr, "unlink(%s)\n", dest);
-               }
-               if (unlink(dest) == -1) {
-                       return seterror(conf, "can't unlink");
-               }
-       } else {
-               if (unlink(dest) == -1) {
-                       return seterror(conf, "can't unlink");
+               flags = AT_REMOVEDIR;
+       }
+       /* TODO check that expected filetype matches actual filetype */
+
+       if (conf->verbose) {
+               fprintf(stderr, "%s(%s)\n", flags ? "rmdir" : "unlink", dest);
+       }
+
+       errno = 0;
+
+       if (unlinkat(AT_FDCWD, dest, flags) == -1) {
+               switch (errno) {
+                       case ENOENT:
+                               break;
+                       default:
+                               return seterror(conf, "can't unlink");
                }
        }
        
@@ -339,6 +342,7 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) {
 #define D_GID 0x80
 #define D_MODE 0x100
 #define D_MTIME 0x200
+#define D_OHASH 0x400
 #define D_ERROR 0x1000
 #define D_STATERROR 0x2000
 #define D_RLERROR 0x4000
@@ -376,6 +380,9 @@ static unsigned int file_compare(struct nitem *n, struct stat *st) {
                        if (strcmp(n->hash, ehash) != 0) {
                                diff |= D_HASH;
                        }
+                       if (n->ohash && strcmp(n->ohash, ehash) != 0) {
+                               diff |= D_OHASH;
+                       }
                }
                if (n->hash && etype == S_IFLNK && stat_type == S_IFLNK) {
                        lsize = readlink(n->dest, link, sizeof link);
@@ -460,6 +467,13 @@ static int read_item(struct config *conf, int ncols, char **vals, char **cols,
 
        n->mode = strtoul(val, NULL, 8);
 
+       val = COL("configuration");
+       if (!val) {
+               seterror(conf, "can't determine config status");
+               return 0;
+       }
+       n->configuration = strtoul(val, NULL, 10);
+
        val = COL("filetype");
        if (!val || strlen(val) == 0) {
                seterror(conf, "can't determine file type");
@@ -467,6 +481,8 @@ static int read_item(struct config *conf, int ncols, char **vals, char **cols,
        }
        n->ftype = *val;
 
+       n->ohash = COL("hash");
+
        if (n->ftype == 'r') {
                n->hash = COL("hash");
                if (!n->hash) {
@@ -601,6 +617,12 @@ static int set_md(struct config *conf, struct nitem *item) {
 /* flags: 1 = set md, 2 = create leading dirs, 4 = unlink existing file,
  * 8 = rmdir existing dir, 16 = return true/false
  */
+#define INS_MD 0x1
+#define INS_CLD 0x2
+#define INS_UNLINK 0x4
+#define INS_RMDIR 0x8
+#define INS_RTF 0x10
+#define INS_ZPMNEW 0x20
 static int install(struct config *conf, struct nitem *item, unsigned int flags) {
        int rv = 1;
        struct zpm *source;
@@ -686,6 +708,7 @@ static int install_files(void *f, int ncols, char **vals, char **cols) {
        struct nitem nitem;
        struct stat existing;
        int update = 0;
+       char dest[4096];
 
        /* TODO put the result row in a hash table.  May not actually
         * be faster
@@ -747,6 +770,22 @@ static int install_files(void *f, int ncols, char **vals, char **cols) {
                        return install(conf, &nitem, 3);
                }
 
+               if (nitem.configuration) {
+                       /* ohash == nhash, not an update */
+                       /* fhash == ohash, just update */
+                       /* fhash != ohash, install as dest.zpmnew, warn */
+                       /* TODO handle replacing config file
+                        * with config directory */
+                       if (diffs & D_OHASH) {
+                               if (strlen(nitem.dest) > sizeof dest - 8) {
+                                       return seterror(conf,"config file path too long for install as %s.zpmnew", nitem.dest);
+                               }
+                               fprintf(stderr, "installing as .zpmnew\n");
+                               sprintf(dest, "%s.zpmnew", nitem.dest);
+                               nitem.dest = dest;
+                       }
+               }
+
                /* file exists in filesystem */
                if (sametype) {
                        if (mdsame && hashsame) {