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