pm

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

commit ce53dfcafe58e9315780df8764352dfb85df965f
parent 8ac938b57e4fe44d05aa7662a32e21939291f555
Author: z3bra <willyatmailoodotorg>
Date:   Sat Jun 18 22:40:19 +0200

Make prototype/function declaration consistent

Diffstat:
pm.c | 712++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 359 insertions(+), 353 deletions(-)
diff --git a/pm.c b/pm.c @@ -64,18 +64,17 @@ struct pack *pack_load_tarball(char *path); struct pack *pack_load_directory(const char *datadir, char *path); struct pack *pack_load(const char *datadir, char *path); void pack_free(struct pack *p); +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_version(const char *datadir, const char *name, char version[]); int inspect_collision(const char *rootfs, struct pack *p); -int inspect_system(int fd, const char *datadir); int inspect_files(int fd, const char *datadir, const char *packname); -int inspect_version(const char *datadir, const char *name, char version[]); -int inspect(const char *datadir, const char *packname); +int inspect_system(int fd, const char *datadir); int write_metadata(const char *datadir, struct pack *pack); int write_entry(struct archive *a, struct archive *w); -int unpack(const char *rootfs, const char *datadir, struct pack *p); int delete_node(char *path); int delete_content(char *map, size_t size); @@ -83,6 +82,7 @@ int delete_content(char *map, size_t size); int install(const char *rootfs, const char *datadir, char *path); int update(const char *rootfs, const char *datadir, char *path); int delete(const char *rootfs, const char *datadir, char *name); +int inspect(const char *datadir, const char *packname); int verbose = LOG_NONE; int overwrite = 0; @@ -90,7 +90,7 @@ int overwrite = 0; void usage(char *name) { - fprintf(stderr, "usage: %s -adfiuv [pack]\n" , name); + fprintf(stderr, "usage: %s [-vvv] -adfiu [pack]\n" , name); } @@ -156,200 +156,121 @@ base_name(char *path) } -int -inspect_version(const char *datadir, const char *name, char version[LINE_MAX]) -{ - FILE *stream; - char tmp[PATH_MAX] = "", *lf = NULL; - - snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, name); - if ((stream = fopen(tmp, "r")) == NULL) { - sprintf(version, "(unknown)"); - return 1; - } else { - fgets(version, LINE_MAX, stream); - if ((lf = strchr(version, '\n')) != NULL) - *lf = 0; - } - - if (stream) - fclose(stream); - - return 0; -} - - /* - * Check for collisions between the filesystem and the tarball + * Load a pack from a tarball and return a pack structure */ -int -inspect_collision(const char *rootfs, struct pack *p) +struct pack * +pack_load_tarball(char *path) { - int r = 0; - char cwd[PATH_MAX] = ""; - struct stat st; - struct archive *a; - struct archive_entry *e; - - a = archive_read_new(); - archive_read_support_filter_bzip2(a); - archive_read_support_format_tar(a); + int fd; + struct pack *pack = NULL; + char tmp[PATH_MAX] = ""; + char *p; - r = archive_read_open_filename(a, p->path, 0); - if (r != ARCHIVE_OK) { - fprintf(stderr, "%s: %s\n", p->path, archive_error_string(a)); - return -1; + if ((fd = open(path, O_RDONLY)) < 0) { + perror(path); + return NULL; } + close(fd); - getcwd(cwd, PATH_MAX); - chdir(rootfs); - 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; - break; - } - archive_read_data_skip(a); + if (!(pack = malloc(sizeof(struct pack)))) { + perror(path); + return NULL; } - archive_read_free(a); - chdir(cwd); - - return r; -} - + pack->path = NULL; + pack->name = NULL; + pack->version = NULL; -/* - * Write files installed by a pack to a file descriptor - */ -int -inspect_files(int fd, const char *datadir, const char *packname) -{ - int meta; - char tmp[PATH_MAX] = ""; - size_t len; + pack->path = strdup(path); + snprintf(tmp, PATH_MAX, "%s", base_name(path)); - snprintf(tmp, PATH_MAX, "%s/%s/files", datadir, packname); - if ((meta = open(tmp, O_RDONLY)) < 0) { - perror(tmp); - return -1; + for (p = tmp; *p && *p != PACK_SEPARATOR; p++); + if (!*p) { + pack_free(pack); + return NULL; } + *p = 0; + pack->name = strdup(tmp); + *p = PACK_SEPARATOR; - while ((len = read(meta, tmp, PATH_MAX)) > 0) { - tmp[len] = 0; - dprintf(fd, "%s", tmp); + snprintf(tmp, PATH_MAX, "%s", p + 1); + for (p = tmp; *p && strcmp(p, PACK_EXTENSION); p++); + if (!*p) { + pack_free(pack); + return NULL; } + *p = 0; + pack->version = strdup(tmp); + *p = '.'; - return 0; + return pack; } /* - * Write packs installed in datadir to a file descriptor + * Load a pack from a metadata directory and return a pack structure */ -int -inspect_system(int fd, const char *datadir) +struct pack * +pack_load_directory(const char *datadir, char *path) { - DIR *d; - struct dirent *p; - char ver[LINE_MAX]; + struct pack *pack = NULL; - if (!(d = opendir(datadir))) { - perror(datadir); - return -1; + if (!(pack = malloc(sizeof(struct pack)))) { + perror(path); + return NULL; } - while ((p = readdir(d))) - if (p->d_name[0] != '.') { - inspect_version(datadir, p->d_name, ver); - dprintf(fd, "%s\t%s\n", p->d_name, ver); - } - - closedir(d); - return 0; -} - + pack->path = NULL; + pack->name = NULL; + pack->version = malloc(LINE_MAX); -/* - * Inspect the system, either by looking into a pack, checking installed - * files, or listing packs actually installed - */ -int -inspect(const char *datadir, const char *packname) -{ - /* name is NULL, list packs installed */ - if (!packname) - return inspect_system(1, datadir); + pack->path = strdup(path); + pack->name = strdup(base_name(path)); + inspect_version(datadir, pack->name, pack->version); - /* otherwise, list files installed by a pack */ - return inspect_files(1, datadir, packname); + return pack; } /* - * Write metadata about a pack file: - * + datadir/packname/version - version of the pack installed + * Guess how a pack should be loaded depending on the path given */ -int -write_metadata(const char *datadir, struct pack *p) +struct pack * +pack_load(const char *datadir, char *path) { - int fd, r; + struct pack *p = NULL; struct stat st; - char tmp[PATH_MAX]; - - snprintf(tmp, PATH_MAX, "%s/%s", datadir, p->name); - - if (stat(tmp, &st) < 0 && errno == ENOENT) { - log(LOG_DEBUG, "creating metadata directory %s\n", tmp); - if ((r = mkdir_parents(tmp, 0755)) < 0) - return r; - } - - snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, p->name); - - log(LOG_DEBUG, "openning %s for writing\n", tmp); - if ((fd = open(tmp, O_CREAT|O_WRONLY|O_TRUNC, 0644)) < 0) { - perror(tmp); - return -1; - } - - r = write(fd, p->version, strnlen(p->version, LINE_MAX)); - r += write(fd, "\n", 1); - if (r < 1) { - perror(tmp); - close(fd); - return -1; + if (stat(path, &st) < 0) { + perror(path); + } else if (S_ISDIR(st.st_mode)) { + p = pack_load_directory(datadir, path); + } else if (S_ISREG(st.st_mode)) { + p = pack_load_tarball(path); } - close(fd); - return 0; + return p; } /* - * Write an archive entry on the disk, thus creating the file + * Free a pack structure */ -int -write_entry(struct archive *a, struct archive *w) +void +pack_free(struct pack *p) { - int r; - const void *buf; - size_t len; - off_t off; + if (!p) + return; - for (;;) { - r = archive_read_data_block(a, &buf, &len, &off); - switch (r) { - case ARCHIVE_EOF: return 0; - case ARCHIVE_OK: break; - default: return r; - } + if (p->path) + free(p->path); + if (p->name) + free(p->name); + if (p->version) + free(p->version); - r = archive_write_data_block(w, buf, len, off); - if (r != ARCHIVE_OK) - return r; - } + free(p); } @@ -357,7 +278,7 @@ write_entry(struct archive *a, struct archive *w) * Extract a tarball to the given directory */ int -unpack(const char *rootfs, const char *datadir, struct pack *p) +pack_extract(const char *rootfs, const char *datadir, struct pack *p) { int r, fd; struct archive *a; @@ -455,32 +376,285 @@ pack_install(const char *rootfs, const char *datadir, struct pack *p) } log(LOG_VERBOSE, "extracting pack to %s\n", rootfs); - r = unpack(rootfs, datadir, p); + r = pack_extract(rootfs, datadir, p); return r; } /* - * Deletes a node, be it a file or a directory. - * In case the node doesn't exists, we're done + * Delete a pack from the system. + * This will read the file datadir/name/files, change directory to rootfs + * and call delete_content() */ int -delete_node(char *path) +pack_delete(const char *rootfs, const char *datadir, struct pack *p) { - int r = 0; + int fd; + char *addr = NULL; + char tmp[PATH_MAX], cwd[PATH_MAX]; struct stat st; - size_t len = 0; - - len = strnlen(path, PATH_MAX); - /* remove potential trailing '/' */ - if (path[len - 1] == '/') - path[--len] = 0; - log(LOG_DEBUG, "- %s\n", path); + snprintf(tmp, PATH_MAX, "%s/%s/files", datadir, p->name); + if (stat(tmp, &st) < 0 && errno == ENOENT) { + fprintf(stderr, "%s: not installed\n", p->name); + return -1; + } + if ((fd = open(tmp, O_RDONLY)) < 0) { + perror(tmp); + return ERR_DELETE; + } - /* - * if path doesn't exist anymore, it's all good :) + addr = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) { + perror(tmp); + close(fd); + } + + getcwd(cwd, PATH_MAX); + if (chdir(rootfs) < 0) { + perror(rootfs); + close(fd); + return ERR_DELETE; + } + + log(LOG_VERBOSE, "deleting installed files\n"); + /* ignore errors so everything gets deleted */ + if (delete_content(addr, st.st_size) < 0) { + fprintf(stderr, "%s: pack not removed\n", p->name); + close(fd); + return ERR_DELETE; + } + close(fd); + + log(LOG_VERBOSE, "removing %s\n", tmp); + if (unlink(tmp) < 0) { + perror(tmp); + return ERR_DELETE; + } + + snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, p->name); + + log(LOG_VERBOSE, "removing %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, "removing %s\n", tmp); + rmdir(tmp); + + chdir(cwd); + + return 0; +} + + +/* + * Read the version file for a pack and fill the given pointer with it + */ +int +inspect_version(const char *datadir, const char *name, char version[LINE_MAX]) +{ + FILE *stream; + char tmp[PATH_MAX] = "", *lf = NULL; + + snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, name); + if ((stream = fopen(tmp, "r")) == NULL) { + sprintf(version, "(unknown)"); + return 1; + } else { + fgets(version, LINE_MAX, stream); + if ((lf = strchr(version, '\n')) != NULL) + *lf = 0; + } + + fclose(stream); + + return 0; +} + + +/* + * Check for collisions between the filesystem and the tarball + */ +int +inspect_collision(const char *rootfs, struct pack *p) +{ + int r = 0; + char cwd[PATH_MAX] = ""; + struct stat st; + struct archive *a; + struct archive_entry *e; + + a = archive_read_new(); + archive_read_support_filter_bzip2(a); + archive_read_support_format_tar(a); + + r = archive_read_open_filename(a, p->path, 0); + if (r != ARCHIVE_OK) { + fprintf(stderr, "%s: %s\n", p->path, archive_error_string(a)); + return -1; + } + + getcwd(cwd, PATH_MAX); + chdir(rootfs); + 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; + break; + } + archive_read_data_skip(a); + } + + archive_read_free(a); + chdir(cwd); + + return r; +} + + +/* + * Write files installed by a pack to a file descriptor + */ +int +inspect_files(int fd, const char *datadir, const char *packname) +{ + int meta; + char tmp[PATH_MAX] = ""; + size_t len; + + snprintf(tmp, PATH_MAX, "%s/%s/files", datadir, packname); + if ((meta = open(tmp, O_RDONLY)) < 0) { + perror(tmp); + return -1; + } + + while ((len = read(meta, tmp, PATH_MAX)) > 0) { + tmp[len] = 0; + dprintf(fd, "%s", tmp); + } + + return 0; +} + + +/* + * Write packs installed in datadir to a file descriptor + */ +int +inspect_system(int fd, const char *datadir) +{ + DIR *d; + struct dirent *p; + char ver[LINE_MAX]; + + if (!(d = opendir(datadir))) { + perror(datadir); + return -1; + } + + while ((p = readdir(d))) + if (p->d_name[0] != '.') { + inspect_version(datadir, p->d_name, ver); + dprintf(fd, "%s\t%s\n", p->d_name, ver); + } + + closedir(d); + return 0; +} + + +/* + * Write metadata about a pack file: + * + datadir/packname/version - version of the pack installed + */ +int +write_metadata(const char *datadir, struct pack *p) +{ + int fd, r; + struct stat st; + char tmp[PATH_MAX]; + + snprintf(tmp, PATH_MAX, "%s/%s", datadir, p->name); + + if (stat(tmp, &st) < 0 && errno == ENOENT) { + log(LOG_DEBUG, "creating metadata directory %s\n", tmp); + if ((r = mkdir_parents(tmp, 0755)) < 0) + return r; + } + + snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, p->name); + + log(LOG_DEBUG, "openning %s for writing\n", tmp); + if ((fd = open(tmp, O_CREAT|O_WRONLY|O_TRUNC, 0644)) < 0) { + perror(tmp); + return -1; + } + + r = write(fd, p->version, strnlen(p->version, LINE_MAX)); + r += write(fd, "\n", 1); + + if (r < 1) { + perror(tmp); + close(fd); + return -1; + } + + close(fd); + return 0; +} + + +/* + * Write an archive entry on the disk, thus creating the file + */ +int +write_entry(struct archive *a, struct archive *w) +{ + int r; + const void *buf; + size_t len; + off_t off; + + for (;;) { + r = archive_read_data_block(a, &buf, &len, &off); + switch (r) { + case ARCHIVE_EOF: return 0; + case ARCHIVE_OK: break; + default: return r; + } + + r = archive_write_data_block(w, buf, len, off); + if (r != ARCHIVE_OK) + return r; + } +} + + +/* + * Deletes a node, be it a file or a directory. + * In case the node doesn't exists, we're done + */ +int +delete_node(char *path) +{ + int r = 0; + struct stat st; + size_t len = 0; + + len = strnlen(path, PATH_MAX); + /* remove potential trailing '/' */ + if (path[len - 1] == '/') + path[--len] = 0; + + log(LOG_DEBUG, "- %s\n", path); + + /* + * if path doesn't exist anymore, it's all good :) * we use lstat here so that dangling links can be delt with too */ if (lstat(path, &st) < 0 && errno == ENOENT) @@ -501,6 +675,7 @@ delete_node(char *path) return 0; } + /* * Delete all entries listed in the given file. * if the entry doesn't exist, it will be ignored @@ -518,7 +693,7 @@ delete_content(char *map, size_t size) /* * it is assumed here that the file is POSIX and thus that * the last char will be \n. - * This might sound stupid; but this is what unpack() will do. + * This might sound stupid; but this is what pack_extract() will do. * We read the mmap file backward until we encounter \n or the * beginning of the file. If it's an \n, we replace it by 0 and * process to the deletion of the inode, either with rmdir or @@ -544,76 +719,6 @@ delete_content(char *map, size_t size) /* - * Delete a pack from the system. - * This will read the file datadir/name/files, change directory to rootfs - * and call delete_content() - */ -int -pack_delete(const char *rootfs, const char *datadir, struct pack *p) -{ - int fd; - char *addr = NULL; - char tmp[PATH_MAX], cwd[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: not installed\n", p->name); - return -1; - } - if ((fd = open(tmp, O_RDONLY)) < 0) { - perror(tmp); - 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); - } - - getcwd(cwd, PATH_MAX); - if (chdir(rootfs) < 0) { - perror(rootfs); - close(fd); - return ERR_DELETE; - } - - log(LOG_VERBOSE, "deleting installed files\n"); - /* ignore errors so everything gets deleted */ - if (delete_content(addr, st.st_size) < 0) { - fprintf(stderr, "%s: pack not removed\n", p->name); - close(fd); - return ERR_DELETE; - } - close(fd); - - log(LOG_VERBOSE, "removing %s\n", tmp); - if (unlink(tmp) < 0) { - perror(tmp); - return ERR_DELETE; - } - - snprintf(tmp, PATH_MAX, "%s/%s/version", datadir, p->name); - - log(LOG_VERBOSE, "removing %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, "removing %s\n", tmp); - rmdir(tmp); - - chdir(cwd); - - return 0; -} - - -/* * Install a pack from the given path. This wraps load/install of a pack */ int @@ -664,6 +769,9 @@ update(const char *rootfs, const char *datadir, char *path) } +/* + * Delete a currently installed pack. This wraps load/delete functions + */ int delete(const char *rootfs, const char *datadir, char *name) { @@ -688,120 +796,18 @@ delete(const char *rootfs, const char *datadir, char *name) /* - * Load a pack from a tarball and return a pack structure - */ -struct pack * -pack_load_tarball(char *path) -{ - int fd; - struct pack *pack = NULL; - char tmp[PATH_MAX] = ""; - char *p; - - if ((fd = open(path, O_RDONLY)) < 0) { - perror(path); - return NULL; - } - close(fd); - - if (!(pack = malloc(sizeof(struct pack)))) { - perror(path); - return NULL; - } - - pack->path = NULL; - pack->name = NULL; - pack->version = NULL; - - pack->path = strdup(path); - snprintf(tmp, PATH_MAX, "%s", base_name(path)); - - for (p = tmp; *p && *p != PACK_SEPARATOR; p++); - if (!*p) { - pack_free(pack); - return NULL; - } - *p = 0; - pack->name = strdup(tmp); - *p = PACK_SEPARATOR; - - snprintf(tmp, PATH_MAX, "%s", p + 1); - for (p = tmp; *p && strcmp(p, PACK_EXTENSION); p++); - if (!*p) { - pack_free(pack); - return NULL; - } - *p = 0; - pack->version = strdup(tmp); - *p = '.'; - - return pack; -} - - -/* - * Load a pack from a metadata directory and return a pack structure - */ -struct pack * -pack_load_directory(const char *datadir, char *path) -{ - struct pack *pack = NULL; - - if (!(pack = malloc(sizeof(struct pack)))) { - perror(path); - return NULL; - } - - pack->path = NULL; - pack->name = NULL; - pack->version = malloc(LINE_MAX); - - pack->path = strdup(path); - pack->name = strdup(base_name(path)); - inspect_version(datadir, pack->name, pack->version); - - return pack; -} - - -/* - * Guess how a pack should be loaded depending on the path given - */ -struct pack * -pack_load(const char *datadir, char *path) -{ - struct pack *p = NULL; - struct stat st; - - if (stat(path, &st) < 0) { - perror(path); - } else if (S_ISDIR(st.st_mode)) { - p = pack_load_directory(datadir, path); - } else if (S_ISREG(st.st_mode)) { - p = pack_load_tarball(path); - } - - return p; -} - - -/* - * Free a pack structure + * Inspect the system, either by looking into a pack, checking installed + * files, or listing packs actually installed */ -void -pack_free(struct pack *p) +int +inspect(const char *datadir, const char *packname) { - if (!p) - return; - - if (p->path) - free(p->path); - if (p->name) - free(p->name); - if (p->version) - free(p->version); + /* name is NULL, list packs installed */ + if (!packname) + return inspect_system(1, datadir); - free(p); + /* otherwise, list files installed by a pack */ + return inspect_files(1, datadir, packname); }