X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-syncfs.c;h=3c0eebb0ff84bc43175d528f13e08c79e0514ce6;hb=4b853577a65802c130837d9a9669ca3e4413dee8;hp=aac86b576c4a0dc33fa942fc742eb89a3d93e579;hpb=17744ae701e5a543ee6fe0d752330f1bbef56a42;p=zpackage diff --git a/zpm-syncfs.c b/zpm-syncfs.c index aac86b5..3c0eebb 100644 --- a/zpm-syncfs.c +++ b/zpm-syncfs.c @@ -32,6 +32,9 @@ struct config { int reverse, exitonerror; int overwrite, accept, acceptdir, ignoredirmd; int ops_total, ops_completed; + int ops_remove, ops_remove_completed; + int ops_update, ops_update_completed; + int ops_install, ops_install_completed; int progress; /* type of progress meter */ }; @@ -57,6 +60,18 @@ static void usage() { printf("usage: zpm $scriptname [-fncC] args ...\n"); } +static void pdots(int len, int ch, int was, int now, int total) { + was = len * was / total; + if (now > total) { + now = total; + } + now = len * now / total; + while (was++ < now) { + putchar(ch); + } + fflush(stdout); +} + static int seterror(struct config *conf, char *msgfmt, ...) { char msg[1024]; va_list ap; @@ -613,8 +628,31 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { return 0; } + if (conf->verbose) { + if (conf->progress == 2) { + fprintf(stderr, "%s(%s)\n", flags ? "rmdir" : "unlink", dest); + } else if (conf->progress == 1) { + /* overwrite */ + pdots(50, '.', conf->ops_completed, conf->ops_completed + 1, conf->ops_total); + conf->ops_completed++; + conf->ops_completed++; + } else { + pdots(50, '.', conf->ops_completed, conf->ops_completed + 1, conf->ops_total); + conf->ops_completed++; + } + } + + errno = 0; + if (lstat(dest, &st) == -1) { - return seterror(conf,"can't stat"); + switch (errno) { + case ENOENT: + /* TODO chatter if verbose */ + break; + default: + return seterror(conf, "can't stat %s: %s", dest, strerror(errno)); + } + return 0; } if (S_ISDIR(st.st_mode)) { @@ -622,9 +660,6 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { } /* TODO check that expected filetype matches actual filetype */ - if (conf->verbose) { - fprintf(stderr, "%s(%s)\n", flags ? "rmdir" : "unlink", dest); - } errno = 0; @@ -632,8 +667,12 @@ static int remove_files(void *f, int ncols, char **vals, char **cols) { switch (errno) { case ENOENT: break; + case ENOTEMPTY: /* fall through */ + case EEXIST: + /* TODO chatter, or possibly require */ + break; default: - return seterror(conf, "can't unlink"); + return seterror(conf, "can't unlink %s: %s", dest, strerror(errno)); } } @@ -682,6 +721,17 @@ static int set_md(struct config *conf, struct nitem *item) { return success; } + if (conf->setuser && conf->setgroup) { + rv = lchown(item->dest, item->uid, item->gid); + if (rv == -1) { + setsyserr(conf, "can't lchown %s", item->dest); + return conf->errabort; + } + } + + /* have to chmod after the chown, setuid bits may (and will) + * be cleared after a chown + */ /* can't chmod a symlink */ if (item->ftype != 'l') { rv = chmod(item->dest, item->mode); @@ -692,13 +742,6 @@ static int set_md(struct config *conf, struct nitem *item) { } } - if (conf->setuser && conf->setgroup) { - rv = lchown(item->dest, item->uid, item->gid); - if (rv == -1) { - setsyserr(conf, "can't lchown %s", item->dest); - return conf->errabort; - } - } rv = utimensat(AT_FDCWD, item->dest, item->times, AT_SYMLINK_NOFOLLOW); if (rv == -1) { @@ -775,16 +818,11 @@ static int install(struct config *conf, struct nitem *item, unsigned int flags) } } - if (item->ftype == 'r') { - rv = zpm_extract(source, item->hash, item->dest, item->mode); - if (rv == 0) { - seterror(conf, "can't extract %s", item->dest); - return failure; - } - return success; - } - + errno = 0; switch (item->ftype) { + case 'r': rv = zpm_extract(source, item->hash, item->dest, item->mode); + if (rv == 0) rv = -1; + break; case 'd': rv = mkdir(item->dest, item->mode); break; case 'l': rv = symlink(item->target, item->dest); @@ -794,6 +832,17 @@ static int install(struct config *conf, struct nitem *item, unsigned int flags) } if (rv == -1) { + switch (item->ftype) { + case 'r': + seterror(conf, "can't extract %s", item->dest); + break; + case 'd': + setsyserr(conf, "install mkdir(\"%s\") failed", item->dest); + break; + case 'l': + setsyserr(conf, "install symlink(\"%s\") failed", item->dest); + break; + } setsyserr(conf, "installing %s failed", item->dest); return failure; } @@ -946,20 +995,11 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { nitem.dest); } else if (conf->progress == 1) { /* overwrite */ - /* one dot per 2% */ - int was = 50 * conf->ops_completed / conf->ops_total; - int now = 50 * (conf->ops_completed+1) / conf->ops_total; - while (was++ < now) { - fprintf(stderr, "."); - } + pdots(50, '.', conf->ops_completed, conf->ops_completed + 1, conf->ops_total); + conf->ops_completed++; conf->ops_completed++; } else { - /* one dot per 2% */ - int was = 50 * conf->ops_completed / conf->ops_total; - int now = 50 * (conf->ops_completed+1) / conf->ops_total; - while (was++ < now) { - fprintf(stderr, "."); - } + pdots(50, '.', conf->ops_completed, conf->ops_completed + 1, conf->ops_total); conf->ops_completed++; } } @@ -1321,8 +1361,11 @@ static void runstage(struct config *conf, char *stage, /* TODO final report function in conf var */ } -static int count_ops(struct config *conf) { - return zpm_db_int(conf->log, "select count(*) from syncinfo where op in ('remove', 'update', 'new')"); +static void count_ops(struct config *conf) { + conf->ops_remove = zpm_db_int(conf->log, "select count(*) from syncinfo where op = 'remove'"); + conf->ops_update = zpm_db_int(conf->log, "select count(*) from syncinfo where op = 'update'"); + conf->ops_install = zpm_db_int(conf->log, "select count(*) from syncinfo where op = 'new'"); + conf->ops_total = conf->ops_remove + conf->ops_update + conf->ops_install; } int main(int ac, char **av) { @@ -1452,25 +1495,48 @@ int main(int ac, char **av) { if (!conf.errors) { conf.exitonerror = conf.dryrun ? 0 : 1; conf.errabort = conf.dryrun ? 0 : 1; - conf.reverse = 1; - conf.ops_total = count_ops(&conf); + count_ops(&conf); fprintf(stderr, "file ops: %d\n", conf.ops_total); - 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.ops_remove > 0) { + if (conf.verbose) { + fprintf(stderr, "removing %d file%s\n", conf.ops_remove, conf.ops_remove > 0 ? "s" : ""); + } + conf.reverse = 1; + conf.ops_completed = 0; + conf.ops_total = conf.ops_remove; + runstage(&conf, "remove", remove_files); + if (conf.verbose && conf.progress < 2) { + fprintf(stderr, " done\n"); + fflush(stderr); + } } - runstage(&conf, "update", install_files); - if (conf.verbose) { - fprintf(stderr, "installing %d files\n", conf.ops_total); + + if (conf.ops_update > 0) { + if (conf.verbose) { + fprintf(stderr, "updating %d file%s\n", conf.ops_update, conf.ops_update > 0 ? "s" : ""); + } + conf.reverse = 0; + conf.ops_completed = 0; + conf.ops_total = conf.ops_update; + runstage(&conf, "update", install_files); + if (conf.verbose && conf.progress < 2) { + fprintf(stderr, " done\n"); + fflush(stderr); + } } - runstage(&conf, "new", install_files); - if (conf.verbose && conf.progress < 2) { - fprintf(stderr, " done\n"); - fflush(stderr); + + if (conf.ops_install > 0) { + if (conf.verbose) { + fprintf(stderr, "installing %d file%s\n", conf.ops_install, conf.ops_install > 0 ? "s" : ""); + } + conf.reverse = 0; + conf.ops_completed = 0; + conf.ops_total = conf.ops_install; + runstage(&conf, "new", install_files); + if (conf.verbose && conf.progress < 2) { + fprintf(stderr, " done\n"); + fflush(stderr); + } } } }