2 This file is part of systemd.
4 Copyright 2010-2012 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
25 #include <linux/magic.h>
26 #include <sys/statvfs.h>
29 #include "dirent-util.h"
34 #include "stat-util.h"
35 #include "string-util.h"
37 int is_symlink(const char *path
) {
42 if (lstat(path
, &info
) < 0)
45 return !!S_ISLNK(info
.st_mode
);
48 int is_dir(const char* path
, bool follow
) {
61 return !!S_ISDIR(st
.st_mode
);
64 int is_device_node(const char *path
) {
69 if (lstat(path
, &info
) < 0)
72 return !!(S_ISBLK(info
.st_mode
) || S_ISCHR(info
.st_mode
));
75 int dir_is_empty(const char *path
) {
76 _cleanup_closedir_
DIR *d
;
83 FOREACH_DIRENT(de
, d
, return -errno
)
89 bool null_or_empty(struct stat
*st
) {
92 if (S_ISREG(st
->st_mode
) && st
->st_size
<= 0)
95 /* We don't want to hardcode the major/minor of /dev/null,
96 * hence we do a simpler "is this a device node?" check. */
98 if (S_ISCHR(st
->st_mode
) || S_ISBLK(st
->st_mode
))
104 int null_or_empty_path(const char *fn
) {
109 if (stat(fn
, &st
) < 0)
112 return null_or_empty(&st
);
115 int null_or_empty_fd(int fd
) {
120 if (fstat(fd
, &st
) < 0)
123 return null_or_empty(&st
);
126 int path_is_read_only_fs(const char *path
) {
131 if (statvfs(path
, &st
) < 0)
134 if (st
.f_flag
& ST_RDONLY
)
137 /* On NFS, statvfs() might not reflect whether we can actually
138 * write to the remote share. Let's try again with
139 * access(W_OK) which is more reliable, at least sometimes. */
140 if (access(path
, W_OK
) < 0 && errno
== EROFS
)
146 int path_is_os_tree(const char *path
) {
151 /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
152 * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
153 * the case where just the os-release file is missing. */
154 if (laccess(path
, F_OK
) < 0)
157 /* We use /usr/lib/os-release as flag file if something is an OS */
158 r
= chase_symlinks("/usr/lib/os-release", path
, CHASE_PREFIX_ROOT
, NULL
);
161 /* Also check for the old location in /etc, just in case. */
162 r
= chase_symlinks("/etc/os-release", path
, CHASE_PREFIX_ROOT
, NULL
);
164 return 0; /* We got nothing */
172 int files_same(const char *filea
, const char *fileb
, int flags
) {
178 if (fstatat(AT_FDCWD
, filea
, &a
, flags
) < 0)
181 if (fstatat(AT_FDCWD
, fileb
, &b
, flags
) < 0)
184 return a
.st_dev
== b
.st_dev
&&
185 a
.st_ino
== b
.st_ino
;
188 bool is_fs_type(const struct statfs
*s
, statfs_f_type_t magic_value
) {
190 assert_cc(sizeof(statfs_f_type_t
) >= sizeof(s
->f_type
));
192 return F_TYPE_EQUAL(s
->f_type
, magic_value
);
195 int fd_check_fstype(int fd
, statfs_f_type_t magic_value
) {
198 if (fstatfs(fd
, &s
) < 0)
201 return is_fs_type(&s
, magic_value
);
204 int path_check_fstype(const char *path
, statfs_f_type_t magic_value
) {
205 _cleanup_close_
int fd
= -1;
207 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
211 return fd_check_fstype(fd
, magic_value
);
214 bool is_temporary_fs(const struct statfs
*s
) {
215 return is_fs_type(s
, TMPFS_MAGIC
) ||
216 is_fs_type(s
, RAMFS_MAGIC
);
219 int fd_is_temporary_fs(int fd
) {
222 if (fstatfs(fd
, &s
) < 0)
225 return is_temporary_fs(&s
);
228 int path_is_temporary_fs(const char *path
) {
229 _cleanup_close_
int fd
= -1;
231 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
);
235 return fd_is_temporary_fs(fd
);