tClean pack from syystem if update fails - pm - barely a pack manager
(HTM) git clone git://z3bra.org/pm
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 11ca8f6728acf195601b904ac0c90cbfff2f2f8f
(DIR) parent 714472bbfbcc98d91cd52a7ebc7ca205a0601666
(HTM) Author: z3bra <willyatmailoodotorg>
Date: Wed, 22 Jun 2016 09:54:01 +0200
Clean pack from syystem if update fails
Packs should not be left "half-installed". In case the update fails during
installation, the pack will simply be removed from the system.
This commit also fixes a few cases where mmap() would fail, and put metadata
removal in its own function, for easier use.
Diffstat:
M pm.c | 116 ++++++++++++++++++++++---------
1 file changed, 82 insertions(+), 34 deletions(-)
---
(DIR) diff --git a/pm.c b/pm.c
t@@ -68,6 +68,7 @@ int pack_extract(const char *rootfs, const char *datadir, struct pack *p);
int pack_install(const char *rootfs, const char *datadir, struct pack *p);
int pack_delete(const char *rootfs, const char *datadir, struct pack *p);
+int inspect_installed(const char *datadir, const char *name);
int inspect_version(const char *datadir, const char *name, char version[]);
int inspect_collision(const char *rootfs, struct pack *p);
int inspect_files(int fd, const char *datadir, const char *name);
t@@ -77,6 +78,7 @@ int write_metadata(const char *datadir, struct pack *pack);
int write_entry(struct archive *a, struct archive *w);
int delete_node(char *path);
int delete_content(const char *rootfs, char *map, size_t size);
+int delete_metadata(const char *datadir, char *name);
/* action wrappers around CLI arguments */
int install(const char *rootfs, const char *datadir, char *path);
t@@ -236,13 +238,12 @@ pack_load_tarball(char *path)
struct pack *
pack_load_metadata(const char *datadir, char *name)
{
- struct stat st;
struct pack *pack = NULL;
char tmp[PATH_MAX] = "";
snprintf(tmp, PATH_MAX, "%s/%s", datadir, name);
- if (stat(tmp, &st) < 0) {
+ if (inspect_installed(datadir, name)) {
fprintf(stderr, "%s: No such pack installed\n", name);
return NULL;
}
t@@ -315,6 +316,7 @@ pack_extract(const char *rootfs, const char *datadir, struct pack *p)
if ((r = archive_read_open_filename(a, p->path, 0)) != ARCHIVE_OK) {
fprintf(stderr, "%s: %s\n", p->path, archive_error_string(a));
archive_read_free(a);
+ close(fd);
return r;
}
t@@ -347,6 +349,7 @@ pack_extract(const char *rootfs, const char *datadir, struct pack *p)
dprintf(fd, "%s\n", archive_entry_pathname(e));
archive_write_finish_entry(w);
}
+ close(fd);
chdir(cwd);
archive_write_free(w);
t@@ -399,14 +402,14 @@ pack_install(const char *rootfs, const char *datadir, struct pack *p)
int
pack_delete(const char *rootfs, const char *datadir, struct pack *p)
{
- int fd;
+ int fd, r = 0;
char *addr = NULL;
char tmp[PATH_MAX];
struct stat st;
snprintf(tmp, PATH_MAX, "%s/%s/files", datadir, p->name);
- if (stat(tmp, &st) < 0 && errno == ENOENT) {
- fprintf(stderr, "%s: No installed files\n", p->name);
+ if (stat(tmp, &st) < 0) {
+ perror(tmp);
return -1;
}
if ((fd = open(tmp, O_RDONLY)) < 0) {
t@@ -414,42 +417,46 @@ pack_delete(const char *rootfs, const char *datadir, struct pack *p)
return ERR_DELETE;
}
- addr = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (addr == MAP_FAILED) {
- perror(tmp);
- close(fd);
- }
-
- log(LOG_VERBOSE, "deleting installed files\n");
- /* ignore errors so everything gets deleted */
- if (delete_content(rootfs, addr, st.st_size) < 0) {
- fprintf(stderr, "%s: Pack removal failed\n", p->name);
- close(fd);
- return ERR_DELETE;
+ if (st.st_size > 0) {
+ addr = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED) {
+ perror("mmap");
+ close(fd);
+ return ERR_DELETE;
+ }
+
+ log(LOG_VERBOSE, "deleting installed files\n");
+ /* ignore errors so everything gets deleted */
+ if (delete_content(rootfs, addr, st.st_size) < 0) {
+ fprintf(stderr, "%s: Pack removal failed\n", p->name);
+ close(fd);
+ r = ERR_DELETE;
+ }
+ munmap(addr, st.st_size);
}
close(fd);
log(LOG_VERBOSE, "cleaning metadata\n");
- log(LOG_DEBUG, "- %s\n", tmp);
- if (unlink(tmp) < 0) {
- perror(tmp);
- return ERR_DELETE;
+ if (delete_metadata(datadir, p->name) < 0) {
+ fprintf(stderr, "%s: Metadata removal failed\n", p->name);
+ r = ERR_DELETE;
}
- snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, p->name);
+ return r;
+}
- log(LOG_DEBUG, "- %s\n", tmp);
- if (unlink(tmp) < 0) {
- perror(tmp);
- return ERR_DELETE;
- }
- /* remove metadata directory, no matter what */
- snprintf(tmp, PATH_MAX, "%s/%s", datadir, p->name);
- log(LOG_DEBUG, "- %s\n", tmp);
- rmdir(tmp);
+/*
+ * Returns 0 if "name" is installed, non-zero otherwise
+ */
+int
+inspect_installed(const char *datadir, const char *name)
+{
+ char tmp[PATH_MAX] = "";
+ struct stat st;
- return 0;
+ snprintf(tmp, PATH_MAX, "%s/%s", datadir, name);
+ return stat(tmp, &st) || S_ISDIR(st.st_mode);
}
t@@ -507,7 +514,7 @@ inspect_collision(const char *rootfs, struct pack *p)
while (archive_read_next_header(a, &e) == ARCHIVE_OK) {
if (stat(archive_entry_pathname(e), &st) == 0 && !S_ISDIR(st.st_mode)) {
fprintf(stderr, "%s: File exists\n", archive_entry_pathname(e));
- r = -1;
+ r++;
break;
}
archive_read_data_skip(a);
t@@ -724,6 +731,32 @@ delete_content(const char *rootfs, char *map, size_t size)
/*
+ * Delete the metadata stored for a given pack name
+ */
+int
+delete_metadata(const char *datadir, char *name)
+{
+ int i;
+ char path[PATH_MAX] = "";
+ char *meta[] = { "files", "version", NULL };
+
+ for (i = 0; meta[i] != NULL; i++) {
+ snprintf(path, PATH_MAX, "%s/%s/%s", datadir, name, meta[i]);
+ log(LOG_DEBUG, "- %s\n", path);
+ if (unlink(path) < 0) {
+ perror(path);
+ return ERR_DELETE;
+ }
+ }
+
+ /* remove metadata directory, no matter what */
+ snprintf(path, PATH_MAX, "%s/%s", datadir, name);
+ log(LOG_DEBUG, "- %s\n", path);
+ return rmdir(path);
+}
+
+
+/*
* Install a pack from the given path. This wraps load/install of a pack
*/
int
t@@ -760,6 +793,12 @@ update(const char *rootfs, const char *datadir, char *path)
if ((p = pack_load_tarball(path)) == NULL)
return ERR_PACK_LOAD;
+ if (inspect_installed(datadir, p->name)) {
+ fprintf(stderr, "%s: No such pack installed\n", p->name);
+ pack_free(p);
+ return ERR_DELETE;
+ }
+
if (pack_delete(rootfs, datadir, p) != 0)
return ERR_DELETE;
t@@ -767,8 +806,12 @@ update(const char *rootfs, const char *datadir, char *path)
r += pack_install(rootfs, datadir, p);
overwrite = tmp;
- if (r == 0)
+ if (r == 0) {
log(LOG_INFO, "updated %s to %s\n", p->name, p->version);
+ } else {
+ fprintf(stderr, "%s: Update failed. Cleaning filesystem\n", p->name);
+ pack_delete(rootfs, datadir, p);
+ }
pack_free(p);
t@@ -785,6 +828,11 @@ delete(const char *rootfs, const char *datadir, char *name)
int r = 0;
struct pack *p = NULL;
+ if (inspect_installed(datadir, name)) {
+ fprintf(stderr, "%s: No such pack installed\n", name);
+ return ERR_DELETE;
+ }
+
if ((p = pack_load_metadata(datadir, name)) == NULL)
return ERR_PACK_LOAD;