diff options
-rw-r--r-- | src/apk_io.h | 1 | ||||
-rw-r--r-- | src/app_extract.c | 30 |
2 files changed, 16 insertions, 15 deletions
diff --git a/src/apk_io.h b/src/apk_io.h index 50464a9..3ad0790 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -44,6 +44,7 @@ struct apk_file_meta { struct apk_file_info { const char *name; const char *link_target; + const char *uvol_name; const char *uname; const char *gname; off_t size; diff --git a/src/app_extract.c b/src/app_extract.c index 89af6db..aa5d8aa 100644 --- a/src/app_extract.c +++ b/src/app_extract.c @@ -31,7 +31,6 @@ struct extract_ctx { unsigned int cur_path, cur_file; struct apk_pathbuilder pb; - unsigned int is_uvol : 1; }; @@ -70,12 +69,13 @@ static void apk_extract_acl(struct apk_file_info *fi, struct adb_obj *o, struct fi->gid = apk_id_cache_resolve_gid(idc, adb_ro_blob(o, ADBI_ACL_GROUP), 65534); } -static int uvol_detect(struct apk_ctx *ac, struct apk_pathbuilder *pb) +static const char *uvol_detect(struct apk_ctx *ac, const char *path) { - apk_blob_t b = apk_pathbuilder_get(pb); if (!apk_ctx_get_uvol(ac)) return 0; - return apk_blob_starts_with(b, APK_BLOB_STRLIT("uvol")) && - (b.len == 4 || b.ptr[4] == '/'); + if (strncmp(path, "uvol", 4) != 0) return 0; + if (path[4] == 0) return path; + if (path[4] == '/') return &path[5]; + return 0; } static int uvol_run(struct apk_ctx *ac, char *action, const char *volname, char *arg1, char *arg2) @@ -146,17 +146,19 @@ static int apk_extract_volume(struct apk_ctx *ac, struct apk_file_info *fi, stru int r; snprintf(size, sizeof size, "%ju", fi->size); - r = uvol_run(ac, "create", fi->name, size, "ro"); + r = uvol_run(ac, "create", fi->uvol_name, size, "ro"); if (r != 0) return r; - return uvol_extract(ac, fi->name, size, fi->size, is, dctx); + return uvol_extract(ac, fi->uvol_name, size, fi->size, is, dctx); } static int apk_extract_file(struct extract_ctx *ctx, off_t sz, struct apk_istream *is) { struct apk_ctx *ac = ctx->ac; struct apk_out *out = &ac->out; + const char *path_name = apk_pathbuilder_cstr(&ctx->pb); struct apk_file_info fi = { - .name = apk_pathbuilder_cstr(&ctx->pb), + .name = path_name, + .uvol_name = uvol_detect(ac, path_name), .size = adb_ro_int(&ctx->file, ADBI_FI_SIZE), .mtime = adb_ro_int(&ctx->file, ADBI_FI_MTIME), }; @@ -207,7 +209,7 @@ static int apk_extract_file(struct extract_ctx *ctx, off_t sz, struct apk_istrea fi.mode |= S_IFREG; apk_digest_ctx_init(&dctx, fi.digest.alg); - if (ctx->is_uvol) { + if (fi.uvol_name) { r = apk_extract_volume(ac, &fi, is, &dctx); } else { r = apk_archive_entry_extract( @@ -218,11 +220,11 @@ static int apk_extract_file(struct extract_ctx *ctx, off_t sz, struct apk_istrea apk_digest_ctx_free(&dctx); if (r == 0 && apk_digest_cmp(&fi.digest, &d) != 0) r = -APKE_FILE_INTEGRITY; - if (ctx->is_uvol) { + if (fi.uvol_name) { if (r == 0) - r = uvol_run(ac, "up", fi.name, 0, 0); + r = uvol_run(ac, "up", fi.uvol_name, 0, 0); else - uvol_run(ac, "remove", fi.name, 0, 0); + uvol_run(ac, "remove", fi.uvol_name, 0, 0); } else if (r != 0) unlinkat(ctx->root_fd, fi.name, 0); return r; @@ -237,7 +239,7 @@ static int apk_extract_directory(struct extract_ctx *ctx) }; struct adb_obj acl; - if (ctx->is_uvol) return 0; + if (uvol_detect(ac, fi.name)) return 0; apk_extract_acl(&fi, adb_ro_obj(&ctx->path, ADBI_DI_ACL, &acl), apk_ctx_get_id_cache(ctx->ac)); fi.mode |= S_IFDIR; @@ -249,7 +251,6 @@ static int apk_extract_directory(struct extract_ctx *ctx) static int apk_extract_next_file(struct extract_ctx *ctx) { - struct apk_ctx *ac = ctx->ac; apk_blob_t target; int r; @@ -271,7 +272,6 @@ static int apk_extract_next_file(struct extract_ctx *ctx) if (ctx->cur_path > adb_ra_num(&ctx->paths)) return 1; adb_ro_obj(&ctx->paths, ctx->cur_path, &ctx->path); apk_pathbuilder_setb(&ctx->pb, adb_ro_blob(&ctx->path, ADBI_DI_NAME)); - ctx->is_uvol = uvol_detect(ac, &ctx->pb); adb_ro_obj(&ctx->path, ADBI_DI_FILES, &ctx->files); r = apk_extract_directory(ctx); if (r != 0) return r; |