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