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_SIZE, "size", scalar_int),
|
||||||
ADB_FIELD(ADBI_FI_MTIME, "mtime", scalar_int),
|
ADB_FIELD(ADBI_FI_MTIME, "mtime", scalar_int),
|
||||||
ADB_FIELD(ADBI_FI_HASHES, "hash", scalar_hexblob),
|
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 adb_obj acl;
|
||||||
struct apk_digest_ctx dctx;
|
struct apk_digest_ctx dctx;
|
||||||
struct apk_digest d;
|
struct apk_digest d;
|
||||||
|
apk_blob_t target;
|
||||||
int r;
|
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));
|
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);
|
target = adb_ro_blob(&ctx->file, ADBI_FI_TARGET);
|
||||||
if (ctx->is_uvol) {
|
if (!APK_BLOB_IS_NULL(target)) {
|
||||||
r = apk_extract_volume(ac, &fi, is, &dctx);
|
char *target_path;
|
||||||
} else {
|
uint16_t mode;
|
||||||
r = apk_archive_entry_extract(
|
|
||||||
ctx->root_fd, &fi, 0, 0, is, 0, 0, &dctx,
|
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);
|
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;
|
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_id_cache *idc = apk_ctx_get_id_cache(ac);
|
||||||
struct apk_file_info fi;
|
struct apk_file_info fi;
|
||||||
struct adb_obj fio, acl;
|
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;
|
int r;
|
||||||
|
|
||||||
r = apk_fileinfo_get(dirfd, entry, APK_FI_NOFOLLOW | APK_FI_DIGEST(APK_DIGEST_SHA256), &fi, NULL);
|
r = apk_fileinfo_get(dirfd, entry, APK_FI_NOFOLLOW | APK_FI_DIGEST(APK_DIGEST_SHA256), &fi, NULL);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
|
|
||||||
switch (fi.mode & S_IFMT) {
|
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:
|
case S_IFDIR:
|
||||||
apk_pathbuilder_push(&ctx->pb, entry);
|
apk_pathbuilder_push(&ctx->pb, entry);
|
||||||
r = mkpkg_process_directory(ctx, openat(dirfd, entry, O_RDONLY), &fi);
|
r = mkpkg_process_directory(ctx, openat(dirfd, entry, O_RDONLY), &fi);
|
||||||
apk_pathbuilder_pop(&ctx->pb);
|
apk_pathbuilder_pop(&ctx->pb);
|
||||||
break;
|
return r;
|
||||||
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;
|
|
||||||
default:
|
default:
|
||||||
apk_pathbuilder_push(&ctx->pb, entry);
|
apk_pathbuilder_push(&ctx->pb, entry);
|
||||||
apk_out(out, "%s: special file ignored",
|
apk_out(out, "%s: special file ignored",
|
||||||
apk_pathbuilder_cstr(&ctx->pb), entry);
|
apk_pathbuilder_cstr(&ctx->pb), entry);
|
||||||
apk_pathbuilder_pop(&ctx->pb);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
src/io.c
2
src/io.c
|
@ -724,7 +724,7 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
|
||||||
.gid = st.st_gid,
|
.gid = st.st_gid,
|
||||||
.mode = st.st_mode,
|
.mode = st.st_mode,
|
||||||
.mtime = st.st_mtime,
|
.mtime = st.st_mtime,
|
||||||
.device = st.st_dev,
|
.device = st.st_rdev,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xattr_hash_alg != APK_DIGEST_NONE) {
|
if (xattr_hash_alg != APK_DIGEST_NONE) {
|
||||||
|
|
Loading…
Reference in New Issue