_q_static int q_vdb_foreach_pkg_sorted(q_vdb_pkg_cb callback, void *priv) { q_vdb_ctx *ctx; q_vdb_cat_ctx *cat_ctx; q_vdb_pkg_ctx *pkg_ctx; int ret = 0; int c, p, cat_cnt, pkg_cnt; struct dirent **cat_de, **pkg_de; ctx = q_vdb_open(); if (!ctx) return EXIT_FAILURE; cat_cnt = scandirat(ctx->vdb_fd, ".", &cat_de, q_vdb_filter_cat, alphasort); for (c = 0; c < cat_cnt; ++c) { cat_ctx = q_vdb_open_cat(ctx, cat_de[c]->d_name); if (!cat_ctx) continue; pkg_cnt = scandirat(ctx->vdb_fd, cat_de[c]->d_name, &pkg_de, q_vdb_filter_pkg, alphasort); for (p = 0; p < pkg_cnt; ++p) { if (pkg_de[p]->d_name[0] == '-') continue; pkg_ctx = q_vdb_open_pkg(cat_ctx, pkg_de[p]->d_name); if (!pkg_ctx) continue; ret |= callback(pkg_ctx, priv); q_vdb_close_pkg(pkg_ctx); } scandir_free(pkg_de, pkg_cnt); q_vdb_close_cat(cat_ctx); } scandir_free(cat_de, cat_cnt); q_vdb_close(ctx); return ret; }
/* process a single dir for cleaning. dir can be a $PKGDIR, $PKGDIR/All/, $PKGDIR/$CAT */ static uint64_t qpkg_clean_dir(char *dirp, set *vdb) { set *ll = NULL; struct dirent **fnames; int i, count; char buf[_Q_PATH_MAX * 2]; struct stat st; uint64_t num_all_bytes = 0; size_t disp_units = 0; char **t; bool ignore; if (dirp == NULL) return 0; if (chdir(dirp) != 0) return 0; if ((count = scandir(".", &fnames, filter_tbz2, alphasort)) < 0) return 0; /* create copy of vdb with only basenames */ for ((void)list_set(vdb, &t); *t != NULL; t++) ll = add_set_unique(basename(*t), ll, &ignore); for (i = 0; i < count; i++) { fnames[i]->d_name[strlen(fnames[i]->d_name)-5] = 0; if (contains_set(fnames[i]->d_name, ll)) continue; snprintf(buf, sizeof(buf), "%s.tbz2", fnames[i]->d_name); if (lstat(buf, &st) != -1) { if (S_ISREG(st.st_mode)) { disp_units = KILOBYTE; if ((st.st_size / KILOBYTE) > 1000) disp_units = MEGABYTE; num_all_bytes += st.st_size; qprintf(" %s[%s%s %3s %s %s%s]%s %s%s/%s%s\n", DKBLUE, NORM, GREEN, make_human_readable_str(st.st_size, 1, disp_units), disp_units == MEGABYTE ? "M" : "K", NORM, DKBLUE, NORM, CYAN, basename(dirp), fnames[i]->d_name, NORM); } if (!pretend) unlink(buf); } } free_set(ll); scandir_free(fnames, count); return num_all_bytes; }
/* process a single dir for cleaning. dir can be a $PKGDIR, $PKGDIR/All/, $PKGDIR/$CAT */ uint64_t qpkg_clean_dir(char *dirp, queue *vdb) { queue *ll; struct dirent **fnames; int i, count; char buf[_Q_PATH_MAX]; struct stat st; uint64_t num_all_bytes = 0; size_t disp_units = 0; if (dirp == NULL) return 0; if (chdir(dirp) != 0) return 0; if ((count = scandir(".", &fnames, filter_tbz2, alphasort)) < 0) return 0; for (i = 0; i < count; i++) { int del = 1; fnames[i]->d_name[strlen(fnames[i]->d_name)-5] = 0; for (ll = vdb; ll != NULL; ll = ll->next) { if (1) { if (strcmp(fnames[i]->d_name, basename(ll->name)) == 0) { del = 0; break; } } } if (!del) continue; snprintf(buf, sizeof(buf), "%s.tbz2", fnames[i]->d_name); if (lstat(buf, &st) != -1) { if (S_ISREG(st.st_mode)) { disp_units = KILOBYTE; if ((st.st_size / KILOBYTE) > 1000) disp_units = MEGABYTE; num_all_bytes += st.st_size; qprintf(" %s[%s%s %3s %s %s%s]%s %s%s/%s%s\n", DKBLUE, NORM, GREEN, make_human_readable_str(st.st_size, 1, disp_units), disp_units == MEGABYTE ? "M" : "K", NORM, DKBLUE, NORM, CYAN, basename(dirp), fnames[i]->d_name, NORM); } if (!pretend) unlink(buf); } } scandir_free(fnames, count); return num_all_bytes; }
/* figure out what dirs we want to process for cleaning and display results. */ static int qpkg_clean(char *dirp) { int i, count; size_t disp_units = 0; uint64_t num_all_bytes; struct dirent **dnames; set *vdb; if (chdir(dirp) != 0) return 1; if ((count = scandir(".", &dnames, filter_hidden, alphasort)) < 0) return 1; vdb = get_vdb_atoms(portroot, portvdb, 1); if (eclean) { size_t n; const char *overlay; array_for_each(overlays, n, overlay) cache_foreach_pkg(portroot, overlay, qpkg_cb, vdb, NULL); } num_all_bytes = qpkg_clean_dir(dirp, vdb); for (i = 0; i < count; i++) { char buf[_Q_PATH_MAX * 2]; snprintf(buf, sizeof(buf), "%s/%s", dirp, dnames[i]->d_name); num_all_bytes += qpkg_clean_dir(buf, vdb); } scandir_free(dnames, count); free_set(vdb); disp_units = KILOBYTE; if ((num_all_bytes / KILOBYTE) > 1000) disp_units = MEGABYTE; qprintf(" %s*%s Total space that would be freed in packages " "directory: %s%s %c%s\n", GREEN, NORM, RED, make_human_readable_str(num_all_bytes, 1, disp_units), disp_units == MEGABYTE ? 'M' : 'K', NORM); return 0; }
/* figure out what dirs we want to process for cleaning and display results. */ int qpkg_clean(char *dirp) { FILE *fp; int i, count; size_t disp_units = 0; uint64_t num_all_bytes; struct dirent **dnames; queue *vdb; vdb = get_vdb_atoms(1); if (chdir(dirp) != 0) { free_sets(vdb); return 1; } if ((count = scandir(".", &dnames, filter_hidden, alphasort)) < 0) { free_sets(vdb); return 1; } if (eclean) { if ((fp = fopen(initialize_ebuild_flat(), "r")) != NULL) { size_t buflen; char *buf; buf = NULL; while (getline(&buf, &buflen, fp) != -1) { char *name, *p; if ((p = strrchr(buf, '.')) == NULL) continue; *p = 0; if ((p = strrchr(buf, '/')) == NULL) continue; *p = 0; name = p + 1; if ((p = strrchr(buf, '/')) == NULL) continue; *p = 0; /* these strcat() are safe. the name is extracted from buf already. */ strcat(buf, "/"); strcat(buf, name); /* num_all_bytes will be off when pretend and eclean are enabled together */ /* vdb = del_set(buf, vdb, &i); */ vdb = add_set(buf, vdb); } free(buf); fclose(fp); } } num_all_bytes = qpkg_clean_dir(dirp, vdb); for (i = 0; i < count; i++) { char buf[_Q_PATH_MAX]; snprintf(buf, sizeof(buf), "%s/%s", dirp, dnames[i]->d_name); num_all_bytes += qpkg_clean_dir(buf, vdb); } scandir_free(dnames, count); free_sets(vdb); disp_units = KILOBYTE; if ((num_all_bytes / KILOBYTE) > 1000) disp_units = MEGABYTE; qprintf(" %s*%s Total space that would be freed in packages directory: %s%s %c%s\n", GREEN, NORM, RED, make_human_readable_str(num_all_bytes, 1, disp_units), disp_units == MEGABYTE ? 'M' : 'K', NORM); return 0; }