1// Copyright 2016 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 <fcntl.h> 6#include <stdint.h> 7#include <stdio.h> 8#include <stdlib.h> 9#include <sys/stat.h> 10#include <unistd.h> 11 12#include <lib/fdio/limits.h> 13#include <lib/fdio/util.h> 14#include <unittest/unittest.h> 15#include <zircon/syscalls.h> 16 17#include "filesystems.h" 18 19bool test_basic(void) { 20 BEGIN_TEST; 21 22 ASSERT_EQ(mkdir("::alpha", 0755), 0, ""); 23 ASSERT_EQ(mkdir("::alpha/bravo", 0755), 0, ""); 24 ASSERT_EQ(mkdir("::alpha/bravo/charlie", 0755), 0, ""); 25 ASSERT_EQ(mkdir("::alpha/bravo/charlie/delta", 0755), 0, ""); 26 ASSERT_EQ(mkdir("::alpha/bravo/charlie/delta/echo", 0755), 0, ""); 27 int fd1 = open("::alpha/bravo/charlie/delta/echo/foxtrot", O_RDWR | O_CREAT, 0644); 28 ASSERT_GT(fd1, 0, ""); 29 int fd2 = open("::alpha/bravo/charlie/delta/echo/foxtrot", O_RDWR, 0644); 30 ASSERT_GT(fd2, 0, ""); 31 ASSERT_EQ(write(fd1, "Hello, World!\n", 14), 14, ""); 32 ASSERT_EQ(close(fd1), 0, ""); 33 ASSERT_EQ(close(fd2), 0, ""); 34 35 // test pipelined opens 36 // the open itself will always succeed if the remote side exists, 37 // but we'll get an error when we try to do an operation on the file 38 fd1 = open("::alpha/bravo/charlie/delta/echo/foxtrot", O_RDONLY | O_PIPELINE, 0644); 39 ASSERT_GT(fd1, 0, ""); 40 char tmp[14]; 41 ASSERT_EQ(read(fd1, tmp, 14), 14, ""); 42 ASSERT_EQ(close(fd1), 0, ""); 43 ASSERT_EQ(memcmp(tmp, "Hello, World!\n", 14), 0, ""); 44 45 fd1 = open("::alpha/banana", O_RDONLY | O_PIPELINE, 0644); 46 ASSERT_GT(fd1, 0, ""); 47 ASSERT_EQ(read(fd1, tmp, 14), -1, ""); 48 ASSERT_EQ(close(fd1), -1, ""); 49 50 fd1 = open("::file.txt", O_CREAT | O_RDWR, 0644); 51 ASSERT_GT(fd1, 0, ""); 52 ASSERT_EQ(close(fd1), 0, ""); 53 54 ASSERT_EQ(unlink("::file.txt"), 0, ""); 55 ASSERT_EQ(mkdir("::emptydir", 0755), 0, ""); 56 fd1 = open("::emptydir", O_RDONLY, 0644); 57 ASSERT_GT(fd1, 0, ""); 58 59 // Zero-sized reads should always succeed 60 ASSERT_EQ(read(fd1, NULL, 0), 0, ""); 61 // But nonzero reads to directories should always fail 62 char buf; 63 ASSERT_EQ(read(fd1, &buf, 1), -1, ""); 64 ASSERT_EQ(write(fd1, "Don't write to directories", 26), -1, ""); 65 ASSERT_EQ(ftruncate(fd1, 0), -1, ""); 66 ASSERT_EQ(rmdir("::emptydir"), 0, ""); 67 ASSERT_EQ(rmdir("::emptydir"), -1, ""); 68 ASSERT_EQ(close(fd1), 0, ""); 69 ASSERT_EQ(rmdir("::emptydir"), -1, ""); 70 71 END_TEST; 72} 73 74bool test_unclean_close(void) { 75 BEGIN_TEST; 76 77 int fd = open("::foobar", O_CREAT | O_RDWR); 78 ASSERT_GT(fd, 0, ""); 79 80 // Try closing a connection to a file with an "unclean" shutdown, 81 // noticed by the filesystem server as a closed handle rather than 82 // an explicit "Close" call. 83 zx_handle_t handles[FDIO_MAX_HANDLES]; 84 uint32_t types[FDIO_MAX_HANDLES]; 85 zx_status_t r = fdio_transfer_fd(fd, 0, handles, types); 86 ASSERT_GE(fd, 0, ""); 87 for (size_t i = 0; i < (size_t) r; i++) { 88 ASSERT_EQ(zx_handle_close(handles[i]), ZX_OK, ""); 89 } 90 91 ASSERT_EQ(unlink("::foobar"), 0, ""); 92 93 END_TEST; 94} 95 96RUN_FOR_ALL_FILESYSTEMS(basic_tests, 97 RUN_TEST_MEDIUM(test_basic) 98 RUN_TEST_MEDIUM(test_unclean_close) 99) 100