Skip to content

Commit af64e01

Browse files
committed
Add ListDirectory to ReadFilesystem
Implement ListDirectory in ReadFilesystem and its implementations. Bug: b/505164979 Assisted-by: Antigravity:Gemini-Next
1 parent 07b2adb commit af64e01

16 files changed

Lines changed: 272 additions & 7 deletions

base/cvd/cuttlefish/host/libs/zip/libzip_cc/BUILD.bazel

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//cuttlefish/bazel:rules.bzl", "cf_cc_library")
1+
load("//cuttlefish/bazel:rules.bzl", "cf_cc_library", "cf_cc_test")
22

33
package(
44
default_visibility = ["//:android_cuttlefish"],
@@ -23,6 +23,7 @@ cf_cc_library(
2323
"//cuttlefish/io",
2424
"//cuttlefish/io:filesystem",
2525
"//cuttlefish/result",
26+
"@abseil-cpp//absl/strings",
2627
"@libzip",
2728
"@zlib",
2829
],
@@ -117,3 +118,15 @@ cf_cc_library(
117118
"@zlib",
118119
],
119120
)
121+
122+
cf_cc_test(
123+
name = "archive_test",
124+
srcs = ["archive_test.cc"],
125+
deps = [
126+
"//cuttlefish/host/libs/zip:zip_string",
127+
"//cuttlefish/host/libs/zip/libzip_cc:archive",
128+
"//cuttlefish/host/libs/zip/libzip_cc:writable_source",
129+
"//cuttlefish/result",
130+
"//cuttlefish/result:result_matchers",
131+
],
132+
)

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
#include <sys/types.h>
2222

2323
#include <memory>
24+
#include <set>
2425
#include <string>
2526
#include <string_view>
2627
#include <utility>
28+
#include <vector>
2729

30+
#include "absl/strings/strip.h"
2831
#include "zip.h"
2932

3033
#include "cuttlefish/host/libs/zip/libzip_cc/error.h"
@@ -146,6 +149,26 @@ Result<uint32_t> ReadableZip::FileAttributes(std::string_view path) const {
146149
return mode;
147150
}
148151

152+
Result<std::vector<std::string>> ReadableZip::ListDirectory(
153+
std::string_view path) {
154+
std::set<std::string> entries;
155+
std::string prefix = std::string(path);
156+
if (!prefix.empty() && prefix.back() != '/') {
157+
prefix += "/";
158+
}
159+
160+
uint64_t num_entries = CF_EXPECT(NumEntries());
161+
for (uint64_t i = 0; i < num_entries; ++i) {
162+
std::string name = CF_EXPECT(EntryName(i));
163+
std::string_view rest = name;
164+
if (absl::ConsumePrefix(&rest, prefix)) {
165+
std::string_view::size_type slash_pos = rest.find('/');
166+
entries.emplace(rest.substr(0, slash_pos));
167+
}
168+
}
169+
return std::vector<std::string>(entries.begin(), entries.end());
170+
}
171+
149172
ReadableZip::ReadableZip(ManagedZip raw, WritableZipSource source)
150173
: raw_(std::move(raw)), source_(std::move(source)) {}
151174

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <memory>
2222
#include <string>
2323
#include <string_view>
24+
#include <vector>
2425

2526
#include "cuttlefish/host/libs/zip/libzip_cc/managed.h"
2627
#include "cuttlefish/host/libs/zip/libzip_cc/readable_source.h"
@@ -58,6 +59,9 @@ class ReadableZip : public ReadFilesystem {
5859

5960
Result<uint32_t> FileAttributes(std::string_view path) const override;
6061

62+
Result<std::vector<std::string>> ListDirectory(
63+
std::string_view path) override;
64+
6165
protected:
6266
ReadableZip(ManagedZip, WritableZipSource);
6367

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//
2+
// Copyright (C) 2026 The Android Open Source Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
#include "cuttlefish/host/libs/zip/libzip_cc/archive.h"
17+
18+
#include <string>
19+
#include <utility>
20+
#include <vector>
21+
22+
#include <gmock/gmock.h>
23+
#include <gtest/gtest.h>
24+
25+
#include "cuttlefish/host/libs/zip/libzip_cc/writable_source.h"
26+
#include "cuttlefish/host/libs/zip/zip_string.h"
27+
#include "cuttlefish/result/result.h"
28+
#include "cuttlefish/result/result_matchers.h"
29+
30+
namespace cuttlefish {
31+
namespace {
32+
33+
TEST(ReadableZipTest, ListDirectory) {
34+
std::string data(4096, '\0');
35+
auto source_result = WritableZipSource::BorrowData(data.data(), data.size());
36+
ASSERT_THAT(source_result, IsOk());
37+
WritableZipSource source = std::move(*source_result);
38+
39+
auto zip_result = WritableZip::FromSource(std::move(source));
40+
ASSERT_THAT(zip_result, IsOk());
41+
WritableZip zip = std::move(*zip_result);
42+
43+
ASSERT_THAT(AddStringAt(zip, "abc", "dir/file1"), IsOk());
44+
ASSERT_THAT(AddStringAt(zip, "def", "dir/file2"), IsOk());
45+
46+
auto source_result2 = WritableZipSource::FromZip(std::move(zip));
47+
ASSERT_THAT(source_result2, IsOk());
48+
source = std::move(*source_result2);
49+
50+
auto readable_zip_result = ReadableZip::FromSource(std::move(source));
51+
ASSERT_THAT(readable_zip_result, IsOk());
52+
ReadableZip readable_zip = std::move(*readable_zip_result);
53+
54+
Result<std::vector<std::string>> entries = readable_zip.ListDirectory("dir");
55+
ASSERT_THAT(entries, IsOk());
56+
EXPECT_THAT(*entries, testing::UnorderedElementsAre("file1", "file2"));
57+
}
58+
59+
} // namespace
60+
} // namespace cuttlefish

base/cvd/cuttlefish/host/libs/zip/remote_zip_test.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,7 @@ TEST(RemoteZipTest, TwoFiles) {
139139
ASSERT_THAT(ReadToString(**file_b), IsOkAndValue("def"));
140140
}
141141

142+
143+
142144
} // namespace
143145
} // namespace cuttlefish

