]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/fstab-util.c
json: add helpers for dealing with id128 + strv
[thirdparty/systemd.git] / src / shared / fstab-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
d15d0333 2
a8fbdf54 3#include <errno.h>
a8fbdf54
TA
4#include <stdio.h>
5#include <stdlib.h>
a8fbdf54 6
b5efdb8a 7#include "alloc-util.h"
6550203e 8#include "device-nodes.h"
6bedfcbb 9#include "fstab-util.h"
a8fbdf54 10#include "macro.h"
4349cd7c 11#include "mount-util.h"
d8b4d14d 12#include "nulstr-util.h"
6bedfcbb 13#include "parse-util.h"
0b6b6787 14#include "path-util.h"
07630cea 15#include "string-util.h"
d15d0333 16#include "strv.h"
d15d0333 17
6c1921e9
FB
18int fstab_has_fstype(const char *fstype) {
19 _cleanup_endmntent_ FILE *f = NULL;
20 struct mntent *m;
21
ed4ad488 22 f = setmntent(fstab_path(), "re");
6c1921e9
FB
23 if (!f)
24 return errno == ENOENT ? false : -errno;
25
26 for (;;) {
27 errno = 0;
28 m = getmntent(f);
29 if (!m)
30 return errno != 0 ? -errno : false;
31
32 if (streq(m->mnt_type, fstype))
33 return true;
34 }
35 return false;
36}
37
bc9e5a4c
FB
38bool fstab_is_extrinsic(const char *mount, const char *opts) {
39
40 /* Don't bother with the OS data itself */
41 if (PATH_IN_SET(mount,
42 "/",
43 "/usr",
44 "/etc"))
45 return true;
46
47 if (PATH_STARTSWITH_SET(mount,
48 "/run/initramfs", /* This should stay around from before we boot until after we shutdown */
49 "/proc", /* All of this is API VFS */
50 "/sys", /* … dito … */
51 "/dev")) /* … dito … */
52 return true;
53
54 /* If this is an initrd mount, and we are not in the initrd, then leave
55 * this around forever, too. */
56 if (opts && fstab_test_option(opts, "x-initrd.mount\0") && !in_initrd())
57 return true;
58
59 return false;
60}
61
b9088048 62int fstab_is_mount_point(const char *mount) {
0b6b6787
KS
63 _cleanup_endmntent_ FILE *f = NULL;
64 struct mntent *m;
65
ed4ad488 66 f = setmntent(fstab_path(), "re");
0b6b6787 67 if (!f)
b9088048
FB
68 return errno == ENOENT ? false : -errno;
69
70 for (;;) {
71 errno = 0;
72 m = getmntent(f);
73 if (!m)
74 return errno != 0 ? -errno : false;
0b6b6787 75
0b6b6787
KS
76 if (path_equal(m->mnt_dir, mount))
77 return true;
b9088048 78 }
0b6b6787
KS
79 return false;
80}
81
d15d0333 82int fstab_filter_options(const char *opts, const char *names,
92a08691 83 const char **ret_namefound, char **ret_value, char **ret_filtered) {
d15d0333
ZJS
84 const char *name, *n = NULL, *x;
85 _cleanup_strv_free_ char **stor = NULL;
86 _cleanup_free_ char *v = NULL, **strv = NULL;
87
88 assert(names && *names);
89
90 if (!opts)
91 goto answer;
92
93 /* If !value and !filtered, this function is not allowed to fail. */
94
92a08691 95 if (!ret_filtered) {
d15d0333
ZJS
96 const char *word, *state;
97 size_t l;
98
99 FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
100 NULSTR_FOREACH(name, names) {
101 if (l < strlen(name))
102 continue;
103 if (!strneq(word, name, strlen(name)))
104 continue;
105
106 /* we know that the string is NUL
107 * terminated, so *x is valid */
108 x = word + strlen(name);
109 if (IN_SET(*x, '\0', '=', ',')) {
110 n = name;
92a08691 111 if (ret_value) {
d15d0333
ZJS
112 free(v);
113 if (IN_SET(*x, '\0', ','))
114 v = NULL;
115 else {
116 assert(*x == '=');
117 x++;
118 v = strndup(x, l - strlen(name) - 1);
119 if (!v)
120 return -ENOMEM;
121 }
122 }
123 }
124 }
125 } else {
126 char **t, **s;
127
128 stor = strv_split(opts, ",");
129 if (!stor)
130 return -ENOMEM;
131 strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
132 if (!strv)
133 return -ENOMEM;
134
135 for (s = t = strv; *s; s++) {
136 NULSTR_FOREACH(name, names) {
137 x = startswith(*s, name);
138 if (x && IN_SET(*x, '\0', '='))
139 goto found;
140 }
141
142 *t = *s;
143 t++;
144 continue;
145 found:
5238e957 146 /* Keep the last occurrence found */
d15d0333 147 n = name;
92a08691 148 if (ret_value) {
d15d0333
ZJS
149 free(v);
150 if (*x == '\0')
151 v = NULL;
152 else {
153 assert(*x == '=');
154 x++;
155 v = strdup(x);
156 if (!v)
157 return -ENOMEM;
158 }
159 }
160 }
161 *t = NULL;
162 }
163
164answer:
92a08691
LP
165 if (ret_namefound)
166 *ret_namefound = n;
167 if (ret_filtered) {
d15d0333
ZJS
168 char *f;
169
170 f = strv_join(strv, ",");
171 if (!f)
172 return -ENOMEM;
173
92a08691 174 *ret_filtered = f;
d15d0333 175 }
92a08691
LP
176 if (ret_value)
177 *ret_value = TAKE_PTR(v);
d15d0333
ZJS
178
179 return !!n;
180}
181
3519d230
KZ
182int fstab_extract_values(const char *opts, const char *name, char ***values) {
183 _cleanup_strv_free_ char **optsv = NULL, **res = NULL;
184 char **s;
185
186 assert(opts);
187 assert(name);
188 assert(values);
189
190 optsv = strv_split(opts, ",");
191 if (!optsv)
192 return -ENOMEM;
193
194 STRV_FOREACH(s, optsv) {
195 char *arg;
196 int r;
197
198 arg = startswith(*s, name);
199 if (!arg || *arg != '=')
200 continue;
201 r = strv_extend(&res, arg + 1);
202 if (r < 0)
203 return r;
204 }
205
ae2a15bc 206 *values = TAKE_PTR(res);
3519d230
KZ
207
208 return !!*values;
209}
210
d15d0333
ZJS
211int fstab_find_pri(const char *options, int *ret) {
212 _cleanup_free_ char *opt = NULL;
7477451b 213 int r, pri;
d15d0333
ZJS
214
215 assert(ret);
216
217 r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL);
a75f4e2a 218 if (r < 0)
d15d0333 219 return r;
a75f4e2a
ZJS
220 if (r == 0 || !opt)
221 return 0;
d15d0333 222
7477451b 223 r = safe_atoi(opt, &pri);
d15d0333
ZJS
224 if (r < 0)
225 return r;
226
7477451b 227 *ret = pri;
d15d0333
ZJS
228 return 1;
229}
6550203e
LP
230
231static char *unquote(const char *s, const char* quotes) {
232 size_t l;
233 assert(s);
234
235 /* This is rather stupid, simply removes the heading and
236 * trailing quotes if there is one. Doesn't care about
237 * escaping or anything.
238 *
13e785f7 239 * DON'T USE THIS FOR NEW CODE ANYMORE! */
6550203e
LP
240
241 l = strlen(s);
242 if (l < 2)
243 return strdup(s);
244
245 if (strchr(quotes, s[0]) && s[l-1] == s[0])
246 return strndup(s+1, l-2);
247
248 return strdup(s);
249}
250
251static char *tag_to_udev_node(const char *tagvalue, const char *by) {
252 _cleanup_free_ char *t = NULL, *u = NULL;
253 size_t enc_len;
254
255 u = unquote(tagvalue, QUOTES);
256 if (!u)
257 return NULL;
258
259 enc_len = strlen(u) * 4 + 1;
260 t = new(char, enc_len);
261 if (!t)
262 return NULL;
263
264 if (encode_devnode_name(u, t, enc_len) < 0)
265 return NULL;
266
605405c6 267 return strjoin("/dev/disk/by-", by, "/", t);
6550203e
LP
268}
269
270char *fstab_node_to_udev_node(const char *p) {
271 assert(p);
272
273 if (startswith(p, "LABEL="))
274 return tag_to_udev_node(p+6, "label");
275
276 if (startswith(p, "UUID="))
277 return tag_to_udev_node(p+5, "uuid");
278
279 if (startswith(p, "PARTUUID="))
280 return tag_to_udev_node(p+9, "partuuid");
281
282 if (startswith(p, "PARTLABEL="))
283 return tag_to_udev_node(p+10, "partlabel");
284
285 return strdup(p);
286}