commit: 704d05c0829aaf03abb95273308116786046b891 Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> AuthorDate: Mon Feb 22 18:28:25 2016 +0000 Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> CommitDate: Mon Feb 22 18:28:25 2016 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=704d05c0
qsize: rework code to use vdb callbacks This helps reduce some of the boiler plate code for vdb walking. There should be no real functional changes. qsize.c | 268 +++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 145 insertions(+), 123 deletions(-) diff --git a/qsize.c b/qsize.c index 2df2fce..db00247 100644 --- a/qsize.c +++ b/qsize.c @@ -31,37 +31,143 @@ static const char * const qsize_opts_help[] = { }; #define qsize_usage(ret) usage(ret, QSIZE_FLAGS, qsize_long_opts, qsize_opts_help, lookup_applet_idx("qsize")) -int qsize_main(int argc, char **argv) +struct qsize_opt_state { + array_t *atoms; + char **argv; + char search_all; + char fs_size; + char summary; + char summary_only; + size_t disp_units; + const char *str_disp_units; + array_t *ignore_regexp; + + size_t buflen; + char *buf; + + size_t num_all_files, num_all_nonfiles, num_all_ignored; + uint64_t num_all_bytes; +}; + +_q_static int qsize_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv) { - q_vdb_ctx *ctx; - q_vdb_cat_ctx *cat_ctx; - q_vdb_pkg_ctx *pkg_ctx; + struct qsize_opt_state *state = priv; + const char *catname = pkg_ctx->cat_ctx->name; + const char *pkgname = pkg_ctx->name; size_t i; - char fs_size = 0, summary = 0, summary_only = 0; - size_t num_all_files, num_all_nonfiles, num_all_ignored; + depend_atom *atom; + FILE *fp; size_t num_files, num_nonfiles, num_ignored; - uint64_t num_all_bytes, num_bytes; - size_t disp_units = 0; - const char *str_disp_units = NULL; - size_t buflen; - char *buf; + uint64_t num_bytes; + bool showit = false; + + /* see if this cat/pkg is requested */ + if (array_cnt(state->atoms)) { + depend_atom *qatom; + + snprintf(state->buf, state->buflen, "%s/%s", catname, pkgname); + qatom = atom_explode(state->buf); + array_for_each(state->atoms, i, atom) + if (atom_compare(atom, qatom) == EQUAL) { + showit = true; + break; + } + atom_implode(qatom); + } else + showit = true; + if (!showit) + return EXIT_SUCCESS; + + if ((fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS")) == NULL) + return EXIT_SUCCESS; + + num_ignored = num_files = num_nonfiles = num_bytes = 0; + while (getline(&state->buf, &state->buflen, fp) != -1) { + contents_entry *e; + regex_t *regex; + int ok = 0; + + e = contents_parse_line(state->buf); + if (!e) + continue; + + array_for_each(state->ignore_regexp, i, regex) + if (!regexec(regex, state->buf, 0, NULL, 0)) { + num_ignored += 1; + ok = 1; + } + if (ok) + continue; + + if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { + struct stat st; + ++num_files; + if (!fstatat(pkg_ctx->cat_ctx->ctx->portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) + num_bytes += (state->fs_size ? st.st_blocks * S_BLKSIZE : st.st_size); + } else + ++num_nonfiles; + } + fclose(fp); + state->num_all_bytes += num_bytes; + state->num_all_files += num_files; + state->num_all_nonfiles += num_nonfiles; + state->num_all_ignored += num_ignored; + + if (!state->summary_only) { + printf("%s%s/%s%s%s: %'zu files, %'zu non-files, ", BOLD, + catname, BLUE, pkgname, NORM, + num_files, num_nonfiles); + if (num_ignored) + printf("%'zu names-ignored, ", num_ignored); + if (state->disp_units) + printf("%s %s\n", + make_human_readable_str(num_bytes, 1, state->disp_units), + state->str_disp_units); + else + printf("%'"PRIu64"%s%"PRIu64" KiB\n", + num_bytes / KILOBYTE, + decimal_point, + ((num_bytes % KILOBYTE) * 1000) / KILOBYTE); + } + + return EXIT_SUCCESS; +} + +int qsize_main(int argc, char **argv) +{ + size_t i; + int ret; + DECLARE_ARRAY(ignore_regexp); depend_atom *atom; DECLARE_ARRAY(atoms); - DECLARE_ARRAY(ignore_regexp); + struct qsize_opt_state state = { + .atoms = atoms, + .search_all = 0, + .fs_size = 0, + .summary = 0, + .summary_only = 0, + .disp_units = 0, + .str_disp_units = NULL, + .ignore_regexp = ignore_regexp, + .num_all_bytes = 0, + .num_all_files = 0, + .num_all_nonfiles = 0, + .num_all_ignored = 0, + }; while ((i = GETOPT_LONG(QSIZE, qsize, "")) != -1) { switch (i) { COMMON_GETOPTS_CASES(qsize) - case 'f': fs_size = 1; break; - case 's': summary = 1; break; - case 'S': summary = summary_only = 1; break; - case 'm': disp_units = MEGABYTE; str_disp_units = "MiB"; break; - case 'k': disp_units = KILOBYTE; str_disp_units = "KiB"; break; - case 'b': disp_units = 1; str_disp_units = "bytes"; break; + case 'f': state.fs_size = 1; break; + case 's': state.summary = 1; break; + case 'S': state.summary = state.summary_only = 1; break; + case 'm': state.disp_units = MEGABYTE; state.str_disp_units = "MiB"; break; + case 'k': state.disp_units = KILOBYTE; state.str_disp_units = "KiB"; break; + case 'b': state.disp_units = 1; state.str_disp_units = "bytes"; break; case 'i': { regex_t regex; xregcomp(®ex, optarg, REG_EXTENDED|REG_NOSUB); - xarraypush(ignore_regexp, ®ex, sizeof(regex)); + xarraypush(state.ignore_regexp, ®ex, sizeof(regex)); break; } } @@ -74,121 +180,37 @@ int qsize_main(int argc, char **argv) if (!atom) warn("invalid atom: %s", argv[i]); else - xarraypush_ptr(atoms, atom); + xarraypush_ptr(state.atoms, atom); } - num_all_bytes = num_all_files = num_all_nonfiles = num_all_ignored = 0; - - buflen = _Q_PATH_MAX; - buf = xmalloc(buflen); - - ctx = q_vdb_open(); - if (!ctx) - return EXIT_FAILURE; - - /* open /var/db/pkg */ - while ((cat_ctx = q_vdb_next_cat(ctx))) { - /* open the cateogry */ - const char *catname = cat_ctx->name; - while ((pkg_ctx = q_vdb_next_pkg(cat_ctx))) { - const char *pkgname = pkg_ctx->name; - FILE *fp; - bool showit = false; - - /* see if this cat/pkg is requested */ - if (array_cnt(atoms)) { - depend_atom *qatom; - - snprintf(buf, buflen, "%s/%s", catname, pkgname); - qatom = atom_explode(buf); - array_for_each(atoms, i, atom) - if (atom_compare(atom, qatom) == EQUAL) { - showit = true; - break; - } - atom_implode(qatom); - } else - showit = true; - if (!showit) - goto next_pkg; - - if ((fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS")) == NULL) - goto next_pkg; - - num_ignored = num_files = num_nonfiles = num_bytes = 0; - while (getline(&buf, &buflen, fp) != -1) { - contents_entry *e; - regex_t *regex; - int ok = 0; - - e = contents_parse_line(buf); - if (!e) - continue; - - array_for_each(ignore_regexp, i, regex) - if (!regexec(regex, buf, 0, NULL, 0)) { - num_ignored += 1; - ok = 1; - } - if (ok) - continue; - - if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { - struct stat st; - ++num_files; - if (!fstatat(ctx->portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) - num_bytes += (fs_size ? st.st_blocks * S_BLKSIZE : st.st_size); - } else - ++num_nonfiles; - } - fclose(fp); - num_all_bytes += num_bytes; - num_all_files += num_files; - num_all_nonfiles += num_nonfiles; - num_all_ignored += num_ignored; - - if (!summary_only) { - printf("%s%s/%s%s%s: %'zu files, %'zu non-files, ", BOLD, - catname, BLUE, pkgname, NORM, - num_files, num_nonfiles); - if (num_ignored) - printf("%'zu names-ignored, ", num_ignored); - if (disp_units) - printf("%s %s\n", - make_human_readable_str(num_bytes, 1, disp_units), - str_disp_units); - else - printf("%'"PRIu64"%s%"PRIu64" KiB\n", - num_bytes / KILOBYTE, - decimal_point, - ((num_bytes % KILOBYTE) * 1000) / KILOBYTE); - } + state.buflen = _Q_PATH_MAX; + state.buf = xmalloc(state.buflen); - next_pkg: - q_vdb_close_pkg(pkg_ctx); - } - } + ret = q_vdb_foreach_pkg(qsize_cb, &state, NULL); - if (summary) { + if (state.summary) { printf(" %sTotals%s: %'zu files, %'zu non-files, ", BOLD, NORM, - num_all_files, num_all_nonfiles); - if (num_all_ignored) - printf("%'zu names-ignored, ", num_all_ignored); - if (disp_units) + state.num_all_files, state.num_all_nonfiles); + if (state.num_all_ignored) + printf("%'zu names-ignored, ", state.num_all_ignored); + if (state.disp_units) printf("%s %s\n", - make_human_readable_str(num_all_bytes, 1, disp_units), - str_disp_units); + make_human_readable_str(state.num_all_bytes, 1, state.disp_units), + state.str_disp_units); else printf("%'"PRIu64"%s%"PRIu64" MiB\n", - num_all_bytes / MEGABYTE, + state.num_all_bytes / MEGABYTE, decimal_point, - ((num_all_bytes % MEGABYTE) * 1000) / MEGABYTE); + ((state.num_all_bytes % MEGABYTE) * 1000) / MEGABYTE); } - array_for_each(atoms, i, atom) + + array_for_each(state.atoms, i, atom) atom_implode(atom); - xarrayfree_int(atoms); - xarrayfree(ignore_regexp); - return EXIT_SUCCESS; + xarrayfree_int(state.atoms); + xarrayfree(state.ignore_regexp); + free(state.buf); + + return ret; } #else