pm

barely a pack manager
git clone git://z3bra.org/pm
Log | Files | Refs | README | LICENSE

commit 413bad1d1c122485dea24f1d3d70b08469225013
parent b1f152ac97a08e6bc3c5c401a36228643ce77672
Author: z3bra <willyatmailoodotorg>
Date:   Wed Dec 30 15:45:37 2015

Delete packages from the system

Diffstat:
 pm.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 119 insertions(+), 11 deletions(-)

diff --git a/pm.c b/pm.c @@ -27,7 +27,7 @@ struct pkg { /* possible actions */ enum { ACTION_INSTALL = 0, - ACTION_REMOVE = 1, + ACTION_DELETE = 1, ACTION_UPDATE = 2, ACTION_INSPECT = 3, ACTION_LIST_FILES = 4, @@ -46,6 +46,7 @@ enum { }; void usage(char *name); +int d_empty(char *dir); int p_mkdir(char *dir, mode_t mode); char *base_name(char *path); int inspect(int fd, char *filename); @@ -53,6 +54,8 @@ int list_local(const char *datadir); int metadata(char *datadir, char *filename); int pack(char *out, char **filename); int unpack(char *root, char *in); +int delete_content(FILE *metafile); +int delete(const char *datadir, const char *rootfs, const char *name); struct pkg *pack_load_file(char *file); struct pkg *pack_load(char *name); @@ -65,6 +68,29 @@ usage(char *name) } /* + * returns 0 if a directory is empty, -1 otherwise + */ +int +d_empty(char *dir) +{ + DIR *d; + struct dirent *p; + + if (!(d = opendir(dir))) { + perror("opendir"); + return -1; + } + + while ((p = readdir(d))) + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { + closedir(d); + return -1; + } + + return 0; +} + +/* * recursive mkdir, taken from the ii project * http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html */ @@ -146,6 +172,7 @@ list_local(const char *datadir) if (strcmp(p->d_name, ".") && strcmp(p->d_name, "..")) printf("%s\n", p->d_name); + closedir(d); return 0; } @@ -295,6 +322,77 @@ unpack(char *root, char *in) return 0; } +/* + * Delete entries listed in a file recursively + * This will also remove directories if they are empty + */ +int +delete_content(FILE *f) +{ + char file[PATH_MAX]; + struct stat st; + size_t len; + + if (fgets(file, PATH_MAX, f)) + delete_content(f); + + /* remove trailing '\n' */ + len = strnlen(file, PATH_MAX); + file[len - 1] = 0; + len--; + + /* remove potential trailing '/' */ + if (file[len - 1] == '/') { + file[len - 1] = 0; + len--; + } + + stat(file, &st); + if (S_ISDIR(st.st_mode) && d_empty(file)) + rmdir(file); + else + unlink(file); + + return 0; +} + +/* + * Delete all files related to a package. Installed files, but also metadata + */ +int +delete(const char *datadir, const char *rootfs, const char *name) +{ + char *cwd; + FILE *f; + char meta[PATH_MAX]; + + snprintf(meta, PATH_MAX, "%s/%s/files", datadir, name); + + if ((f = fopen(meta, "r")) == NULL) { + perror("fopen"); + return -1; + } + + /* hack to allow relative path for metadata */ + cwd = getcwd(NULL, PATH_MAX); + if (chdir(rootfs) < 0) { + perror("chdir"); + return -1; + } + + delete_content(f); + fclose(f); + + /* hack again */ + chdir(cwd); + + unlink(meta); + snprintf(meta, PATH_MAX, "%s/%s", datadir, name); + rmdir(meta); + + return 0; +} + struct pkg * pack_load_file(char *path) { @@ -342,6 +440,8 @@ pack_load(char *name) if (strchr(name, '/')) p = pack_load_file(name); + else + return NULL; if (!p) { fprintf(stderr, "could not load package %s\n", name); @@ -355,7 +455,7 @@ pack_load(char *name) int main (int argc, char **argv) { - char *fn = NULL; + char *n = NULL; struct pkg *p = NULL; uint8_t action = ACTION_INVALID; @@ -364,45 +464,53 @@ main (int argc, char **argv) if (argc <3) /* what a cute variable */ usage(argv0); action = ACTION_PACKAGE; - fn = ARGF(); + n = ARGF(); break; case 'a': action = ACTION_INSTALL; - fn = EARGF(usage(argv0)); + n = EARGF(usage(argv0)); break; case 'i': action = ACTION_INSPECT; - fn = EARGF(usage(argv0)); + n = EARGF(usage(argv0)); break; case 'l': action = ACTION_LIST_LOCAL; break; + case 'r': + action = ACTION_DELETE; + n = EARGF(usage(argv0)); + break; case 'h': default: usage(argv0); return 0; }ARGEND; - if (fn) { - p = pack_load(fn); - if (!p) - return ERR_PACKAGE_LOAD; - } + if (n) + p = pack_load(n); switch (action) { case ACTION_INSTALL: + if (!p) + return ERR_PACKAGE_LOAD; if (metadata(PACKAGE_DATA, p->path) == 0) return unpack(PACKAGE_ROOT, p->path); fprintf(stderr, "could not write metadata for %s\n", p->name); return ERR_METADATA; case ACTION_INSPECT: + if (!p) + return ERR_PACKAGE_LOAD; return inspect(1, p->path); case ACTION_PACKAGE: + if (!p) + return ERR_PACKAGE_LOAD; return pack(p->path, argv); case ACTION_LIST_LOCAL: return list_local(PACKAGE_DATA); + case ACTION_DELETE: + return delete(PACKAGE_DATA, PACKAGE_ROOT, n); /* handle me, Octave */ - case ACTION_REMOVE: case ACTION_UPDATE: case ACTION_LIST_FILES: case ACTION_LIST_DEPS: