Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 63 additions & 14 deletions pkgutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ static void usage(FILE *out) {

static char *strip_components_path(const char *path, int strip);
static int apply_strip_components(struct archive_entry *e, int strip);
static int path_component_count(const char *path);
static char *normalize_rel_path(const char *path);
static int match_excluded_with_prefix(struct archive *match,
struct archive_entry *e,
const char *prefix);
Expand Down Expand Up @@ -302,23 +304,31 @@ static void extract_nested_archive_from_stream(struct astream *in,
fail_archive(a, "read nested header");
}

const char *p = archive_entry_pathname(e);
char *rel = normalize_rel_path(p);
archive_entry_set_pathname(e, rel);

if (match != NULL) {
r = match_excluded_with_prefix(match, e, prefix);
if (r != 0) {
archive_read_data_skip(a);
free(rel);
continue;
}
}

if (apply_strip_components(e, strip_components)) {
archive_read_data_skip(a);
free(rel);
continue;
}

r = archive_read_extract2(a, e, disk);
if (r != ARCHIVE_OK) {
free(rel);
fail_archive(a, "extract nested entry");
}
free(rel);
}

archive_write_free(disk);
Expand Down Expand Up @@ -418,6 +428,34 @@ static int apply_strip_components(struct archive_entry *e, int strip) {
return (0);
}

static int path_component_count(const char *path) {
int count = 0;
int in_component = 0;

if (path == NULL) {
return (0);
}

for (const char *p = path; *p != '\0'; p++) {
switch (*p) {
case '/':
#if defined(_WIN32) && !defined(__CYGWIN__)
case '\\':
#endif
in_component = 0;
break;
default:
if (!in_component) {
count++;
in_component = 1;
}
break;
}
}

return (count);
}

static int match_excluded_with_prefix(struct archive *match,
struct archive_entry *e,
const char *prefix) {
Expand Down Expand Up @@ -682,19 +720,24 @@ int main(int argc, char **argv) {
}
}
int is_nested = should_be_treated_as_nested_archive(rel);
if (apply_strip_components(e, strip_components)) {
archive_read_data_skip(xar);
free(rel);
continue;
}
free(rel);
rel = strdup(archive_entry_pathname(e));
if (rel == NULL) {
fail_errno("strdup");
}

if (do_expand_full && is_nested) {
mkdirs_for_path(rel);
char *nested_outdir = strip_components_path(rel, strip_components);
int nested_strip = strip_components;
int rel_components = path_component_count(rel);

if (nested_outdir == NULL) {
nested_outdir = strdup(".");
if (nested_outdir == NULL) {
fail_errno("strdup");
}
}
if (nested_strip > rel_components) {
nested_strip -= rel_components;
} else {
nested_strip = 0;
}

mkdirs_for_path(nested_outdir);

{
struct astream in = {
Expand All @@ -706,11 +749,17 @@ int main(int argc, char **argv) {
.eof = 0,
};

extract_nested_archive_from_stream(&in, rel, flags, match,
strip_components, rel);
extract_nested_archive_from_stream(&in, nested_outdir, flags, match,
nested_strip, rel);
}
free(nested_outdir);
free(rel);
} else {
if (apply_strip_components(e, strip_components)) {
archive_read_data_skip(xar);
free(rel);
continue;
}
r = archive_read_extract2(xar, e, disk);
if (r != ARCHIVE_OK) {
free(rel);
Expand Down
33 changes: 33 additions & 0 deletions tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ run_binary(
tags = ["manual"],
)

run_binary(
name = "pkgutil_component_expand_full_strip_6_action",
tool = "//:pkgutil",
srcs = [
"@component_pkg//file",
],
args = [
"--exclude",
"Payload/Library/Developer/CommandLineTools/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/Headers/ruby/ruby",
"--expand-full",
"--strip-components",
"6",
"$(location @component_pkg//file)",
"$@",
],
out_dirs = ["pkgutil-component-expand-full-strip-6"],
testonly = True,
tags = ["manual"],
)

run_binary(
name = "pkgutil_product_expand_action",
tool = "//:pkgutil",
Expand Down Expand Up @@ -136,6 +156,19 @@ exec_test(
],
)

exec_test(
native_test,
name = "pkgutil_component_expand_full_strip_6_test",
src = ":test",
args = [
"-e",
"$(location :pkgutil_component_expand_full_strip_6_action)/usr/bin/cups-config",
],
data = [
":pkgutil_component_expand_full_strip_6_action",
],
)

exec_test(
native_test,
name = "pkgutil_product_expand_test",
Expand Down