1/* 2 * Copyright (C) 2013 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 17#include <gtest/gtest.h> 18 19#include <errno.h> 20#include <fcntl.h> 21 22#include "TemporaryFile.h" 23 24TEST(fcntl, fcntl_smoke) { 25 int fd = open("/proc/version", O_RDONLY); 26 ASSERT_TRUE(fd != -1); 27 28 int flags = fcntl(fd, F_GETFD); 29 ASSERT_TRUE(flags != -1); 30 ASSERT_EQ(0, flags & FD_CLOEXEC); 31 32 int rc = fcntl(fd, F_SETFD, FD_CLOEXEC); 33 ASSERT_EQ(0, rc); 34 35 flags = fcntl(fd, F_GETFD); 36 ASSERT_TRUE(flags != -1); 37 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC); 38 39 close(fd); 40} 41 42TEST(fcntl, open_open64) { 43 int fd; 44 45 fd = open("/proc/version", O_RDONLY); 46 ASSERT_TRUE(fd != -1); 47 close(fd); 48 49 fd = open64("/proc/version", O_RDONLY); 50 ASSERT_TRUE(fd != -1); 51 close(fd); 52} 53 54TEST(fcntl, openat_openat64) { 55 int fd; 56 57 fd = openat(AT_FDCWD, "/proc/version", O_RDONLY); 58 ASSERT_TRUE(fd != -1); 59 close(fd); 60 61 fd = openat64(AT_FDCWD, "/proc/version", O_RDONLY); 62 ASSERT_TRUE(fd != -1); 63 close(fd); 64} 65 66TEST(fcntl, creat_creat64) { 67 ASSERT_EQ(-1, creat("", 0666)); 68 ASSERT_EQ(ENOENT, errno); 69 ASSERT_EQ(-1, creat64("", 0666)); 70 ASSERT_EQ(ENOENT, errno); 71} 72 73TEST(fcntl, posix_fadvise) { 74 TemporaryFile tf; 75 errno = 0; 76 77 EXPECT_EQ(EBADF, posix_fadvise(-1, 0, 0, POSIX_FADV_NORMAL)); 78 EXPECT_EQ(0, errno); 79 80 EXPECT_EQ(EBADF, posix_fadvise64(-1, 0, 0, POSIX_FADV_NORMAL)); 81 EXPECT_EQ(0, errno); 82 83 EXPECT_EQ(EINVAL, posix_fadvise(tf.fd, 0, 0, -1)); 84 EXPECT_EQ(0, errno); 85 86 EXPECT_EQ(EINVAL, posix_fadvise64(tf.fd, 0, 0, -1)); 87 EXPECT_EQ(0, errno); 88 89 EXPECT_EQ(0, posix_fadvise(tf.fd, 0, 0, POSIX_FADV_NORMAL)); 90 EXPECT_EQ(0, posix_fadvise64(tf.fd, 0, 0, POSIX_FADV_NORMAL)); 91} 92 93TEST(fcntl, fallocate_EINVAL) { 94 TemporaryFile tf; 95 96 // fallocate/fallocate64 set errno. 97 // posix_fallocate/posix_fallocate64 return an errno value. 98 99 errno = 0; 100 ASSERT_EQ(-1, fallocate(tf.fd, 0, 0, -1)); 101 ASSERT_EQ(EINVAL, errno); 102 103 errno = 0; 104 ASSERT_EQ(-1, fallocate64(tf.fd, 0, 0, -1)); 105 ASSERT_EQ(EINVAL, errno); 106 107 errno = 0; 108 ASSERT_EQ(EINVAL, posix_fallocate(tf.fd, 0, -1)); 109 ASSERT_EQ(0, errno); 110 111 errno = 0; 112 ASSERT_EQ(EINVAL, posix_fallocate64(tf.fd, 0, -1)); 113 ASSERT_EQ(0, errno); 114} 115 116TEST(fcntl, fallocate) { 117 TemporaryFile tf; 118 struct stat sb; 119 ASSERT_EQ(0, fstat(tf.fd, &sb)); 120 ASSERT_EQ(0, sb.st_size); 121 122#if defined(__BIONIC__) 123 ASSERT_EQ(0, fallocate(tf.fd, 0, 0, 1)); 124 ASSERT_EQ(0, fstat(tf.fd, &sb)); 125 ASSERT_EQ(1, sb.st_size); 126 127 ASSERT_EQ(0, fallocate64(tf.fd, 0, 0, 2)); 128 ASSERT_EQ(0, fstat(tf.fd, &sb)); 129 ASSERT_EQ(2, sb.st_size); 130#endif 131 132 ASSERT_EQ(0, posix_fallocate(tf.fd, 0, 3)); 133 ASSERT_EQ(0, fstat(tf.fd, &sb)); 134 ASSERT_EQ(3, sb.st_size); 135 136 ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, 4)); 137 ASSERT_EQ(0, fstat(tf.fd, &sb)); 138 ASSERT_EQ(4, sb.st_size); 139} 140 141TEST(fcntl, f_getlk64) { 142 int fd = open64("/proc/version", O_RDONLY); 143 ASSERT_TRUE(fd != -1); 144 145 struct flock64 check_lock; 146 check_lock.l_type = F_WRLCK; 147 check_lock.l_start = 0; 148 check_lock.l_whence = SEEK_SET; 149 check_lock.l_len = 0; 150 151 int rc = fcntl(fd, F_GETLK64, &check_lock); 152 ASSERT_EQ(0, rc); 153 154 close(fd); 155} 156 157TEST(fcntl, splice) { 158 int pipe_fds[2]; 159 ASSERT_EQ(0, pipe(pipe_fds)); 160 161 int in = open("/proc/cpuinfo", O_RDONLY); 162 ASSERT_NE(in, -1); 163 164 TemporaryFile tf; 165 166 ssize_t bytes_read = splice(in, 0, pipe_fds[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE); 167 ASSERT_NE(bytes_read, -1); 168 169 ssize_t bytes_written = splice(pipe_fds[0], NULL, tf.fd, 0, bytes_read, SPLICE_F_MORE | SPLICE_F_MOVE); 170 ASSERT_EQ(bytes_read, bytes_written); 171 172 close(pipe_fds[0]); 173 close(pipe_fds[1]); 174 close(in); 175} 176 177TEST(fcntl, vmsplice) { 178 int pipe_fds[2]; 179 ASSERT_EQ(0, pipe(pipe_fds)); 180 181 iovec v[2]; 182 v[0].iov_base = const_cast<char*>("hello "); 183 v[0].iov_len = 6; 184 v[1].iov_base = const_cast<char*>("world\n"); 185 v[1].iov_len = 6; 186 ssize_t bytes_written = vmsplice(pipe_fds[1], v, sizeof(v)/sizeof(iovec), 0); 187 ASSERT_EQ(v[0].iov_len + v[1].iov_len, static_cast<size_t>(bytes_written)); 188 close(pipe_fds[1]); 189 190 char buf[BUFSIZ]; 191 FILE* fp = fdopen(pipe_fds[0], "r"); 192 ASSERT_TRUE(fp != NULL); 193 ASSERT_TRUE(fgets(buf, sizeof(buf), fp) != NULL); 194 fclose(fp); 195 ASSERT_STREQ("hello world\n", buf); 196} 197 198TEST(fcntl, tee) { 199 char expected[256]; 200 FILE* expected_fp = fopen("/proc/version", "r"); 201 ASSERT_TRUE(expected_fp != NULL); 202 ASSERT_TRUE(fgets(expected, sizeof(expected), expected_fp) != NULL); 203 fclose(expected_fp); 204 205 int pipe1[2]; 206 ASSERT_EQ(0, pipe(pipe1)); 207 208 int pipe2[2]; 209 ASSERT_EQ(0, pipe(pipe2)); 210 211 int in = open("/proc/version", O_RDONLY); 212 ASSERT_NE(in, -1); 213 214 // Write /proc/version into pipe1. 215 ssize_t bytes_read = splice(in, 0, pipe1[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE); 216 ASSERT_NE(bytes_read, -1); 217 close(pipe1[1]); 218 219 // Tee /proc/version from pipe1 into pipe2. 220 ssize_t bytes_teed = tee(pipe1[0], pipe2[1], SIZE_MAX, 0); 221 ASSERT_EQ(bytes_read, bytes_teed); 222 close(pipe2[1]); 223 224 // The out fds of both pipe1 and pipe2 should now contain /proc/version. 225 char buf1[BUFSIZ]; 226 FILE* fp1 = fdopen(pipe1[0], "r"); 227 ASSERT_TRUE(fp1 != NULL); 228 ASSERT_TRUE(fgets(buf1, sizeof(buf1), fp1) != NULL); 229 fclose(fp1); 230 231 char buf2[BUFSIZ]; 232 FILE* fp2 = fdopen(pipe2[0], "r"); 233 ASSERT_TRUE(fp2 != NULL); 234 ASSERT_TRUE(fgets(buf2, sizeof(buf2), fp2) != NULL); 235 fclose(fp2); 236 237 ASSERT_STREQ(expected, buf1); 238 ASSERT_STREQ(expected, buf2); 239} 240