/* * Copyright 2005-2014 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 * * Copyright 2005-2010 Ned Ludd - * Copyright 2005-2014 Mike Frysinger - */ #ifdef APPLET_qsize #define QSIZE_FLAGS "fasSmkbi:" COMMON_FLAGS static struct option const qsize_long_opts[] = { {"filesystem", no_argument, NULL, 'f'}, {"all", no_argument, NULL, 'a'}, {"sum", no_argument, NULL, 's'}, {"sum-only", no_argument, NULL, 'S'}, {"megabytes", no_argument, NULL, 'm'}, {"kilobytes", no_argument, NULL, 'k'}, {"bytes", no_argument, NULL, 'b'}, {"ignore", a_argument, NULL, 'i'}, COMMON_LONG_OPTS }; static const char * const qsize_opts_help[] = { "Show size used on disk", "Size all installed packages", "Include a summary", "Show just the summary", "Display size in megabytes", "Display size in kilobytes", "Display size in bytes", "Ignore regexp string", COMMON_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) { q_vdb_ctx *ctx; q_vdb_cat_ctx *cat_ctx; q_vdb_pkg_ctx *pkg_ctx; int i; char search_all = 0; struct stat st; char fs_size = 0, summary = 0, summary_only = 0; size_t num_all_files, num_all_nonfiles, num_all_ignored; 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; char filename[_Q_PATH_MAX], *filename_root; queue *ignore_regexp = NULL; DBG("argc=%d argv[0]=%s argv[1]=%s", argc, argv[0], argc > 1 ? argv[1] : "NULL?"); while ((i = GETOPT_LONG(QSIZE, qsize, "")) != -1) { switch (i) { COMMON_GETOPTS_CASES(qsize) case 'f': fs_size = 1; break; case 'a': search_all = 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 'i': ignore_regexp = add_set(optarg, optarg, ignore_regexp); break; } } if ((argc == optind) && !search_all) qsize_usage(EXIT_FAILURE); num_all_bytes = num_all_files = num_all_nonfiles = num_all_ignored = 0; strcpy(filename, portroot); filename_root = filename + strlen(filename); 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; /* see if this cat/pkg is requested */ if (!search_all) { for (i = optind; i < argc; ++i) { snprintf(buf, buflen, "%s/%s", catname, pkgname); if (rematch(argv[i], buf, REG_EXTENDED) == 0) break; if (rematch(argv[i], pkgname, REG_EXTENDED) == 0) break; } if (i == argc) 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; queue *ll; int ok = 0; e = contents_parse_line(buf); if (!e) continue; for (ll = ignore_regexp; ll != NULL; ll = ll->next) { if (rematch(ll->name, e->name, REG_EXTENDED) == 0) { num_ignored += 1; ok = 1; } } if (ok) continue; if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { strcpy(filename_root, e->name); ++num_files; if (!lstat(filename, &st)) 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: %'lu files, %'lu non-files, ", BOLD, catname, BLUE, pkgname, NORM, (unsigned long)num_files, (unsigned long)num_nonfiles); if (num_ignored) printf("%'lu names-ignored, ", (unsigned long)num_ignored); if (disp_units) printf("%s %s\n", make_human_readable_str(num_bytes, 1, disp_units), str_disp_units); else printf("%'lu%s%lu KiB\n", (unsigned long)(num_bytes / KILOBYTE), decimal_point, (unsigned long)(((num_bytes%KILOBYTE)*1000)/KILOBYTE)); } next_pkg: q_vdb_close_pkg(pkg_ctx); } } if (summary) { printf(" %sTotals%s: %'lu files, %'lu non-files, ", BOLD, NORM, (unsigned long)num_all_files, (unsigned long)num_all_nonfiles); if (num_all_ignored) printf("%'lu names-ignored, ", (unsigned long)num_all_ignored); if (disp_units) printf("%s %s\n", make_human_readable_str(num_all_bytes, 1, disp_units), str_disp_units); else printf("%'lu%s%lu MiB\n", (unsigned long)(num_all_bytes / MEGABYTE), decimal_point, (unsigned long)(((num_all_bytes%MEGABYTE)*1000)/MEGABYTE)); } free_sets(ignore_regexp); return EXIT_SUCCESS; } #else DEFINE_APPLET_STUB(qsize) #endif