Skip to content

Commit 12b31b5

Browse files
committed
Fix unzipping when there is a nested directory
Android CTS's `android-cts.zip` has a nested `android-cts/` subdirectory that would fail in `ExtractOneTo()`. Bug: b/466404901 Test: bazel run cuttlefish/host/commands/cvd:cvd -- \ fetch \ --default_build=aosp-android-latest-release/aosp_cf_x86_64_only_phone-userdebug \ --test_suites_build=aosp-android13-tests-release/test_suites_x86_64 \ --target_directory=/tmp/fetch-test
1 parent 3219916 commit 12b31b5

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

base/cvd/cuttlefish/host/commands/cvd/fetch/fetch_context.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ Result<void> FetchArtifact::ExtractAll(const std::string& local_path) {
111111
CF_EXPECT(!absl::StartsWith(member_name, "."));
112112
CF_EXPECT(!absl::StartsWith(member_name, "/"));
113113
CF_EXPECT(!absl::StrContains(member_name, "/../"));
114-
std::string extract_path = fmt::format("{}/{}", local_path, member_name);
115-
CF_EXPECT(ExtractOneTo(member_name, extract_path));
114+
if (!CF_EXPECT(zip->EntryIsDirectory(i))) {
115+
std::string extract_path = fmt::format("{}/{}", local_path, member_name);
116+
CF_EXPECT(ExtractOneTo(member_name, extract_path));
117+
}
116118
}
117119
return {};
118120
}
@@ -132,7 +134,8 @@ Result<void> FetchArtifact::ExtractOneTo(const std::string& member_name,
132134
CF_EXPECT(EnsureDirectoryExists(dir, kRwxAllMode));
133135
}
134136

135-
CF_EXPECT(ExtractFile(*zip, member_name, extract_path));
137+
CF_EXPECT(ExtractFile(*zip, member_name, extract_path),
138+
"Failed to extract " << member_name << " to " << extract_path);
136139

137140
CF_EXPECT(fetch_build_context_.AddFileToConfig(extract_path, artifact_name_,
138141
local_path));

base/cvd/cuttlefish/host/libs/zip/libzip_cc/archive.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <stddef.h>
1919
#include <stdint.h>
2020
#include <stdio.h>
21+
#include <sys/stat.h>
22+
#include <sys/types.h>
2123

2224
#include <string>
2325
#include <utility>
@@ -88,6 +90,19 @@ Result<uint32_t> ReadableZip::EntryUnixAttributes(uint64_t index) {
8890
return attributes;
8991
}
9092

93+
Result<bool> ReadableZip::EntryIsDirectory(uint64_t index) {
94+
const uint32_t attributes =
95+
CF_EXPECT(EntryUnixAttributes(index),
96+
"Failed to get attributes for entry " << index);
97+
98+
// See
99+
// * https://cs.android.com/android/platform/superproject/main/+/main:build/soong/zip/zip.go;drc=8967d7562557001eb10e216ba7a947fb6054c67c;l=782
100+
// * https://cs.android.com/android/platform/superproject/main/+/main:build/soong/third_party/zip/struct.go;drc=61197364367c9e404c7da6900658f1b16c42d0da;l=225
101+
const mode_t mode = (attributes >> 16);
102+
103+
return S_ISDIR(mode);
104+
}
105+
91106
Result<SeekableZipSource> ReadableZip::GetFile(const std::string& name) {
92107
zip_t* raw_zip = CF_EXPECT(raw_.get());
93108

base/cvd/cuttlefish/host/libs/zip/libzip_cc/archive.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ReadableZip {
4444

4545
Result<std::string> EntryName(uint64_t index);
4646
Result<uint32_t> EntryUnixAttributes(uint64_t index);
47+
Result<bool> EntryIsDirectory(uint64_t index);
4748

4849
/* Decompresses and extract a file from the archive. */
4950
Result<SeekableZipSource> GetFile(const std::string& name);

0 commit comments

Comments
 (0)