Argument parsing. Some other stuff too.

cute-signatures
Timo Teras 2008-04-21 16:30:10 +00:00
parent 951602e551
commit 823283edca
15 changed files with 202 additions and 115 deletions

View File

@ -22,7 +22,13 @@ INSTALLDIR=$(INSTALL) -d
CFLAGS=-O2 -g -D_GNU_SOURCE -Werror -Wall -Wstrict-prototypes -std=gnu99 \ CFLAGS=-O2 -g -D_GNU_SOURCE -Werror -Wall -Wstrict-prototypes -std=gnu99 \
-DAPK_VERSION=\"$(FULL_VERSION)\" -DAPK_VERSION=\"$(FULL_VERSION)\"
LDFLAGS=-g -lpthread -nopie LDFLAGS=-g -nopie
LIBS=-lpthread
ifeq ($(STATIC),yes)
CFLAGS+=-fno-stack-protector
LDFLAGS+=-static
endif
DESTDIR= DESTDIR=
SBINDIR=/usr/sbin SBINDIR=/usr/sbin

4
TODO
View File

@ -1,5 +1,5 @@
- Command line parsing - Handle properly gunzip failure
- Get repositories/root from command line
- Repository index/package fetching from URLs - Repository index/package fetching from URLs
- Installation of local files - Installation of local files

View File

@ -18,6 +18,7 @@ apk_OBJS = \
blob.o \ blob.o \
hash.o \ hash.o \
md5.o \ md5.o \
create.o \
add.o \ add.o \
del.o \ del.o \
ver.o \ ver.o \
@ -29,6 +30,7 @@ ALL_OBJS = $(apk_OBJS)
all: $(TARGETS) all: $(TARGETS)
apk: $(apk_OBJS) apk: $(apk_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:: clean::
@rm -f $(TARGETS) $(ALL_OBJS) @rm -f $(TARGETS) $(ALL_OBJS)

View File

@ -18,8 +18,9 @@ static int add_main(int argc, char **argv)
struct apk_database db; struct apk_database db;
int i; int i;
apk_db_init(&db, "/home/fabled/tmproot/"); if (apk_db_open(&db, apk_root) < 0)
apk_db_read_config(&db); return -1;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
struct apk_dependency dep = { struct apk_dependency dep = {
.name = apk_db_get_name(&db, argv[i]), .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_deps_add(&db.world, &dep);
} }
apk_db_recalculate_and_commit(&db); apk_db_recalculate_and_commit(&db);
apk_db_free(&db); apk_db_close(&db);
return 0; return 0;
} }

View File

