Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright 2015 Zbigniew Jędrzejewski-Szmek
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 "fstab-util.h"
23 : #include "strv.h"
24 : #include "util.h"
25 :
26 159 : int fstab_filter_options(const char *opts, const char *names,
27 : const char **namefound, char **value, char **filtered) {
28 159 : const char *name, *n = NULL, *x;
29 318 : _cleanup_strv_free_ char **stor = NULL;
30 318 : _cleanup_free_ char *v = NULL, **strv = NULL;
31 :
32 159 : assert(names && *names);
33 :
34 159 : if (!opts)
35 2 : goto answer;
36 :
37 : /* If !value and !filtered, this function is not allowed to fail. */
38 :
39 157 : if (!filtered) {
40 : const char *word, *state;
41 : size_t l;
42 :
43 481 : FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)
44 1060 : NULSTR_FOREACH(name, names) {
45 702 : if (l < strlen(name))
46 201 : continue;
47 501 : if (!strneq(word, name, strlen(name)))
48 448 : continue;
49 :
50 : /* we know that the string is NUL
51 : * terminated, so *x is valid */
52 53 : x = word + strlen(name);
53 53 : if (IN_SET(*x, '\0', '=', ',')) {
54 47 : n = name;
55 47 : if (value) {
56 5 : free(v);
57 5 : if (IN_SET(*x, '\0', ','))
58 1 : v = NULL;
59 : else {
60 4 : assert(*x == '=');
61 4 : x++;
62 4 : v = strndup(x, l - strlen(name) - 1);
63 4 : if (!v)
64 0 : return -ENOMEM;
65 : }
66 : }
67 : }
68 : }
69 : } else {
70 : char **t, **s;
71 :
72 34 : stor = strv_split(opts, ",");
73 34 : if (!stor)
74 0 : return -ENOMEM;
75 34 : strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1));
76 34 : if (!strv)
77 0 : return -ENOMEM;
78 :
79 98 : for (s = t = strv; *s; s++) {
80 144 : NULSTR_FOREACH(name, names) {
81 110 : x = startswith(*s, name);
82 110 : if (x && IN_SET(*x, '\0', '='))
83 30 : goto found;
84 : }
85 :
86 34 : *t = *s;
87 34 : t++;
88 34 : continue;
89 : found:
90 : /* Keep the last occurence found */
91 30 : n = name;
92 30 : if (value) {
93 30 : free(v);
94 30 : if (*x == '\0')
95 11 : v = NULL;
96 : else {
97 19 : assert(*x == '=');
98 19 : x++;
99 19 : v = strdup(x);
100 19 : if (!v)
101 0 : return -ENOMEM;
102 : }
103 : }
104 : }
105 34 : *t = NULL;
106 : }
107 :
108 : answer:
109 159 : if (namefound)
110 75 : *namefound = n;
111 159 : if (filtered) {
112 : char *f;
113 :
114 35 : f = strv_join(strv, ",");
115 35 : if (!f)
116 0 : return -ENOMEM;
117 :
118 35 : *filtered = f;
119 : }
120 159 : if (value) {
121 39 : *value = v;
122 39 : v = NULL;
123 : }
124 :
125 159 : return !!n;
126 : }
127 :
128 0 : int fstab_extract_values(const char *opts, const char *name, char ***values) {
129 0 : _cleanup_strv_free_ char **optsv = NULL, **res = NULL;
130 : char **s;
131 :
132 0 : assert(opts);
133 0 : assert(name);
134 0 : assert(values);
135 :
136 0 : optsv = strv_split(opts, ",");
137 0 : if (!optsv)
138 0 : return -ENOMEM;
139 :
140 0 : STRV_FOREACH(s, optsv) {
141 : char *arg;
142 : int r;
143 :
144 0 : arg = startswith(*s, name);
145 0 : if (!arg || *arg != '=')
146 0 : continue;
147 0 : r = strv_extend(&res, arg + 1);
148 0 : if (r < 0)
149 0 : return r;
150 : }
151 :
152 0 : *values = res;
153 0 : res = NULL;
154 :
155 0 : return !!*values;
156 : }
157 :
158 4 : int fstab_find_pri(const char *options, int *ret) {
159 8 : _cleanup_free_ char *opt = NULL;
160 : int r;
161 : unsigned pri;
162 :
163 4 : assert(ret);
164 :
165 4 : r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL);
166 4 : if (r < 0)
167 0 : return r;
168 4 : if (r == 0 || !opt)
169 1 : return 0;
170 :
171 3 : r = safe_atou(opt, &pri);
172 3 : if (r < 0)
173 0 : return r;
174 :
175 3 : if ((int) pri < 0)
176 0 : return -ERANGE;
177 :
178 3 : *ret = (int) pri;
179 3 : return 1;
180 : }
|