1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010-2012 Lennart Poettering
11 #include <linux/magic.h>
14 #include <sys/statvfs.h>
15 #include <sys/types.h>
18 #include "dirent-util.h"
23 #include "stat-util.h"
24 #include "string-util.h"
26 int is_symlink(const char *path
) {
31 if (lstat(path
, &info
) < 0)
34 return !!S_ISLNK(info
.st_mode
);
37 int is_dir(const char* path
, bool follow
) {
50 return !!S_ISDIR(st
.st_mode
);
53 int is_device_node(const char *path
) {
58 if (lstat(path
, &info
) < 0)
61 return !!(S_ISBLK(info
.st_mode
) || S_ISCHR(info
.st_mode
));
64 int dir_is_empty(const char *path
) {
65 _cleanup_closedir_
DIR *d
;
72 FOREACH_DIRENT(de
, d
, return -errno
)
78 bool null_or_empty(struct stat
*st
) {
81 if (S_ISREG(st
->st_mode
) && st
->st_size
<= 0)
84 /* We don't want to hardcode the major/minor of /dev/null,
85 * hence we do a simpler "is this a device node?" check. */
87 if (S_ISCHR(st
->st_mode
) || S_ISBLK(st
->st_mode
))
93 int null_or_empty_path(const char *fn
) {
98 if (stat(fn
, &st
) < 0)
101 return null_or_empty(&st
);
104 int null_or_empty_fd(int fd
) {
109 if (fstat(fd
, &st
) < 0)
112 return null_or_empty(&st
);
115 int path_is_read_only_fs(const char *path
) {
120 if (statvfs(path
, &st
) < 0)
123 if (st
.f_flag
& ST_RDONLY
)
126 /* On NFS, statvfs() might not reflect whether we can actually
127 * write to the remote share. Let's try again with
128 * access(W_OK) which is more reliable, at least sometimes. */
129 if (access(path
, W_OK
) < 0 && errno
== EROFS
)
135 int files_same(const char *filea
, const char *fileb
, int flags
) {
141 if (fstatat(AT_FDCWD
, filea
, &a
, flags
) < 0)
144 if (fstatat(AT_FDCWD
, fileb
, &b
, flags
) < 0)
147 return a
.st_dev
== b
.st_dev
&&
148 a
.st_ino
== b
.st_ino
;
151 bool is_fs_type(const struct statfs
*s
, statfs_f_type_t magic_value
) {
153 assert_cc(sizeof(statfs_f_type_t
) >= sizeof(s
->f_type
));
155 return F_TYPE_EQUAL(s
->f_type
, magic_value
);
158 int fd_is_fs_type(int fd
, statfs_f_type_t magic_value
) {
161 if (fstatfs(fd
, &s
) < 0)
164 return is_fs_type(&s
, magic_value
);
167 int path_is_fs_type(const char *path
, statfs_f_type_t magic_value
) {
168 _cleanup_close_
int fd
= -1;
170 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
174 return fd_is_fs_type(fd
, magic_value
);
177 bool is_temporary_fs(const struct statfs
*s
) {
178 return is_fs_type(s
, TMPFS_MAGIC
) ||
179 is_fs_type(s
, RAMFS_MAGIC
);
182 bool is_network_fs(const struct statfs
*s
) {
183 return is_fs_type(s
, CIFS_MAGIC_NUMBER
) ||
184 is_fs_type(s
, CODA_SUPER_MAGIC
) ||
185 is_fs_type(s
, NCP_SUPER_MAGIC
) ||
186 is_fs_type(s
, NFS_SUPER_MAGIC
) ||
187 is_fs_type(s
, SMB_SUPER_MAGIC
) ||
188 is_fs_type(s
, V9FS_MAGIC
) ||
189 is_fs_type(s
, AFS_SUPER_MAGIC
) ||
190 is_fs_type(s
, OCFS2_SUPER_MAGIC
);
193 int fd_is_temporary_fs(int fd
) {
196 if (fstatfs(fd
, &s
) < 0)
199 return is_temporary_fs(&s
);
202 int fd_is_network_fs(int fd
) {
205 if (fstatfs(fd
, &s
) < 0)
208 return is_network_fs(&s
);
211 int fd_is_network_ns(int fd
) {
214 r
= fd_is_fs_type(fd
, NSFS_MAGIC
);
218 r
= ioctl(fd
, NS_GET_NSTYPE
);
222 return r
== CLONE_NEWNET
;
225 int path_is_temporary_fs(const char *path
) {
226 _cleanup_close_
int fd
= -1;
228 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
232 return fd_is_temporary_fs(fd
);
235 int stat_verify_regular(const struct stat
*st
) {
238 /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error
241 if (S_ISDIR(st
->st_mode
))
244 if (S_ISLNK(st
->st_mode
))
247 if (!S_ISREG(st
->st_mode
))
253 int fd_verify_regular(int fd
) {
258 if (fstat(fd
, &st
) < 0)
261 return stat_verify_regular(&st
);