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 # if HAVE_READLINKAT
87 char readlink_buf[1];
88
89 # ifdef O_PATH
90
91
92
93
94 int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
95 if (fd < 0)
96 return fd;
97
98 int err;
99 if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
100 err = EOPNOTSUPP;
101 else if (errno == EINVAL)
102 {
103 static char const fmt[] = "/proc/self/fd/%d";
104 char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
105 sprintf (buf, fmt, fd);
106 err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
107 }
108 else
109 err = errno == ENOENT ? -1 : errno;
110
111 close (fd);
112
113 errno = err;
114 if (0 <= err)
115 return err == 0 ? 0 : -1;
116 # endif
117
118
119
120 if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf))
121 {
122 errno = EOPNOTSUPP;
123 return -1;
124 }
125 # endif
126
127
128 flags = 0;
129 }
130 # endif
131
132 return orig_fchmodat (dir, file, mode, flags);
133 }
134 #else
135 # define AT_FUNC_NAME fchmodat
136 # define AT_FUNC_F1 lchmod
137 # define AT_FUNC_F2 chmod
138 # define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
139 # define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
140 # define AT_FUNC_POST_FILE_ARGS , mode
141 # include "at-func.c"
142 #endif