From 823283edca0d8403742999917a4ff0698ad641cb Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Mon, 21 Apr 2008 16:30:10 +0000 Subject: Argument parsing. Some other stuff too. --- Makefile | 8 ++- TODO | 4 +- src/Makefile | 2 + src/add.c | 7 +-- src/apk.c | 74 +++++++++++++++++++++------- src/apk_applet.h | 3 ++ src/apk_database.h | 8 +-- src/archive.c | 2 +- src/blob.c | 3 ++ src/create.c | 28 +++++++++++ src/database.c | 142 ++++++++++++++++++++++++++++++++--------------------- src/del.c | 6 +-- src/index.c | 4 +- src/package.c | 20 -------- src/ver.c | 6 +-- 15 files changed, 202 insertions(+), 115 deletions(-) create mode 100644 src/create.c diff --git a/Makefile b/Makefile index 783b7ce..ee4ca1e 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,13 @@ INSTALLDIR=$(INSTALL) -d CFLAGS=-O2 -g -D_GNU_SOURCE -Werror -Wall -Wstrict-prototypes -std=gnu99 \ -DAPK_VERSION=\"$(FULL_VERSION)\" -LDFLAGS=-g -lpthread -nopie +LDFLAGS=-g -nopie +LIBS=-lpthread + +ifeq ($(STATIC),yes) +CFLAGS+=-fno-stack-protector +LDFLAGS+=-static +endif DESTDIR= SBINDIR=/usr/sbin diff --git a/TODO b/TODO index 5c67bdb..72e1bc1 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ -- Command line parsing -- Get repositories/root from command line +- Handle properly gunzip failure + - Repository index/package fetching from URLs - Installation of local files diff --git a/src/Makefile b/src/Makefile index 0964012..15eeb00 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,6 +18,7 @@ apk_OBJS = \ blob.o \ hash.o \ md5.o \ + create.o \ add.o \ del.o \ ver.o \ @@ -29,6 +30,7 @@ ALL_OBJS = $(apk_OBJS) all: $(TARGETS) apk: $(apk_OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) clean:: @rm -f $(TARGETS) $(ALL_OBJS) diff --git a/src/add.c b/src/add.c index 28dcb9b..be8012b 100644 --- a/src/add.c +++ b/src/add.c @@ -18,8 +18,9 @@ static int add_main(int argc, char **argv) struct apk_database db; int i; - apk_db_init(&db, "/home/fabled/tmproot/"); - apk_db_read_config(&db); + if (apk_db_open(&db, apk_root) < 0) + return -1; + for (i = 0; i < argc; i++) { struct apk_dependency dep = { .name = apk_db_get_name(&db, argv[i]), @@ -27,7 +28,7 @@ static int add_main(int argc, char **argv) apk_deps_add(&db.world, &dep); } apk_db_recalculate_and_commit(&db); - apk_db_free(&db); + apk_db_close(&db); return 0; } diff --git a/src/apk.c b/src/apk.c index f8f13dd..e59074a 100644 --- a/src/apk.c +++ b/src/apk.c @@ -11,11 +11,17 @@ #include #include +#include #include +#include +#include #include "apk_defines.h" #include "apk_applet.h" +const char *apk_root = "/"; +const char *apk_repository = NULL; + void apk_log(const char *prefix, const char *format, ...) { va_list va; @@ -46,10 +52,30 @@ int usage(void) return 1; } +static struct apk_applet *find_applet(const char *name) +{ + struct apk_applet **a; + + for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) { + if (strcmp(name, (*a)->name) == 0) + return *a; + } + + return NULL; +} + int main(int argc, char **argv) { - struct apk_applet **a, *applet; - char *prog; + static struct option generic_options[] = { + {"root", required_argument, NULL, 'Q' }, + {"repository", required_argument, NULL, 'X' }, + {0, 0, 0, 0}, + }; + struct apk_applet *applet = NULL; + const char *prog; + int r; + + umask(0); prog = strrchr(argv[0], '/'); if (prog == NULL) @@ -57,25 +83,35 @@ int main(int argc, char **argv) else prog++; - if (strcmp(prog, "apk") == 0) { - if (argc < 2) - return usage(); - prog = argv[1]; - argv++; - argc--; - } else if (strncmp(prog, "apk_", 4) == 0) { - prog += 4; - } else - return usage(); + if (strncmp(prog, "apk_", 4) == 0) + applet = find_applet(prog + 4); - for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) { - applet = *a; - if (strcmp(prog, applet->name) == 0) { - argv++; - argc--; - return applet->main(argc, argv); + while ((r = getopt_long(argc, argv, "", + generic_options, NULL)) != -1) { + switch (r) { + case 'Q': + apk_root = optarg; + break; + case 'X': + apk_repository = optarg; + break; + default: + return usage(); } } - return usage(); + argc -= optind; + argv += optind; + + if (applet == NULL) { + if (argc > 0) + applet = find_applet(argv[0]); + if (applet == NULL) + return usage(); + + argc--; + argv++; + } + + return applet->main(argc, argv); } diff --git a/src/apk_applet.h b/src/apk_applet.h index 4107135..e4c2e1d 100644 --- a/src/apk_applet.h +++ b/src/apk_applet.h @@ -12,6 +12,9 @@ #ifndef APK_APPLET_H #define APK_APPLET_H +extern const char *apk_root; +extern const char *apk_repository; + struct apk_applet { const char *name; const char *usage; diff --git a/src/apk_database.h b/src/apk_database.h index 96ff361..fcb9c54 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -52,6 +52,7 @@ struct apk_repository { struct apk_database { char *root; + int root_fd; unsigned pkg_id, num_repos; struct apk_dependency_array *world; @@ -76,10 +77,9 @@ struct apk_database { struct apk_name *apk_db_get_name(struct apk_database *db, const char *name); void apk_name_free(struct apk_name *pkgname); -void apk_db_init(struct apk_database *db, const char *root); -void apk_db_free(struct apk_database *db); -int apk_db_read_config(struct apk_database *db); -int apk_db_write_config(struct apk_database *db); +int apk_db_create(const char *root); +int apk_db_open(struct apk_database *db, const char *root); +void apk_db_close(struct apk_database *db); int apk_db_pkg_add_file(struct apk_database *db, const char *file); struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum); diff --git a/src/archive.c b/src/archive.c index e5092dc..6b91a1e 100644 --- a/src/archive.c +++ b/src/archive.c @@ -57,7 +57,6 @@ static int get_dev_null(void) err(EX_OSFILE, "/dev/null"); } return fd_null; - } pid_t apk_open_gz(int *fd) @@ -243,6 +242,7 @@ int apk_archive_entry_extract(struct apk_archive_entry *ae, const char *fn) /* BIG HONKING FIXME */ unlink(fn); + apk_message("Extracting %s...", ae->mode); switch (ae->mode & S_IFMT) { case S_IFDIR: diff --git a/src/blob.c b/src/blob.c index eecf642..f7c14b5 100644 --- a/src/blob.c +++ b/src/blob.c @@ -18,6 +18,9 @@ char *apk_blob_cstr(apk_blob_t blob) { char *cstr; + if (blob.ptr == NULL) + return strdup(""); + if (blob.ptr[blob.len-1] == 0) return strdup(blob.ptr); diff --git a/src/create.c b/src/create.c new file mode 100644 index 0000000..a033170 --- /dev/null +++ b/src/create.c @@ -0,0 +1,28 @@ +/* create.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa + * Copyright (C) 2008 Timo Teräs + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ + +#include +#include "apk_applet.h" +#include "apk_database.h" + +static int create_main(int argc, char **argv) +{ + return apk_db_create(apk_root); +} + +static struct apk_applet apk_create = { + .name = "create", + .usage = "", + .main = create_main, +}; + +APK_DEFINE_APPLET(apk_create); + diff --git a/src/database.c b/src/database.c index f98be64..fa3f8c6 100644 --- a/src/database.c +++ b/src/database.c @@ -20,6 +20,7 @@ #include "apk_package.h" #include "apk_database.h" #include "apk_state.h" +#include "apk_applet.h" struct install_ctx { struct apk_database *db; @@ -107,7 +108,7 @@ static struct apk_db_dir *apk_db_dir_ref(struct apk_database *db, if (dir->parent != NULL) apk_db_dir_ref(db, dir->parent, create_dir); db->installed.stats.dirs++; - if (create_dir) + if (create_dir && dir->mode) mkdir(dir->dirname, dir->mode); } dir->refs++; @@ -135,7 +136,7 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t bparent; char *cstr; - if (name.ptr[name.len-1] == '/') + if (name.len && name.ptr[name.len-1] == '/') name.len--; cstr = apk_blob_cstr(name); @@ -149,8 +150,12 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db, dir->dirname[name.len] = 0; apk_hash_insert(&db->installed.dirs, dir); - if (apk_blob_rsplit(name, '/', &bparent, NULL)) + if (name.len == 0) + dir->parent = NULL; + else if (apk_blob_rsplit(name, '/', &bparent, NULL)) dir->parent = apk_db_dir_get(db, bparent); + else + dir->parent = apk_db_dir_get(db, APK_BLOB_NULL); return dir; } @@ -194,22 +199,21 @@ static struct apk_db_file *apk_db_file_get(struct apk_database *db, struct hlist_node *cur; apk_blob_t bdir, bfile; - if (!apk_blob_rsplit(name, '/', &bdir, &bfile)) - return NULL; - dir = NULL; - if (ctx != NULL && ctx->dircache != NULL) { + if (!apk_blob_rsplit(name, '/', &bdir, &bfile)) { + dir = apk_db_dir_get(db, APK_BLOB_NULL); + bfile = name; + } else if (ctx != NULL && ctx->dircache != NULL) { dir = ctx->dircache; if (strncmp(dir->dirname, bdir.ptr, bdir.len) != 0 || dir->dirname[bdir.len] != 0) dir = NULL; } - if (dir == NULL) { + if (dir == NULL) dir = apk_db_dir_get(db, bdir); - if (ctx != NULL) { - ctx->dircache = dir; - ctx->file_dir_node = &dir->files.first; - } + if (ctx != NULL && dir != ctx->dircache) { + ctx->dircache = dir; + ctx->file_dir_node = &dir->files.first; } hlist_for_each_entry(file, cur, &dir->files, dir_files_list) { @@ -382,39 +386,45 @@ static int apk_db_read_scriptdb(struct apk_database *db, int fd) return 0; } -static const char *get_db_path(struct apk_database *db, const char *f) +static const char *get_db_path(const char *root, const char *f) { static char fn[1024]; - snprintf(fn, sizeof(fn), "%s%s", db->root, f); + snprintf(fn, sizeof(fn), "%s/%s", root, f); return fn; } -void apk_db_init(struct apk_database *db, const char *root) +int apk_db_create(const char *root) { - memset(db, 0, sizeof(*db)); - apk_hash_init(&db->available.names, &pkg_name_hash_ops, 1000); - apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000); - apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000); + apk_blob_t deps = APK_BLOB_STR("busybox, alpine-baselayout, " + "apk-tools, alpine-conf"); + int fd; - if (root != NULL) { - db->root = strdup(root); - apk_db_add_repository(db, "/home/fabled/foo/"); - mkdir(get_db_path(db, "tmp"), 01777); - mkdir(get_db_path(db, "dev"), 0755); - mknod(get_db_path(db, "dev/null"), 0666, makedev(1, 3)); - } + mkdir(get_db_path(root, "tmp"), 01777); + mkdir(get_db_path(root, "dev"), 0755); + mknod(get_db_path(root, "dev/null"), 0666, makedev(1, 3)); + mkdir(get_db_path(root, "var"), 0755); + mkdir(get_db_path(root, "var/lib"), 0755); + mkdir(get_db_path(root, "var/lib/apk"), 0755); + + fd = creat(get_db_path(root, "var/lib/apk/world"), 0600); + if (fd < 0) + return -1; + write(fd, deps.ptr, deps.len); + close(fd); + + return 0; } -int apk_db_read_config(struct apk_database *db) +static int apk_db_read_config(struct apk_database *db) { struct stat st; char *buf; int fd; if (db->root == NULL) - return -1; + return 0; /* Read: * 1. installed repository @@ -424,27 +434,24 @@ int apk_db_read_config(struct apk_database *db) * 5. files db * 6. script db */ - fd = open(get_db_path(db, "var/lib/apk/world"), O_RDONLY); - if (fd >= 0) { - fstat(fd, &st); - buf = malloc(st.st_size); - read(fd, buf, st.st_size); - apk_deps_parse(db, &db->world, - APK_BLOB_PTR_LEN(buf, st.st_size)); - close(fd); - } else { - apk_deps_parse(db, &db->world, - APK_BLOB_STR("busybox, alpine-baselayout, " - "apk-tools, alpine-conf")); - } + fd = open(get_db_path(db->root, "var/lib/apk/world"), O_RDONLY); + if (fd < 0) + return -1; + + fstat(fd, &st); + buf = malloc(st.st_size); + read(fd, buf, st.st_size); + apk_deps_parse(db, &db->world, + APK_BLOB_PTR_LEN(buf, st.st_size)); + close(fd); - fd = open(get_db_path(db, "var/lib/apk/files"), O_RDONLY); + fd = open(get_db_path(db->root, "var/lib/apk/files"), O_RDONLY); if (fd >= 0) { apk_db_read_fdb(db, fd); close(fd); } - fd = open(get_db_path(db, "var/lib/apk/scripts"), O_RDONLY); + fd = open(get_db_path(db->root, "var/lib/apk/scripts"), O_RDONLY); if (fd >= 0) { apk_db_read_scriptdb(db, fd); close(fd); @@ -453,37 +460,54 @@ int apk_db_read_config(struct apk_database *db) return 0; } +int apk_db_open(struct apk_database *db, const char *root) +{ + memset(db, 0, sizeof(*db)); + apk_hash_init(&db->available.names, &pkg_name_hash_ops, 1000); + apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000); + apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000); + + if (root != NULL) { + db->root = strdup(root); + db->root_fd = open(root, O_RDONLY); + if (db->root_fd < 0) { + free(db->root); + return -1; + } + + apk_db_add_repository(db, apk_repository); + } + + return apk_db_read_config(db); +} + struct write_ctx { struct apk_database *db; int fd; }; -int apk_db_write_config(struct apk_database *db) +static int apk_db_write_config(struct apk_database *db) { char buf[1024]; int n, fd; if (db->root == NULL) - return -1; - - mkdir(get_db_path(db, "var"), 0755); - mkdir(get_db_path(db, "var/lib"), 0755); - mkdir(get_db_path(db, "var/lib/apk"), 0755); + return 0; - fd = creat(get_db_path(db, "var/lib/apk/world"), 0600); + fd = creat(get_db_path(db->root, "var/lib/apk/world"), 0600); if (fd < 0) return -1; n = apk_deps_format(buf, sizeof(buf), db->world); write(fd, buf, n); close(fd); - fd = creat(get_db_path(db, "var/lib/apk/files"), 0600); + fd = creat(get_db_path(db->root, "var/lib/apk/files"), 0600); if (fd < 0) return -1; apk_db_write_fdb(db, fd); close(fd); - fd = creat(get_db_path(db, "var/lib/apk/scripts"), 0600); + fd = creat(get_db_path(db->root, "var/lib/apk/scripts"), 0600); if (fd < 0) return -1; apk_db_write_scriptdb(db, fd); @@ -492,13 +516,17 @@ int apk_db_write_config(struct apk_database *db) return 0; } -void apk_db_free(struct apk_database *db) +void apk_db_close(struct apk_database *db) { + apk_db_write_config(db); + apk_hash_free(&db->available.names); apk_hash_free(&db->available.packages); apk_hash_free(&db->installed.dirs); - if (db->root != NULL) + if (db->root != NULL) { + close(db->root_fd); free(db->root); + } } static void apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg) @@ -593,7 +621,7 @@ int apk_db_add_repository(struct apk_database *db, const char *repo) .url = strdup(repo) }; - snprintf(tmp, sizeof(tmp), "%sAPK_INDEX", repo); + snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", repo); fd = open(tmp, O_RDONLY); if (fd < 0) { apk_error("Failed to open index file %s", tmp); @@ -732,7 +760,7 @@ int apk_db_install_pkg(struct apk_database *db, pthread_t tid = 0; int fd, r; - if (chdir(db->root) < 0) + if (fchdir(db->root_fd) < 0) return errno; /* Purge the old package if there */ @@ -753,7 +781,7 @@ int apk_db_install_pkg(struct apk_database *db, /* Install the new stuff */ snprintf(file, sizeof(file), - "%s%s-%s.apk", + "%s/%s-%s.apk", db->repos[0].url, newpkg->name->name, newpkg->version); fd = open(file, O_RDONLY); diff --git a/src/del.c b/src/del.c index c4d7539..2fc6048 100644 --- a/src/del.c +++ b/src/del.c @@ -18,8 +18,8 @@ static int del_main(int argc, char **argv) struct apk_database db; int i, j; - apk_db_init(&db, "/home/fabled/tmproot/"); - apk_db_read_config(&db); + if (apk_db_open(&db, apk_root) < 0) + return -1; if (db.world == NULL) goto out; @@ -38,7 +38,7 @@ static int del_main(int argc, char **argv) apk_db_recalculate_and_commit(&db); out: - apk_db_free(&db); + apk_db_close(&db); return 0; } diff --git a/src/index.c b/src/index.c index 4234002..eeaa337 100644 --- a/src/index.c +++ b/src/index.c @@ -44,12 +44,12 @@ static int index_main(int argc, char **argv) struct counts counts = {0,0}; int i; - apk_db_init(&db, NULL); + apk_db_open(&db, NULL); for (i = 0; i < argc; i++) apk_db_pkg_add_file(&db, argv[i]); apk_db_index_write(&db, STDOUT_FILENO); apk_hash_foreach(&db.available.names, warn_if_no_providers, &counts); - apk_db_free(&db); + apk_db_close(&db); if (counts.unsatisfied != 0) apk_warning("Total of %d unsatisfiable package " diff --git a/src/package.c b/src/package.c index 88aef70..04ec2be 100644 --- a/src/package.c +++ b/src/package.c @@ -362,26 +362,6 @@ int apk_pkg_run_script(struct apk_package *pkg, const char *root, return -1; } - /* FIXME: Remove this ugly kludge */ - if (strcmp(pkg->name->name, "busybox") == 0 && - type == APK_SCRIPT_POST_INSTALL) { - apk_message("Create busybox links"); - - pid = fork(); - if (pid == -1) - return -1; - if (pid == 0) { - chroot(root); - execl("/bin/busybox", "busybox", "--install", "-s", NULL); - exit(1); - } - waitpid(pid, &status, 0); - if (WIFEXITED(status)) - return WEXITSTATUS(status); - return -1; - - } - return 0; } diff --git a/src/ver.c b/src/ver.c index c8b2e2b..8d62f3a 100644 --- a/src/ver.c +++ b/src/ver.c @@ -44,8 +44,8 @@ static int ver_main(int argc, char **argv) return 0; } - apk_db_init(&db, "/home/fabled/tmproot/"); - apk_db_read_config(&db); + if (apk_db_open(&db, apk_root) < 0) + return -1; hlist_for_each_entry(pkg, c, &db.installed.packages, installed_pkgs_list) { name = pkg->name; @@ -61,7 +61,7 @@ static int ver_main(int argc, char **argv) } printf("%-40s%c\n", name->name, pkg != upg ? '<' : '='); } - apk_db_free(&db); + apk_db_close(&db); return 0; } -- cgit v1.2.3-60-g2f50