Commit ea901526 authored by Timo Teräs's avatar Timo Teräs

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.
parent 67108bf0
......@@ -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
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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
......@@ -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,
......
......@@ -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
......
......@@ -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
......@@ -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);
......
......@@ -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));
......
......@@ -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;
......
......@@ -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;
......
This diff is collapsed.
......@@ -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();
......
......@@ -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) {
......
......@@ -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));
}