chiark / gitweb /
tree-wide: remove Lennart's copyright lines
[elogind.git] / src / basic / stat-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <dirent.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/magic.h>
7 //#include <sched.h>
8 //#include <sys/stat.h>
9 #include <sys/statvfs.h>
10 //#include <sys/types.h>
11 #include <unistd.h>
12
13 #include "dirent-util.h"
14 #include "fd-util.h"
15 #include "fs-util.h"
16 #include "macro.h"
17 #include "missing.h"
18 #include "stat-util.h"
19 #include "string-util.h"
20
21 #if 0 /// UNNEEDED by elogind
22 int is_symlink(const char *path) {
23         struct stat info;
24
25         assert(path);
26
27         if (lstat(path, &info) < 0)
28                 return -errno;
29
30         return !!S_ISLNK(info.st_mode);
31 }
32 #endif // 0
33
34 int is_dir(const char* path, bool follow) {
35         struct stat st;
36         int r;
37
38         assert(path);
39
40         if (follow)
41                 r = stat(path, &st);
42         else
43                 r = lstat(path, &st);
44         if (r < 0)
45                 return -errno;
46
47         return !!S_ISDIR(st.st_mode);
48 }
49
50 #if 0 /// UNNEEDED by elogind
51 int is_device_node(const char *path) {
52         struct stat info;
53
54         assert(path);
55
56         if (lstat(path, &info) < 0)
57                 return -errno;
58
59         return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
60 }
61
62 int dir_is_empty(const char *path) {
63         _cleanup_closedir_ DIR *d;
64         struct dirent *de;
65
66         d = opendir(path);
67         if (!d)
68                 return -errno;
69
70         FOREACH_DIRENT(de, d, return -errno)
71                 return 0;
72
73         return 1;
74 }
75 #endif // 0
76
77 bool null_or_empty(struct stat *st) {
78         assert(st);
79
80         if (S_ISREG(st->st_mode) && st->st_size <= 0)
81                 return true;
82
83         /* We don't want to hardcode the major/minor of /dev/null,
84          * hence we do a simpler "is this a device node?" check. */
85
86         if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
87                 return true;
88
89         return false;
90 }
91
92 int null_or_empty_path(const char *fn) {
93         struct stat st;
94
95         assert(fn);
96
97         if (stat(fn, &st) < 0)
98                 return -errno;
99
100         return null_or_empty(&st);
101 }
102
103 #if 0 /// UNNEEDED by elogind
104 int null_or_empty_fd(int fd) {
105         struct stat st;
106
107         assert(fd >= 0);
108
109         if (fstat(fd, &st) < 0)
110                 return -errno;
111
112         return null_or_empty(&st);
113 }
114 #endif // 0
115
116 int path_is_read_only_fs(const char *path) {
117         struct statvfs st;
118
119         assert(path);
120
121         if (statvfs(path, &st) < 0)
122                 return -errno;
123
124         if (st.f_flag & ST_RDONLY)
125                 return true;
126
127         /* On NFS, statvfs() might not reflect whether we can actually
128          * write to the remote share. Let's try again with
129          * access(W_OK) which is more reliable, at least sometimes. */
130         if (access(path, W_OK) < 0 && errno == EROFS)
131                 return true;
132
133         return false;
134 }
135
136 #if 0 /// UNNEEDED by elogind
137 #endif // 0
138 int files_same(const char *filea, const char *fileb, int flags) {
139         struct stat a, b;
140
141         assert(filea);
142         assert(fileb);
143
144         if (fstatat(AT_FDCWD, filea, &a, flags) < 0)
145                 return -errno;
146
147         if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
148                 return -errno;
149
150         return a.st_dev == b.st_dev &&
151                a.st_ino == b.st_ino;
152 }
153
154 bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
155         assert(s);
156         assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
157
158         return F_TYPE_EQUAL(s->f_type, magic_value);
159 }
160
161 int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
162         struct statfs s;
163
164         if (fstatfs(fd, &s) < 0)
165                 return -errno;
166
167         return is_fs_type(&s, magic_value);
168 }
169
170 #if 0 /// UNNEEDED by elogind
171 int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
172         _cleanup_close_ int fd = -1;
173
174         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
175         if (fd < 0)
176                 return -errno;
177
178         return fd_is_fs_type(fd, magic_value);
179 }
180 #endif // 0
181
182 bool is_temporary_fs(const struct statfs *s) {
183         return is_fs_type(s, TMPFS_MAGIC) ||
184                 is_fs_type(s, RAMFS_MAGIC);
185 }
186
187 bool is_network_fs(const struct statfs *s) {
188         return is_fs_type(s, CIFS_MAGIC_NUMBER) ||
189                 is_fs_type(s, CODA_SUPER_MAGIC) ||
190                 is_fs_type(s, NCP_SUPER_MAGIC) ||
191                 is_fs_type(s, NFS_SUPER_MAGIC) ||
192                 is_fs_type(s, SMB_SUPER_MAGIC) ||
193                 is_fs_type(s, V9FS_MAGIC) ||
194                 is_fs_type(s, AFS_SUPER_MAGIC) ||
195                 is_fs_type(s, OCFS2_SUPER_MAGIC);
196 }
197
198 #if 0 /// UNNEEDED by elogind
199 int fd_is_temporary_fs(int fd) {
200         struct statfs s;
201
202         if (fstatfs(fd, &s) < 0)
203                 return -errno;
204
205         return is_temporary_fs(&s);
206 }
207
208 int fd_is_network_fs(int fd) {
209         struct statfs s;
210
211         if (fstatfs(fd, &s) < 0)
212                 return -errno;
213
214         return is_network_fs(&s);
215 }
216
217 int fd_is_network_ns(int fd) {
218         int r;
219
220         r = fd_is_fs_type(fd, NSFS_MAGIC);
221         if (r <= 0)
222                 return r;
223
224         r = ioctl(fd, NS_GET_NSTYPE);
225         if (r < 0)
226                 return -errno;
227
228         return r == CLONE_NEWNET;
229 }
230
231 int path_is_temporary_fs(const char *path) {
232         _cleanup_close_ int fd = -1;
233
234         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
235         if (fd < 0)
236                 return -errno;
237
238         return fd_is_temporary_fs(fd);
239 }
240 #endif // 0
241
242 int stat_verify_regular(const struct stat *st) {
243         assert(st);
244
245         /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
246          * code. */
247
248         if (S_ISDIR(st->st_mode))
249                 return -EISDIR;
250
251         if (S_ISLNK(st->st_mode))
252                 return -ELOOP;
253
254         if (!S_ISREG(st->st_mode))
255                 return -EBADFD;
256
257         return 0;
258 }
259
260 int fd_verify_regular(int fd) {
261         struct stat st;
262
263         assert(fd >= 0);
264
265         if (fstat(fd, &st) < 0)
266                 return -errno;
267
268         return stat_verify_regular(&st);
269 }