X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-syncfs.c;h=d2847cf2387f295b9e2d393e94dcd8e29189cbca;hb=383712eefa950c5dc619f8cd5fb60be8e8041502;hp=935e71509f2591ae20cc3a9801c22548c0a53ae1;hpb=c22f072a98c1117f334367f46740c05d48296044;p=zpackage diff --git a/zpm-syncfs.c b/zpm-syncfs.c index 935e715..d2847cf 100644 --- a/zpm-syncfs.c +++ b/zpm-syncfs.c @@ -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) {