chiark / gitweb /
baa3b5c822f49df5ededea7ab3d8af099fb18029
[elogind.git] / src / basic / stat-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010-2012 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <fcntl.h>
23 #include <linux/magic.h>
24 #include <sys/statvfs.h>
25 #include <unistd.h>
26
27 #include "dirent-util.h"
28 #include "fd-util.h"
29 #include "macro.h"
30 #include "missing.h"
31 #include "stat-util.h"
32 #include "string-util.h"
33
34 /// UNNEEDED by elogind
35 #if 0
36 int is_symlink(const char *path) {
37         struct stat info;
38
39         assert(path);
40
41         if (lstat(path, &info) < 0)
42                 return -errno;
43
44         return !!S_ISLNK(info.st_mode);
45 }
46 #endif // 0
47
48 int is_dir(const char* path, bool follow) {
49         struct stat st;
50         int r;
51
52         assert(path);
53
54         if (follow)
55                 r = stat(path, &st);
56         else
57                 r = lstat(path, &st);
58         if (r < 0)
59                 return -errno;
60
61         return !!S_ISDIR(st.st_mode);
62 }
63
64 /// UNNEEDED by elogind
65 #if 0
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 /// UNNEEDED by elogind
119 #if 0
120 int null_or_empty_fd(int fd) {
121         struct stat st;
122
123         assert(fd >= 0);
124
125         if (fstat(fd, &st) < 0)
126                 return -errno;
127
128         return null_or_empty(&st);
129 }
130 #endif // 0
131
132 int path_is_read_only_fs(const char *path) {
133         struct statvfs st;
134
135         assert(path);
136
137         if (statvfs(path, &st) < 0)
138                 return -errno;
139
140         if (st.f_flag & ST_RDONLY)
141                 return true;
142
143         /* On NFS, statvfs() might not reflect whether we can actually
144          * write to the remote share. Let's try again with
145          * access(W_OK) which is more reliable, at least sometimes. */
146         if (access(path, W_OK) < 0 && errno == EROFS)
147                 return true;
148
149         return false;
150 }
151
152 /// UNNEEDED by elogind
153 #if 0
154 int path_is_os_tree(const char *path) {
155         char *p;
156         int r;
157
158         assert(path);
159
160         /* We use /usr/lib/os-release as flag file if something is an OS */
161         p = strjoina(path, "/usr/lib/os-release");
162         r = access(p, F_OK);
163         if (r >= 0)
164                 return 1;
165
166         /* Also check for the old location in /etc, just in case. */
167         p = strjoina(path, "/etc/os-release");
168         r = access(p, F_OK);
169
170         return r >= 0;
171 }
172 #endif // 0
173
174 int files_same(const char *filea, const char *fileb) {
175         struct stat a, b;
176
177         assert(filea);
178         assert(fileb);
179
180         if (stat(filea, &a) < 0)
181                 return -errno;
182
183         if (stat(fileb, &b) < 0)
184                 return -errno;
185
186         return a.st_dev == b.st_dev &&
187                a.st_ino == b.st_ino;
188 }
189
190 bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
191         assert(s);
192         assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
193
194         return F_TYPE_EQUAL(s->f_type, magic_value);
195 }
196
197 /// UNNEEDED by elogind
198 #if 0
199 int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
200         struct statfs s;
201
202         if (fstatfs(fd, &s) < 0)
203                 return -errno;
204
205         return is_fs_type(&s, magic_value);
206 }
207
208 int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
209         _cleanup_close_ int fd = -1;
210
211         fd = open(path, O_RDONLY);
212         if (fd < 0)
213                 return -errno;
214
215         return fd_check_fstype(fd, magic_value);
216 }
217 #endif // 0
218
219 bool is_temporary_fs(const struct statfs *s) {
220     return is_fs_type(s, TMPFS_MAGIC) ||
221            is_fs_type(s, RAMFS_MAGIC);
222 }
223
224 int fd_is_temporary_fs(int fd) {
225         struct statfs s;
226
227         if (fstatfs(fd, &s) < 0)
228                 return -errno;
229
230         return is_temporary_fs(&s);
231 }