apk: use *at instead of chdir+normal file syscall

this way we never change cwd, and relative filenames are always
parsed consistently. this also helps filename construction in many
places. this patch also changes '--root' to override location of
all configuration to be in the new root. previously it depended
on the file which one was used.
cute-signatures
Timo Teras 2009-07-31 16:08:09 +03:00
parent 67108bf07a
commit ea90152664
19 changed files with 360 additions and 341 deletions

View File

@ -9,6 +9,7 @@ apk-objs := state.o database.o package.o archive.o \
version.o io.o url.o gunzip.o blob.o hash.o apk.o \
add.o del.o update.o info.o search.o upgrade.o \
cache.o ver.o index.o fetch.o audit.o verify.o
CFLAGS += -D_ATFILE_SOURCE
CFLAGS_apk.o := -DAPK_VERSION=\"$(FULL_VERSION)\"
progs-$(STATIC) += apk.static

View File

@ -101,7 +101,7 @@ static int add_main(void *ctx, int argc, char **argv)
goto err;
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY_AND_GENERATE,
NULL);
NULL, db.keys_fd);
r = apk_pkg_read(&db, argv[i], &sctx, &pkg);
apk_sign_ctx_free(&sctx);
if (r != 0) {

View File

@ -26,7 +26,7 @@
const char *apk_root;
struct apk_repository_url apk_repository_list;
int apk_verbosity = 1, apk_cwd_fd, apk_wait;
int apk_verbosity = 1, apk_wait;
unsigned int apk_flags = 0;
static struct apk_option generic_options[] = {
@ -292,7 +292,6 @@ int main(int argc, char **argv)
struct apk_repository_url *repo = NULL;
umask(0);
apk_cwd_fd = open(".", O_RDONLY);
apk_root = getenv("ROOT");
list_init(&apk_repository_list.list);

View File

@ -27,9 +27,8 @@ int apk_tar_write_entry(struct apk_ostream *, const struct apk_file_info *ae,
char *data);
int apk_tar_write_padding(struct apk_ostream *, const struct apk_file_info *ae);
int apk_archive_entry_extract(const struct apk_file_info *ae,
struct apk_istream *is,
const char *to,
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
const char *suffix, struct apk_istream *is,
apk_progress_cb cb, void *cb_ctx);
#endif

View File

@ -80,7 +80,7 @@ struct apk_repository {
struct apk_database {
char *root;
int root_fd, lock_fd;
int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd;
unsigned name_id, num_repos;
const char *cache_dir;
int permanent;
@ -134,7 +134,6 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db,
int apk_db_open(struct apk_database *db, const char *root, unsigned int flags);
int apk_db_write_config(struct apk_database *db);
void apk_db_close(struct apk_database *db);
int apk_db_cache_active(struct apk_database *db);
int apk_db_permanent(struct apk_database *db);
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg);
@ -147,10 +146,11 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os);
int apk_db_add_repository(apk_database_t db, apk_blob_t repository);
int apk_repository_update(struct apk_database *db, struct apk_repository *repo);
int apk_cache_download(struct apk_database *db, struct apk_checksum *csum,
const char *url, const char *item, int verify);
int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum,
const char *item);
int apk_db_cache_active(struct apk_database *db);
void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo, int ver);
int apk_cache_download(struct apk_database *db, const char *url,
const char *item, const char *cache_item, int verify);
int apk_db_install_pkg(struct apk_database *db,
struct apk_package *oldpkg,

View File

@ -48,7 +48,7 @@
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
extern int apk_cwd_fd, apk_verbosity, apk_wait;
extern int apk_verbosity, apk_wait;
extern unsigned int apk_flags;
#define APK_FORCE 0x0001

View File

@ -66,8 +66,8 @@ struct apk_ostream *apk_ostream_gzip(struct apk_ostream *);
struct apk_ostream *apk_ostream_counter(off_t *);
struct apk_istream *apk_istream_from_fd(int fd);
struct apk_istream *apk_istream_from_file(const char *file);
struct apk_istream *apk_istream_from_file_gz(const char *file);
struct apk_istream *apk_istream_from_file(int atfd, const char *file);
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file);
struct apk_istream *apk_istream_from_url(const char *url);
struct apk_istream *apk_istream_from_url_gz(const char *url);
size_t apk_istream_skip(struct apk_istream *istream, size_t size);
@ -76,20 +76,21 @@ size_t apk_istream_splice(void *stream, int fd, size_t size,
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream);
struct apk_bstream *apk_bstream_from_fd(int fd);
struct apk_bstream *apk_bstream_from_file(const char *file);
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file);
struct apk_bstream *apk_bstream_from_url(const char *url);
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, const char *to);
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to);
struct apk_ostream *apk_ostream_to_fd(int fd);
struct apk_ostream *apk_ostream_to_file(const char *file, mode_t mode);
struct apk_ostream *apk_ostream_to_file_gz(const char *file, mode_t mode);
struct apk_ostream *apk_ostream_to_file(int atfd, const char *file, mode_t mode);
struct apk_ostream *apk_ostream_to_file_gz(int atfd, const char *file, mode_t mode);
size_t apk_ostream_write_string(struct apk_ostream *ostream, const char *string);
apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size);
apk_blob_t apk_blob_from_file(const char *file);
apk_blob_t apk_blob_from_file(int atfd, const char *file);
int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi);
int apk_url_download(const char *url, const char *file);
int apk_file_get_info(int atfd, const char *filename, int checksum,
struct apk_file_info *fi);
int apk_url_download(const char *url, int atfd, const char *file);
const char *apk_url_local_file(const char *url);
#endif

View File

@ -38,6 +38,7 @@ struct apk_name;
#define APK_SIGN_VERIFY_AND_GENERATE 5
struct apk_sign_ctx {
int keys_fd;
int action;
const EVP_MD *md;
int num_signatures;
@ -97,7 +98,7 @@ APK_ARRAY(apk_package_array, struct apk_package *);
extern const char *apk_script_types[];
void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action,
struct apk_checksum *identity);
struct apk_checksum *identity, int keys_fd);
void apk_sign_ctx_free(struct apk_sign_ctx *ctx);
int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
const struct apk_file_info *fi,
@ -121,6 +122,8 @@ void apk_deps_parse(struct apk_database *db,
int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os);
int apk_script_type(const char *name);
void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to);
void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to);
struct apk_package *apk_pkg_new(void);
int apk_pkg_read(struct apk_database *db, const char *name,
struct apk_sign_ctx *ctx, struct apk_package **pkg);

View File

