mkpkg, extract: implement support for symlinks, devices and fifos
parent
2433c9d23b
commit
22a81e8fb5
|
@ -448,7 +448,7 @@ const struct adb_object_schema schema_file = {
|
|||
ADB_FIELD(ADBI_FI_SIZE, "size", scalar_int),
|
||||
ADB_FIELD(ADBI_FI_MTIME, "mtime", scalar_int),
|
||||
ADB_FIELD(ADBI_FI_HASHES, "hash", scalar_hexblob),
|
||||
ADB_FIELD(ADBI_FI_TARGET, "target", scalar_string),
|
||||
ADB_FIELD(ADBI_FI_TARGET, "target", scalar_hexblob),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -169,25 +169,62 @@ static int apk_extract_file(struct extract_ctx *ctx, off_t sz, struct apk_istrea
|
|||
struct adb_obj acl;
|
||||
struct apk_digest_ctx dctx;
|
||||
struct apk_digest d;
|
||||
apk_blob_t target;
|
||||
int r;
|
||||
|
||||
apk_digest_from_blob(&fi.digest, adb_ro_blob(&ctx->file, ADBI_FI_HASHES));
|
||||
if (fi.digest.alg == APK_DIGEST_NONE) return -APKE_ADB_SCHEMA;
|
||||
apk_extract_acl(&fi, adb_ro_obj(&ctx->file, ADBI_FI_ACL, &acl), apk_ctx_get_id_cache(ctx->ac));
|
||||
fi.mode |= S_IFREG;
|
||||
|
||||
apk_digest_ctx_init(&dctx, fi.digest.alg);
|
||||
if (ctx->is_uvol) {
|
||||
r = apk_extract_volume(ac, &fi, is, &dctx);
|
||||
} else {
|
||||
r = apk_archive_entry_extract(
|
||||
ctx->root_fd, &fi, 0, 0, is, 0, 0, &dctx,
|
||||
target = adb_ro_blob(&ctx->file, ADBI_FI_TARGET);
|
||||
if (!APK_BLOB_IS_NULL(target)) {
|
||||
char *target_path;
|
||||
uint16_t mode;
|
||||
|
||||
if (target.len < 2) return -APKE_ADB_SCHEMA;
|
||||
mode = *(uint16_t*)target.ptr;
|
||||
target.ptr += 2;
|
||||
target.len -= 2;
|
||||
switch (mode) {
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
case S_IFIFO:
|
||||
if (target.len != sizeof(uint64_t)) return -APKE_ADB_SCHEMA;
|
||||
struct unaligned64 {
|
||||
uint64_t value;
|
||||
} __attribute__((packed));
|
||||
fi.device = ((struct unaligned64 *)target.ptr)->value;
|
||||
break;
|
||||
case S_IFLNK:
|
||||
target_path = alloca(target.len + 1);
|
||||
memcpy(target_path, target.ptr, target.len);
|
||||
target_path[target.len] = 0;
|
||||
fi.link_target = target_path;
|
||||
break;
|
||||
default:
|
||||
return -APKE_ADB_SCHEMA;
|
||||
}
|
||||
fi.mode |= mode;
|
||||
return apk_archive_entry_extract(
|
||||
ctx->root_fd, &fi, 0, 0, is, 0, 0, 0,
|
||||
ctx->extract_flags, out);
|
||||
} else {
|
||||
apk_digest_from_blob(&fi.digest, adb_ro_blob(&ctx->file, ADBI_FI_HASHES));
|
||||
if (fi.digest.alg == APK_DIGEST_NONE) return -APKE_ADB_SCHEMA;
|
||||
|
||||
fi.mode |= S_IFREG;
|
||||
apk_digest_ctx_init(&dctx, fi.digest.alg);
|
||||
if (ctx->is_uvol) {
|
||||
r = apk_extract_volume(ac, &fi, is, &dctx);
|
||||
} else {
|
||||
r = apk_archive_entry_extract(
|
||||
ctx->root_fd, &fi, 0, 0, is, 0, 0, &dctx,
|
||||
ctx->extract_flags, out);
|
||||
}
|
||||
apk_digest_ctx_final(&dctx, &d);
|
||||
apk_digest_ctx_free(&dctx);
|
||||
if (r != 0) return r;
|
||||
if (apk_digest_cmp(&fi.digest, &d) != 0) return -APKE_FILE_INTEGRITY;
|
||||
}
|
||||
apk_digest_ctx_final(&dctx, &d);
|
||||
apk_digest_ctx_free(&dctx);
|
||||
if (r != 0) return r;
|
||||
if (apk_digest_cmp(&fi.digest, &d) != 0) return -APKE_FILE_INTEGRITY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,40 +119,71 @@ static int mkpkg_process_dirent(void *pctx, int dirfd, const char *entry)
|
|||
struct apk_id_cache *idc = apk_ctx_get_id_cache(ac);
|
||||
struct apk_file_info fi;
|
||||
struct adb_obj fio, acl;
|
||||
apk_blob_t target = APK_BLOB_NULL;
|
||||
union {
|
||||
uint16_t mode;
|
||||
struct {
|
||||
uint16_t mode;
|
||||
uint64_t dev;
|
||||
} __attribute__((packed)) dev;
|
||||
struct {
|
||||
uint16_t mode;
|
||||
char target[1022];
|
||||
} symlink;
|
||||
} ft;
|
||||
int r;
|
||||
|
||||
r = apk_fileinfo_get(dirfd, entry, APK_FI_NOFOLLOW | APK_FI_DIGEST(APK_DIGEST_SHA256), &fi, NULL);
|
||||
if (r) return r;
|
||||
|
||||
switch (fi.mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
ctx->installed_size += (fi.size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE-1);
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
case S_IFIFO:
|
||||
ft.dev.mode = fi.mode & S_IFMT;
|
||||
ft.dev.dev = fi.device;
|
||||
target = APK_BLOB_STRUCT(ft.dev);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
ft.symlink.mode = fi.mode & S_IFMT;
|
||||
r = readlinkat(dirfd, entry, ft.symlink.target, sizeof ft.symlink.target);
|
||||
if (r < 0) return r;
|
||||
target = APK_BLOB_PTR_LEN((void*)&ft.symlink, sizeof(ft.symlink.mode) + r);
|
||||
r = 0;
|
||||
break;
|
||||
case S_IFDIR:
|
||||
apk_pathbuilder_push(&ctx->pb, entry);
|
||||
r = mkpkg_process_directory(ctx, openat(dirfd, entry, O_RDONLY), &fi);
|
||||
apk_pathbuilder_pop(&ctx->pb);
|
||||
break;
|
||||
case S_IFREG:
|
||||
adb_wo_alloca(&fio, &schema_file, &ctx->db);
|
||||
adb_wo_alloca(&acl, &schema_acl, &ctx->db);
|
||||
adb_wo_blob(&fio, ADBI_FI_NAME, APK_BLOB_STR(entry));
|
||||
adb_wo_blob(&fio, ADBI_FI_HASHES, APK_DIGEST_BLOB(fi.digest));
|
||||
adb_wo_int(&fio, ADBI_FI_MTIME, fi.mtime);
|
||||
adb_wo_int(&fio, ADBI_FI_SIZE, fi.size);
|
||||
ctx->installed_size += (fi.size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE-1);
|
||||
|
||||
adb_wo_int(&acl, ADBI_ACL_MODE, fi.mode & 07777);
|
||||
adb_wo_blob(&acl, ADBI_ACL_USER, apk_id_cache_resolve_user(idc, fi.uid));
|
||||
adb_wo_blob(&acl, ADBI_ACL_GROUP, apk_id_cache_resolve_group(idc, fi.gid));
|
||||
adb_wo_obj(&fio, ADBI_FI_ACL, &acl);
|
||||
|
||||
adb_wa_append_obj(ctx->files, &fio);
|
||||
break;
|
||||
return r;
|
||||
default:
|
||||
apk_pathbuilder_push(&ctx->pb, entry);
|
||||
apk_out(out, "%s: special file ignored",
|
||||
apk_pathbuilder_cstr(&ctx->pb), entry);
|
||||
apk_pathbuilder_pop(&ctx->pb);
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
adb_wo_alloca(&fio, &schema_file, &ctx->db);
|
||||
adb_wo_alloca(&acl, &schema_acl, &ctx->db);
|
||||
adb_wo_blob(&fio, ADBI_FI_NAME, APK_BLOB_STR(entry));
|
||||
if (APK_BLOB_IS_NULL(target))
|
||||
adb_wo_blob(&fio, ADBI_FI_HASHES, APK_DIGEST_BLOB(fi.digest));
|
||||
else
|
||||
adb_wo_blob(&fio, ADBI_FI_TARGET, target);
|
||||
adb_wo_int(&fio, ADBI_FI_MTIME, fi.mtime);
|
||||
adb_wo_int(&fio, ADBI_FI_SIZE, fi.size);
|
||||
|
||||
adb_wo_int(&acl, ADBI_ACL_MODE, fi.mode & 07777);
|
||||
adb_wo_blob(&acl, ADBI_ACL_USER, apk_id_cache_resolve_user(idc, fi.uid));
|
||||
adb_wo_blob(&acl, ADBI_ACL_GROUP, apk_id_cache_resolve_group(idc, fi.gid));
|
||||
adb_wo_obj(&fio, ADBI_FI_ACL, &acl);
|
||||
|
||||
adb_wa_append_obj(ctx->files, &fio);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue