]> git.proxmox.com Git - systemd.git/blame - src/shared/fstab-util.c
New upstream version 236
[systemd.git] / src / shared / fstab-util.c
CommitLineData
52ad194e 1/* SPDX-License-Identifier: LGPL-2.1+ */
e735f4d4
MP
2/***
3 This file is part of systemd.
4
5 Copyright 2015 Zbigniew Jędrzejewski-Szmek
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
4c89c718
MP
21#include <errno.h>
22#include <mntent.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
db2df898
MP
27#include "alloc-util.h"
28#include "device-nodes.h"
e735f4d4 29#include "fstab-util.h"
4c89c718 30#include "macro.h"
db2df898
MP
31#include "mount-util.h"
32#include "parse-util.h"
6300502b 33#include "path-util.h"
db2df898 34#include "string-util.h"
e735f4d4
MP
35#include "strv.h"
36#include "util.h"
37
81c58355 38int fstab_has_fstype(const char *fstype) {
6300502b
MP
39 _cleanup_endmntent_ FILE *f = NULL;
40 struct mntent *m;
41
2897b343 42 f = setmntent("/etc/fstab", "re");
6300502b 43 if (!f)
81c58355 44 return errno == ENOENT ? false : -errno;
6300502b 45
81c58355
MB
46 for (;;) {
47 errno = 0;
48 m = getmntent(f);
49 if (!m)
50 return errno != 0 ? -errno : false;
51
52 if (streq(m->mnt_type, fstype))
6300502b 53 return true;
81c58355
MB
54 }
55 return false;
56}
57
58int fstab_is_mount_point(const char *mount) {
59 _cleanup_endmntent_ FILE *f = NULL;
60 struct mntent *m;
6300502b 61
81c58355
MB
62 f = setmntent("/etc/fstab", "re");
63 if (!f)
64 return errno == ENOENT ? false : -errno;
65
66 for (;;) {
67 errno = 0;
68 m = getmntent(f);
69 if (!m)
70 return errno != 0 ? -errno : false;
71
72 if (path_equal(m->mnt_dir, mount))
73 return true;
74 }
6300502b
MP
75 return false;
76}
77
e735f4d4
MP
78int fstab_filter_options(const char *opts, const char *names,
79 const char **namefound, char **value, char **filtered) {
80 const char *name, *n = NULL, *x;
81 _cleanup_strv_free_ char **stor = NULL;
82 _cleanup_free_ char *v = NULL, **strv = NULL;
83
84 assert(names && *names);
85
86 if (!opts)
87 goto answer;
88
89 /* If !value and !filtered, this function is not allowed to fail. */
90
91 if (!filtered) {
92 const char *word, *state;
93 size_t l;
94
95 FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
96 NULSTR_FOREACH(name, names) {
97 if (l < strlen(name))
98 continue;
99 if (!strneq(word, name, strlen(name)))
100 continue;
101
102 /* we know that the string is NUL
103 * terminated, so *x is valid */
104 x = word + strlen(name);
105 if (IN_SET(*x, '\0', '=', ',')) {
106 n = name;
107 if (value) {
108 free(v);
109 if (IN_SET(*x, '\0', ','))
110 v = NULL;
111 else {
112 assert(*x == '=');
113 x++;
114 v = strndup(x, l - strlen(name) - 1);
115 if (!v)
116 return -ENOMEM;
117 }
118 }
119 }
120 }
121 } else {
122 char **t, **s;
123
124 stor = strv_split(opts, ",");
125 if (!stor)
126 return -ENOMEM;
127 strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
128 if (!strv)
129 return -ENOMEM;
130
131 for (s = t = strv; *s; s++) {
132 NULSTR_FOREACH(name, names) {
133 x = startswith(*s, name);
134 if (x && IN_SET(*x, '\0', '='))
135 goto found;
136 }
137
138 *t = *s;
139 t++;
140 continue;
141 found:
142 /* Keep the last occurence found */
143 n = name;
144 if (value) {
145 free(v);
146 if (*x == '\0')
147 v = NULL;
148 else {
149 assert(*x == '=');
150 x++;
151 v = strdup(x);
152 if (!v)
153 return -ENOMEM;
154 }
155 }
156 }
157 *t = NULL;
158 }
159
160answer:
161 if (namefound)
162 *namefound = n;
163 if (filtered) {
164 char *f;
165
166 f = strv_join(strv, ",");
167 if (!f)
168 return -ENOMEM;
169
170 *filtered = f;
171 }
172 if (value) {
173 *value = v;
174 v = NULL;
175 }
176
177 return !!n;
178}
179
e3bff60a
MP
180int fstab_extract_values(const char *opts, const char *name, char ***values) {
181 _cleanup_strv_free_ char **optsv = NULL, **res = NULL;
182 char **s;
183
184 assert(opts);
185 assert(name);
186 assert(values);
187
188 optsv = strv_split(opts, ",");
189 if (!optsv)
190 return -ENOMEM;
191
192 STRV_FOREACH(s, optsv) {
193 char *arg;
194 int r;
195
196 arg = startswith(*s, name);
197 if (!arg || *arg != '=')
198 continue;
199 r = strv_extend(&res, arg + 1);
200 if (r < 0)
201 return r;
202 }
203
204 *values = res;
205 res = NULL;
206
207 return !!*values;
208}
209
e735f4d4
MP
210int fstab_find_pri(const char *options, int *ret) {
211 _cleanup_free_ char *opt = NULL;
212 int r;
213 unsigned pri;
214
215 assert(ret);
216
217 r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL);
218 if (r < 0)
219 return r;
220 if (r == 0 || !opt)
221 return 0;
222
223 r = safe_atou(opt, &pri);
224 if (r < 0)
225 return r;
226
227 if ((int) pri < 0)
228 return -ERANGE;
229
230 *ret = (int) pri;
231 return 1;
232}
db2df898
MP
233
234static char *unquote(const char *s, const char* quotes) {
235 size_t l;
236 assert(s);
237
238 /* This is rather stupid, simply removes the heading and
239 * trailing quotes if there is one. Doesn't care about
240 * escaping or anything.
241 *
2897b343 242 * DON'T USE THIS FOR NEW CODE ANYMORE! */
db2df898
MP
243
244 l = strlen(s);
245 if (l < 2)
246 return strdup(s);
247
248 if (strchr(quotes, s[0]) && s[l-1] == s[0])
249 return strndup(s+1, l-2);
250
251 return strdup(s);
252}
253
254static char *tag_to_udev_node(const char *tagvalue, const char *by) {
255 _cleanup_free_ char *t = NULL, *u = NULL;
256 size_t enc_len;
257
258 u = unquote(tagvalue, QUOTES);
259 if (!u)
260 return NULL;
261
262 enc_len = strlen(u) * 4 + 1;
263 t = new(char, enc_len);
264 if (!t)
265 return NULL;
266
267 if (encode_devnode_name(u, t, enc_len) < 0)
268 return NULL;
269
2897b343 270 return strjoin("/dev/disk/by-", by, "/", t);
db2df898
MP
271}
272
273char *fstab_node_to_udev_node(const char *p) {
274 assert(p);
275
276 if (startswith(p, "LABEL="))
277 return tag_to_udev_node(p+6, "label");
278
279 if (startswith(p, "UUID="))
280 return tag_to_udev_node(p+5, "uuid");
281
282 if (startswith(p, "PARTUUID="))
283 return tag_to_udev_node(p+9, "partuuid");
284
285 if (startswith(p, "PARTLABEL="))
286 return tag_to_udev_node(p+10, "partlabel");
287
288 return strdup(p);
289}