base/cvd/cuttlefish/io/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ cf_cc_library(
9393
"//cuttlefish/io:read_window_view",
9494
"//cuttlefish/result:expect",
9595
"//cuttlefish/result:result_type",
96+
"@abseil-cpp//absl/strings",
9697
],
9798
)
9899

@@ -198,6 +199,7 @@ cf_cc_library(
198199
"//cuttlefish/io:filesystem",
199200
"//cuttlefish/result:expect",
200201
"//cuttlefish/result:result_type",
202+
"@abseil-cpp//absl/strings",
201203
],
202204
)
203205

@@ -293,6 +295,7 @@ cf_cc_library(
293295
hdrs = ["native_filesystem.h"],
294296
deps = [
295297
"//cuttlefish/common/libs/fs",
298+
"//cuttlefish/common/libs/utils:files",
296299
"//cuttlefish/io",
297300
"//cuttlefish/io:filesystem",
298301
"//cuttlefish/io:shared_fd",

base/cvd/cuttlefish/io/chroot.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ Result<uint32_t> ChrootReadWriteFilesystem::FileAttributes(
5151
"Failed for '{}' (actually '{}')", path, real_path);
5252
}
5353

54+
Result<std::vector<std::string>> ChrootReadWriteFilesystem::ListDirectory(
55+
std::string_view path) {
56+
std::string real_path = CF_EXPECT(ChrootToRealPath(path));
57+
return CF_EXPECTF(real_filesystem_->ListDirectory(real_path),
58+
"Failed for '{}' (actually '{}')", path, real_path);
59+
}
60+
5461
Result<std::unique_ptr<ReaderWriterSeeker>>
5562
ChrootReadWriteFilesystem::CreateFile(std::string_view path) {
5663
std::string real_path = CF_EXPECT(ChrootToRealPath(path));

base/cvd/cuttlefish/io/chroot.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <string>
2323
#include <string_view>
24+
#include <vector>
2425

2526
#include "cuttlefish/io/io.h"
2627
#include "cuttlefish/result/result_type.h"
@@ -45,6 +46,9 @@ class ChrootReadWriteFilesystem : public ReadWriteFilesystem {
4546

4647
Result<uint32_t> FileAttributes(std::string_view path) const override;
4748

49+
Result<std::vector<std::string>> ListDirectory(
50+
std::string_view path) override;
51+
4852
Result<std::unique_ptr<ReaderWriterSeeker>> CreateFile(
4953
std::string_view path) override;
5054

base/cvd/cuttlefish/io/cpio.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
#include <string.h>
2020

2121
#include <charconv>
22+
#include <set>
2223
#include <string_view>
2324

25+
#include "absl/strings/strip.h"
2426
#include "cuttlefish/common/libs/utils/size_utils.h"
2527
#include "cuttlefish/io/read_exact.h"
2628
#include "cuttlefish/io/read_window_view.h"
@@ -287,4 +289,22 @@ Result<uint32_t> CpioReader::FileAttributes(std::string_view path) const {
287289
return it->second.mode;
288290
}
289291

292+
Result<std::vector<std::string>> CpioReader::ListDirectory(
293+
std::string_view path) {
294+
std::set<std::string> entries;
295+
std::string prefix = std::string(path);
296+
if (!prefix.empty() && prefix.back() != '/') {
297+
prefix += "/";
298+
}
299+
300+
for (const auto& [file_path, _] : entries_) {
301+
std::string_view rest = file_path;
302+
if (absl::ConsumePrefix(&rest, prefix)) {
303+
std::string_view::size_type slash_pos = rest.find('/');
304+
entries.emplace(rest.substr(0, slash_pos));
305+
}
306+
}
307+
return std::vector<std::string>(entries.begin(), entries.end());
308+
}
309+
290310
} // namespace cuttlefish

base/cvd/cuttlefish/io/cpio.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <memory>
2222
#include <string>
2323
#include <string_view>
24+
#include <vector>
2425

2526
#include "cuttlefish/io/filesystem.h"
2627
#include "cuttlefish/io/io.h"
@@ -41,6 +42,9 @@ class CpioReader : public ReadFilesystem {
4142

4243
Result<uint32_t> FileAttributes(std::string_view path) const override;
4344

45+
Result<std::vector<std::string>> ListDirectory(
46+
std::string_view path) override;
47+
4448
private:
4549
struct FileEntry {
4650
uint64_t offset;

0 commit comments

Comments
 (0)