1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <dirent.h> 6#include <errno.h> 7#include <fcntl.h> 8#include <stdlib.h> 9#include <stdio.h> 10#include <string.h> 11#include <sys/stat.h> 12#include <unistd.h> 13 14#include <launchpad/launchpad.h> 15#include <lib/fdio/namespace.h> 16#include <zircon/compiler.h> 17#include <zircon/syscalls.h> 18#include <unittest/unittest.h> 19 20typedef struct { 21 const char* local; 22 const char* remote; 23} nstab_t; 24 25static nstab_t NS[] = { 26 { "/bin", "/boot/bin" }, 27 { "/lib", "/boot/lib" }, 28 { "/fake/dev", "/tmp/fake-namespace-test/dev" }, 29 { "/fake/tmp", "/tmp/fake-namespace-test-tmp" }, 30}; 31 32static bool namespace_create_test(void) { 33 BEGIN_TEST; 34 35 ASSERT_TRUE(mkdir("/tmp/fake-namespace-test", 066) == 0 || errno == EEXIST, ""); 36 ASSERT_TRUE(mkdir("/tmp/fake-namespace-test/dev", 066) == 0 || errno == EEXIST, ""); 37 ASSERT_TRUE(mkdir("/tmp/fake-namespace-test-tmp", 066) == 0 || errno == EEXIST, ""); 38 39 // Create new ns 40 fdio_ns_t* ns; 41 ASSERT_EQ(fdio_ns_create(&ns), ZX_OK, ""); 42 for (unsigned n = 0; n < countof(NS); n++) { 43 int fd = open(NS[n].remote, O_RDONLY | O_DIRECTORY); 44 ASSERT_GT(fd, 0, ""); 45 ASSERT_EQ(fdio_ns_bind_fd(ns, NS[n].local, fd), ZX_OK, ""); 46 ASSERT_EQ(close(fd), 0, ""); 47 } 48 ASSERT_EQ(fdio_ns_chdir(ns), ZX_OK, ""); 49 50 DIR* dir; 51 struct dirent* de; 52 53 // should show "bin", "lib", "fake" -- our rootdir 54 ASSERT_NONNULL((dir = opendir(".")), ""); 55 ASSERT_NONNULL((de = readdir(dir)), ""); 56 ASSERT_EQ(strcmp(de->d_name, "."), 0, ""); 57 ASSERT_NONNULL((de = readdir(dir)), ""); 58 ASSERT_EQ(strcmp(de->d_name, "fake"), 0, ""); 59 ASSERT_NONNULL((de = readdir(dir)), ""); 60 ASSERT_EQ(strcmp(de->d_name, "lib"), 0, ""); 61 ASSERT_NONNULL((de = readdir(dir)), ""); 62 ASSERT_EQ(strcmp(de->d_name, "bin"), 0, ""); 63 ASSERT_EQ(closedir(dir), 0, ""); 64 65 // should show "fake" directory, containing parent's pre-allocated tmp dir. 66 ASSERT_NONNULL((dir = opendir("fake")), ""); 67 ASSERT_NONNULL((de = readdir(dir)), ""); 68 ASSERT_EQ(strcmp(de->d_name, "."), 0, ""); 69 ASSERT_NONNULL((de = readdir(dir)), ""); 70 ASSERT_EQ(strcmp(de->d_name, "tmp"), 0, ""); 71 ASSERT_NONNULL((de = readdir(dir)), ""); 72 ASSERT_EQ(strcmp(de->d_name, "dev"), 0, ""); 73 ASSERT_EQ(closedir(dir), 0, ""); 74 75 // Try doing some basic file ops within the namespace 76 int fd = open("fake/tmp/newfile", O_CREAT | O_RDWR | O_EXCL); 77 ASSERT_GT(fd, 0, ""); 78 ASSERT_GT(write(fd, "hello", strlen("hello")), 0, ""); 79 ASSERT_EQ(close(fd), 0, ""); 80 ASSERT_EQ(unlink("fake/tmp/newfile"), 0, ""); 81 ASSERT_EQ(mkdir("fake/tmp/newdir", 0666), 0, ""); 82 ASSERT_EQ(rename("fake/tmp/newdir", "fake/tmp/olddir"), 0, ""); 83 ASSERT_EQ(rmdir("fake/tmp/olddir"), 0, ""); 84 85 END_TEST; 86} 87 88BEGIN_TEST_CASE(namespace_tests) 89RUN_TEST_MEDIUM(namespace_create_test) 90END_TEST_CASE(namespace_tests) 91 92int main(int argc, char** argv) { 93 return unittest_run_all_tests(argc, argv) ? 0 : -1; 94} 95