sys_stat_test.cpp revision c6e5874a4c19f398eb179a23de9b1d2c06bccea0
1d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes/* 2d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * Copyright (C) 2013 The Android Open Source Project 3d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * 4d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * you may not use this file except in compliance with the License. 6d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * You may obtain a copy of the License at 7d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * 8d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * 10d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * Unless required by applicable law or agreed to in writing, software 11d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * See the License for the specific language governing permissions and 14d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes * limitations under the License. 15d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes */ 16d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 17d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes#include <gtest/gtest.h> 18d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 19d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes#include <errno.h> 20db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes#include <fcntl.h> 21d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes#include <stdlib.h> 22d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes#include <sys/stat.h> 23d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 24594b1a4af204aa9de2b4913182f4556e38d71648Elliott Hughes#include "TemporaryFile.h" 25594b1a4af204aa9de2b4913182f4556e38d71648Elliott Hughes 26d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott HughesTEST(sys_stat, futimens) { 27d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes FILE* fp = tmpfile(); 28d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_TRUE(fp != NULL); 29d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 30d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes int fd = fileno(fp); 31d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_NE(fd, -1); 32d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 33d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes timespec times[2]; 34d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[0].tv_sec = 123; 35d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[0].tv_nsec = 0; 36d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[1].tv_sec = 456; 37d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[1].tv_nsec = 0; 38d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(0, futimens(fd, times)) << strerror(errno); 39d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 40d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes struct stat sb; 41d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(0, fstat(fd, &sb)); 42d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(times[0].tv_sec, static_cast<long>(sb.st_atime)); 43d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(times[1].tv_sec, static_cast<long>(sb.st_mtime)); 44d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 45d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes fclose(fp); 46d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes} 47d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes 48d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott HughesTEST(sys_stat, futimens_EBADF) { 49d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes timespec times[2]; 50d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[0].tv_sec = 123; 51d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[0].tv_nsec = 0; 52d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[1].tv_sec = 456; 53d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes times[1].tv_nsec = 0; 54d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(-1, futimens(-1, times)); 55d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes ASSERT_EQ(EBADF, errno); 56d0be7c8f9a06b3ca8ea7647ea35c8f9dc63f0fe1Elliott Hughes} 57594b1a4af204aa9de2b4913182f4556e38d71648Elliott Hughes 58ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott HughesTEST(sys_stat, mkfifo_failure) { 59ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes errno = 0; 60ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes ASSERT_EQ(-1, mkfifo("/", 0666)); 61ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes ASSERT_EQ(EEXIST, errno); 62ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes} 63ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes 64ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott HughesTEST(sys_stat, mkfifoat_failure) { 65ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes errno = 0; 66ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes ASSERT_EQ(-1, mkfifoat(-2, "x", 0666)); 67ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes ASSERT_EQ(EBADF, errno); 68ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes} 69ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes 70594b1a4af204aa9de2b4913182f4556e38d71648Elliott HughesTEST(sys_stat, mkfifo) { 71528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris if (getuid() == 0) { 72528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris // Racy but probably sufficient way to get a suitable filename. 73528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris std::string path; 74528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris { 75528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris TemporaryFile tf; 76528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris path = tf.filename; 77528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris } 78594b1a4af204aa9de2b4913182f4556e38d71648Elliott Hughes 79528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris ASSERT_EQ(0, mkfifo(path.c_str(), 0666)); 80528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris struct stat sb; 81528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris ASSERT_EQ(0, stat(path.c_str(), &sb)); 82528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris ASSERT_TRUE(S_ISFIFO(sb.st_mode)); 83528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris unlink(path.c_str()); 84528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris } else { 85ca8e84c6ff55640aef94d25a86a25778a542bfc2Elliott Hughes // SELinux policy forbids us from creating FIFOs. http://b/17646702. 86528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris GTEST_LOG_(INFO) << "This test only performs a test when run as root."; 87528ad742c671f17a9f8731ad8de4bcc931631bc9Christopher Ferris } 88594b1a4af204aa9de2b4913182f4556e38d71648Elliott Hughes} 89db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes 90db1ea3474899ebbd783aba872d3005f95a816d0fElliott HughesTEST(sys_stat, stat64_lstat64_fstat64) { 91db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes struct stat64 sb; 92db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes ASSERT_EQ(0, stat64("/proc/version", &sb)); 93db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes ASSERT_EQ(0, lstat64("/proc/version", &sb)); 94db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes int fd = open("/proc/version", O_RDONLY); 95db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes ASSERT_EQ(0, fstat64(fd, &sb)); 96db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes close(fd); 97db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes} 983cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 993cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_EFAULT_file) { 1003cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, (char *) 0x1, 0751, 0)); 1013cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(EFAULT, errno); 1023cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1033cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1043cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_EFAULT_file) { 1053cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, (char *) 0x1, 0751, AT_SYMLINK_NOFOLLOW)); 1063cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#if defined(__BIONIC__) 1073cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(EFAULT, errno); 1083cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#else 1093cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always 1103cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // returns ENOTSUP 1113cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOTSUP, errno); 1123cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#endif 1133cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1143cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1153cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_bad_flags) { 1163cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, ~AT_SYMLINK_NOFOLLOW)); 1173cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(EINVAL, errno); 1183cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1193cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1203cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_bad_flags_ALL) { 1213cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, ~0)); 1223cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(EINVAL, errno); 1233cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1243cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1253cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_nonexistant_file) { 1263cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, 0)); 1273cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOENT, errno); 1283cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1293cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1303cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_nonexistant_file) { 1313cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, AT_SYMLINK_NOFOLLOW)); 1323cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#if defined(__BIONIC__) 1333cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOENT, errno); 1343cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#else 1353cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always 1363cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // returns ENOTSUP 1373cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOTSUP, errno); 1383cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#endif 1393cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1403cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 141c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cuistatic void AssertFileModeEquals(mode_t expected_mode, const char* filename) { 142c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui struct stat sb; 143c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(0, stat(filename, &sb)); 144c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO; 145c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(expected_mode & mask, static_cast<mode_t>(sb.st_mode) & mask); 146c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui} 147c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui 1483cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_file) { 1493cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 1503cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1513cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.filename, 0751, 0)); 152c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertFileModeEquals(0751, tf.filename); 1533cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1543cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1553cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_file) { 1563cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 1573cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich errno = 0; 1583cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich int result = fchmodat(AT_FDCWD, tf.filename, 0751, AT_SYMLINK_NOFOLLOW); 1593cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1603cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#if defined(__BIONIC__) 1613cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, result); 1623cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, errno); 163c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertFileModeEquals(0751, tf.filename); 1643cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#else 1653cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always 1663cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // returns ENOTSUP 1673cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, result); 1683cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOTSUP, errno); 1693cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#endif 1703cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1713cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1723cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_symlink) { 1733cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 1743cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich char linkname[255]; 1753cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1763cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(linkname, sizeof(linkname), "%s.link", tf.filename); 1773cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1783cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, symlink(tf.filename, linkname)); 1793cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, fchmodat(AT_FDCWD, linkname, 0751, 0)); 180c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertFileModeEquals(0751, tf.filename); 1813cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich unlink(linkname); 1823cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1833cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1843cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_dangling_symlink) { 1853cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 1863cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich char linkname[255]; 1873cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich char target[255]; 1883cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1893cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(linkname, sizeof(linkname), "%s.link", tf.filename); 1903cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename); 1913cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 1923cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, symlink(target, linkname)); 1933cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(-1, fchmodat(AT_FDCWD, linkname, 0751, 0)); 1943cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(ENOENT, errno); 1953cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich unlink(linkname); 1963cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 1973cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 198c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cuistatic void AssertSymlinkModeEquals(mode_t expected_mode, const char* linkname) { 199c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui struct stat sb; 200c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(0, fstatat(AT_FDCWD, linkname, &sb, AT_SYMLINK_NOFOLLOW)); 201c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO; 202c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(expected_mode & mask, static_cast<mode_t>(sb.st_mode) & mask); 203c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui} 204c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui 2053cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_symlink) { 2063cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 207c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui struct stat tf_sb; 208c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(0, stat(tf.filename, &tf_sb)); 2093cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 210c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui char linkname[255]; 2113cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(linkname, sizeof(linkname), "%s.link", tf.filename); 2123cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 2133cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, symlink(tf.filename, linkname)); 214c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW); 215c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui // It depends on the kernel whether chmod operation on symlink is allowed. 216c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui if (result == 0) { 217c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertSymlinkModeEquals(0751, linkname); 218c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui } else { 219c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(-1, result); 220c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(ENOTSUP, errno); 221c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui } 222c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui 223c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui // Target file mode shouldn't be modified. 224c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertFileModeEquals(tf_sb.st_mode, tf.filename); 2253cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich unlink(linkname); 2263cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 2273cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 2283cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick KralevichTEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_dangling_symlink) { 2293cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich TemporaryFile tf; 230c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui 2313cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich char linkname[255]; 2323cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich char target[255]; 2333cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(linkname, sizeof(linkname), "%s.link", tf.filename); 2343cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename); 2353cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 2363cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ASSERT_EQ(0, symlink(target, linkname)); 237c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW); 238c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui // It depends on the kernel whether chmod operation on symlink is allowed. 239c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui if (result == 0) { 240c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui AssertSymlinkModeEquals(0751, linkname); 241c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui } else { 242c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(-1, result); 243c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui ASSERT_EQ(ENOTSUP, errno); 244c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui } 245c6e5874a4c19f398eb179a23de9b1d2c06bccea0Yabin Cui 2463cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich unlink(linkname); 2473cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 24835778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich 24935778253a5ed71e87a608ca590b63729d9f88567Nick KralevichTEST(sys_stat, faccessat_EINVAL) { 25035778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", F_OK, ~AT_SYMLINK_NOFOLLOW)); 25135778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(EINVAL, errno); 25235778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#if defined(__BIONIC__) 25335778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), 0)); 25435778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(EINVAL, errno); 25535778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#else 25635778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), AT_SYMLINK_NOFOLLOW)); 25735778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), 0)); 25835778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(EINVAL, errno); 25935778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#endif 26035778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich} 26135778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich 26235778253a5ed71e87a608ca590b63729d9f88567Nick KralevichTEST(sys_stat, faccessat_AT_SYMLINK_NOFOLLOW_EINVAL) { 26335778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#if defined(__BIONIC__) 26435778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich // Android doesn't support AT_SYMLINK_NOFOLLOW 26535778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", F_OK, AT_SYMLINK_NOFOLLOW)); 26635778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(EINVAL, errno); 26735778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#else 26835778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", F_OK, AT_SYMLINK_NOFOLLOW)); 26935778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#endif 27035778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich} 27135778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich 27235778253a5ed71e87a608ca590b63729d9f88567Nick KralevichTEST(sys_stat, faccessat_dev_null) { 27335778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", F_OK, 0)); 27435778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", R_OK, 0)); 27535778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", W_OK, 0)); 27635778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", R_OK|W_OK, 0)); 27735778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich} 27835778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich 27935778253a5ed71e87a608ca590b63729d9f88567Nick KralevichTEST(sys_stat, faccessat_nonexistant) { 28035778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(-1, faccessat(AT_FDCWD, "/blah", F_OK, AT_SYMLINK_NOFOLLOW)); 28135778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#if defined(__BIONIC__) 28235778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich // Android doesn't support AT_SYMLINK_NOFOLLOW 28335778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(EINVAL, errno); 28435778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#else 28535778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich ASSERT_EQ(ENOENT, errno); 28635778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich#endif 28735778253a5ed71e87a608ca590b63729d9f88567Nick Kralevich} 288