@ -309,29 +309,28 @@ int apk_tar_write_padding(struct apk_ostream *os, const struct apk_file_info *ae
return 0;
}
int apk_archive_entry_extract(const struct apk_file_info *ae,
struct apk_istream *is,
const char *fn, apk_progress_cb cb,
void *cb_ctx)
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
const char *suffix, struct apk_istream *is,
apk_progress_cb cb, void *cb_ctx)
{
struct utimbuf utb;
int r = -1, fd;
char *fn = ae->name;
int fd, r = -1, atflags = 0;
if (fn == NULL)
fn = ae->name;
/* BIG HONKING FIXME */
unlink(fn);
if (suffix != NULL) {
fn = alloca(PATH_MAX);
snprintf(fn, PATH_MAX, "%s%s", ae->name, suffix);
}
unlinkat(atfd, fn, 0);
switch (ae->mode & S_IFMT) {
case S_IFDIR:
r = mkdir(fn, ae->mode & 07777);
r = mkdirat(atfd, fn, ae->mode & 07777);
if (r < 0 && errno == EEXIST)
r = 0;
break;
case S_IFREG:
if (ae->link_target == NULL) {
fd = open(fn, O_RDWR | O_CREAT, ae->mode & 07777);
fd = openat(atfd, fn, O_RDWR | O_CREAT, ae->mode & 07777);
if (fd < 0) {
r = -1;
break;
@ -341,27 +340,28 @@ int apk_archive_entry_extract(const struct apk_file_info *ae,
r = 0;
close(fd);
} else {
char link_target[PATH_MAX];
snprintf(link_target, sizeof(link_target),
"%s.apk-new", ae->link_target);
r = link(link_target, fn);
char *link_target = ae->link_target;
if (suffix != NULL) {
link_target = alloca(PATH_MAX);
snprintf(link_target, PATH_MAX, "%s%s",
ae->link_target, suffix);
}
r = linkat(atfd, link_target, atfd, fn, 0);
}
break;
case S_IFLNK:
r = symlink(ae->link_target, fn);
r = symlinkat(ae->link_target, atfd, fn);
atflags |= AT_SYMLINK_NOFOLLOW;
break;
case S_IFSOCK:
case S_IFBLK:
case S_IFCHR:
case S_IFIFO:
r = mknod(fn, ae->mode & 07777, ae->device);
r = mknodat(atfd, fn, ae->mode & 07777, ae->device);
break;
}
if (r == 0) {
if (!S_ISLNK(ae->mode))
r = chown(fn, ae->uid, ae->gid);
else
r = lchown(fn, ae->uid, ae->gid);
r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
if (r < 0) {
apk_error("Failed to set ownership on %s: %s",
fn, strerror(errno));
@ -370,7 +370,7 @@ int apk_archive_entry_extract(const struct apk_file_info *ae,
/* chown resets suid bit so we need set it again */
if (ae->mode & 07000) {
r = chmod(fn, ae->mode & 07777);
r = fchmodat(atfd, fn, ae->mode & 07777, atflags);
if (r < 0) {
apk_error("Failed to set file permissions "
"on %s: %s",
@ -381,8 +381,11 @@ int apk_archive_entry_extract(const struct apk_file_info *ae,
if (!S_ISLNK(ae->mode)) {
/* preserve modification time */
utb.actime = utb.modtime = ae->mtime;
r = utime(fn, &utb);
struct timespec times[2];
times[0].tv_sec = times[1].tv_sec = ae->mtime;
times[0].tv_nsec = times[1].tv_nsec = 0;
r = utimensat(atfd, fn, times, atflags);
if (r < 0) {
apk_error("Failed to preserve modification time on %s: %s",
fn, strerror(errno));

View File

@ -11,6 +11,7 @@
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
@ -42,7 +43,7 @@ static int audit_directory(apk_hash_item item, void *ctx)
if (!(actx->type & AUDIT_BACKUP) && (dbd->flags & APK_DBDIRF_PROTECTED))
return 0;
dir = opendir(dbd->name);
dir = fdopendir(openat(db->root_fd, dbd->name, O_RDONLY));
if (dir == NULL)
return 0;
@ -53,7 +54,7 @@ static int audit_directory(apk_hash_item item, void *ctx)
snprintf(tmp, sizeof(tmp), "%s/%s", dbd->name, de->d_name);
if (apk_file_get_info(tmp, APK_CHECKSUM_NONE, &fi) < 0)
if (apk_file_get_info(db->root_fd, tmp, APK_CHECKSUM_NONE, &fi) < 0)
continue;
if (!(actx->type & AUDIT_SYSTEM) &&
@ -70,7 +71,7 @@ static int audit_directory(apk_hash_item item, void *ctx)
dbf = apk_db_file_query(db, bdir, APK_BLOB_STR(de->d_name));
if (dbf != NULL) {
if (dbf->csum.type != APK_CHECKSUM_NONE &&
apk_file_get_info(tmp, dbf->csum.type, &fi) == 0 &&
apk_file_get_info(db->root_fd, tmp, dbf->csum.type, &fi) == 0 &&
apk_checksum_compare(&fi.csum, &dbf->csum) == 0)
continue;

View File

@ -28,7 +28,7 @@ static int cache_download(struct apk_database *db)
struct apk_state *state;
struct apk_change *change;
struct apk_package *pkg;
char pkgfile[256];
char item[PATH_MAX], cacheitem[PATH_MAX];
int i, r;
if (db->world == NULL)
@ -38,24 +38,27 @@ static int cache_download(struct apk_database *db)
for (i = 0; i < db->world->num; i++) {
r = apk_state_lock_dependency(state, &db->world->item[i]);
if (r != 0) {
apk_error("Unable to select version for '%s'",
db->world->item[i].name->name);
apk_error("Unable to select version for '%s': %d",
db->world->item[i].name->name, r);
goto err;
}
}
list_for_each_entry(change, &state->change_list_head, change_list) {
pkg = change->newpkg;
snprintf(pkgfile, sizeof(pkgfile), "%s-%s.apk",
pkg->name->name, pkg->version);
if (apk_cache_exists(db, &pkg->csum, pkgfile))
apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem));
if (faccessat(db->cache_fd, cacheitem, R_OK, 0) == 0)
continue;
for (i = 0; i < db->num_repos; i++) {
if (!(pkg->repos & BIT(i)))
continue;
r = apk_cache_download(db, &pkg->csum, db->repos[i].url,
pkgfile, APK_SIGN_VERIFY_IDENTITY);
apk_pkg_format_plain(pkg, APK_BLOB_BUF(item));
r = apk_cache_download(db, db->repos[i].url,
item, cacheitem,
APK_SIGN_VERIFY_IDENTITY);
if (r != 0)
return r;
}
@ -68,54 +71,54 @@ err:
static int cache_clean(struct apk_database *db)
{
char tmp[PATH_MAX];
DIR *dir;
struct dirent *de;
char path[256], csum[APK_CACHE_CSUM_BYTES];
int delete, i;
apk_blob_t b, bname, bver;
struct apk_name *name;
snprintf(path, sizeof(path), "%s/%s", db->root, db->cache_dir);
if (chdir(path) != 0)
return -1;
dir = opendir(path);
dir = fdopendir(dup(db->cache_fd));
if (dir == NULL)
return -1;
while ((de = readdir(dir)) != NULL) {
if (de->d_name[0] == '.')
continue;
delete = TRUE;
do {
b = APK_BLOB_STR(de->d_name);
apk_blob_pull_hexdump(&b, APK_BLOB_BUF(csum));
apk_blob_pull_char(&b, '.');
if (apk_blob_compare(b, APK_BLOB_STR(apk_index_gz)) == 0 ||
apk_blob_compare(b, APK_BLOB_STR(apkindex_tar_gz)) == 0) {
if (apk_blob_compare(b, APK_BLOB_STR("installed")) == 0) {
delete = FALSE;
break;
}
if (apk_pkg_parse_name(b, &bname, &bver) < 0) {
/* Index - check for matching repository */
for (i = 0; i < db->num_repos; i++) {
if (memcmp(db->repos[i].csum.data,
csum, APK_CACHE_CSUM_BYTES) != 0)
apk_cache_format_index(APK_BLOB_BUF(tmp), &db->repos[i], 0);
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) != 0) {
apk_cache_format_index(APK_BLOB_BUF(tmp), &db->repos[i], 1);
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) != 0)
continue;
}
delete = 0;
break;
}
} else if (b.len > 4 &&
memcmp(b.ptr+b.len-4, ".apk", 4) == 0) {
} else {
/* Package - search for it */
if (apk_pkg_parse_name(b, &bname, &bver) < 0)
break;
name = apk_db_get_name(db, bname);
if (name == NULL || name->pkgs == NULL)
break;
for (i = 0; i < name->pkgs->num; i++) {
struct apk_package *pkg = name->pkgs->item[i];
if (memcmp(pkg->csum.data, csum, APK_CACHE_CSUM_BYTES) != 0)
apk_pkg_format_cache(pkg, APK_BLOB_BUF(tmp));
if (apk_blob_compare(b, APK_BLOB_STR(tmp)) != 0)
continue;
delete = 0;
break;
}
@ -126,7 +129,7 @@ static int cache_clean(struct apk_database *db)
if (apk_verbosity >= 2)
apk_message("deleting %s", de->d_name);
if (!(apk_flags & APK_SIMULATE))
unlink(de->d_name);
unlinkat(db->cache_fd, de->d_name, 0);
}
}
@ -152,7 +155,7 @@ static int cache_main(void *ctx, int argc, char **argv)
else
return -EINVAL;
r = apk_db_open(&db, apk_root,
r = apk_db_open(&db, apk_root, APK_OPENF_READ |
APK_OPENF_NO_SCRIPTS | APK_OPENF_NO_INSTALLED);
if (r != 0)
return r;

View File

@ -285,16 +285,16 @@ static void apk_db_diri_set(struct apk_db_dir_instance *diri, mode_t mode,
diri->gid = gid;
}
static void apk_db_diri_mkdir(struct apk_db_dir_instance *diri)
static void apk_db_diri_mkdir(struct apk_database *db, struct apk_db_dir_instance *diri)
{
if (mkdir(diri->dir->name, diri->mode) == 0)
chown(diri->dir->name, diri->uid, diri->gid);
if (mkdirat(db->root_fd, diri->dir->name, diri->mode) == 0)
fchownat(db->root_fd, diri->dir->name, diri->uid, diri->gid, 0);
}
static void apk_db_diri_rmdir(struct apk_db_dir_instance *diri)
static void apk_db_diri_rmdir(struct apk_database *db, struct apk_db_dir_instance *diri)
{
if (diri->dir->refs == 1)
rmdir(diri->dir->name);
unlinkat(db->root_fd, diri->dir->name, 1);
}
static void apk_db_diri_free(struct apk_database *db,
@ -409,21 +409,62 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *
return idb;
}
static void apk_db_cache_get_name(char *buf, size_t bufsz,
struct apk_database *db,
struct apk_checksum *csum,
const char *file, int temp)
void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo, int ver)
{
char csumstr[APK_CACHE_CSUM_BYTES*2+1];
apk_blob_t bbuf = APK_BLOB_BUF(csumstr);
apk_blob_push_hexdump(&bbuf,
APK_BLOB_PTR_LEN((char *) csum->data,
/* APKINDEX.12345678.tar.gz */
/* APK_INDEX.12345678.gz */
if (ver == 0)
apk_blob_push_blob(&to, APK_BLOB_STR("APKINDEX."));
else
apk_blob_push_blob(&to, APK_BLOB_STR("APK_INDEX."));
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) repo->csum.data,
APK_CACHE_CSUM_BYTES));
apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1));
if (ver == 0)
apk_blob_push_blob(&to, APK_BLOB_STR(".tar.gz"));
else
apk_blob_push_blob(&to, APK_BLOB_STR(".gz"));
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
}
snprintf(buf, bufsz, "%s/%s/%s.%s%s",
db->root, db->cache_dir, csumstr, file, temp ? ".new" : "");
int apk_cache_download(struct apk_database *db, const char *url,
const char *item, const char *cacheitem, int verify)
{
char fullurl[PATH_MAX];
int r;
snprintf(fullurl, sizeof(fullurl), "%s%s%s",
url, url[strlen(url)-1] == '/' ? "" : "/", item);
apk_message("fetch %s", fullurl);
if (apk_flags & APK_SIMULATE)
return 0;
r = apk_url_download(fullurl, db->cachetmp_fd, cacheitem);
if (r < 0)
return r;
if (verify != APK_SIGN_NONE) {
struct apk_istream *is;
struct apk_sign_ctx sctx;
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
is = apk_bstream_gunzip_mpart(
apk_bstream_from_file(db->cachetmp_fd, cacheitem),
apk_sign_ctx_mpart_cb, &sctx);
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE);
is->close(is);
apk_sign_ctx_free(&sctx);
if (r != 0) {
unlinkat(db->cachetmp_fd, cacheitem, 0);
return r;
}
}
if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
return -errno;
return 0;
}
int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
@ -690,10 +731,8 @@ static int apk_db_read_state(struct apk_database *db, int flags)
* 5. files db
* 6. script db
*/
fchdir(db->root_fd);
if (!(flags & APK_OPENF_NO_WORLD)) {
blob = apk_blob_from_file("var/lib/apk/world");
blob = apk_blob_from_file(db->root_fd, "var/lib/apk/world");
if (APK_BLOB_IS_NULL(blob))
return -ENOENT;
apk_deps_parse(db, &db->world, blob);
@ -704,13 +743,13 @@ static int apk_db_read_state(struct apk_database *db, int flags)
}
if (!(flags & APK_OPENF_NO_INSTALLED)) {
bs = apk_bstream_from_file("var/lib/apk/installed");
bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/installed");
if (bs != NULL) {
apk_db_index_read(db, bs, -1);
bs->close(bs, NULL);
}
bs = apk_bstream_from_file("etc/apk/cache/installed");
bs = apk_bstream_from_file(db->cache_fd, "installed");
if (bs != NULL) {
apk_db_index_read(db, bs, -2);
bs->close(bs, NULL);
@ -718,12 +757,12 @@ static int apk_db_read_state(struct apk_database *db, int flags)
}
if (!(flags & APK_OPENF_NO_SCRIPTS)) {
is = apk_istream_from_file("var/lib/apk/scripts.tar");
is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts.tar");
if (is != NULL) {
apk_tar_parse(is, apk_read_script_archive_entry, db,
FALSE);
} else {
is = apk_istream_from_file("var/lib/apk/scripts");
is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts");
if (is != NULL)
apk_db_scriptdb_read_v1(db, is);
}
@ -772,10 +811,11 @@ static int apk_db_index_write_nr_cache(struct apk_database *db)
/* Write list of installed non-repository packages to
* cached index file */
ctx.os = os = apk_ostream_to_file("etc/apk/cache/installed.new", 0644);
os = apk_ostream_to_file(db->cache_fd, "installed.new", 0644);
if (os == NULL)
return -1;
ctx.os = os;
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
if (pkg->repos != 0)
continue;
@ -785,8 +825,8 @@ static int apk_db_index_write_nr_cache(struct apk_database *db)
}
os->close(os);
if (rename("etc/apk/cache/installed.new",
"etc/apk/cache/installed") < 0)
if (renameat(db->cache_fd, "installed.new",
db->cache_fd, "installed") < 0)
return -errno;
return ctx.count;
@ -815,15 +855,14 @@ static int apk_db_create(struct apk_database *db)
"apk-tools alpine-conf");
int fd;
fchdir(db->root_fd);
mkdir("tmp", 01777);
mkdir("dev", 0755);
mknod("dev/null", 0666, makedev(1, 3));
mkdir("var", 0755);
mkdir("var/lib", 0755);
mkdir("var/lib/apk", 0755);
mkdirat(db->root_fd, "tmp", 01777);
mkdirat(db->root_fd, "dev", 0755);
mknodat(db->root_fd, "dev/null", 0666, makedev(1, 3));
mkdirat(db->root_fd, "var", 0755);
mkdirat(db->root_fd, "var/lib", 0755);
mkdirat(db->root_fd, "var/lib/apk", 0755);
fd = creat("var/lib/apk/world", 0644);
fd = openat(db->root_fd, "var/lib/apk/world", O_CREAT|O_RDWR|O_TRUNC, 0644);
if (fd < 0)
return -errno;
write(fd, deps.ptr, deps.len);
@ -840,7 +879,7 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
{
const char *apk_repos = getenv("APK_REPOS"), *msg = NULL;
struct apk_repository_url *repo = NULL;
struct stat st;
struct stat64 st;
apk_blob_t blob;
int r;
@ -854,27 +893,26 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
db->permanent = 1;
if (root != NULL) {
fchdir(apk_cwd_fd);
db->root = strdup(root);
db->root_fd = open(root, O_RDONLY);
db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY);
if (db->root_fd < 0 && (flags & APK_OPENF_CREATE)) {
mkdir(db->root, 0755);
db->root_fd = open(root, O_RDONLY);
mkdirat(AT_FDCWD, db->root, 0755);
db->root_fd = openat(AT_FDCWD, root, O_RDONLY);
}
if (db->root_fd < 0) {
msg = "Unable to open root";
goto ret_errno;
}
if (fstat(db->root_fd, &st) != 0 || major(st.st_dev) == 0)
if (fstat64(db->root_fd, &st) != 0 || major(st.st_dev) == 0)
db->permanent = 0;
fchdir(db->root_fd);
if (stat(apk_linked_cache_dir, &st) == 0 && S_ISDIR(st.st_mode))
if (fstatat64(db->root_fd, apk_linked_cache_dir, &st, 0) == 0 &&
S_ISDIR(st.st_mode))
db->cache_dir = apk_linked_cache_dir;
if (flags & APK_OPENF_WRITE) {
db->lock_fd = open("var/lib/apk/lock",
O_CREAT | O_WRONLY, 0400);
db->lock_fd = openat(db->root_fd, "var/lib/apk/lock",
O_CREAT | O_RDWR, 0400);
if (db->lock_fd < 0 && errno == ENOENT &&
(flags & APK_OPENF_CREATE)) {
r = apk_db_create(db);
@ -882,8 +920,9 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
msg = "Unable to create database";
goto ret_r;
}
db->lock_fd = open("var/lib/apk/lock",
O_CREAT | O_WRONLY, 0400);
db->lock_fd = openat(db->root_fd,
"var/lib/apk/lock",
O_CREAT | O_RDWR, 0400);
}
if (db->lock_fd < 0 ||
flock(db->lock_fd, LOCK_EX | LOCK_NB) < 0) {
@ -912,6 +951,11 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
blob = APK_BLOB_STR("etc:*etc/init.d");
apk_blob_for_each_segment(blob, ":", add_protected_path, db);
db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY);
mkdirat(db->cache_fd, "tmp", 0644);
db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY);
db->keys_fd = openat(db->root_fd, "etc/apk/keys", O_RDONLY);
if (root != NULL) {
r = apk_db_read_state(db, flags);
if (r == -ENOENT && (flags & APK_OPENF_CREATE)) {
@ -929,8 +973,8 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
if (!(flags & APK_OPENF_NO_REPOS)) {
if (apk_repos == NULL)
apk_repos = "/etc/apk/repositories";
blob = apk_blob_from_file(apk_repos);
apk_repos = "etc/apk/repositories";
blob = apk_blob_from_file(db->root_fd, apk_repos);
if (!APK_BLOB_IS_NULL(blob)) {
apk_blob_for_each_segment(blob, "\n",
apk_db_add_repository, db);
@ -947,7 +991,6 @@ int apk_db_open(struct apk_database *db, const char *root, unsigned int flags)
apk_db_index_write_nr_cache(db);
}
fchdir(apk_cwd_fd);
return 0;
ret_errno:
@ -956,7 +999,7 @@ ret_r:
if (msg != NULL)
apk_error("%s: %s", msg, strerror(-r));
apk_db_close(db);
fchdir(apk_cwd_fd);
return r;
}
@ -977,35 +1020,36 @@ int apk_db_write_config(struct apk_database *db)
return -1;
}
fchdir(db->root_fd);
os = apk_ostream_to_file("var/lib/apk/world.new", 0644);
os = apk_ostream_to_file(db->root_fd, "var/lib/apk/world.new", 0644);
if (os == NULL)
return -1;
apk_deps_write(db->world, os);
os->write(os, "\n", 1);
os->close(os);
if (rename("var/lib/apk/world.new", "var/lib/apk/world") < 0)
if (renameat(db->root_fd, "var/lib/apk/world.new",
db->root_fd, "var/lib/apk/world") < 0)
return -errno;
os = apk_ostream_to_file("var/lib/apk/installed.new", 0644);
os = apk_ostream_to_file(db->root_fd, "var/lib/apk/installed.new", 0644);
if (os == NULL)
return -1;
apk_db_write_fdb(db, os);
os->close(os);
if (rename("var/lib/apk/installed.new", "var/lib/apk/installed") < 0)
if (renameat(db->root_fd, "var/lib/apk/installed.new",
db->root_fd, "var/lib/apk/installed") < 0)
return -errno;
os = apk_ostream_to_file("var/lib/apk/scripts.tar.new", 0644);
os = apk_ostream_to_file(db->root_fd, "var/lib/apk/scripts.tar.new", 0644);
if (os == NULL)
return -1;
apk_db_scriptdb_write(db, os);
os->close(os);
if (rename("var/lib/apk/scripts.tar.new", "var/lib/apk/scripts.tar") < 0)
if (renameat(db->root_fd, "var/lib/apk/scripts.tar.new",
db->root_fd, "var/lib/apk/scripts.tar") < 0)
return -errno;
unlink("var/lib/apk/scripts");
unlinkat(db->root_fd, "var/lib/apk/scripts", 0);
apk_db_index_write_nr_cache(db);
return 0;
@ -1040,6 +1084,12 @@ void apk_db_close(struct apk_database *db)
apk_hash_free(&db->installed.files);
apk_hash_free(&db->installed.dirs);
if (db->keys_fd)
close(db->keys_fd);
if (db->cachetmp_fd)
close(db->cachetmp_fd);
if (db->cache_fd)
close(db->cache_fd);
if (db->root_fd)
close(db->root_fd);
if (db->lock_fd)
@ -1084,19 +1134,6 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db,
return dbf->diri->pkg;
}
static struct apk_bstream *apk_db_cache_open(struct apk_database *db,
struct apk_checksum *csum,
const char *file)
{
char tmp[256];
if (db->root == NULL)
return NULL;
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, file, FALSE);
return apk_bstream_from_file(tmp);
}
static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo,
const char *file)
{
@ -1109,91 +1146,26 @@ static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo,
return apk_bstream_from_url(tmp);
}
int apk_cache_download(struct apk_database *db, struct apk_checksum *csum,
const char *url, const char *item, int verify)
{
char tmp[256], tmp2[256];
int r;
snprintf(tmp, sizeof(tmp), "%s%s%s",
url, url[strlen(url)-1] == '/' ? "" : "/", item);
apk_message("fetch %s", tmp);
if (apk_flags & APK_SIMULATE)
return 0;
apk_db_cache_get_name(tmp2, sizeof(tmp2), db, csum, item, TRUE);
r = apk_url_download(tmp, tmp2);
if (r < 0)
return r;
if (verify != APK_SIGN_NONE) {
struct apk_istream *is;
struct apk_sign_ctx sctx;
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(tmp2),
apk_sign_ctx_mpart_cb, &sctx);
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE);
is->close(is);
apk_sign_ctx_free(&sctx);
if (r != 0) {
unlink(tmp2);
return r;
}
}
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, item, FALSE);
if (rename(tmp2, tmp) < 0)
return -errno;
return 0;
}
int apk_cache_exists(struct apk_database *db, struct apk_checksum *csum,
const char *item)
{
char tmp[256];
if (db->root == NULL)
return 0;
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, item, FALSE);
return access(tmp, R_OK | W_OK) == 0;
}
static int apk_cache_delete(struct apk_database *db, struct apk_checksum *csum,
const char *item)
{
char tmp[256];
if (db->root == NULL)
return 0;
apk_db_cache_get_name(tmp, sizeof(tmp), db, csum, item, FALSE);
return unlink(tmp);
}
int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
{
char cacheitem[PATH_MAX];
int r;
if (repo->csum.type == APK_CHECKSUM_NONE)
return 0;
r = apk_cache_download(db, &repo->csum, repo->url, apkindex_tar_gz,
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo, 0);
r = apk_cache_download(db, repo->url, apkindex_tar_gz, cacheitem,
(apk_flags & APK_ALLOW_UNTRUSTED) ?
APK_SIGN_NONE : APK_SIGN_VERIFY);
if (r == 0 || r == -ENOKEY || r == -EKEYREJECTED) {
if (r == -ENOKEY)
apk_error("%s: verify: UNTRUSTED", repo->url);
else if (r == -EKEYREJECTED)
apk_error("%s: verify: FAILED", repo->url);
apk_cache_delete(db, &repo->csum, apk_index_gz);
if (r != 0)
apk_error("%s: %s", repo->url, apk_error_str(r));
return r;
}
r = apk_cache_download(db, &repo->csum, repo->url, apk_index_gz,
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo, 1);
r = apk_cache_download(db, repo->url, apk_index_gz, cacheitem,
APK_SIGN_NONE);
if (r != 0)
apk_error("Failed to update %s: download failed", repo->url);
@ -1238,7 +1210,7 @@ static int load_index(struct apk_database *db, struct apk_bstream *bs,
ctx.db = db;
ctx.repo = repo;
ctx.found = 0;
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL);
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx);
r = apk_tar_parse(is, load_apkindex, &ctx, FALSE);
is->close(is);
@ -1260,7 +1232,7 @@ int apk_db_index_read_file(struct apk_database *db, const char *file, int repo)
if (strstr(file, ".tar.gz") == NULL && strstr(file, ".gz") != NULL)
targz = 0;
return load_index(db, apk_bstream_from_file(file), targz, repo);
return load_index(db, apk_bstream_from_file(AT_FDCWD, file), targz, repo);
}
int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
@ -1285,14 +1257,18 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
};
if (apk_url_local_file(repo->url) == NULL) {
char cacheitem[PATH_MAX];
apk_blob_checksum(repository, apk_default_checksum(), &repo->csum);
if (apk_flags & APK_UPDATE_CACHE)
apk_repository_update(db, repo);
bs = apk_db_cache_open(db, &repo->csum, apkindex_tar_gz);
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo, 0);
bs = apk_bstream_from_file(db->cache_fd, cacheitem);
if (bs == NULL) {
bs = apk_db_cache_open(db, &repo->csum, apk_index_gz);
apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo, 1);
bs = apk_bstream_from_file(db->cache_fd, cacheitem);
targz = 0;
}
} else {
@ -1356,7 +1332,6 @@ static int apk_db_install_archive_entry(void *_ctx,
apk_blob_t name = APK_BLOB_STR(ae->name), bdir, bfile;
struct apk_db_dir_instance *diri = ctx->diri;
struct apk_db_file *file;
char alt_name[PATH_MAX];
const char *p;
int r = 0, type = APK_SCRIPT_INVALID;
@ -1455,9 +1430,7 @@ static int apk_db_install_archive_entry(void *_ctx,
apk_message("%s", ae->name);
/* Extract the file as name.apk-new */
snprintf(alt_name, sizeof(alt_name), "%s/%s.apk-new",
diri->dir->name, file->name);
r = apk_archive_entry_extract(ae, is, alt_name,
r = apk_archive_entry_extract(db->root_fd, ae, ".apk-new", is,
extract_cb, ctx);
memcpy(&file->csum, &ae->csum, sizeof(file->csum));
} else {
@ -1474,7 +1447,7 @@ static int apk_db_install_archive_entry(void *_ctx,
ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
apk_db_diri_set(diri, ae->mode & 0777, ae->uid, ae->gid);
apk_db_diri_mkdir(diri);
apk_db_diri_mkdir(db, diri);
}
ctx->installed_size += ctx->current_file_size;
@ -1505,9 +1478,9 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_package *pkg,
if (!(diri->dir->flags & APK_DBDIRF_PROTECTED) ||
(apk_flags & APK_PURGE) ||
(file->csum.type != APK_CHECKSUM_NONE &&
apk_file_get_info(name, file->csum.type, &fi) == 0 &&
apk_file_get_info(db->root_fd, name, file->csum.type, &fi) == 0 &&
apk_checksum_compare(&file->csum, &fi.csum) == 0))
unlink(name);
unlinkat(db->root_fd, name, 0);
if (apk_verbosity >= 3)
apk_message("%s", name);
__hlist_del(fc, &diri->owned_files.first);
@ -1516,7 +1489,7 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_package *pkg,
db->installed.stats.files--;
}
}
apk_db_diri_rmdir(diri);
apk_db_diri_rmdir(db, diri);
__hlist_del(dc, &pkg->owned_dirs.first);
apk_db_diri_free(db, diri);
}
@ -1564,7 +1537,7 @@ static void apk_db_migrate_files(struct apk_database *db,
(diri->dir->flags & APK_DBDIRF_PROTECTED))
cstype = ofile->csum.type;
r = apk_file_get_info(name, cstype, &fi);
r = apk_file_get_info(db->root_fd, name, cstype, &fi);
if ((diri->dir->flags & APK_DBDIRF_PROTECTED) &&
(r == 0) &&
(ofile == NULL ||
@ -1577,14 +1550,15 @@ static void apk_db_migrate_files(struct apk_database *db,
* existing file */
if (ofile == NULL ||
ofile->csum.type != file->csum.type)
apk_file_get_info(name, file->csum.type, &fi);
apk_file_get_info(db->root_fd, name, file->csum.type, &fi);
if ((apk_flags & APK_CLEAN_PROTECTED) ||
(file->csum.type != APK_CHECKSUM_NONE &&
apk_checksum_compare(&file->csum, &fi.csum) == 0))
unlink(tmpname);
unlinkat(db->root_fd, tmpname, 0);
} else {
/* Overwrite the old file */
rename(tmpname, name);
renameat(db->root_fd, tmpname,
db->root_fd, name);
}
/* Claim ownership of the file in db */
@ -1608,12 +1582,9 @@ static int apk_db_unpack_pkg(struct apk_database *db,
struct install_ctx ctx;
struct apk_bstream *bs = NULL;
struct apk_istream *tar;
char pkgname[256], file[256];
char file[PATH_MAX];
int r, i, need_copy = FALSE;
snprintf(pkgname, sizeof(pkgname), "%s-%s.apk",
newpkg->name->name, newpkg->version);
if (newpkg->filename == NULL) {
struct apk_repository *repo;
@ -1629,24 +1600,26 @@ static int apk_db_unpack_pkg(struct apk_database *db,
repo = &db->repos[i];
if (apk_db_cache_active(db) &&
repo->csum.type != APK_CHECKSUM_NONE)
bs = apk_db_cache_open(db, &newpkg->csum, pkgname);
repo->csum.type != APK_CHECKSUM_NONE) {
apk_pkg_format_cache(newpkg, APK_BLOB_BUF(file));
bs = apk_bstream_from_file(db->cache_fd, file);
}
if (bs == NULL) {
bs = apk_repository_file_open(repo, pkgname);
apk_pkg_format_plain(newpkg, APK_BLOB_BUF(file));
bs = apk_repository_file_open(repo, file);
if (repo->csum.type != APK_CHECKSUM_NONE)
need_copy = TRUE;
}
} else {
bs = apk_bstream_from_file(newpkg->filename);
bs = apk_bstream_from_file(AT_FDCWD, newpkg->filename);
need_copy = TRUE;
}
if (!apk_db_cache_active(db))
need_copy = FALSE;
if (need_copy) {
apk_db_cache_get_name(file, sizeof(file), db, &newpkg->csum,
pkgname, TRUE);
bs = apk_bstream_tee(bs, file);
apk_pkg_format_cache(newpkg, APK_BLOB_BUF(file));
bs = apk_bstream_tee(bs, db->cachetmp_fd, file);
}
if (bs == NULL) {
@ -1662,7 +1635,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
.cb = cb,
.cb_ctx = cb_ctx,
};
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &newpkg->csum);
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &newpkg->csum, db->keys_fd);
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx);
r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, TRUE);
apk_sign_ctx_free(&ctx.sctx);
@ -1680,12 +1653,8 @@ static int apk_db_unpack_pkg(struct apk_database *db,
apk_db_migrate_files(db, newpkg);
if (need_copy) {
char file2[256];
apk_db_cache_get_name(file2, sizeof(file2), db,
&newpkg->csum, pkgname, FALSE);
rename(file, file2);
}
if (need_copy)
renameat(db->cachetmp_fd, file, db->cache_fd, file);
return 0;
err:
@ -1700,9 +1669,6 @@ int apk_db_install_pkg(struct apk_database *db,
{
int r;
if (fchdir(db->root_fd) < 0)
return errno;
/* Just purging? */
if (oldpkg != NULL && newpkg == NULL) {
r = apk_pkg_run_script(oldpkg, db->root_fd,

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <zlib.h>
@ -26,7 +27,7 @@
struct fetch_ctx {
unsigned int flags;
const char *outdir;
int outdir_fd;
};
static int cup(void)
@ -80,7 +81,7 @@ static int fetch_parse(void *ctx, int optch, int optindex, const char *optarg)
fctx->flags |= FETCH_LINK;
break;
case 'o':
fctx->outdir = optarg;
fctx->outdir_fd = openat(AT_FDCWD, optarg, O_RDONLY);
break;
default:
return -1;
@ -93,22 +94,21 @@ static int fetch_package(struct fetch_ctx *fctx,
struct apk_package *pkg)
{
struct apk_istream *is;
char infile[256];
char outfile[256];
char pkgfile[PATH_MAX], url[PATH_MAX];
int i, r, fd;
apk_pkg_format_plain(pkg, APK_BLOB_BUF(pkgfile));
if (!(fctx->flags & FETCH_STDOUT)) {
struct stat st;
struct apk_file_info fi;
snprintf(outfile, sizeof(outfile), "%s/%s-%s.apk",
fctx->outdir ? fctx->outdir : ".",
pkg->name->name, pkg->version);
if (lstat(outfile, &st) == 0 && st.st_size == pkg->size)
if (apk_file_get_info(fctx->outdir_fd, pkgfile,
APK_CHECKSUM_NONE, &fi) == 0 &&
fi.size == pkg->size)
return 0;
}
apk_message("Downloading %s-%s", pkg->name->name, pkg->version);
apk_message("Downloading %s-%s", pkg->name->name, pkg->version);
for (i = 0; i < APK_MAX_REPOS; i++)
if (pkg->repos & BIT(i))
break;
@ -122,31 +122,30 @@ static int fetch_package(struct fetch_ctx *fctx,
if (apk_flags & APK_SIMULATE)
return 0;
snprintf(infile, sizeof(infile), "%s/%s-%s.apk",
db->repos[i].url, pkg->name->name, pkg->version);
snprintf(url, sizeof(url), "%s%s%s", db->repos[i].url,
db->repos[i].url[strlen(db->repos[i].url)-1] == '/' ? "" : "/",
pkgfile);
if (fctx->flags & FETCH_STDOUT) {
fd = STDOUT_FILENO;
} else {
if ((fctx->flags & FETCH_LINK) && apk_url_local_file(infile)) {
char real_infile[256];
int n;
n = readlink(infile, real_infile, sizeof(real_infile));
if (n > 0 && n < sizeof(real_infile))
real_infile[n] = '\0';
if (link(real_infile, outfile) == 0)
if ((fctx->flags & FETCH_LINK) && apk_url_local_file(url)) {
if (linkat(AT_FDCWD, url,
fctx->outdir_fd, pkgfile,
AT_SYMLINK_FOLLOW) == 0)
return 0;
}
fd = creat(outfile, 0644);
fd = openat(fctx->outdir_fd, pkgfile,
O_CREAT|O_RDWR|O_TRUNC, 0644);
if (fd < 0) {
apk_error("%s: %s", outfile, strerror(errno));
apk_error("%s: %s", pkgfile, strerror(errno));
return -1;
}
}
is = apk_istream_from_url(infile);
is = apk_istream_from_url(url);
if (is == NULL) {
apk_error("Unable to download '%s'", infile);
apk_error("Unable to download '%s'", url);
return -1;
}
@ -155,8 +154,8 @@ static int fetch_package(struct fetch_ctx *fctx,
if (fd != STDOUT_FILENO)
close(fd);
if (r != pkg->size) {
apk_error("Unable to download '%s'", infile);
unlink(outfile);
apk_error("Unable to download '%s'", url);
unlinkat(fctx->outdir_fd, pkgfile, 0);
return -1;
}
@ -169,6 +168,9 @@ static int fetch_main(void *ctx, int argc, char **argv)
struct apk_database db;
int i, j, r;
if (fctx->outdir_fd == 0)
fctx->outdir_fd = AT_FDCWD;
if ((argc > 0) && (strcmp(argv[0], "coffee") == 0)) {
if (apk_flags & APK_FORCE)
return cup();

View File

@ -55,7 +55,7 @@ static int index_read_file(struct apk_database *db, struct index_ctx *ictx)
if (ictx->index == NULL)
return 0;
if (apk_file_get_info(ictx->index, APK_CHECKSUM_NONE, &fi) < 0)
if (apk_file_get_info(AT_FDCWD, ictx->index, APK_CHECKSUM_NONE, &fi) < 0)
return -1;
ictx->index_mtime = fi.mtime;
@ -107,7 +107,7 @@ static int index_main(void *ctx, int argc, char **argv)
}
for (i = 0; i < argc; i++) {
if (apk_file_get_info(argv[i], APK_CHECKSUM_NONE, &fi) < 0) {
if (apk_file_get_info(AT_FDCWD, argv[i], APK_CHECKSUM_NONE, &fi) < 0) {
apk_warning("File '%s' is unaccessible", argv[i]);
continue;
}
@ -154,7 +154,7 @@ static int index_main(void *ctx, int argc, char **argv)
if (!found) {
struct apk_sign_ctx sctx;
apk_sign_ctx_init(&sctx, ictx->method, NULL);
apk_sign_ctx_init(&sctx, ictx->method, NULL, db.keys_fd);
if (apk_pkg_read(&db, argv[i], &sctx, NULL) == 0)
newpkgs++;
apk_sign_ctx_free(&sctx);
@ -171,7 +171,7 @@ static int index_main(void *ctx, int argc, char **argv)
}
if (ictx->output != NULL)
os = apk_ostream_to_file(ictx->output, 0644);
os = apk_ostream_to_file(AT_FDCWD, ictx->output, 0644);
else
os = apk_ostream_to_fd(STDOUT_FILENO);
if (ictx->method == APK_SIGN_GENERATE) {

View File

@ -77,11 +77,11 @@ struct apk_istream *apk_istream_from_fd(int fd)
return &fis->is;
}
struct apk_istream *apk_istream_from_file(const char *file)
struct apk_istream *apk_istream_from_file(int atfd, const char *file)
{
int fd;
fd = open(file, O_RDONLY);
fd = openat(atfd, file, O_RDONLY);
if (fd < 0)
return NULL;
@ -342,11 +342,11 @@ struct apk_bstream *apk_bstream_from_fd(int fd)
return apk_bstream_from_istream(apk_istream_from_fd(fd));
}
struct apk_bstream *apk_bstream_from_file(const char *file)
struct apk_bstream *apk_bstream_from_file(int atfd, const char *file)
{
int fd;
fd = open(file, O_RDONLY);
fd = openat(atfd, file, O_RDONLY);
if (fd < 0)
return NULL;
@ -387,12 +387,13 @@ static void tee_close(void *stream, size_t *size)
free(tbs);
}
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, const char *to)
struct apk_bstream *apk_bstream_tee(struct apk_bstream *from, int atfd, const char *to)
{
struct apk_tee_bstream *tbs;
int fd;
fd = creat(to, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
fd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0)
return NULL;
@ -433,13 +434,13 @@ apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size)
return APK_BLOB_PTR_LEN(ptr, rsize);
}
apk_blob_t apk_blob_from_file(const char *file)
apk_blob_t apk_blob_from_file(int atfd, const char *file)
{
int fd;
struct stat st;
char *buf;
fd = open(file, O_RDONLY);
fd = openat(atfd, file, O_RDONLY);
if (fd < 0)
return APK_BLOB_NULL;
@ -462,12 +463,13 @@ err_fd:
return APK_BLOB_NULL;
}
int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *fi)
int apk_file_get_info(int atfd, const char *filename, int checksum,
struct apk_file_info *fi)
{
struct stat st;
struct stat64 st;
struct apk_bstream *bs;
if (lstat(filename, &st) != 0)
if (fstatat64(atfd, filename, &st, AT_SYMLINK_NOFOLLOW) != 0)
return -errno;
*fi = (struct apk_file_info) {
@ -482,7 +484,7 @@ int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *
if (checksum == APK_CHECKSUM_NONE)
return 0;
bs = apk_bstream_from_file(filename);
bs = apk_bstream_from_file(atfd, filename);
if (bs != NULL) {
EVP_MD_CTX mdctx;
apk_blob_t blob;
@ -501,9 +503,9 @@ int apk_file_get_info(const char *filename, int checksum, struct apk_file_info *
return 0;
}
struct apk_istream *apk_istream_from_file_gz(const char *file)
struct apk_istream *apk_istream_from_file_gz(int atfd, const char *file)
{
return apk_bstream_gunzip(apk_bstream_from_file(file));
return apk_bstream_gunzip(apk_bstream_from_file(atfd, file));
}
struct apk_fd_ostream {
@ -593,11 +595,11 @@ struct apk_ostream *apk_ostream_to_fd(int fd)
return &fos->os;
}
struct apk_ostream *apk_ostream_to_file(const char *file, mode_t mode)
struct apk_ostream *apk_ostream_to_file(int atfd, const char *file, mode_t mode)
{
int fd;
fd = creat(file, mode);
fd = openat(atfd, file, O_CREAT | O_RDWR | O_TRUNC, mode);
if (fd < 0)
return NULL;

View File

@ -28,6 +28,29 @@
#include "apk_database.h"
#include "apk_state.h"
void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to)
{
/* pkgname-1.0.apk */
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->name->name));
apk_blob_push_blob(&to, APK_BLOB_STR("-"));
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->version));
apk_blob_push_blob(&to, APK_BLOB_STR(".apk"));
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
}
void apk_pkg_format_cache(struct apk_package *pkg, apk_blob_t to)
{
/* pkgname-1.0_alpha1.12345678.apk */
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->name->name));
apk_blob_push_blob(&to, APK_BLOB_STR("-"));
apk_blob_push_blob(&to, APK_BLOB_STR(pkg->version));
apk_blob_push_blob(&to, APK_BLOB_STR("."));
apk_blob_push_hexdump(&to, APK_BLOB_PTR_LEN((char *) pkg->csum.data,
APK_CACHE_CSUM_BYTES));
apk_blob_push_blob(&to, APK_BLOB_STR(".apk"));
apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1));
}
struct apk_package *apk_pkg_new(void)
{
struct apk_package *pkg;
@ -56,6 +79,9 @@ int apk_pkg_parse_name(apk_blob_t apkname,
if (++dash >= 2)
return -1;
}
if (i < 0)
return -1;
if (name != NULL)
*name = APK_BLOB_PTR_LEN(apkname.ptr, i);
if (version != NULL)
@ -282,9 +308,10 @@ int apk_script_type(const char *name)
}
void apk_sign_ctx_init(struct apk_sign_ctx *ctx, int action,
struct apk_checksum *identity)
struct apk_checksum *identity, int keys_fd)
{
memset(ctx, 0, sizeof(struct apk_sign_ctx));
ctx->keys_fd = keys_fd;
ctx->action = action;
switch (action) {
case APK_SIGN_NONE:
@ -359,14 +386,19 @@ int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx,
ctx->signature.pkey != NULL)
return 0;
if (ctx->keys_fd < 0)
return 0;
if (strncmp(&fi->name[6], "RSA.", 4) == 0 ||
strncmp(&fi->name[6], "DSA.", 4) == 0) {
char file[256];
BIO *bio = BIO_new(BIO_s_file());
snprintf(file, sizeof(file), "/etc/apk/keys/%s", &fi->name[10]);
if (BIO_read_filename(bio, file) > 0)
ctx->signature.pkey =
PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
int fd = openat(ctx->keys_fd, &fi->name[10], O_RDONLY);
BIO *bio;
if (fd < 0)
return 0;
bio = BIO_new_fp(fdopen(fd, "r"), 0);
ctx->signature.pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
if (ctx->signature.pkey != NULL) {
if (fi->name[6] == 'R')
ctx->md = EVP_sha1();
@ -690,12 +722,9 @@ int apk_pkg_read(struct apk_database *db, const char *file,
struct apk_file_info fi;
struct apk_bstream *bs;
struct apk_istream *tar;
char realfile[PATH_MAX];
int r;
if (realpath(file, realfile) < 0)
return -errno;
r = apk_file_get_info(realfile, APK_CHECKSUM_NONE, &fi);
r = apk_file_get_info(AT_FDCWD, file, APK_CHECKSUM_NONE, &fi);
if (r != 0)
return r;
@ -705,7 +734,7 @@ int apk_pkg_read(struct apk_database *db, const char *file,
r = -ENOMEM;
if (ctx.pkg == NULL)
goto err;
bs = apk_bstream_from_file(realfile);
bs = apk_bstream_from_file(AT_FDCWD, file);
if (bs == NULL)
goto err;
@ -723,7 +752,7 @@ int apk_pkg_read(struct apk_database *db, const char *file,
}
if (sctx->action != APK_SIGN_VERIFY)
ctx.pkg->csum = sctx->identity;
ctx.pkg->filename = strdup(realfile);
ctx.pkg->filename = strdup(file);
ctx.pkg = apk_db_pkg_add(db, ctx.pkg);
if (pkg != NULL)
@ -814,18 +843,17 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
struct hlist_node *c;
int fd, status;
pid_t pid;
char fn[1024];
char fn[PATH_MAX];
fchdir(root_fd);
hlist_for_each_entry(script, c, &pkg->scripts, script_list) {
if (script->type != type)
continue;
snprintf(fn, sizeof(fn),
"tmp/%s-%s.%s",
snprintf(fn, sizeof(fn), "tmp/%s-%s.%s",
pkg->name->name, pkg->version,
apk_script_types[type]);
fd = creat(fn, 0777);
fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC, 0777);
if (fd < 0)
return fd;
write(fd, script->script, script->size);
@ -837,6 +865,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
if (pid == -1)
return -1;
if (pid == 0) {
fchdir(root_fd);
if (chroot(".") < 0) {
apk_error("chroot: %s", strerror(errno));
} else {
@ -846,7 +875,7 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd,
exit(1);
}
waitpid(pid, &status, 0);
unlink(fn);
unlinkat(root_fd, fn, 0);
if (WIFEXITED(status))
return WEXITSTATUS(status);
return -1;

View File

@ -711,7 +711,7 @@ int apk_state_commit(struct apk_state *state,
if (apk_flags & APK_PROGRESS)
apk_draw_progress(20, 1);
if (!(apk_flags & APK_SIMULATE) && prog.done.packages != 0)
if (!(apk_flags & APK_SIMULATE))
apk_db_write_config(db);
if (r == 0)

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
@ -61,7 +62,7 @@ static int fork_wget(const char *url)
struct apk_istream *apk_istream_from_url(const char *url)
{
if (apk_url_local_file(url) != NULL)
return apk_istream_from_file(apk_url_local_file(url));
return apk_istream_from_file(AT_FDCWD, apk_url_local_file(url));
return apk_istream_from_fd(fork_wget(url));
}
@ -74,16 +75,19 @@ struct apk_istream *apk_istream_from_url_gz(const char *file)
struct apk_bstream *apk_bstream_from_url(const char *url)
{
if (apk_url_local_file(url))
return apk_bstream_from_file(url);
return apk_bstream_from_file(AT_FDCWD, url);
return apk_bstream_from_fd(fork_wget(url));
}
int apk_url_download(const char *url, const char *file)
int apk_url_download(const char *url, int atfd, const char *file)
{
pid_t pid;
int status;
char tmp[256];
int status, fd;
fd = openat(atfd, file, O_CREAT|O_RDWR|O_TRUNC, 0644);
if (fd < 0)
return -errno;
pid = fork();
if (pid == -1)
@ -92,15 +96,14 @@ int apk_url_download(const char *url, const char *file)
if (pid == 0) {
setsid();
dup2(open("/dev/null", O_RDONLY), STDIN_FILENO);
snprintf(tmp, sizeof(tmp), "%s.backup", file);
rename(file, tmp);
execlp("wget", "wget", "-q", "-O", file, url, NULL);
dup2(fd, STDOUT_FILENO);
execlp("wget", "wget", "-q", "-O", "-", url, NULL);
exit(0);
}
waitpid(pid, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
unlink(file);
unlinkat(atfd, file, 0);
return -1;
}

View File

@ -10,6 +10,7 @@
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "apk_applet.h"
@ -19,12 +20,17 @@ static int verify_main(void *ctx, int argc, char **argv)
{
struct apk_sign_ctx sctx;
struct apk_istream *is;
struct apk_database db;
int i, r, ok, rc = 0;
apk_flags |= APK_ALLOW_UNTRUSTED;
r = apk_db_open(&db, apk_root, APK_OPENF_READ | APK_OPENF_NO_STATE);
if (r != 0)
return r;
for (i = 0; i < argc; i++) {
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(argv[i]),
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db.keys_fd);
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(AT_FDCWD, argv[i]),
apk_sign_ctx_mpart_cb, &sctx);
if (is == NULL) {
apk_error("%s: %s", strerror(errno), argv[i]);
@ -43,6 +49,7 @@ static int verify_main(void *ctx, int argc, char **argv)
rc++;
apk_sign_ctx_free(&sctx);
}
apk_db_close(&db);
return rc;
}