This source file includes following definitions.
- orig_fchmodat
- fchmodat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #define __need_system_sys_stat_h
23 #include <config.h>
24
25
26 #include <sys/stat.h>
27 #undef __need_system_sys_stat_h
28
29 #if HAVE_FCHMODAT
30 static int
31 orig_fchmodat (int dir, char const *file, mode_t mode, int flags)
32 {
33 return fchmodat (dir, file, mode, flags);
34 }
35 #endif
36
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #ifdef __osf__
45
46
47
48 # include "sys/stat.h"
49 #else
50 # include <sys/stat.h>
51 #endif
52
53 #include <intprops.h>
54
55
56
57
58
59
60
61
62
63 #if HAVE_FCHMODAT
64 int
65 fchmodat (int dir, char const *file, mode_t mode, int flags)
66 {
67 # if HAVE_NEARLY_WORKING_FCHMODAT
68
69 size_t len = strlen (file);
70 if (len && file[len - 1] == '/')
71 {
72 struct stat st;
73 if (fstatat (dir, file, &st, flags & AT_SYMLINK_NOFOLLOW) < 0)
74 return -1;
75 if (!S_ISDIR (st.st_mode))
76 {
77 errno = ENOTDIR;
78 return -1;
79 }
80 }
81 # endif
82
83 # if NEED_FCHMODAT_NONSYMLINK_FIX
84 if (flags == AT_SYMLINK_NOFOLLOW)
85 {
86 struct stat st;
87
88 # if defined O_PATH && defined AT_EMPTY_PATH
89
90
91
92
93 int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
94 if (fd < 0)
95 return fd;
96
97
98
99
100
101
102
103
104 if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0)
105 {
106 int stat_errno = errno;
107 close (fd);
108 errno = stat_errno;
109 return -1;
110 }
111 if (S_ISLNK (st.st_mode))
112 {
113 close (fd);
114 errno = EOPNOTSUPP;
115 return -1;
116 }
117
118 # if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__
119 static char const fmt[] = "/proc/self/fd/%d";
120 char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
121 sprintf (buf, fmt, fd);
122 int chmod_result = chmod (buf, mode);
123 int chmod_errno = errno;
124 close (fd);
125 if (chmod_result == 0)
126 return chmod_result;
127 if (chmod_errno != ENOENT)
128 {
129 errno = chmod_errno;
130 return chmod_result;
131 }
132 # endif
133
134
135 # else
136 int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW);
137 if (fstatat_result != 0)
138 return fstatat_result;
139 if (S_ISLNK (st.st_mode))
140 {
141 errno = EOPNOTSUPP;
142 return -1;
143 }
144 # endif
145
146
147 flags = 0;
148 }
149 # endif
150
151 return orig_fchmodat (dir, file, mode, flags);
152 }
153 #else
154 # define AT_FUNC_NAME fchmodat
155 # define AT_FUNC_F1 lchmod
156 # define AT_FUNC_F2 chmod
157 # define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
158 # define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
159 # define AT_FUNC_POST_FILE_ARGS , mode
160 # include "at-func.c"
161 #endif