[fdio] Add fdio_open, a variant of fdio_open_at
It uses fdio_root_ns with fdio_ns_connect, which traverses the root
namespace to then call fdio_open_at.
Test: Added a test to system/utest/memfs.
Change-Id: I5e08e69083a86227cf82efa2f69f86ea2c2f2a4b
diff --git a/system/ulib/fdio/include/lib/fdio/util.h b/system/ulib/fdio/include/lib/fdio/util.h
index eb68ee9..fd30748 100644
--- a/system/ulib/fdio/include/lib/fdio/util.h
+++ b/system/ulib/fdio/include/lib/fdio/util.h
@@ -94,7 +94,10 @@
// an error is returned and the handle is closed.
zx_status_t fdio_service_connect_at(zx_handle_t dir, const char* path, zx_handle_t h);
-// As above but allows the passing of flags
+// Same as |fdio_service_connect|, but allows the passing of flags.
+zx_status_t fdio_open(const char* path, uint32_t zxflags, zx_handle_t h);
+
+// Same as |fdio_service_connect_at, but allows the passing of flags.
zx_status_t fdio_open_at(zx_handle_t dir, const char* path, uint32_t zxflags, zx_handle_t h);
// Attempt to clone a service handle by doing a pipelined
diff --git a/system/ulib/fdio/remoteio.c b/system/ulib/fdio/remoteio.c
index 439443e..fbba602 100644
--- a/system/ulib/fdio/remoteio.c
+++ b/system/ulib/fdio/remoteio.c
@@ -270,6 +270,21 @@
}
__EXPORT
+zx_status_t fdio_open(const char* path, uint32_t flags, zx_handle_t h) {
+ if (path == NULL) {
+ zx_handle_close(h);
+ return ZX_ERR_INVALID_ARGS;
+ }
+ // Otherwise attempt to connect through the root namespace
+ if (fdio_root_ns != NULL) {
+ return fdio_ns_connect(fdio_root_ns, path, flags, h);
+ }
+ // Otherwise we fail
+ zx_handle_close(h);
+ return ZX_ERR_NOT_FOUND;
+}
+
+__EXPORT
zx_status_t fdio_open_at(zx_handle_t dir, const char* path, uint32_t flags, zx_handle_t h) {
if (path == NULL) {
zx_handle_close(h);
diff --git a/system/utest/memfs/fidl-tests.cpp b/system/utest/memfs/fidl-tests.cpp
index 74426c7..1830bc2 100644
--- a/system/utest/memfs/fidl-tests.cpp
+++ b/system/utest/memfs/fidl-tests.cpp
@@ -36,19 +36,16 @@
fbl::unique_fd fd(open("/fidltmp", O_DIRECTORY | O_RDONLY));
ASSERT_GE(fd.get(), 0);
- // Access files within the filesystem.
- DIR* d = fdopendir(fd.release());
-
// Create a file
const char* filename = "file-a";
- fd.reset(openat(dirfd(d), filename, O_CREAT | O_RDWR));
+ fd.reset(openat(fd.get(), filename, O_CREAT | O_RDWR));
ASSERT_GE(fd.get(), 0);
const char* data = "hello";
ssize_t datalen = strlen(data);
ASSERT_EQ(write(fd.get(), data, datalen), datalen);
fd.reset();
- zx_handle_t h, request = ZX_HANDLE_INVALID;
+ zx_handle_t h, request;
ASSERT_EQ(zx_channel_create(0, &h, &request), ZX_OK);
ASSERT_EQ(fdio_service_connect("/fidltmp/file-a", request), ZX_OK);
@@ -57,7 +54,40 @@
ASSERT_EQ(info.tag, fuchsia_io_NodeInfoTag_file);
ASSERT_EQ(info.file.event, ZX_HANDLE_INVALID);
zx_handle_close(h);
- closedir(d);
+
+ loop.Shutdown();
+
+ // No way to clean up the namespace entry. See ZX-2013 for more details.
+
+ END_TEST;
+}
+
+bool TestFidlOpenReadOnly() {
+ BEGIN_TEST;
+
+ async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
+ ASSERT_EQ(loop.StartThread(), ZX_OK);
+
+ ASSERT_EQ(memfs_install_at(loop.dispatcher(), "/fidltmp-ro"), ZX_OK);
+ fbl::unique_fd fd(open("/fidltmp-ro", O_DIRECTORY | O_RDONLY));
+ ASSERT_GE(fd.get(), 0);
+
+ // Create a file
+ const char* filename = "file-ro";
+ fd.reset(openat(fd.get(), filename, O_CREAT | O_RDWR));
+ ASSERT_GE(fd.get(), 0);
+ fd.reset();
+
+ zx_handle_t h, request;
+ ASSERT_EQ(zx_channel_create(0, &h, &request), ZX_OK);
+ ASSERT_EQ(fdio_open("/fidltmp-ro/file-ro", ZX_FS_RIGHT_READABLE, request), ZX_OK);
+
+ zx_status_t status;
+ uint32_t flags;
+ ASSERT_EQ(fuchsia_io_FileGetFlags(h, &status, &flags), ZX_OK);
+ ASSERT_EQ(status, ZX_OK);
+ ASSERT_EQ(flags, ZX_FS_RIGHT_READABLE);
+ zx_handle_close(h);
loop.Shutdown();
@@ -164,5 +194,6 @@
BEGIN_TEST_CASE(fidl_tests)
RUN_TEST(TestFidlBasic)
+RUN_TEST(TestFidlOpenReadOnly)
RUN_TEST(TestFidlQueryFilesystem)
END_TEST_CASE(fidl_tests)