X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-syncfs.c;h=2e43dbef9299c8599bb400ff10916f3dfbedeb80;hb=8d5b72e66760d0aebf364ed7b2cdf05d821bea6e;hp=218c53812ae22756019f5dfe251ddb3ab438a093;hpb=a4c082eb84ba2313af33892d2869485fd3319902;p=zpackage diff --git a/zpm-syncfs.c b/zpm-syncfs.c index 218c538..2e43dbe 100644 --- a/zpm-syncfs.c +++ b/zpm-syncfs.c @@ -334,19 +334,35 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { #define MARK fprintf(stderr, "%s %d: mark\n", __func__, __LINE__) +/* file does not exist */ #define D_NOEXIST 0x1 +/* files are different types */ #define D_TYPE 0x2 +/* metadata is different */ #define D_MD 0x4 +/* content or link target is different */ #define D_HASH 0x8 +/* file to be installed is a directory */ #define D_ISDIR 0x10 +/* path on disk is a directory */ #define D_EISDIR 0x20 +/* usernames different */ #define D_UID 0x40 +/* group names different */ #define D_GID 0x80 +/* file mode is different */ #define D_MODE 0x100 +/* mtimes are different */ #define D_MTIME 0x200 +/* the hash of the file we are supposedly replacing is different than + * the the hash of the file on disk + */ #define D_OHASH 0x400 +/* an error occurred trying to compare the file (other than it doesn't exist */ #define D_ERROR 0x1000 +/* there was a stat error */ #define D_STATERROR 0x2000 +/* there was an error calling readlink */ #define D_RLERROR 0x4000 /* 1 = file doesn't exist, 2 = file is a directory, target isn't */ @@ -388,11 +404,15 @@ static unsigned int file_compare(struct nitem *n, struct stat *st) { } if (n->hash && etype == S_IFLNK && stat_type == S_IFLNK) { lsize = readlink(n->dest, link, sizeof link); + if (lsize == -1 || lsize == sizeof link) { diff |= D_RLERROR; diff |= D_ERROR; - } else if (strcmp(n->target, link) != 0) { - diff |= D_HASH; + } else { + link[lsize] = 0; + if (strcmp(n->target, link) != 0) { + diff |= D_HASH; + } } } if (n->uid != st->st_uid) { @@ -709,12 +729,94 @@ static int install(struct config *conf, struct nitem *item, unsigned int flags) return success; } +/* + * + */ +static int adjust_for_config(struct config *conf, struct nitem *n, unsigned int + diffs) { +#if 0 + if (!n->oldwasconf) { + return 0; + } +#endif + /* TODO what if old was a directory? */ + if (!n->configuration) { + /* replacing conf with non-conf */ + /* absorb file, mark todo */ + char hash[ZPM_HASH_STRLEN+1]; + if (zpm_import(conf->log, n->dest, 0, hash)) { + zpm_note_add(conf->log, n->pkglist, n->dest, hash, + "replaced config file with non-config. zpm-cat %.8s", hash); + } else { + fprintf(stderr, "unable to import existing config file %s\n", n->dest); + return 1; + } + return 0; + } + + int sametype = (!(diffs & D_TYPE)); + int isdir = (diffs & D_ISDIR); + int eisdir = (diffs & D_EISDIR); + + /* both old and new are config files */ + if (isdir && sametype) { + /* both config directories, can only be changing + * metadata, so no adjustment needed + */ + return 0; + } + + if (isdir) { + char hash[ZPM_HASH_STRLEN+1]; + + /* replacing old file with new directory */ + /* absorb, make note */ + if (zpm_import(conf->log, n->dest, 0, hash)) { + zpm_note_add(conf->log, n->pkglist, n->dest, hash, + "replaced config file with config directory. zpm-cat %.8s", hash); + } else { + fprintf(stderr, "unable to import existing config file %s\n", n->dest); + return -1; + } + return 0; + } + + if (eisdir) { + /* replacing old conf directory with a conf file. + * nothing needs to be done, if the directory + * is empty, it's ok to remove. if it's not empty, + * the install will fail + */ + return 0; + } + + /* replacing old file with new file */ + /* new is same as on disk */ + if (!(diffs & D_HASH)) { + return 0; + } + + /* new is different than on disk, but on disk is same as old */ + if (!(diffs & D_OHASH)) { + /* ok to do the update, since same as default */ + fprintf(stderr, "updating default config %s\n", n->dest); + return 0; + } + + /* new is different than on disk, and disk different than old */ + /* log */ + zpm_note_add(conf->log, n->pkglist, n->dest, n->hash, + "default config file update. zpm-cat %.8s", n->hash); + /* TODO check for note error */ + return 1; + +} + static int install_files(void *f, int ncols, char **vals, char **cols) { struct config *conf = f; 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 @@ -776,24 +878,12 @@ 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 */ - /* We don't have the information as to which - * package this is a config file for, so - * we'll need to look it up. - */ - 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; - } + switch (adjust_for_config(conf, &nitem, diffs)) { + case -1: return conf->errabort; break; + case 1: + fprintf(stderr, "skipping changed default config file: %s\n", nitem.dest); + return 0; break; + default: break; } /* file exists in filesystem */ @@ -857,6 +947,7 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { return install(conf, &nitem, 7); } /* error, should not be possible, assert(0)? */ + fprintf(stderr,"impossible state: %s:%d\n", __func__, __LINE__); } if (installing) { @@ -869,13 +960,14 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { if (mdsame && hashsame && (accept || overwrite)) { /* do nothing */ if (conf->dryrun || conf->verbose) { - fprintf(stderr, "accepting existing file: %s\n", nitem.dest); + fprintf(stderr, "accept %s: %s\n", + eisdir ? "directory" : "file", nitem.dest); } return 0; } if (mdsame && hashsame && !(accept || overwrite)) { /* error */ - return seterror(conf, "will not accept or overwrite existing file: %s", nitem.dest); + return seterror(conf, "file exists: %s", nitem.dest); } if (mdsame && !hashsame && overwrite) { /* install */ @@ -885,7 +977,20 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { /* accept doesn't matter, since it's * not an acceptable file */ /* error */ - return seterror(conf, "%s (hashdiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); + if (nitem.ftype == 'l') { + char link[1024]; + ssize_t lsize; + lsize = readlink(nitem.dest, link, sizeof link); + if (lsize == -1 || (size_t)lsize >= sizeof link) { + return seterror(conf, "%s (linkdiff): expecting %s -> %s, unable to read link", accept ? "existing file not acceptable" : "file exists", nitem.dest, nitem.target, link); + } else { + link[lsize] = 0; + /* links must be different */ + return seterror(conf, "%s (linkdiff): expecting %s -> %s, have -> %s", accept ? "existing file not acceptable" : "file exists", nitem.dest, nitem.target, link); + } + } else { + return seterror(conf, "%s (hashdiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); + } } if (!mdsame && hashsame && overwrite) { /* fix md */