summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile1
-rw-r--r--src/add.c2
-rw-r--r--src/apk.c3
-rw-r--r--src/apk_archive.h5
-rw-r--r--src/apk_database.h12
-rw-r--r--src/apk_defines.h2
-rw-r--r--src/apk_io.h19
-rw-r--r--src/apk_package.h5
-rw-r--r--src/archive.c55
-rw-r--r--src/audit.c7
-rw-r--r--src/cache.c63
-rw-r--r--src/database.c330
-rw-r--r--src/fetch.c54
-rw-r--r--src/index.c8
-rw-r--r--src/io.c34
-rw-r--r--src/package.c67
-rw-r--r--src/state.c2
-rw-r--r--src/url.c21
-rw-r--r--src/verify.c11
19 files changed, 360 insertions, 341 deletions
diff --git a/src/Makefile b/src/Makefile
index 96e36b3..e0e97f1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -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
diff --git a/src/add.c b/src/add.c
index 003fcfc..e89a4cd 100644
--- a/src/add.c
+++ b/src/add.c
@@ -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) {
diff --git a/src/apk.c b/src/apk.c
index a21427f..122f9a7 100644
--- a/src/apk.c
+++ b/src/apk.c
@@ -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);
diff --git a/src/apk_archive.h b/src/apk_archive.h
index 320db5e..f983203 100644
--- a/src/apk_archive.h
+++ b/src/apk_archive.h
@@ -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
diff --git a/src/apk_database.h b/src/apk_database.h
index 241719d..094725d 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -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,
diff --git a/src/apk_defines.h b/src/apk_defines.h
index 2ce3535..0dc0c20 100644
--- a/src/apk_defines.h
+++ b/src/apk_defines.h
@@ -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
diff --git a/src/apk_io.h b/src/apk_io.h
index b76385c..759bec4 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -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
diff --git a/src/apk_package.h b/src/apk_package.h
index 96d7840..791df93 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -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);
diff --git a/src/archive.c b/src/archive.c
index 31c0909..e20caa7 100644
--- a/src/archive.c
+++ b/src/archive.c
@@ -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));
diff --git a/src/audit.c b/src/audit.c
index 76bd492..6191a2c 100644
--- a/src/audit.c
+++ b/src/audit.c
@@ -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;
diff --git a/src/cache.c b/src/cache.c
index ac2281e..c961fc9 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -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)
- continue;
+ 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;
diff --git a/src/database.c b/src/database.c
index 15e4730..e71f4c2 100644
--- a/src/database.c
+++ b/src/database.c
@@ -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);
+ /* 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));
+ 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));
+}
+
+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;
+ }
+ }
- apk_blob_push_hexdump(&bbuf,
- APK_BLOB_PTR_LEN((char *) csum->data,
- APK_CACHE_CSUM_BYTES));
- apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN("", 1));
+ if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0)
+ return -errno;
- snprintf(buf, bufsz, "%s/%s/%s.%s%s",
- db->root, db->cache_dir, csumstr, file, temp ? ".new" : "");
+ 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,
diff --git a/src/fetch.c b/src/fetch.c
index c64590e..f93e465 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -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;
- if (!(fctx->flags & FETCH_STDOUT)) {
- struct stat st;
+ apk_pkg_format_plain(pkg, APK_BLOB_BUF(pkgfile));
- snprintf(outfile, sizeof(outfile), "%s/%s-%s.apk",
- fctx->outdir ? fctx->outdir : ".",
- pkg->name->name, pkg->version);
+ if (!(fctx->flags & FETCH_STDOUT)) {
+ struct apk_file_info fi;
- 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();
diff --git a/src/index.c b/src/index.c
index c27d020..4ef8aef 100644
--- a/src/index.c
+++ b/src/index.c
@@ -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) {
diff --git a/src/io.c b/src/io.c
index 3929ba1..a6cdd4d 100644
--- a/src/io.c
+++ b/src/io.c
@@ -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;
diff --git a/src/package.c b/src/package.c
index 43ce646..152edf6 100644
--- a/src/package.c
+++ b/src/package.c
@@ -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;
diff --git a/src/state.c b/src/state.c
index 16acfba..c539b02 100644
--- a/src/state.c
+++ b/src/state.c
@@ -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)
diff --git a/src/url.c b/src/url.c
index e09ec4c..be5e285 100644
--- a/src/url.c
+++ b/src/url.c
@@ -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;
}
diff --git a/src/verify.c b/src/verify.c
index 82e9b2d..dc9ddb6 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -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;
}