tDelete packages from the system - pm - barely a pack manager
(HTM) git clone git://z3bra.org/pm
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 413bad1d1c122485dea24f1d3d70b08469225013
(DIR) parent b1f152ac97a08e6bc3c5c401a36228643ce77672
(HTM) Author: z3bra <willyatmailoodotorg>
Date: Wed, 30 Dec 2015 15:45:37 +0100
Delete packages from the system
Diffstat:
M pm.c | 130 ++++++++++++++++++++++++++++---
1 file changed, 119 insertions(+), 11 deletions(-)
---
(DIR) diff --git a/pm.c b/pm.c
t@@ -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,
t@@ -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);
t@@ -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);
t@@ -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
*/
t@@ -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;
}
t@@ -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)
{
t@@ -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);
t@@ -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;
t@@ -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: