xref: /aosp_15_r20/bionic/tests/sys_stat_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
18*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
19*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <sys/stat.h>
21*8d67ca89SAndroid Build Coastguard Worker 
22*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
24*8d67ca89SAndroid Build Coastguard Worker 
25*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
26*8d67ca89SAndroid Build Coastguard Worker 
27*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
28*8d67ca89SAndroid Build Coastguard Worker #define HAVE_STATX
29*8d67ca89SAndroid Build Coastguard Worker #elif defined(__GLIBC_PREREQ)
30*8d67ca89SAndroid Build Coastguard Worker #if __GLIBC_PREREQ(2, 28)
31*8d67ca89SAndroid Build Coastguard Worker #define HAVE_STATX
32*8d67ca89SAndroid Build Coastguard Worker #endif
33*8d67ca89SAndroid Build Coastguard Worker #endif
34*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,futimens)35*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, futimens) {
36*8d67ca89SAndroid Build Coastguard Worker   FILE* fp = tmpfile();
37*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(fp != nullptr);
38*8d67ca89SAndroid Build Coastguard Worker 
39*8d67ca89SAndroid Build Coastguard Worker   int fd = fileno(fp);
40*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd, -1);
41*8d67ca89SAndroid Build Coastguard Worker 
42*8d67ca89SAndroid Build Coastguard Worker   timespec times[2];
43*8d67ca89SAndroid Build Coastguard Worker   times[0].tv_sec = 123;
44*8d67ca89SAndroid Build Coastguard Worker   times[0].tv_nsec = 0;
45*8d67ca89SAndroid Build Coastguard Worker   times[1].tv_sec = 456;
46*8d67ca89SAndroid Build Coastguard Worker   times[1].tv_nsec = 0;
47*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, futimens(fd, times)) << strerror(errno);
48*8d67ca89SAndroid Build Coastguard Worker 
49*8d67ca89SAndroid Build Coastguard Worker   struct stat sb;
50*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, fstat(fd, &sb));
51*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(times[0].tv_sec, static_cast<long>(sb.st_atime));
52*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(times[1].tv_sec, static_cast<long>(sb.st_mtime));
53*8d67ca89SAndroid Build Coastguard Worker 
54*8d67ca89SAndroid Build Coastguard Worker   fclose(fp);
55*8d67ca89SAndroid Build Coastguard Worker }
56*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,futimens_EBADF)57*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, futimens_EBADF) {
58*8d67ca89SAndroid Build Coastguard Worker   timespec times[2];
59*8d67ca89SAndroid Build Coastguard Worker   times[0].tv_sec = 123;
60*8d67ca89SAndroid Build Coastguard Worker   times[0].tv_nsec = 0;
61*8d67ca89SAndroid Build Coastguard Worker   times[1].tv_sec = 456;
62*8d67ca89SAndroid Build Coastguard Worker   times[1].tv_nsec = 0;
63*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, futimens(-1, times));
64*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
65*8d67ca89SAndroid Build Coastguard Worker }
66*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,mkfifo_failure)67*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, mkfifo_failure) {
68*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
69*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, mkfifo("/", 0666));
70*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EEXIST);
71*8d67ca89SAndroid Build Coastguard Worker }
72*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,mkfifoat_failure)73*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, mkfifoat_failure) {
74*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
75*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, mkfifoat(-2, "x", 0666));
76*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
77*8d67ca89SAndroid Build Coastguard Worker }
78*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,mkfifo)79*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, mkfifo) {
80*8d67ca89SAndroid Build Coastguard Worker   if (getuid() == 0) {
81*8d67ca89SAndroid Build Coastguard Worker     // Racy but probably sufficient way to get a suitable filename.
82*8d67ca89SAndroid Build Coastguard Worker     std::string path;
83*8d67ca89SAndroid Build Coastguard Worker     {
84*8d67ca89SAndroid Build Coastguard Worker       TemporaryFile tf;
85*8d67ca89SAndroid Build Coastguard Worker       path = tf.path;
86*8d67ca89SAndroid Build Coastguard Worker     }
87*8d67ca89SAndroid Build Coastguard Worker 
88*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(0, mkfifo(path.c_str(), 0666));
89*8d67ca89SAndroid Build Coastguard Worker     struct stat sb;
90*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(0, stat(path.c_str(), &sb));
91*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(S_ISFIFO(sb.st_mode));
92*8d67ca89SAndroid Build Coastguard Worker     unlink(path.c_str());
93*8d67ca89SAndroid Build Coastguard Worker   } else {
94*8d67ca89SAndroid Build Coastguard Worker     // SELinux policy forbids us from creating FIFOs. http://b/17646702.
95*8d67ca89SAndroid Build Coastguard Worker     GTEST_SKIP() << "SELinux policy forbids non-root from creating FIFOs";
96*8d67ca89SAndroid Build Coastguard Worker   }
97*8d67ca89SAndroid Build Coastguard Worker }
98*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,stat64_lstat64_fstat64)99*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, stat64_lstat64_fstat64) {
100*8d67ca89SAndroid Build Coastguard Worker   struct stat64 sb;
101*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat64("/proc/version", &sb));
102*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, lstat64("/proc/version", &sb));
103*8d67ca89SAndroid Build Coastguard Worker   int fd = open("/proc/version", O_RDONLY);
104*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, fstat64(fd, &sb));
105*8d67ca89SAndroid Build Coastguard Worker   close(fd);
106*8d67ca89SAndroid Build Coastguard Worker }
107*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,statx)108*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, statx) {
109*8d67ca89SAndroid Build Coastguard Worker #if defined(HAVE_STATX)
110*8d67ca89SAndroid Build Coastguard Worker   struct statx sx;
111*8d67ca89SAndroid Build Coastguard Worker   int rc = statx(AT_FDCWD, "/proc/version", AT_STATX_SYNC_AS_STAT, STATX_ALL, &sx);
112*8d67ca89SAndroid Build Coastguard Worker   if (rc == -1 && errno == ENOSYS) GTEST_SKIP() << "no statx() in this kernel";
113*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, rc);
114*8d67ca89SAndroid Build Coastguard Worker   struct stat64 sb;
115*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat64("/proc/version", &sb));
116*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(sb.st_ino, sx.stx_ino);
117*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(sb.st_mode, sx.stx_mode);
118*8d67ca89SAndroid Build Coastguard Worker #else
119*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "statx not available";
120*8d67ca89SAndroid Build Coastguard Worker #endif
121*8d67ca89SAndroid Build Coastguard Worker }
122*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmod_EBADF)123*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmod_EBADF) {
124*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmod(-1, 0751));
125*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
126*8d67ca89SAndroid Build Coastguard Worker }
127*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_EFAULT_file)128*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_EFAULT_file) {
129*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, (char *) 0x1, 0751, 0));
130*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EFAULT);
131*8d67ca89SAndroid Build Coastguard Worker }
132*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_AT_SYMLINK_NOFOLLOW_EFAULT_file)133*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_EFAULT_file) {
134*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, (char *) 0x1, 0751, AT_SYMLINK_NOFOLLOW));
135*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
136*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EFAULT);
137*8d67ca89SAndroid Build Coastguard Worker #else
138*8d67ca89SAndroid Build Coastguard Worker   // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always
139*8d67ca89SAndroid Build Coastguard Worker   // returns ENOTSUP
140*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOTSUP);
141*8d67ca89SAndroid Build Coastguard Worker #endif
142*8d67ca89SAndroid Build Coastguard Worker }
143*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_bad_flags)144*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_bad_flags) {
145*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, ~AT_SYMLINK_NOFOLLOW));
146*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
147*8d67ca89SAndroid Build Coastguard Worker }
148*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_bad_flags_ALL)149*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_bad_flags_ALL) {
150*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, ~0));
151*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
152*8d67ca89SAndroid Build Coastguard Worker }
153*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_nonexistent_file)154*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_nonexistent_file) {
155*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, 0));
156*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
157*8d67ca89SAndroid Build Coastguard Worker }
158*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_AT_SYMLINK_NOFOLLOW_nonexistent_file)159*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_nonexistent_file) {
160*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, AT_SYMLINK_NOFOLLOW));
161*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
162*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
163*8d67ca89SAndroid Build Coastguard Worker #else
164*8d67ca89SAndroid Build Coastguard Worker   // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always
165*8d67ca89SAndroid Build Coastguard Worker   // returns ENOTSUP
166*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOTSUP);
167*8d67ca89SAndroid Build Coastguard Worker #endif
168*8d67ca89SAndroid Build Coastguard Worker }
169*8d67ca89SAndroid Build Coastguard Worker 
AssertFileModeEquals(mode_t expected_mode,const char * filename)170*8d67ca89SAndroid Build Coastguard Worker static void AssertFileModeEquals(mode_t expected_mode, const char* filename) {
171*8d67ca89SAndroid Build Coastguard Worker   struct stat sb;
172*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat(filename, &sb));
173*8d67ca89SAndroid Build Coastguard Worker   mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO;
174*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(expected_mode & mask, static_cast<mode_t>(sb.st_mode) & mask);
175*8d67ca89SAndroid Build Coastguard Worker }
176*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_file)177*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_file) {
178*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
179*8d67ca89SAndroid Build Coastguard Worker 
180*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.path, 0751, 0));
181*8d67ca89SAndroid Build Coastguard Worker   AssertFileModeEquals(0751, tf.path);
182*8d67ca89SAndroid Build Coastguard Worker }
183*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_AT_SYMLINK_NOFOLLOW_file)184*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_file) {
185*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
186*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
187*8d67ca89SAndroid Build Coastguard Worker   int result = fchmodat(AT_FDCWD, tf.path, 0751, AT_SYMLINK_NOFOLLOW);
188*8d67ca89SAndroid Build Coastguard Worker 
189*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
190*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, result);
191*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
192*8d67ca89SAndroid Build Coastguard Worker   AssertFileModeEquals(0751, tf.path);
193*8d67ca89SAndroid Build Coastguard Worker #else
194*8d67ca89SAndroid Build Coastguard Worker   // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always
195*8d67ca89SAndroid Build Coastguard Worker   // returns ENOTSUP
196*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, result);
197*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOTSUP);
198*8d67ca89SAndroid Build Coastguard Worker #endif
199*8d67ca89SAndroid Build Coastguard Worker }
200*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_symlink)201*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_symlink) {
202*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
203*8d67ca89SAndroid Build Coastguard Worker   char linkname[255];
204*8d67ca89SAndroid Build Coastguard Worker 
205*8d67ca89SAndroid Build Coastguard Worker   snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
206*8d67ca89SAndroid Build Coastguard Worker 
207*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, symlink(tf.path, linkname));
208*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, fchmodat(AT_FDCWD, linkname, 0751, 0));
209*8d67ca89SAndroid Build Coastguard Worker   AssertFileModeEquals(0751, tf.path);
210*8d67ca89SAndroid Build Coastguard Worker   unlink(linkname);
211*8d67ca89SAndroid Build Coastguard Worker }
212*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_dangling_symlink)213*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_dangling_symlink) {
214*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
215*8d67ca89SAndroid Build Coastguard Worker   char linkname[255];
216*8d67ca89SAndroid Build Coastguard Worker   char target[255];
217*8d67ca89SAndroid Build Coastguard Worker 
218*8d67ca89SAndroid Build Coastguard Worker   snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
219*8d67ca89SAndroid Build Coastguard Worker   snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
220*8d67ca89SAndroid Build Coastguard Worker 
221*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, symlink(target, linkname));
222*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, fchmodat(AT_FDCWD, linkname, 0751, 0));
223*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
224*8d67ca89SAndroid Build Coastguard Worker   unlink(linkname);
225*8d67ca89SAndroid Build Coastguard Worker }
226*8d67ca89SAndroid Build Coastguard Worker 
AssertSymlinkModeEquals(mode_t expected_mode,const char * linkname)227*8d67ca89SAndroid Build Coastguard Worker static void AssertSymlinkModeEquals(mode_t expected_mode, const char* linkname) {
228*8d67ca89SAndroid Build Coastguard Worker   struct stat sb;
229*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, fstatat(AT_FDCWD, linkname, &sb, AT_SYMLINK_NOFOLLOW));
230*8d67ca89SAndroid Build Coastguard Worker   mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO;
231*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(expected_mode & mask, static_cast<mode_t>(sb.st_mode) & mask);
232*8d67ca89SAndroid Build Coastguard Worker }
233*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_AT_SYMLINK_NOFOLLOW_with_symlink)234*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_symlink) {
235*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
236*8d67ca89SAndroid Build Coastguard Worker   struct stat tf_sb;
237*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat(tf.path, &tf_sb));
238*8d67ca89SAndroid Build Coastguard Worker 
239*8d67ca89SAndroid Build Coastguard Worker   char linkname[255];
240*8d67ca89SAndroid Build Coastguard Worker   snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
241*8d67ca89SAndroid Build Coastguard Worker 
242*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, symlink(tf.path, linkname));
243*8d67ca89SAndroid Build Coastguard Worker   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
244*8d67ca89SAndroid Build Coastguard Worker   // It depends on the kernel whether chmod operation on symlink is allowed.
245*8d67ca89SAndroid Build Coastguard Worker   if (result == 0) {
246*8d67ca89SAndroid Build Coastguard Worker     AssertSymlinkModeEquals(0751, linkname);
247*8d67ca89SAndroid Build Coastguard Worker   } else {
248*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(-1, result);
249*8d67ca89SAndroid Build Coastguard Worker     ASSERT_ERRNO(ENOTSUP);
250*8d67ca89SAndroid Build Coastguard Worker   }
251*8d67ca89SAndroid Build Coastguard Worker 
252*8d67ca89SAndroid Build Coastguard Worker   // Target file mode shouldn't be modified.
253*8d67ca89SAndroid Build Coastguard Worker   AssertFileModeEquals(tf_sb.st_mode, tf.path);
254*8d67ca89SAndroid Build Coastguard Worker   unlink(linkname);
255*8d67ca89SAndroid Build Coastguard Worker }
256*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,fchmodat_AT_SYMLINK_NOFOLLOW_with_dangling_symlink)257*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_dangling_symlink) {
258*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
259*8d67ca89SAndroid Build Coastguard Worker 
260*8d67ca89SAndroid Build Coastguard Worker   char linkname[255];
261*8d67ca89SAndroid Build Coastguard Worker   char target[255];
262*8d67ca89SAndroid Build Coastguard Worker   snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
263*8d67ca89SAndroid Build Coastguard Worker   snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
264*8d67ca89SAndroid Build Coastguard Worker 
265*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, symlink(target, linkname));
266*8d67ca89SAndroid Build Coastguard Worker   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
267*8d67ca89SAndroid Build Coastguard Worker   // It depends on the kernel whether chmod operation on symlink is allowed.
268*8d67ca89SAndroid Build Coastguard Worker   if (result == 0) {
269*8d67ca89SAndroid Build Coastguard Worker     AssertSymlinkModeEquals(0751, linkname);
270*8d67ca89SAndroid Build Coastguard Worker   } else {
271*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(-1, result);
272*8d67ca89SAndroid Build Coastguard Worker     ASSERT_ERRNO(ENOTSUP);
273*8d67ca89SAndroid Build Coastguard Worker   }
274*8d67ca89SAndroid Build Coastguard Worker 
275*8d67ca89SAndroid Build Coastguard Worker   unlink(linkname);
276*8d67ca89SAndroid Build Coastguard Worker }
277*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,faccessat_EINVAL)278*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, faccessat_EINVAL) {
279*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", F_OK, ~AT_SYMLINK_NOFOLLOW));
280*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
281*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
282*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), 0));
283*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
284*8d67ca89SAndroid Build Coastguard Worker #else
285*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), AT_SYMLINK_NOFOLLOW));
286*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", ~(R_OK | W_OK | X_OK), 0));
287*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
288*8d67ca89SAndroid Build Coastguard Worker #endif
289*8d67ca89SAndroid Build Coastguard Worker }
290*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,faccessat_AT_SYMLINK_NOFOLLOW_EINVAL)291*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, faccessat_AT_SYMLINK_NOFOLLOW_EINVAL) {
292*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
293*8d67ca89SAndroid Build Coastguard Worker   // Android doesn't support AT_SYMLINK_NOFOLLOW
294*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/dev/null", F_OK, AT_SYMLINK_NOFOLLOW));
295*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
296*8d67ca89SAndroid Build Coastguard Worker #else
297*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", F_OK, AT_SYMLINK_NOFOLLOW));
298*8d67ca89SAndroid Build Coastguard Worker #endif
299*8d67ca89SAndroid Build Coastguard Worker }
300*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,faccessat_dev_null)301*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, faccessat_dev_null) {
302*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", F_OK, 0));
303*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", R_OK, 0));
304*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", W_OK, 0));
305*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", R_OK|W_OK, 0));
306*8d67ca89SAndroid Build Coastguard Worker }
307*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,faccessat_nonexistent)308*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, faccessat_nonexistent) {
309*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/blah", F_OK, AT_SYMLINK_NOFOLLOW));
310*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
311*8d67ca89SAndroid Build Coastguard Worker   // Android doesn't support AT_SYMLINK_NOFOLLOW
312*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
313*8d67ca89SAndroid Build Coastguard Worker #else
314*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
315*8d67ca89SAndroid Build Coastguard Worker #endif
316*8d67ca89SAndroid Build Coastguard Worker }
317*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_stat,lchmod)318*8d67ca89SAndroid Build Coastguard Worker TEST(sys_stat, lchmod) {
319*8d67ca89SAndroid Build Coastguard Worker   TemporaryFile tf;
320*8d67ca89SAndroid Build Coastguard Worker   struct stat tf_sb;
321*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, stat(tf.path, &tf_sb));
322*8d67ca89SAndroid Build Coastguard Worker 
323*8d67ca89SAndroid Build Coastguard Worker   char linkname[255];
324*8d67ca89SAndroid Build Coastguard Worker   snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
325*8d67ca89SAndroid Build Coastguard Worker 
326*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, symlink(tf.path, linkname));
327*8d67ca89SAndroid Build Coastguard Worker   int result = lchmod(linkname, 0751);
328*8d67ca89SAndroid Build Coastguard Worker   // Whether or not chmod is allowed on a symlink depends on the kernel.
329*8d67ca89SAndroid Build Coastguard Worker   if (result == 0) {
330*8d67ca89SAndroid Build Coastguard Worker     AssertSymlinkModeEquals(0751, linkname);
331*8d67ca89SAndroid Build Coastguard Worker   } else {
332*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(-1, result);
333*8d67ca89SAndroid Build Coastguard Worker     ASSERT_ERRNO(ENOTSUP);
334*8d67ca89SAndroid Build Coastguard Worker   }
335*8d67ca89SAndroid Build Coastguard Worker 
336*8d67ca89SAndroid Build Coastguard Worker   // The target file mode shouldn't be modified.
337*8d67ca89SAndroid Build Coastguard Worker   AssertFileModeEquals(tf_sb.st_mode, tf.path);
338*8d67ca89SAndroid Build Coastguard Worker   unlink(linkname);
339*8d67ca89SAndroid Build Coastguard Worker }
340