From 3eba5d5fa46e471f429d25fbc1f27251bee4cbfc Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Wed, 17 Oct 2018 10:08:32 +0000 Subject: [PATCH] improve syncfs dry-run output --- zpm-syncfs.c | 143 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 54 deletions(-) diff --git a/zpm-syncfs.c b/zpm-syncfs.c index c08407e..9985188 100644 --- a/zpm-syncfs.c +++ b/zpm-syncfs.c @@ -12,6 +12,7 @@ #include #include #include +#include /* needed for S_IFMT and AT_FDCWD */ #include @@ -32,6 +33,21 @@ struct config { int overwrite, absorb; }; +struct nitem { + int op; + char *opstr; + uid_t uid; + gid_t gid; + char *dest; + char *path; + char *hash; + char *target; + time_t mtime; + mode_t mode; + int ftype; + struct timespec times[2]; +}; + static void usage() { printf("usage: zpm $scriptname [-fncC] args ...\n"); } @@ -134,17 +150,18 @@ static int create_leading_dirs(char *path) { /* try to create the directory, if it exists * and is a directory or a symlink, that's ok + * should be (eventually) a symlink to a directory + * so we want stat here, not lstat */ if (mkdir(pcopy, 0755) == -1) { switch (errno) { case EEXIST: - if (lstat(pcopy, &st) == -1) { + if (stat(pcopy, &st) == -1) { /* can't stat? */ return 0; } switch (st.st_mode & S_IFMT) { case S_IFDIR: - case S_IFLNK: break; default: return 0; @@ -239,6 +256,7 @@ static int check_existing(void *f, int ncols, char **vals, char **cols) { if (conf->dryrun) { printf("checkfor %s\n", path); + fflush(stdout); return 0; } @@ -279,6 +297,7 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { case 'd': printf("rmdir %s\n", dest); break; default: printf("unlink %s\n", dest); break; } + fflush(stdout); return 0; } @@ -310,20 +329,6 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { #define MARK fprintf(stderr, "%s %d: mark\n", __func__, __LINE__) -struct nitem { - int op; - uid_t uid; - gid_t gid; - char *dest; - char *path; - char *hash; - char *target; - time_t mtime; - mode_t mode; - int ftype; - struct timespec times[2]; -}; - #define D_NOEXIST 0x1 #define D_TYPE 0x2 #define D_MD 0x4 @@ -417,6 +422,7 @@ static int read_item(struct config *conf, int ncols, char **vals, char **cols, seterror(conf, "can't determine op"); return 0; } + n->opstr = val; n->op = getop(val); if (!n->op) { seterror(conf, "can't determine op"); @@ -512,7 +518,13 @@ static int read_item(struct config *conf, int ncols, char **vals, char **cols, n->gid = getegid(); } + errno = 0; double mtime = strtod(COL("mtime"),NULL); + if (errno) { + mtime = (double)time(NULL); + } + + n->mtime = (time_t)mtime; n->times[0].tv_sec = 0; n->times[0].tv_nsec = UTIME_OMIT; @@ -546,15 +558,28 @@ static int remove_existing(struct config *conf, char *path) { static int set_md(struct config *conf, struct nitem *item) { int rv; + int success = 0; + + if (conf->dryrun) { + printf("chmod %o %s\n", item->mode, item->dest); + if (conf->setuser && conf->setgroup) { + printf("chown %d:%d %s\n", item->uid, item->gid, + item->dest); + } + printf("mtime %.0f %s\n", (double)item->mtime, item->dest); + fflush(stdout); + return success; + } + + rv = chmod(item->dest, item->mode); - rv = chmod(item->path, item->mode); if (rv == -1) { - setsyserr(conf, "can't chmod"); + setsyserr(conf, "can't chmod %o %s", item->mode, item->dest); return conf->errabort; } if (conf->setuser && conf->setgroup) { - rv = chown(item->path, item->uid, item->gid); + rv = chown(item->dest, item->uid, item->gid); if (rv == -1) { setsyserr(conf, "can't chown %s", item->dest); return conf->errabort; @@ -563,7 +588,8 @@ static int set_md(struct config *conf, struct nitem *item) { rv = utimensat(AT_FDCWD, item->dest, item->times, AT_SYMLINK_NOFOLLOW); if (rv == -1) { - setsyserr(conf, "can't set mtime"); + setsyserr(conf, "can't set mtime %.0f %s", (double)item->mtime, + item->dest); return conf->errabort; } return 0; @@ -591,6 +617,20 @@ static int install(struct config *conf, struct nitem *item, unsigned int flags) success = 1; } + if (conf->dryrun) { + if (unlink_file) { + printf("unlink %s\n", item->dest); + } else if (rm_dir) { + printf("rmdir %s\n", item->dest); + } + + printf("install %c%o %d:%d %s -> %s\n", item->ftype, + item->mode, item->uid, item->gid, item->path, + item->dest); + fflush(stdout); + return success; + } + source = conf->src ? conf->src : conf->log; if (unlink_file) { @@ -656,25 +696,15 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { } if (conf->verbose) { - fprintf(stderr, "%d '%c' %s\n", nitem.op, nitem.ftype, + fprintf(stderr, "%s '%c' %s\n", nitem.opstr, nitem.ftype, nitem.dest); } - if (conf->dryrun) { - printf("new %c%o %d:%d %s -> %s\n", nitem.ftype, nitem.mode, - nitem.uid, nitem.gid, nitem.path, nitem.dest); - return 0; - } - unsigned int diffs = file_compare(&nitem, &existing); if (diffs >= D_ERROR) { return seterror(conf, "can't check %s", nitem.dest); } - if (conf->verbose) { - fprintf(stderr, "diffs = %u\n", diffs); - } - /* updates: * exist & same type & md same & hash same: do nothing, but warn bug * exist & same type & md diff & hash same: fix md @@ -773,11 +803,14 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { if (sametype) { if (mdsame && hashsame && (accept || overwrite)) { /* do nothing */ + if (conf->dryrun || conf->verbose) { + fprintf(stderr, "accepting existing file: %s\n", nitem.dest); + } return 0; } if (mdsame && hashsame && !(accept || overwrite)) { /* error */ - return seterror(conf, "bad conditions"); + return seterror(conf, "will not accept or overwrite existing file: %s", nitem.dest); } if (mdsame && !hashsame && overwrite) { /* install */ @@ -787,7 +820,7 @@ 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, accept ? "existing file not acceptable" : "file exists"); + return seterror(conf, "%s (hashdiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); } if (!mdsame && hashsame && overwrite) { /* fix md */ @@ -797,7 +830,7 @@ 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, accept ? "existing file not acceptable" : "file exists"); + return seterror(conf, "%s (mddiff): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); } if (!mdsame && !hashsame && overwrite) { /* install */ @@ -807,7 +840,7 @@ 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, accept ? "existing file not acceptable" : "file exists"); + return seterror(conf, "%s (md+hash): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); } /* TODO error, should be impossible */ return seterror(conf, "impossible state reached"); @@ -816,7 +849,7 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { /* file exists, and is not the same type */ if (!overwrite) { /* error */ - return seterror(conf, accept ? "existing file not acceptable" : "file exists"); + return seterror(conf, "%s (difftype): %s", accept ? "existing file not acceptable" : "file exists", nitem.dest); } /* not the same type, but ok to overwrite */ @@ -843,6 +876,9 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { return seterror(conf, "impossible state 2 reached"); } + /* TODO extra verbose print perms, mtime, etc, probably ls -l + * format + */ if (conf->verbose) { printf("%s\n", nitem.path); } @@ -877,9 +913,6 @@ static void check_conflicts(struct config *conf, char *conflict_type, } sql = sqlite3_str_value(s); - if (conf->verbose > 2) { - fprintf(stderr, "stage query: %s\n", sql); - } rv = zpm_exec(conf->log, sql, callback, conf, &errmsg); @@ -933,9 +966,6 @@ static void runstage(struct config *conf, char *stage, } sql = sqlite3_str_value(s); - if (conf->verbose > 2) { - fprintf(stderr, "stage query: %s\n", sql); - } rv = zpm_exec(conf->log, sql, callback, conf, &errmsg); @@ -954,9 +984,11 @@ static void runstage(struct config *conf, char *stage, conf->log->errmsg ? conf->log->errmsg : "unknown"); conf->errors++; } +#if 0 if (conf->log->errmsg) { fprintf(stderr, "error: %s\n", conf->log->errmsg); } +#endif if (conf->errors && conf->exitonerror) { zpm_close(conf->log); zpm_close(conf->src); @@ -1063,6 +1095,7 @@ int main(int ac, char **av){ conf.errors = 0; conf.exitonerror = 0; check_conflicts(&conf, NULL, report_conflicts); + if (conf.conflicts) { fprintf(stderr, "%d conflicts reported, aborting sync\n", conf.conflicts); @@ -1071,32 +1104,34 @@ int main(int ac, char **av){ /* no point in running it if we're just going to * overwrite everything */ - if (conf.overwrite == 0 || conf.absorb == 0) { + if ((conf.overwrite == 0 || conf.absorb == 0) && !conf.dryrun) { runstage(&conf, "new", check_existing); } if (conf.verbose) { - fprintf(stderr, "beginning sync\n"); + fprintf(stderr, "beginning %ssync\n", conf.dryrun ? + "dryrun " : ""); } /* have to do the removes first otherwise * old files may conflict with update file * type changes */ if (!conf.errors) { - conf.exitonerror = 1; + conf.exitonerror = conf.dryrun ? 0 : 1; + conf.errabort = conf.dryrun ? 0 : 1; conf.reverse = 1; - if (conf.verbose) { - fprintf(stderr, "removing old files\n"); - } + if (conf.verbose) { + fprintf(stderr, "removing old files\n"); + } runstage(&conf, "remove", remove_files); conf.reverse = 0; - if (conf.verbose) { - fprintf(stderr, "updating files\n"); - } + if (conf.verbose) { + fprintf(stderr, "updating files\n"); + } runstage(&conf, "update", install_files); - if (conf.verbose) { - fprintf(stderr, "installing files\n"); - } + if (conf.verbose) { + fprintf(stderr, "installing files\n"); + } runstage(&conf, "new", install_files); } } -- 2.40.0