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