@ -11,11 +11,17 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <getopt.h>
#include <sys/stat.h>
#include "apk_defines.h" #include "apk_defines.h"
#include "apk_applet.h" #include "apk_applet.h"
const char *apk_root = "/";
const char *apk_repository = NULL;
void apk_log(const char *prefix, const char *format, ...) void apk_log(const char *prefix, const char *format, ...)
{ {
va_list va; va_list va;
@ -46,10 +52,30 @@ int usage(void)
return 1; 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) int main(int argc, char **argv)
{ {
struct apk_applet **a, *applet; static struct option generic_options[] = {
char *prog; {"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], '/'); prog = strrchr(argv[0], '/');
if (prog == NULL) if (prog == NULL)
@ -57,25 +83,35 @@ int main(int argc, char **argv)
else else
prog++; prog++;
if (strcmp(prog, "apk") == 0) { if (strncmp(prog, "apk_", 4) == 0)
if (argc < 2) applet = find_applet(prog + 4);
return usage();
prog = argv[1];
argv++;
argc--;
} else if (strncmp(prog, "apk_", 4) == 0) {
prog += 4;
} else
return usage();
for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) { while ((r = getopt_long(argc, argv, "",
applet = *a; generic_options, NULL)) != -1) {
if (strcmp(prog, applet->name) == 0) { switch (r) {
argv++; case 'Q':
argc--; apk_root = optarg;
return applet->main(argc, argv); 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);
} }

View File

@ -12,6 +12,9 @@
#ifndef APK_APPLET_H #ifndef APK_APPLET_H
#define APK_APPLET_H #define APK_APPLET_H
extern const char *apk_root;
extern const char *apk_repository;
struct apk_applet { struct apk_applet {
const char *name; const char *name;
const char *usage; const char *usage;

View File

@ -52,6 +52,7 @@ struct apk_repository {
struct apk_database { struct apk_database {
char *root; char *root;
int root_fd;
unsigned pkg_id, num_repos; unsigned pkg_id, num_repos;
struct apk_dependency_array *world; 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); struct apk_name *apk_db_get_name(struct apk_database *db, const char *name);
void apk_name_free(struct apk_name *pkgname); void apk_name_free(struct apk_name *pkgname);
void apk_db_init(struct apk_database *db, const char *root); int apk_db_create(const char *root);
void apk_db_free(struct apk_database *db); int apk_db_open(struct apk_database *db, const char *root);
int apk_db_read_config(struct apk_database *db); void apk_db_close(struct apk_database *db);
int apk_db_write_config(struct apk_database *db);
int apk_db_pkg_add_file(struct apk_database *db, const char *file); 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); struct apk_package *apk_db_get_pkg(struct apk_database *db, csum_t sum);

View File

@ -57,7 +57,6 @@ static int get_dev_null(void)
err(EX_OSFILE, "/dev/null"); err(EX_OSFILE, "/dev/null");
} }
return fd_null; return fd_null;
} }
pid_t apk_open_gz(int *fd) 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 */ /* BIG HONKING FIXME */
unlink(fn); unlink(fn);
apk_message("Extracting %s...", ae->mode);
switch (ae->mode & S_IFMT) { switch (ae->mode & S_IFMT) {
case S_IFDIR: case S_IFDIR:

View File

@ -18,6 +18,9 @@ char *apk_blob_cstr(apk_blob_t blob)
{ {
char *cstr; char *cstr;
if (blob.ptr == NULL)
return strdup("");
if (blob.ptr[blob.len-1] == 0) if (blob.ptr[blob.len-1] == 0)
return strdup(blob.ptr); return strdup(blob.ptr);

28
src/create.c Normal file
View File

@ -0,0 +1,28 @@
/* create.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
* 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 <stdio.h>
#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);

View File

@ -20,6 +20,7 @@
#include "apk_package.h" #include "apk_package.h"
#include "apk_database.h" #include "apk_database.h"
#include "apk_state.h" #include "apk_state.h"
#include "apk_applet.h"
struct install_ctx { struct install_ctx {
struct apk_database *db; 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) if (dir->parent != NULL)
apk_db_dir_ref(db, dir->parent, create_dir); apk_db_dir_ref(db, dir->parent, create_dir);
db->installed.stats.dirs++; db->installed.stats.dirs++;
if (create_dir) if (create_dir && dir->mode)
mkdir(dir->dirname, dir->mode); mkdir(dir->dirname, dir->mode);
} }
dir->refs++; dir->refs++;
@ -135,7 +136,7 @@ static struct apk_db_dir *apk_db_dir_get(struct apk_database *db,
apk_blob_t bparent; apk_blob_t bparent;
char *cstr; char *cstr;
if (name.ptr[name.len-1] == '/') if (name.len && name.ptr[name.len-1] == '/')
name.len--; name.len--;
cstr = apk_blob_cstr(name); 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; dir->dirname[name.len] = 0;
apk_hash_insert(&db->installed.dirs, dir); 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); dir->parent = apk_db_dir_get(db, bparent);
else
dir->parent = apk_db_dir_get(db, APK_BLOB_NULL);
return dir; return dir;
} }
@ -194,22 +199,21 @@ static struct apk_db_file *apk_db_file_get(struct apk_database *db,
struct hlist_node *cur; struct hlist_node *cur;
apk_blob_t bdir, bfile; apk_blob_t bdir, bfile;
if (!apk_blob_rsplit(name, '/', &bdir, &bfile))
return NULL;
dir = 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; dir = ctx->dircache;
if (strncmp(dir->dirname, bdir.ptr, bdir.len) != 0 || if (strncmp(dir->dirname, bdir.ptr, bdir.len) != 0 ||
dir->dirname[bdir.len] != 0) dir->dirname[bdir.len] != 0)
dir = NULL; dir = NULL;
} }
if (dir == NULL) { if (dir == NULL)
dir = apk_db_dir_get(db, bdir); dir = apk_db_dir_get(db, bdir);
if (ctx != NULL) { if (ctx != NULL && dir != ctx->dircache) {
ctx->dircache = dir; ctx->dircache = dir;
ctx->file_dir_node = &dir->files.first; ctx->file_dir_node = &dir->files.first;
}
} }
hlist_for_each_entry(file, cur, &dir->files, dir_files_list) { 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; 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]; static char fn[1024];
snprintf(fn, sizeof(fn), "%s%s", db->root, f); snprintf(fn, sizeof(fn), "%s/%s", root, f);
return fn; 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_blob_t deps = APK_BLOB_STR("busybox, alpine-baselayout, "
apk_hash_init(&db->available.names, &pkg_name_hash_ops, 1000); "apk-tools, alpine-conf");
apk_hash_init(&db->available.packages, &pkg_info_hash_ops, 4000); int fd;
apk_hash_init(&db->installed.dirs, &dir_hash_ops, 1000);
if (root != NULL) { mkdir(get_db_path(root, "tmp"), 01777);
db->root = strdup(root); mkdir(get_db_path(root, "dev"), 0755);
apk_db_add_repository(db, "/home/fabled/foo/"); mknod(get_db_path(root, "dev/null"), 0666, makedev(1, 3));
mkdir(get_db_path(db, "tmp"), 01777); mkdir(get_db_path(root, "var"), 0755);
mkdir(get_db_path(db, "dev"), 0755); mkdir(get_db_path(root, "var/lib"), 0755);
mknod(get_db_path(db, "dev/null"), 0666, makedev(1, 3)); 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; struct stat st;
char *buf; char *buf;
int fd; int fd;
if (db->root == NULL) if (db->root == NULL)
return -1; return 0;
/* Read: /* Read:
* 1. installed repository * 1. installed repository
@ -424,27 +434,24 @@ int apk_db_read_config(struct apk_database *db)
* 5. files db * 5. files db
* 6. script db * 6. script db
*/ */
fd = open(get_db_path(db, "var/lib/apk/world"), O_RDONLY); fd = open(get_db_path(db->root, "var/lib/apk/world"), O_RDONLY);
if (fd >= 0) { if (fd < 0)
fstat(fd, &st); return -1;
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, "var/lib/apk/files"), O_RDONLY); 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->root, "var/lib/apk/files"), O_RDONLY);
if (fd >= 0) { if (fd >= 0) {
apk_db_read_fdb(db, fd); apk_db_read_fdb(db, fd);
close(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) { if (fd >= 0) {
apk_db_read_scriptdb(db, fd); apk_db_read_scriptdb(db, fd);
close(fd); close(fd);
@ -453,37 +460,54 @@ int apk_db_read_config(struct apk_database *db)
return 0; 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 write_ctx {
struct apk_database *db; struct apk_database *db;
int fd; int fd;
}; };
int apk_db_write_config(struct apk_database *db) static int apk_db_write_config(struct apk_database *db)
{ {
char buf[1024]; char buf[1024];
int n, fd; int n, fd;
if (db->root == NULL) if (db->root == NULL)
return -1; return 0;
mkdir(get_db_path(db, "var"), 0755); fd = creat(get_db_path(db->root, "var/lib/apk/world"), 0600);
mkdir(get_db_path(db, "var/lib"), 0755);
mkdir(get_db_path(db, "var/lib/apk"), 0755);
fd = creat(get_db_path(db, "var/lib/apk/world"), 0600);
if (fd < 0) if (fd < 0)
return -1; return -1;
n = apk_deps_format(buf, sizeof(buf), db->world); n = apk_deps_format(buf, sizeof(buf), db->world);
write(fd, buf, n); write(fd, buf, n);
close(fd); 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) if (fd < 0)
return -1; return -1;
apk_db_write_fdb(db, fd); apk_db_write_fdb(db, fd);
close(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) if (fd < 0)
return -1; return -1;
apk_db_write_scriptdb(db, fd); apk_db_write_scriptdb(db, fd);
@ -492,13 +516,17 @@ int apk_db_write_config(struct apk_database *db)
return 0; 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.names);
apk_hash_free(&db->available.packages); apk_hash_free(&db->available.packages);
apk_hash_free(&db->installed.dirs); apk_hash_free(&db->installed.dirs);
if (db->root != NULL) if (db->root != NULL) {
close(db->root_fd);
free(db->root); free(db->root);
}
} }
static void apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg) 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) .url = strdup(repo)
}; };
snprintf(tmp, sizeof(tmp), "%sAPK_INDEX", repo); snprintf(tmp, sizeof(tmp), "%s/APK_INDEX", repo);
fd = open(tmp, O_RDONLY); fd = open(tmp, O_RDONLY);
if (fd < 0) { if (fd < 0) {
apk_error("Failed to open index file %s", tmp); 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; pthread_t tid = 0;
int fd, r; int fd, r;
if (chdir(db->root) < 0) if (fchdir(db->root_fd) < 0)
return errno; return errno;
/* Purge the old package if there */ /* Purge the old package if there */
@ -753,7 +781,7 @@ int apk_db_install_pkg(struct apk_database *db,
/* Install the new stuff */ /* Install the new stuff */
snprintf(file, sizeof(file), snprintf(file, sizeof(file),
"%s%s-%s.apk", "%s/%s-%s.apk",
db->repos[0].url, newpkg->name->name, newpkg->version); db->repos[0].url, newpkg->name->name, newpkg->version);
fd = open(file, O_RDONLY); fd = open(file, O_RDONLY);

View File

@ -18,8 +18,8 @@ static int del_main(int argc, char **argv)
struct apk_database db; struct apk_database db;
int i, j; int i, j;
apk_db_init(&db, "/home/fabled/tmproot/"); if (apk_db_open(&db, apk_root) < 0)
apk_db_read_config(&db); return -1;
if (db.world == NULL) if (db.world == NULL)
goto out; goto out;
@ -38,7 +38,7 @@ static int del_main(int argc, char **argv)
apk_db_recalculate_and_commit(&db); apk_db_recalculate_and_commit(&db);
out: out:
apk_db_free(&db); apk_db_close(&db);
return 0; return 0;
} }

View File

@ -44,12 +44,12 @@ static int index_main(int argc, char **argv)
struct counts counts = {0,0}; struct counts counts = {0,0};
int i; int i;
apk_db_init(&db, NULL); apk_db_open(&db, NULL);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
apk_db_pkg_add_file(&db, argv[i]); apk_db_pkg_add_file(&db, argv[i]);
apk_db_index_write(&db, STDOUT_FILENO); apk_db_index_write(&db, STDOUT_FILENO);
apk_hash_foreach(&db.available.names, warn_if_no_providers, &counts); apk_hash_foreach(&db.available.names, warn_if_no_providers, &counts);
apk_db_free(&db); apk_db_close(&db);
if (counts.unsatisfied != 0) if (counts.unsatisfied != 0)
apk_warning("Total of %d unsatisfiable package " apk_warning("Total of %d unsatisfiable package "

View File

@ -362,26 +362,6 @@ int apk_pkg_run_script(struct apk_package *pkg, const char *root,
return -1; 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; return 0;
} }

View File

@ -44,8 +44,8 @@ static int ver_main(int argc, char **argv)
return 0; return 0;
} }
apk_db_init(&db, "/home/fabled/tmproot/"); if (apk_db_open(&db, apk_root) < 0)
apk_db_read_config(&db); return -1;
hlist_for_each_entry(pkg, c, &db.installed.packages, installed_pkgs_list) { hlist_for_each_entry(pkg, c, &db.installed.packages, installed_pkgs_list) {
name = pkg->name; name = pkg->name;
@ -61,7 +61,7 @@ static int ver_main(int argc, char **argv)
} }
printf("%-40s%c\n", name->name, pkg != upg ? '<' : '='); printf("%-40s%c\n", name->name, pkg != upg ? '<' : '=');
} }
apk_db_free(&db); apk_db_close(&db);
return 0; return 0;
} }