1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include <linux/magic.h>
9 #include <sys/statvfs.h>
10 #include <sys/types.h>
13 #include "dirent-util.h"
18 #include "stat-util.h"
19 #include "string-util.h"
21 int is_symlink(const char *path
) {
26 if (lstat(path
, &info
) < 0)
29 return !!S_ISLNK(info
.st_mode
);
32 int is_dir(const char* path
, bool follow
) {
45 return !!S_ISDIR(st
.st_mode
);
48 int is_dir_fd(int fd
) {
51 if (fstat(fd
, &st
) < 0)
54 return !!S_ISDIR(st
.st_mode
);
57 int is_device_node(const char *path
) {
62 if (lstat(path
, &info
) < 0)
65 return !!(S_ISBLK(info
.st_mode
) || S_ISCHR(info
.st_mode
));
68 int dir_is_empty(const char *path
) {
69 _cleanup_closedir_
DIR *d
;
76 FOREACH_DIRENT(de
, d
, return -errno
)
82 bool null_or_empty(struct stat
*st
) {
85 if (S_ISREG(st
->st_mode
) && st
->st_size
<= 0)
88 /* We don't want to hardcode the major/minor of /dev/null,
89 * hence we do a simpler "is this a device node?" check. */
91 if (S_ISCHR(st
->st_mode
) || S_ISBLK(st
->st_mode
))
97 int null_or_empty_path(const char *fn
) {
102 if (stat(fn
, &st
) < 0)
105 return null_or_empty(&st
);
108 int null_or_empty_fd(int fd
) {
113 if (fstat(fd
, &st
) < 0)
116 return null_or_empty(&st
);
119 int path_is_read_only_fs(const char *path
) {
124 if (statvfs(path
, &st
) < 0)
127 if (st
.f_flag
& ST_RDONLY
)
130 /* On NFS, statvfs() might not reflect whether we can actually
131 * write to the remote share. Let's try again with
132 * access(W_OK) which is more reliable, at least sometimes. */
133 if (access(path
, W_OK
) < 0 && errno
== EROFS
)
139 int files_same(const char *filea
, const char *fileb
, int flags
) {
145 if (fstatat(AT_FDCWD
, filea
, &a
, flags
) < 0)
148 if (fstatat(AT_FDCWD
, fileb
, &b
, flags
) < 0)
151 return a
.st_dev
== b
.st_dev
&&
152 a
.st_ino
== b
.st_ino
;
155 bool is_fs_type(const struct statfs
*s
, statfs_f_type_t magic_value
) {
157 assert_cc(sizeof(statfs_f_type_t
) >= sizeof(s
->f_type
));
159 return F_TYPE_EQUAL(s
->f_type
, magic_value
);
162 int fd_is_fs_type(int fd
, statfs_f_type_t magic_value
) {
165 if (fstatfs(fd
, &s
) < 0)
168 return is_fs_type(&s
, magic_value
);
171 int path_is_fs_type(const char *path
, statfs_f_type_t magic_value
) {
172 _cleanup_close_
int fd
= -1;
174 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
178 return fd_is_fs_type(fd
, magic_value
);
181 bool is_temporary_fs(const struct statfs
*s
) {
182 return is_fs_type(s
, TMPFS_MAGIC
) ||
183 is_fs_type(s
, RAMFS_MAGIC
);
186 bool is_network_fs(const struct statfs
*s
) {
187 return is_fs_type(s
, CIFS_MAGIC_NUMBER
) ||
188 is_fs_type(s
, CODA_SUPER_MAGIC
) ||
189 is_fs_type(s
, NCP_SUPER_MAGIC
) ||
190 is_fs_type(s
, NFS_SUPER_MAGIC
) ||
191 is_fs_type(s
, SMB_SUPER_MAGIC
) ||
192 is_fs_type(s
, V9FS_MAGIC
) ||
193 is_fs_type(s
, AFS_SUPER_MAGIC
) ||
194 is_fs_type(s
, OCFS2_SUPER_MAGIC
);
197 int fd_is_temporary_fs(int fd
) {
200 if (fstatfs(fd
, &s
) < 0)
203 return is_temporary_fs(&s
);
206 int fd_is_network_fs(int fd
) {
209 if (fstatfs(fd
, &s
) < 0)
212 return is_network_fs(&s
);
215 int fd_is_network_ns(int fd
) {
219 /* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice
220 * way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle
221 * this somewhat nicely.
223 * This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not
224 * refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */
226 if (fstatfs(fd
, &s
) < 0)
229 if (!is_fs_type(&s
, NSFS_MAGIC
)) {
230 /* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs
231 * instead. Handle that in a somewhat smart way. */
233 if (is_fs_type(&s
, PROC_SUPER_MAGIC
)) {
236 /* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the
237 * passed fd might refer to a network namespace, but we can't know for sure. In that case,
238 * return a recognizable error. */
240 if (statfs("/proc/self/ns/net", &t
) < 0)
243 if (s
.f_type
== t
.f_type
)
244 return -EUCLEAN
; /* It's possible, we simply don't know */
250 r
= ioctl(fd
, NS_GET_NSTYPE
);
252 if (errno
== ENOTTY
) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */
258 return r
== CLONE_NEWNET
;
261 int path_is_temporary_fs(const char *path
) {
262 _cleanup_close_
int fd
= -1;
264 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
268 return fd_is_temporary_fs(fd
);
271 int stat_verify_regular(const struct stat
*st
) {
274 /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
277 if (S_ISDIR(st
->st_mode
))
280 if (S_ISLNK(st
->st_mode
))
283 if (!S_ISREG(st
->st_mode
))
289 int fd_verify_regular(int fd
) {
294 if (fstat(fd
, &st
) < 0)
297 return stat_verify_regular(&st
);