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 \
-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

4
TODO
View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -11,11 +11,17 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/stat.h>
#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)
if (strncmp(prog, "apk_", 4) == 0)
applet = find_applet(prog + 4);
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();
prog = argv[1];
argv++;
argc--;
} else if (strncmp(prog, "apk_", 4) == 0) {
prog += 4;
} else
}
}
argc -= optind;
argv += optind;
if (applet == NULL) {
if (argc > 0)
applet = find_applet(argv[0]);
if (applet == NULL)
return usage();
for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) {
applet = *a;
if (strcmp(prog, applet->name) == 0) {
argv++;
argc--;
argv++;
}
return applet->main(argc, argv);
}
}
return usage();
}

View File

@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -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);

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_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,23 +199,22 @@ 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) {
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) {
if (strncmp(file->filename, bfile.ptr, bfile.len) == 0 &&
@ -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) {
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);
} 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);
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;
return 0;
mkdir(get_db_path(db, "var"), 0755);
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);
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);

View File

@ -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;
}

View File

@ -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 "

View File

@ -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;
}

View File

@ -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;
}