Compare commits
5 Commits
232067b3d1
...
e02ab1d0be
Author | SHA1 | Date |
---|---|---|
Aydin Mercan | e02ab1d0be | |
Timo Teräs | ff7c8f6ee9 | |
Timo Teräs | f8cf7a0a0d | |
Ariadne Conill | 44994a46d4 | |
Timo Teräs | 191e2d412d |
|
@ -42,7 +42,9 @@ following options:
|
|||
*-t, --virtual* _NAME_
|
||||
Create virtual package _NAME_ with given dependencies. This new package
|
||||
will get the _packages_ as dependencies instead of _world_. Finally the
|
||||
_NAME_ is added to _world_.
|
||||
_NAME_ is added to _world_. An optional version specifier for the virtual
|
||||
package can be given via syntax _NAME_=_VERSION_. The version defaults
|
||||
to synthesized version based on time.
|
||||
|
||||
One can use this to ensure that selected set of packages are installed,
|
||||
and later the temporary modification be undone with *apk-del*(8) _NAME_
|
||||
|
|
|
@ -32,6 +32,9 @@ specified.
|
|||
*Note*: this option is incompatible with *-o*, *-R*, and the global
|
||||
*--progress* option.
|
||||
|
||||
*-w, --world*
|
||||
Download packages needed to satisfy _world_. Implies *--recursive*.
|
||||
|
||||
*--simulate*
|
||||
Simulate the requested operation without making any changes.
|
||||
|
||||
|
|
|
@ -17,11 +17,13 @@ scdoc_dep = dependency('scdoc', version: '>=1.10', required: get_option('docs'))
|
|||
shared_deps = [
|
||||
dependency('zlib'),
|
||||
dependency('openssl'),
|
||||
dependency('libsodium'),
|
||||
]
|
||||
|
||||
static_deps = [
|
||||
dependency('openssl', static: true),
|
||||
dependency('zlib', static: true),
|
||||
dependency('libsodium', static: true),
|
||||
]
|
||||
|
||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
||||
|
|
|
@ -21,6 +21,20 @@ foreach f : check_functions
|
|||
endforeach
|
||||
|
||||
|
||||
# Check for wrong (non-POSIX) qsort_r prototype
|
||||
qsort_r_test = '''
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
_Static_assert(_Generic((qsort_r),
|
||||
void (*)(void *, size_t, size_t, void *,
|
||||
int (*)(void *, const void *, const void *)) : 1, default: 0),
|
||||
"Bad prototype not matched");
|
||||
'''
|
||||
if cc.compiles(qsort_r_test, name: 'Test qsort_r non-POSIX prototype')
|
||||
add_project_arguments('-DHAVE_BROKEN_QSORT_R', language: 'c')
|
||||
endif
|
||||
|
||||
|
||||
if libportability_src.length() > 0
|
||||
libportability = static_library(
|
||||
'portability',
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include_next <stdlib.h>
|
||||
|
||||
#ifdef NEED_QSORT_R
|
||||
|
@ -5,3 +6,28 @@ void qsort_r(void *base, size_t nmemb, size_t size,
|
|||
int (*compar)(const void *, const void *, void *),
|
||||
void *arg);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_QSORT_R
|
||||
struct __portable_qsort_r_compat_arg {
|
||||
int (*compar)(const void *, const void *, void *);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static inline int __portable_qsort_r_compar_compat(void *arg, const void *a, const void *b)
|
||||
{
|
||||
struct __portable_qsort_r_compat_arg *compat_arg = arg;
|
||||
return compat_arg->compar(a, b, compat_arg->arg);
|
||||
}
|
||||
|
||||
static inline void __portable_qsort_r(void *base, size_t nmemb, size_t size,
|
||||
int (*compar)(const void *, const void *, void *),
|
||||
void *arg)
|
||||
{
|
||||
struct __portable_qsort_r_compat_arg compat_arg = {
|
||||
.compar = compar,
|
||||
.arg = arg,
|
||||
};
|
||||
qsort_r(base, nmemb, size, &compat_arg, __portable_qsort_r_compar_compat);
|
||||
}
|
||||
#define qsort_r(...) __portable_qsort_r(__VA_ARGS__)
|
||||
#endif
|
||||
|
|
|
@ -15,12 +15,15 @@ OPENSSL_LIBS := $(shell $(PKG_CONFIG) --libs openssl)
|
|||
ZLIB_CFLAGS := $(shell $(PKG_CONFIG) --cflags zlib)
|
||||
ZLIB_LIBS := $(shell $(PKG_CONFIG) --libs zlib)
|
||||
|
||||
SODIUM_FLAGS := $(shell $(PKG_CONFIG) --cflags libsodium)
|
||||
SODIUM_LIBS := $(shell $(PKG_CONFIG) --libs libsodium)
|
||||
|
||||
# Dynamic library
|
||||
libapk_soname := 2.99.0
|
||||
libapk_so := $(obj)/libapk.so.$(libapk_soname)
|
||||
libapk.so.$(libapk_soname)-objs := \
|
||||
adb.o adb_comp.o adb_walk_adb.o adb_walk_genadb.o adb_walk_gentext.o adb_walk_text.o apk_adb.o \
|
||||
atom.o blob.o commit.o common.o context.o crypto_openssl.o database.o hash.o \
|
||||
atom.o blob.o commit.o common.o context.o crypto_core.o crypto_digest.o crypto_openssl.o database.o hash.o \
|
||||
extract_v2.o extract_v3.o fs_fsys.o fs_uvol.o io.o io_gunzip.o io_url.o tar.o \
|
||||
package.o pathbuilder.o print.o solver.o trust.o version.o
|
||||
|
||||
|
@ -90,9 +93,9 @@ LIBS_apk.static := -Wl,--as-needed -ldl -Wl,--no-as-needed
|
|||
LDFLAGS_apk += -L$(obj)
|
||||
LDFLAGS_apk-test += -L$(obj)
|
||||
|
||||
CFLAGS_ALL += $(OPENSSL_CFLAGS) $(ZLIB_CFLAGS)
|
||||
CFLAGS_ALL += $(OPENSSL_CFLAGS) $(ZLIB_CFLAGS) $(SODIUM_CFLAGS)
|
||||
LIBS := -Wl,--as-needed \
|
||||
$(OPENSSL_LIBS) $(ZLIB_LIBS) \
|
||||
$(OPENSSL_LIBS) $(ZLIB_LIBS) $(SODIUM_LIBS) \
|
||||
-Wl,--no-as-needed
|
||||
|
||||
# Help generation
|
||||
|
|
|
@ -441,7 +441,11 @@ int main(int argc, char **argv)
|
|||
ctx.force |= applet->forced_force;
|
||||
}
|
||||
|
||||
apk_crypto_init();
|
||||
if (apk_crypto_init() != 0) {
|
||||
apk_err(out, "failure to initialize");
|
||||
return 1;
|
||||
}
|
||||
|
||||
setup_automatic_flags(&ctx);
|
||||
fetchConnectionCacheInit(32, 4);
|
||||
|
||||
|
|
|
@ -5,6 +5,6 @@ includedir=@INCLUDE_DIR@
|
|||
Name: apk
|
||||
Description: Alpine Package Manager
|
||||
Version: @VERSION@
|
||||
Requires: zlib openssl
|
||||
Libs: -L${libdir} -lapk
|
||||
Requires: zlib openssl sodium
|
||||
Libs: -L${libdir} -lapk -lsodium
|
||||
Cflags: -I${includedir}
|
||||
|
|
144
src/apk_crypto.h
144
src/apk_crypto.h
|
@ -10,26 +10,39 @@
|
|||
#define APK_CRYPTO_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "apk_blob.h"
|
||||
#include "apk_defines.h"
|
||||
#include "apk_openssl.h"
|
||||
|
||||
// Digest
|
||||
|
||||
struct apk_digest_ctx {
|
||||
EVP_MD_CTX *mdctx;
|
||||
uint8_t alg;
|
||||
void *impl;
|
||||
EVP_MD_CTX *mdctx;
|
||||
};
|
||||
|
||||
#define APK_DIGEST_NONE 0x00
|
||||
#define APK_DIGEST_MD5 0x01
|
||||
#define APK_DIGEST_SHA1 0x02
|
||||
#define APK_DIGEST_SHA256 0x03
|
||||
#define APK_DIGEST_SHA512 0x04
|
||||
#define APK_DIGEST_SHA256_160 0x05
|
||||
#define APK_DIGEST_NONE 0x00
|
||||
#define APK_DIGEST_MD5 0x01
|
||||
#define APK_DIGEST_SHA1 0x02
|
||||
#define APK_DIGEST_SHA256 0x03
|
||||
#define APK_DIGEST_SHA512 0x04
|
||||
#define APK_DIGEST_SHA256_160 0x05
|
||||
|
||||
#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512
|
||||
#define APK_DIGEST_MAX_LENGTH 64 // longest is SHA512
|
||||
|
||||
#define APK_PKEY_ED25519 0x00
|
||||
#define APK_PKEY_RSAPKCS1v15 0x01
|
||||
|
||||
#define APK_PKEY_TYPE_PUBLIC 0x00
|
||||
#define APK_PKEY_TYPE_SECRET 0x01
|
||||
|
||||
// includes '\0'
|
||||
#define APK_PKEY_CUTE_PUBLIC_SIZE 69
|
||||
#define APK_PKEY_CUTE_SECRET_SIZE 113
|
||||
|
||||
const char *apk_digest_alg_str(uint8_t);
|
||||
uint8_t apk_digest_alg_from_csum(int);
|
||||
|
@ -39,16 +52,22 @@ struct apk_digest {
|
|||
uint8_t data[APK_DIGEST_MAX_LENGTH];
|
||||
};
|
||||
|
||||
#define APK_DIGEST_BLOB(d) APK_BLOB_PTR_LEN((void*)((d).data), (d).len)
|
||||
#define APK_DIGEST_BLOB(d) APK_BLOB_PTR_LEN((void *) ((d).data), (d).len)
|
||||
|
||||
static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg) {
|
||||
static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg)
|
||||
{
|
||||
switch (alg) {
|
||||
case APK_DIGEST_NONE: return EVP_md_null();
|
||||
case APK_DIGEST_MD5: return EVP_md5();
|
||||
case APK_DIGEST_SHA1: return EVP_sha1();
|
||||
case APK_DIGEST_NONE:
|
||||
return EVP_md_null();
|
||||
case APK_DIGEST_MD5:
|
||||
return EVP_md5();
|
||||
case APK_DIGEST_SHA1:
|
||||
return EVP_sha1();
|
||||
case APK_DIGEST_SHA256_160:
|
||||
case APK_DIGEST_SHA256: return EVP_sha256();
|
||||
case APK_DIGEST_SHA512: return EVP_sha512();
|
||||
case APK_DIGEST_SHA256:
|
||||
return EVP_sha256();
|
||||
case APK_DIGEST_SHA512:
|
||||
return EVP_sha512();
|
||||
default:
|
||||
assert(alg);
|
||||
return EVP_md_null();
|
||||
|
@ -58,21 +77,27 @@ static inline const EVP_MD *apk_digest_alg_to_evp(uint8_t alg) {
|
|||
int apk_digest_alg_len(uint8_t alg);
|
||||
uint8_t apk_digest_alg_by_len(int len);
|
||||
|
||||
static inline int apk_digest_cmp(struct apk_digest *a, struct apk_digest *b) {
|
||||
if (a->alg != b->alg) return b->alg - a->alg;
|
||||
static inline int apk_digest_cmp(struct apk_digest *a, struct apk_digest *b)
|
||||
{
|
||||
if (a->alg != b->alg)
|
||||
return b->alg - a->alg;
|
||||
return memcmp(a->data, b->data, a->len);
|
||||
}
|
||||
|
||||
static inline void apk_digest_reset(struct apk_digest *d) {
|
||||
static inline void apk_digest_reset(struct apk_digest *d)
|
||||
{
|
||||
d->alg = APK_DIGEST_NONE;
|
||||
d->len = 0;
|
||||
}
|
||||
|
||||
static inline void apk_digest_set(struct apk_digest *d, uint8_t alg) {
|
||||
static inline void apk_digest_set(struct apk_digest *d, uint8_t alg)
|
||||
{
|
||||
d->alg = alg;
|
||||
d->len = apk_digest_alg_len(alg);
|
||||
}
|
||||
|
||||
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz);
|
||||
/*
|
||||
static inline int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
|
||||
{
|
||||
unsigned int md_sz = sizeof d->data;
|
||||
|
@ -82,45 +107,14 @@ static inline int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void
|
|||
d->len = apk_digest_alg_len(alg);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
|
||||
dctx->alg = alg;
|
||||
dctx->mdctx = EVP_MD_CTX_new();
|
||||
if (!dctx->mdctx) return -ENOMEM;
|
||||
#ifdef EVP_MD_CTX_FLAG_FINALISE
|
||||
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
|
||||
#endif
|
||||
if (alg != APK_DIGEST_NONE) EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
|
||||
return 0;
|
||||
}
|
||||
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg);
|
||||
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg);
|
||||
void apk_digest_ctx_free(struct apk_digest_ctx *dctx);
|
||||
int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz);
|
||||
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d);
|
||||
|
||||
static inline void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
|
||||
{
|
||||
dctx->alg = alg;
|
||||
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
|
||||
}
|
||||
|
||||
static inline void apk_digest_ctx_free(struct apk_digest_ctx *dctx) {
|
||||
EVP_MD_CTX_free(dctx->mdctx);
|
||||
dctx->mdctx = 0;
|
||||
}
|
||||
|
||||
static inline int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz) {
|
||||
return EVP_DigestUpdate(dctx->mdctx, ptr, sz) == 1 ? 0 : -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
static inline int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d) {
|
||||
unsigned int mdlen = sizeof d->data;
|
||||
if (EVP_DigestFinal_ex(dctx->mdctx, d->data, &mdlen) != 1) {
|
||||
apk_digest_reset(d);
|
||||
return -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
d->alg = dctx->alg;
|
||||
d->len = apk_digest_alg_len(d->alg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "apk_blob.h"
|
||||
uint8_t apk_digest_from_blob(struct apk_digest *d, apk_blob_t b);
|
||||
static inline int apk_digest_cmp_csum(const struct apk_digest *d, const struct apk_checksum *csum)
|
||||
{
|
||||
|
@ -139,13 +133,14 @@ static inline void apk_checksum_from_digest(struct apk_checksum *csum, const str
|
|||
// Asymmetric keys
|
||||
|
||||
struct apk_pkey {
|
||||
uint8_t id[16];
|
||||
EVP_PKEY *key;
|
||||
uint8_t type;
|
||||
uint8_t alg;
|
||||
uint8_t id[16];
|
||||
void *impl;
|
||||
};
|
||||
|
||||
int apk_pkey_init(struct apk_pkey *pkey, EVP_PKEY *key);
|
||||
void apk_pkey_free(struct apk_pkey *pkey);
|
||||
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn);
|
||||
void apk_pkey_free(struct apk_pkey *pkey);
|
||||
|
||||
// Signing
|
||||
|
||||
|
@ -156,31 +151,6 @@ int apk_verify(struct apk_digest_ctx *, void *, size_t);
|
|||
|
||||
// Initializiation
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
|
||||
static inline void apk_crypto_cleanup(void)
|
||||
{
|
||||
EVP_cleanup();
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_cleanup();
|
||||
#endif
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
}
|
||||
|
||||
static inline void apk_crypto_init(void)
|
||||
{
|
||||
atexit(apk_crypto_cleanup);
|
||||
OpenSSL_add_all_algorithms();
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_register_all_complete();
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void apk_crypto_init(void) {}
|
||||
|
||||
#endif
|
||||
int apk_crypto_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "apk_atom.h"
|
||||
#include "apk_crypto.h"
|
||||
|
||||
int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode);
|
||||
ssize_t apk_write_fully(int fd, const void *ptr, size_t size);
|
||||
|
||||
struct apk_id_hash {
|
||||
|
|
|
@ -81,32 +81,26 @@ static int non_repository_check(struct apk_database *db)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_name *name)
|
||||
static struct apk_package *create_virtual_package(struct apk_database *db, struct apk_dependency *dep)
|
||||
{
|
||||
char ver[32];
|
||||
struct apk_package *virtpkg;
|
||||
struct apk_digest_ctx dctx;
|
||||
struct apk_digest d;
|
||||
struct tm tm;
|
||||
time_t now = time(NULL);
|
||||
pid_t pid = getpid();
|
||||
|
||||
gmtime_r(&now, &tm);
|
||||
strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm);
|
||||
|
||||
virtpkg = apk_pkg_new();
|
||||
if (virtpkg == NULL) return 0;
|
||||
|
||||
virtpkg->name = name;
|
||||
virtpkg->version = apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver));
|
||||
virtpkg->name = dep->name;
|
||||
virtpkg->version = dep->version;
|
||||
virtpkg->description = strdup("virtual meta package");
|
||||
virtpkg->arch = apk_atomize(&db->atoms, APK_BLOB_STR("noarch"));
|
||||
virtpkg->repos |= BIT(APK_REPOSITORY_CACHED);
|
||||
|
||||
apk_digest_ctx_init(&dctx, APK_DIGEST_SHA1);
|
||||
apk_digest_ctx_update(&dctx, &tm, sizeof tm);
|
||||
apk_digest_ctx_update(&dctx, &pid, sizeof pid);
|
||||
apk_digest_ctx_update(&dctx, virtpkg->name->name, strlen(virtpkg->name->name) + 1);
|
||||
apk_digest_ctx_update(&dctx, dep->version->ptr, dep->version->len);
|
||||
apk_digest_ctx_final(&dctx, &d);
|
||||
apk_digest_ctx_free(&dctx);
|
||||
apk_checksum_from_digest(&virtpkg->csum, &d);
|
||||
|
@ -114,6 +108,17 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc
|
|||
return virtpkg;
|
||||
}
|
||||
|
||||
static apk_blob_t *generate_version(struct apk_database *db)
|
||||
{
|
||||
char ver[32];
|
||||
struct tm tm;
|
||||
time_t now = time(NULL);
|
||||
|
||||
gmtime_r(&now, &tm);
|
||||
strftime(ver, sizeof ver, "%Y%m%d.%H%M%S", &tm);
|
||||
return apk_atomize_dup(&db->atoms, APK_BLOB_STR(ver));
|
||||
}
|
||||
|
||||
static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args)
|
||||
{
|
||||
struct apk_out *out = &ac->out;
|
||||
|
@ -133,24 +138,32 @@ static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args
|
|||
if (actx->virtpkg) {
|
||||
apk_blob_t b = APK_BLOB_STR(actx->virtpkg);
|
||||
apk_blob_pull_dep(&b, db, &virtdep);
|
||||
|
||||
if (APK_BLOB_IS_NULL(b) || virtdep.conflict ||
|
||||
virtdep.result_mask != APK_DEPMASK_ANY ||
|
||||
virtdep.version != &apk_atom_null) {
|
||||
(virtdep.name->name[0] != '.' && non_repository_check(db)))
|
||||
goto bad_spec;
|
||||
|
||||
switch (virtdep.result_mask) {
|
||||
case APK_DEPMASK_ANY:
|
||||
if (virtdep.version != &apk_atom_null) goto bad_spec;
|
||||
virtdep.result_mask = APK_VERSION_EQUAL;
|
||||
virtdep.version = generate_version(db);
|
||||
break;
|
||||
case APK_VERSION_EQUAL:
|
||||
if (virtdep.version == &apk_atom_null) goto bad_spec;
|
||||
break;
|
||||
default:
|
||||
bad_spec:
|
||||
apk_err(out, "%s: bad package specifier", actx->virtpkg);
|
||||
return -1;
|
||||
}
|
||||
if (virtdep.name->name[0] != '.' && non_repository_check(db))
|
||||
return -1;
|
||||
|
||||
virtpkg = create_virtual_package(db, virtdep.name);
|
||||
virtpkg = create_virtual_package(db, &virtdep);
|
||||
if (!virtpkg) {
|
||||
apk_err(out, "Failed to allocate virtual meta package");
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtdep.result_mask = APK_VERSION_EQUAL;
|
||||
virtdep.version = virtpkg->version;
|
||||
|
||||
if (!args->num) apk_warn(out, "creating empty virtual package");
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#include "apk_print.h"
|
||||
#include "apk_solver.h"
|
||||
|
||||
#define FETCH_RECURSIVE 1
|
||||
#define FETCH_STDOUT 2
|
||||
#define FETCH_LINK 4
|
||||
#define FETCH_URL 8
|
||||
#define FETCH_RECURSIVE 0x01
|
||||
#define FETCH_STDOUT 0x02
|
||||
#define FETCH_LINK 0x04
|
||||
#define FETCH_URL 0x08
|
||||
#define FETCH_WORLD 0x10
|
||||
|
||||
struct fetch_ctx {
|
||||
unsigned int flags;
|
||||
|
@ -75,6 +76,7 @@ static int cup(void)
|
|||
OPT(OPT_FETCH_simulate, "simulate") \
|
||||
OPT(OPT_FETCH_stdout, APK_OPT_SH("s") "stdout") \
|
||||
OPT(OPT_FETCH_url, "url") \
|
||||
OPT(OPT_FETCH_world, APK_OPT_SH("w") "world") \
|
||||
|
||||
APK_OPT_APPLET(option_desc, FETCH_OPTIONS);
|
||||
|
||||
|
@ -101,6 +103,10 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const cha
|
|||
case OPT_FETCH_url:
|
||||
fctx->flags |= FETCH_URL;
|
||||
break;
|
||||
case OPT_FETCH_world:
|
||||
fctx->flags |= FETCH_WORLD | FETCH_RECURSIVE;
|
||||
ac->open_flags &= ~APK_OPENF_NO_WORLD;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
@ -218,6 +224,12 @@ static void mark_error(struct fetch_ctx *ctx, const char *match, struct apk_name
|
|||
ctx->errors++;
|
||||
}
|
||||
|
||||
static void mark_dep_flags(struct fetch_ctx *ctx, struct apk_dependency *dep)
|
||||
{
|
||||
dep->name->auto_select_virtual = 1;
|
||||
apk_deps_add(&ctx->world, dep);
|
||||
}
|
||||
|
||||
static void mark_name_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx)
|
||||
{
|
||||
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
|
||||
|
@ -228,8 +240,7 @@ static void mark_name_flags(struct apk_database *db, const char *match, struct a
|
|||
};
|
||||
|
||||
if (name) {
|
||||
name->auto_select_virtual = 1;
|
||||
apk_deps_add(&ctx->world, &dep);
|
||||
mark_dep_flags(ctx, &dep);
|
||||
} else {
|
||||
ctx->errors++;
|
||||
mark_error(ctx, match, name);
|
||||
|
@ -310,6 +321,7 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
struct apk_out *out = &ac->out;
|
||||
struct apk_database *db = ac->db;
|
||||
struct fetch_ctx *ctx = (struct fetch_ctx *) pctx;
|
||||
struct apk_dependency *dep;
|
||||
|
||||
ctx->db = db;
|
||||
ctx->prog = db->ctx->progress;
|
||||
|
@ -329,6 +341,8 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
|
||||
if (ctx->flags & FETCH_RECURSIVE) {
|
||||
apk_dependency_array_init(&ctx->world);
|
||||
foreach_array_item(dep, db->world)
|
||||
mark_dep_flags(ctx, dep);
|
||||
apk_name_foreach_matching(db, args, apk_foreach_genid(), mark_name_flags, ctx);
|
||||
if (ctx->errors == 0)
|
||||
mark_names_recursive(db, args, ctx);
|
||||
|
@ -349,7 +363,7 @@ static int fetch_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
|
||||
static struct apk_applet apk_fetch = {
|
||||
.name = "fetch",
|
||||
.open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE,
|
||||
.open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE,
|
||||
.context_size = sizeof(struct fetch_ctx),
|
||||
.optgroups = { &optgroup_global, &optgroup_applet },
|
||||
.main = fetch_main,
|
||||
|
|
|
@ -74,8 +74,7 @@ int apk_ctx_prepare(struct apk_ctx *ac)
|
|||
const int lflags = O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC;
|
||||
int fd = openat(ac->root_fd, log_path, lflags, 0644);
|
||||
if (fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) {
|
||||
mkdirat(ac->root_fd, "var", 0755);
|
||||
mkdirat(ac->root_fd, "var/log", 0755);
|
||||
apk_make_dirs(ac->root_fd, "var/log", 0755, 0755);
|
||||
fd = openat(ac->root_fd, log_path, lflags, 0644);
|
||||
}
|
||||
if (fd < 0) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#include <sodium.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "apk_crypto.h"
|
||||
#include "apk_defines.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
static void apk_crypto_cleanup(void)
|
||||
{
|
||||
EVP_cleanup();
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_cleanup();
|
||||
#endif
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int apk_crypto_init(void)
|
||||
{
|
||||
if (sodium_init() < 0) {
|
||||
return -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
atexit(apk_crypto_cleanup);
|
||||
OpenSSL_add_all_algorithms();
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_load_builtin_engines();
|
||||
ENGINE_register_all_complete();
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
#include <sodium.h>
|
||||
|
||||
#include "apk_crypto.h"
|
||||
|
||||
/*
|
||||
static inline int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg) {
|
||||
dctx->alg = alg;
|
||||
dctx->mdctx = EVP_MD_CTX_new();
|
||||
if (!dctx->mdctx) return -ENOMEM;
|
||||
#ifdef EVP_MD_CTX_FLAG_FINALISE
|
||||
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
|
||||
#endif
|
||||
if (alg != APK_DIGEST_NONE) EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
union digest_state {
|
||||
crypto_hash_sha256_state sha256;
|
||||
crypto_hash_sha512_state sha512;
|
||||
EVP_MD_CTX *mdctx;
|
||||
};
|
||||
|
||||
static const char *apk_digest_str[] = {
|
||||
[APK_DIGEST_NONE] = "none",
|
||||
[APK_DIGEST_MD5] = "md5",
|
||||
[APK_DIGEST_SHA1] = "sha1",
|
||||
[APK_DIGEST_SHA256_160] = "sha256-160",
|
||||
[APK_DIGEST_SHA256] = "sha256",
|
||||
[APK_DIGEST_SHA512] = "sha512",
|
||||
};
|
||||
|
||||
const char *apk_digest_alg_str(uint8_t alg)
|
||||
{
|
||||
const char *alg_str = "unknown";
|
||||
if (alg < ARRAY_SIZE(apk_digest_str))
|
||||
alg_str = apk_digest_str[alg];
|
||||
return alg_str;
|
||||
}
|
||||
|
||||
int apk_digest_calc(struct apk_digest *d, uint8_t alg, const void *ptr, size_t sz)
|
||||
{
|
||||
switch (alg) {
|
||||
case APK_DIGEST_SHA256:
|
||||
case APK_DIGEST_SHA256_160:
|
||||
crypto_hash_sha256(d->data, ptr, sz);
|
||||
break;
|
||||
case APK_DIGEST_SHA512:
|
||||
crypto_hash_sha512(d->data, ptr, sz);
|
||||
break;
|
||||
case APK_DIGEST_NONE:
|
||||
break;
|
||||
case APK_DIGEST_MD5:
|
||||
break;
|
||||
case APK_DIGEST_SHA1:
|
||||
break;
|
||||
default:
|
||||
return -APKE_CRYPTO_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
d->alg = alg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apk_digest_ctx_init(struct apk_digest_ctx *dctx, uint8_t alg)
|
||||
{
|
||||
union digest_state *state = NULL;
|
||||
const EVP_MD *evp_md = NULL;
|
||||
|
||||
dctx->impl = malloc(sizeof(union digest_state));
|
||||
if (dctx->impl == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
state = (union digest_state *) dctx->impl;
|
||||
|
||||
dctx->alg = alg;
|
||||
switch (alg) {
|
||||
case APK_DIGEST_SHA256:
|
||||
case APK_DIGEST_SHA256_160:
|
||||
crypto_hash_sha256_init(&state->sha256);
|
||||
break;
|
||||
case APK_DIGEST_SHA512:
|
||||
crypto_hash_sha512_init(&state->sha512);
|
||||
break;
|
||||
case APK_DIGEST_NONE:
|
||||
evp_md = EVP_md_null();
|
||||
case APK_DIGEST_MD5:
|
||||
evp_md = EVP_md5();
|
||||
break;
|
||||
case APK_DIGEST_SHA1:
|
||||
evp_md = EVP_sha1();
|
||||
break;
|
||||
default:
|
||||
free(dctx->impl);
|
||||
return -APKE_CRYPTO_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (evp_md != NULL) {
|
||||
state->mdctx = EVP_MD_CTX_new();
|
||||
if (state->mdctx == NULL) {
|
||||
goto a;
|
||||
}
|
||||
|
||||
#ifdef EVP_MD_CTX_FLAG_FINALISE
|
||||
EVP_MD_CTX_set_flags(dctx->mdctx, EVP_MD_CTX_FLAG_FINALISE);
|
||||
#endif
|
||||
|
||||
EVP_DigestInit_ex(dctx->mdctx, apk_digest_alg_to_evp(alg), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
a:
|
||||
free(dctx->impl);
|
||||
return -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
|
||||
void apk_digest_ctx_reset(struct apk_digest_ctx *dctx, uint8_t alg)
|
||||
{
|
||||
apk_digest_ctx_free(dctx);
|
||||
apk_digest_ctx_init(dctx, alg);
|
||||
}
|
||||
|
||||
void apk_digest_ctx_free(struct apk_digest_ctx *dctx)
|
||||
{
|
||||
union digest_state *state = (union digest_state *) dctx->impl;
|
||||
|
||||
if (dctx->impl == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dctx->alg) {
|
||||
case APK_DIGEST_NONE:
|
||||
case APK_DIGEST_MD5:
|
||||
case APK_DIGEST_SHA1:
|
||||
EVP_MD_CTX_free(state->mdctx);
|
||||
case APK_DIGEST_SHA256:
|
||||
case APK_DIGEST_SHA512:
|
||||
case APK_DIGEST_SHA256_160:
|
||||
break;
|
||||
default:
|
||||
/* illegal state, don't touch impl? */
|
||||
return;
|
||||
}
|
||||
|
||||
free(dctx->impl);
|
||||
|
||||
dctx->impl = NULL;
|
||||
}
|
||||
|
||||
int apk_digest_ctx_update(struct apk_digest_ctx *dctx, const void *ptr, size_t sz)
|
||||
{
|
||||
union digest_state *state = (union digest_state *) dctx->impl;
|
||||
|
||||
switch (dctx->alg) {
|
||||
case APK_DIGEST_SHA256:
|
||||
case APK_DIGEST_SHA256_160:
|
||||
crypto_hash_sha256_update(&state->sha256, ptr, sz);
|
||||
break;
|
||||
case APK_DIGEST_SHA512:
|
||||
crypto_hash_sha512_update(&state->sha512, ptr, sz);
|
||||
break;
|
||||
case APK_DIGEST_NONE:
|
||||
case APK_DIGEST_MD5:
|
||||
case APK_DIGEST_SHA1:
|
||||
if (EVP_DigestUpdate(state->mdctx, ptr, sz) != 1) {
|
||||
return -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -APKE_CRYPTO_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int apk_digest_ctx_final(struct apk_digest_ctx *dctx, struct apk_digest *d)
|
||||
{
|
||||
union digest_state *state = dctx->impl;
|
||||
unsigned int mdlen;
|
||||
|
||||
switch (dctx->alg) {
|
||||
case APK_DIGEST_SHA256:
|
||||
case APK_DIGEST_SHA256_160:
|
||||
crypto_hash_sha256_final(&state->sha256, d->data);
|
||||
break;
|
||||
case APK_DIGEST_SHA512:
|
||||
crypto_hash_sha512_final(&state->sha512, d->data);
|
||||
break;
|
||||
case APK_DIGEST_NONE:
|
||||
case APK_DIGEST_MD5:
|
||||
case APK_DIGEST_SHA1:
|
||||
mdlen = sizeof d->data;
|
||||
if (EVP_DigestFinal_ex(state->mdctx, d->data, &mdlen) != 1) {
|
||||
apk_digest_reset(d);
|
||||
return -APKE_CRYPTO_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -APKE_CRYPTO_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
d->alg = dctx->alg;
|
||||
d->len = apk_digest_alg_len(d->alg);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -7,23 +7,6 @@
|
|||
|
||||
#include "apk_crypto.h"
|
||||
|
||||
static const char *apk_digest_str[] = {
|
||||
[APK_DIGEST_NONE] = "none",
|
||||
[APK_DIGEST_MD5] = "md5",
|
||||
[APK_DIGEST_SHA1] = "sha1",
|
||||
[APK_DIGEST_SHA256_160] = "sha256-160",
|
||||
[APK_DIGEST_SHA256] = "sha256",
|
||||
[APK_DIGEST_SHA512] = "sha512",
|
||||
};
|
||||
|
||||
const char *apk_digest_alg_str(uint8_t alg)
|
||||
{
|
||||
const char *alg_str = "unknown";
|
||||
if (alg < ARRAY_SIZE(apk_digest_str))
|
||||
alg_str = apk_digest_str[alg];
|
||||
return alg_str;
|
||||
}
|
||||
|
||||
int apk_digest_alg_len(uint8_t alg)
|
||||
{
|
||||
switch (alg) {
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
#include <fcntl.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <sodium.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "apk_crypto.h"
|
||||
|
||||
union pkey_state {
|
||||
unsigned char cute_pk[crypto_sign_ed25519_PUBLICKEYBYTES];
|
||||
unsigned char cute_sk[crypto_sign_ed25519_SECRETKEYBYTES];
|
||||
EVP_PKEY *pkey;
|
||||
};
|
||||
|
||||
static int load_openssl(int fd, struct apk_pkey *pkey)
|
||||
{
|
||||
int r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
union pkey_state *state;
|
||||
BIO *bio;
|
||||
|
||||
pkey->impl = malloc(sizeof(union pkey_state));
|
||||
if (pkey->impl == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
bio = BIO_new_fd(fd, BIO_NOCLOSE);
|
||||
if (bio == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err_bio_new;
|
||||
}
|
||||
|
||||
state = (union pkey_state *) pkey->impl;
|
||||
|
||||
pkey->type = APK_PKEY_TYPE_PUBLIC;
|
||||
state->pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
|
||||
if (state->pkey == NULL) {
|
||||
pkey->type = APK_PKEY_TYPE_SECRET;
|
||||
BIO_reset(bio);
|
||||
state->pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
if (state->pkey == NULL) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_load;
|
||||
}
|
||||
|
||||
BIO_free(bio);
|
||||
|
||||
return 0;
|
||||
|
||||
err_load:
|
||||
BIO_free(bio);
|
||||
err_bio_new:
|
||||
free(pkey->impl);
|
||||
err_alloc:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int load_public_cute(int fd, struct apk_pkey *pkey)
|
||||
{
|
||||
char b64[APK_PKEY_CUTE_PUBLIC_SIZE];
|
||||
int r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
union pkey_state *state;
|
||||
uint8_t raw[50]; // 2 + 16 + 32
|
||||
size_t len;
|
||||
|
||||
pkey->impl = malloc(sizeof(union pkey_state));
|
||||
if (pkey->impl == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
state = (union pkey_state *) pkey->impl;
|
||||
|
||||
if (read(fd, b64, APK_PKEY_CUTE_PUBLIC_SIZE) != APK_PKEY_CUTE_PUBLIC_SIZE) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_read;
|
||||
}
|
||||
|
||||
if (sodium_base642bin(raw,
|
||||
50,
|
||||
b64,
|
||||
APK_PKEY_CUTE_PUBLIC_SIZE,
|
||||
NULL,
|
||||
&len,
|
||||
NULL,
|
||||
sodium_base64_VARIANT_URLSAFE)
|
||||
!= 0) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_b64decode;
|
||||
}
|
||||
|
||||
if (raw[0] != 'q' || raw[1] != 't') {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_rawheader;
|
||||
}
|
||||
|
||||
pkey->type = APK_PKEY_TYPE_PUBLIC;
|
||||
pkey->alg = APK_PKEY_ED25519;
|
||||
memcpy(pkey->id, raw + 2, 16);
|
||||
memcpy(state->cute_pk, raw + 18, crypto_sign_ed25519_PUBLICKEYBYTES);
|
||||
|
||||
return 0;
|
||||
|
||||
err_rawheader:
|
||||
err_b64decode:
|
||||
err_read:
|
||||
free(pkey->impl);
|
||||
err_alloc:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int load_secret_cute(int fd, struct apk_pkey *pkey)
|
||||
{
|
||||
char b64[APK_PKEY_CUTE_SECRET_SIZE];
|
||||
int r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
union pkey_state *state;
|
||||
uint8_t raw[82]; // 2 + 16 + 64
|
||||
size_t len;
|
||||
|
||||
pkey->impl = malloc(sizeof(union pkey_state));
|
||||
if (pkey->impl == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
state = (union pkey_state *) pkey->impl;
|
||||
|
||||
if (read(fd, b64, APK_PKEY_CUTE_SECRET_SIZE) != APK_PKEY_CUTE_SECRET_SIZE) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_read;
|
||||
}
|
||||
|
||||
if (sodium_base642bin(raw,
|
||||
82,
|
||||
b64,
|
||||
APK_PKEY_CUTE_PUBLIC_SIZE,
|
||||
NULL,
|
||||
&len,
|
||||
NULL,
|
||||
sodium_base64_VARIANT_URLSAFE)
|
||||
!= 0) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_b64decode;
|
||||
}
|
||||
|
||||
if (len != 82) {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_decodelen;
|
||||
}
|
||||
|
||||
if (raw[0] != 'q' || raw[1] != 't') {
|
||||
r = -APKE_CRYPTO_KEY_FORMAT;
|
||||
goto err_rawheader;
|
||||
}
|
||||
|
||||
pkey->type = APK_PKEY_TYPE_SECRET;
|
||||
pkey->alg = APK_PKEY_ED25519;
|
||||
memcpy(pkey->id, raw + 2, 16);
|
||||
memcpy(state->cute_sk, raw + 18, crypto_sign_ed25519_SECRETKEYBYTES);
|
||||
|
||||
return 0;
|
||||
|
||||
err_rawheader:
|
||||
err_decodelen:
|
||||
err_b64decode:
|
||||
err_read:
|
||||
free(pkey->impl);
|
||||
err_alloc:
|
||||
return r;
|
||||
}
|
||||
|
||||
void apk_pkey_free(struct apk_pkey *pkey)
|
||||
{
|
||||
union pkey_state *state = (union pkey_state *) pkey->impl;
|
||||
|
||||
switch (pkey->alg) {
|
||||
case APK_PKEY_ED25519:
|
||||
break;
|
||||
case APK_PKEY_RSAPKCS1v15:
|
||||
EVP_PKEY_free(state->pkey);
|
||||
break;
|
||||
default:
|
||||
/* invalid state, don't touch impl */
|
||||
return;
|
||||
}
|
||||
|
||||
free(pkey->impl);
|
||||
|
||||
pkey->impl = NULL;
|
||||
}
|
||||
|
||||
int apk_pkey_load(struct apk_pkey *pkey, int dirfd, const char *fn)
|
||||
{
|
||||
struct stat st;
|
||||
int fd, r = 0;
|
||||
|
||||
fd = openat(dirfd, fn, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
r = -errno;
|
||||
goto err_openat;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) != 0) {
|
||||
r = -errno;
|
||||
goto err_fstat;
|
||||
}
|
||||
|
||||
switch (st.st_size) {
|
||||
case APK_PKEY_CUTE_SECRET_SIZE:
|
||||
r = load_secret_cute(fd, pkey);
|
||||
break;
|
||||
case APK_PKEY_CUTE_PUBLIC_SIZE:
|
||||
r = load_public_cute(fd, pkey);
|
||||
break;
|
||||
default:
|
||||
r = load_openssl(fd, pkey);
|
||||
break;
|
||||
}
|
||||
|
||||
err_fstat:
|
||||
close(fd);
|
||||
err_openat:
|
||||
return r;
|
||||
}
|
|
@ -1451,9 +1451,7 @@ static inline int setup_static_cache(struct apk_database *db, struct apk_ctx *ac
|
|||
db->cache_dir = apk_static_cache_dir;
|
||||
db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
|
||||
if (db->cache_fd < 0) {
|
||||
mkdirat(db->root_fd, "var", 0755);
|
||||
mkdirat(db->root_fd, "var/cache", 0755);
|
||||
mkdirat(db->root_fd, "var/cache/apk", 0755);
|
||||
apk_make_dirs(db->root_fd, db->cache_dir, 0755, 0755);
|
||||
db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC);
|
||||
if (db->cache_fd < 0) {
|
||||
if (ac->open_flags & APK_OPENF_WRITE) return -EROFS;
|
||||
|
@ -1884,15 +1882,8 @@ int apk_db_write_config(struct apk_database *db)
|
|||
return 0;
|
||||
|
||||
if (db->ctx->open_flags & APK_OPENF_CREATE) {
|
||||
if (faccessat(db->root_fd, "lib/apk/db", F_OK, 0) != 0) {
|
||||
mkdirat(db->root_fd, "lib", 0755);
|
||||
mkdirat(db->root_fd, "lib/apk", 0755);
|
||||
mkdirat(db->root_fd, "lib/apk/db", 0755);
|
||||
}
|
||||
if (faccessat(db->root_fd, "etc/apk", F_OK, 0) != 0) {
|
||||
mkdirat(db->root_fd, "etc", 0755);
|
||||
mkdirat(db->root_fd, "etc/apk", 0755);
|
||||
}
|
||||
apk_make_dirs(db->root_fd, "lib/apk/db", 0755, 0755);
|
||||
apk_make_dirs(db->root_fd, "etc/apk", 0755, 0755);
|
||||
} else if (db->lock_fd == 0) {
|
||||
apk_err(out, "Refusing to write db without write lock!");
|
||||
return -1;
|
||||
|
|
15
src/io.c
15
src/io.c
|
@ -38,6 +38,21 @@ static inline int atfd_error(int atfd)
|
|||
return atfd < -1 && atfd != AT_FDCWD;
|
||||
}
|
||||
|
||||
int apk_make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode)
|
||||
{
|
||||
char parentdir[PATH_MAX], *slash;
|
||||
|
||||
if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0;
|
||||
if (mkdirat(root_fd, dirname, dirmode) == 0) return 0;
|
||||
if (errno != ENOENT || !parentmode) return -1;
|
||||
|
||||
slash = strrchr(dirname, '/');
|
||||
if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1;
|
||||
strlcpy(parentdir, dirname, slash-dirname+1);
|
||||
if (apk_make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1;
|
||||
return mkdirat(root_fd, dirname, dirmode);
|
||||
}
|
||||
|
||||
ssize_t apk_write_fully(int fd, const void *ptr, size_t size)
|
||||
{
|
||||
ssize_t i = 0, r;
|
||||
|
|
|
@ -12,6 +12,8 @@ libapk_src = [
|
|||
'commit.c',
|
||||
'common.c',
|
||||
'context.c',
|
||||
'crypto_core.c',
|
||||
'crypto_digest.c',
|
||||
'crypto_openssl.c',
|
||||
'database.c',
|
||||
'extract_v2.c',
|
||||
|
|
|
@ -768,21 +768,6 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg,
|
|||
return apk_ipkg_assign_script(ipkg, type, apk_blob_from_istream(is, size));
|
||||
}
|
||||
|
||||
static inline int make_dirs(int root_fd, const char *dirname, mode_t dirmode, mode_t parentmode)
|
||||
{
|
||||
char parentdir[PATH_MAX], *slash;
|
||||
|
||||
if (faccessat(root_fd, dirname, F_OK, 0) == 0) return 0;
|
||||
if (mkdirat(root_fd, dirname, dirmode) == 0) return 0;
|
||||
if (errno != ENOENT || !parentmode) return -1;
|
||||
|
||||
slash = strrchr(dirname, '/');
|
||||
if (!slash || slash == dirname || slash-dirname+1 >= sizeof parentdir) return -1;
|
||||
strlcpy(parentdir, dirname, slash-dirname+1);
|
||||
if (make_dirs(root_fd, parentdir, parentmode, parentmode) < 0) return -1;
|
||||
return mkdirat(root_fd, dirname, dirmode);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static inline int make_device_tree(struct apk_database *db)
|
||||
{
|
||||
|
@ -834,8 +819,8 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg,
|
|||
return;
|
||||
|
||||
if (!db->script_dirs_checked) {
|
||||
if (make_dirs(root_fd, "tmp", 01777, 0) <0 ||
|
||||
make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0||
|
||||
if (apk_make_dirs(root_fd, "tmp", 01777, 0) <0 ||
|
||||
apk_make_dirs(root_fd, script_exec_dir, 0700, 0755) < 0||
|
||||
make_device_tree(db) < 0) {
|
||||
apk_err(out, "failed to prepare dirs for hook scripts: %s",
|
||||
apk_error_str(errno));
|
||||
|
|
Loading…
Reference in New Issue