chiark / gitweb /
nspawn: support ephemeral boots from images
[elogind.git] / src / basic / stat-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010-2012 Lennart Poettering
5
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.
10
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.
15
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/>.
18 ***/
19
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <linux/magic.h>
26 #include <sys/statvfs.h>
27 #include <unistd.h>
28
29 #include "dirent-util.h"
30 #include "fd-util.h"
31 #include "macro.h"
32 #include "missing.h"
33 #include "stat-util.h"
34 #include "string-util.h"
35
36 #if 0 /// UNNEEDED by elogind
37 int is_symlink(const char *path) {
38         struct stat info;
39
40         assert(path);
41
42         if (lstat(path, &info) < 0)
43                 return -errno;
44
45         return !!S_ISLNK(info.st_mode);
46 }
47 #endif // 0
48
49 int is_dir(const char* path, bool follow) {
50         struct stat st;
51         int r;
52
53         assert(path);
54
55         if (follow)
56                 r = stat(path, &st);
57         else
58                 r = lstat(path, &st);
59         if (r < 0)
60                 return -errno;
61
62         return !!S_ISDIR(st.st_mode);
63 }
64
65 #if 0 /// UNNEEDED by elogind
66 int is_device_node(const char *path) {
67         struct stat info;
68
69         assert(path);
70
71         if (lstat(path, &info) < 0)
72                 return -errno;
73
74         return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
75 }
76
77 int dir_is_empty(const char *path) {
78         _cleanup_closedir_ DIR *d;
79         struct dirent *de;
80
81         d = opendir(path);
82         if (!d)
83                 return -errno;
84
85         FOREACH_DIRENT(de, d, return -errno)
86                 return 0;
87
88         return 1;
89 }
90 #endif // 0
91
92 bool null_or_empty(struct stat *st) {
93         assert(st);
94
95         if (S_ISREG(st->st_mode) && st->st_size <= 0)
96                 return true;
97
98         /* We don't want to hardcode the major/minor of /dev/null,
99          * hence we do a simpler "is this a device node?" check. */
100
101         if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
102                 return true;
103
104         return false;
105 }
106
107 int null_or_empty_path(const char *fn) {
108         struct stat st;
109
110         assert(fn);
111
112         if (stat(fn, &st) < 0)
113                 return -errno;
114
115         return null_or_empty(&st);
116 }
117
118 #if 0 /// UNNEEDED by elogind
119 int null_or_empty_fd(int fd) {
120         struct stat st;
121
122         assert(fd >= 0);
123
124         if (fstat(fd, &st) < 0)
125                 return -errno;
126
127         return null_or_empty(&st);
128 }
129 #endif // 0
130
131 int path_is_read_only_fs(const char *path) {
132         struct statvfs st;
133
134         assert(path);
135
136         if (statvfs(path, &st) < 0)
137                 return -errno;
138
139         if (st.f_flag & ST_RDONLY)
140                 return true;
141
142         /* On NFS, statvfs() might not reflect whether we can actually
143          * write to the remote share. Let's try again with
144          * access(W_OK) which is more reliable, at least sometimes. */
145         if (access(path, W_OK) < 0 && errno == EROFS)
146                 return true;
147
148         return false;
149 }
150
151 #if 0 /// UNNEEDED by elogind
152 int path_is_os_tree(const char *path) {
153         char *p;
154         int r;
155
156         assert(path);
157
158         /* We use /usr/lib/os-release as flag file if something is an OS */
159         p = strjoina(path, "/usr/lib/os-release");
160         r = access(p, F_OK);
161         if (r >= 0)
162                 return 1;
163
164         /* Also check for the old location in /etc, just in case. */
165         p = strjoina(path, "/etc/os-release");
166         r = access(p, F_OK);
167
168         return r >= 0;
169 }
170 #endif // 0
171
172 int files_same(const char *filea, const char *fileb) {
173         struct stat a, b;
174
175         assert(filea);
176         assert(fileb);
177
178         if (stat(filea, &a) < 0)
179                 return -errno;
180
181         if (stat(fileb, &b) < 0)
182                 return -errno;
183
184         return a.st_dev == b.st_dev &&
185                a.st_ino == b.st_ino;
186 }
187
188 bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
189         assert(s);
190         assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
191
192         return F_TYPE_EQUAL(s->f_type, magic_value);
193 }
194
195 #if 0 /// UNNEEDED by elogind
196 int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
197         struct statfs s;
198
199         if (fstatfs(fd, &s) < 0)
200                 return -errno;
201
202         return is_fs_type(&s, magic_value);
203 }
204
205 int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
206         _cleanup_close_ int fd = -1;
207
208         fd = open(path, O_RDONLY);
209         if (fd < 0)
210                 return -errno;
211
212         return fd_check_fstype(fd, magic_value);
213 }
214 #endif // 0
215
216 bool is_temporary_fs(const struct statfs *s) {
217     return is_fs_type(s, TMPFS_MAGIC) ||
218            is_fs_type(s, RAMFS_MAGIC);
219 }
220
221 int fd_is_temporary_fs(int fd) {
222         struct statfs s;
223
224         if (fstatfs(fd, &s) < 0)
225                 return -errno;
226
227         return is_temporary_fs(&s);
228 }