This source file includes following definitions.
- lchmod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include <sys/stat.h>
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include <intprops.h>
32
33
34
35
36
37 int
38 lchmod (char const *file, mode_t mode)
39 {
40 char readlink_buf[1];
41
42 #ifdef O_PATH
43
44
45
46
47 int fd = open (file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
48 if (fd < 0)
49 return fd;
50
51 int err;
52 if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf))
53 err = EOPNOTSUPP;
54 else if (errno == EINVAL)
55 {
56 static char const fmt[] = "/proc/self/fd/%d";
57 char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
58 sprintf (buf, fmt, fd);
59 err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno;
60 }
61 else
62 err = errno == ENOENT ? -1 : errno;
63
64 close (fd);
65
66 errno = err;
67 if (0 <= err)
68 return err == 0 ? 0 : -1;
69 #endif
70
71 size_t len = strlen (file);
72 if (len && file[len - 1] == '/')
73 {
74 struct stat st;
75 if (lstat (file, &st) < 0)
76 return -1;
77 if (!S_ISDIR (st.st_mode))
78 {
79 errno = ENOTDIR;
80 return -1;
81 }
82 }
83
84
85
86 if (0 <= readlink (file, readlink_buf, sizeof readlink_buf))
87 {
88 errno = EOPNOTSUPP;
89 return -1;
90 }
91
92
93 return chmod (file, mode);
94 }