File: | build-scan/../src/shared/fstab-util.c |
Warning: | line 202, column 11 Potential leak of memory pointed to by 'opt' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | ||||
2 | |||||
3 | #include <errno(*__errno_location ()).h> | ||||
4 | #include <mntent.h> | ||||
5 | #include <stdio.h> | ||||
6 | #include <stdlib.h> | ||||
7 | #include <string.h> | ||||
8 | |||||
9 | #include "alloc-util.h" | ||||
10 | #include "device-nodes.h" | ||||
11 | #include "fstab-util.h" | ||||
12 | #include "macro.h" | ||||
13 | #include "mount-util.h" | ||||
14 | #include "parse-util.h" | ||||
15 | #include "path-util.h" | ||||
16 | #include "string-util.h" | ||||
17 | #include "strv.h" | ||||
18 | #include "util.h" | ||||
19 | |||||
20 | int fstab_has_fstype(const char *fstype) { | ||||
21 | _cleanup_endmntent___attribute__((cleanup(endmntentp))) FILE *f = NULL((void*)0); | ||||
22 | struct mntent *m; | ||||
23 | |||||
24 | f = setmntent("/etc/fstab", "re"); | ||||
25 | if (!f) | ||||
26 | return errno(*__errno_location ()) == ENOENT2 ? false0 : -errno(*__errno_location ()); | ||||
27 | |||||
28 | for (;;) { | ||||
29 | errno(*__errno_location ()) = 0; | ||||
30 | m = getmntent(f); | ||||
31 | if (!m) | ||||
32 | return errno(*__errno_location ()) != 0 ? -errno(*__errno_location ()) : false0; | ||||
33 | |||||
34 | if (streq(m->mnt_type, fstype)(strcmp((m->mnt_type),(fstype)) == 0)) | ||||
35 | return true1; | ||||
36 | } | ||||
37 | return false0; | ||||
38 | } | ||||
39 | |||||
40 | int fstab_is_mount_point(const char *mount) { | ||||
41 | _cleanup_endmntent___attribute__((cleanup(endmntentp))) FILE *f = NULL((void*)0); | ||||
42 | struct mntent *m; | ||||
43 | |||||
44 | f = setmntent("/etc/fstab", "re"); | ||||
45 | if (!f) | ||||
46 | return errno(*__errno_location ()) == ENOENT2 ? false0 : -errno(*__errno_location ()); | ||||
47 | |||||
48 | for (;;) { | ||||
49 | errno(*__errno_location ()) = 0; | ||||
50 | m = getmntent(f); | ||||
51 | if (!m) | ||||
52 | return errno(*__errno_location ()) != 0 ? -errno(*__errno_location ()) : false0; | ||||
53 | |||||
54 | if (path_equal(m->mnt_dir, mount)) | ||||
55 | return true1; | ||||
56 | } | ||||
57 | return false0; | ||||
58 | } | ||||
59 | |||||
60 | int fstab_filter_options(const char *opts, const char *names, | ||||
61 | const char **namefound, char **value, char **filtered) { | ||||
62 | const char *name, *n = NULL((void*)0), *x; | ||||
63 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **stor = NULL((void*)0); | ||||
64 | _cleanup_free___attribute__((cleanup(freep))) char *v = NULL((void*)0), **strv = NULL((void*)0); | ||||
65 | |||||
66 | assert(names && *names)do { if ((__builtin_expect(!!(!(names && *names)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("names && *names" ), "../src/shared/fstab-util.c", 66, __PRETTY_FUNCTION__); } while (0); | ||||
67 | |||||
68 | if (!opts) | ||||
69 | goto answer; | ||||
70 | |||||
71 | /* If !value and !filtered, this function is not allowed to fail. */ | ||||
72 | |||||
73 | if (!filtered
| ||||
74 | const char *word, *state; | ||||
75 | size_t l; | ||||
76 | |||||
77 | FOREACH_WORD_SEPARATOR(word, l, opts, ",", state)for ((state) = (opts), (word) = split(&(state), &(l), (","), (0)); (word); (word) = split(&(state), &(l), ( ","), (0))) | ||||
78 | NULSTR_FOREACH(name, names)for ((name) = (names); (name) && *(name); (name) = strchr ((name), 0)+1) { | ||||
79 | if (l < strlen(name)) | ||||
80 | continue; | ||||
81 | if (!strneq(word, name, strlen(name))(strncmp((word), (name), (strlen(name))) == 0)) | ||||
82 | continue; | ||||
83 | |||||
84 | /* we know that the string is NUL | ||||
85 | * terminated, so *x is valid */ | ||||
86 | x = word + strlen(name); | ||||
87 | if (IN_SET(*x, '\0', '=', ',')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){'\0', '=', ','})/sizeof(int)]; switch(*x ) { case '\0': case '=': case ',': _found = 1; break; default : break; } _found; })) { | ||||
88 | n = name; | ||||
89 | if (value
| ||||
90 | free(v); | ||||
91 | if (IN_SET(*x, '\0', ',')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){'\0', ','})/sizeof(int)]; switch(*x) { case '\0': case ',': _found = 1; break; default: break; } _found; })) | ||||
92 | v = NULL((void*)0); | ||||
93 | else { | ||||
94 | assert(*x == '=')do { if ((__builtin_expect(!!(!(*x == '=')),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*x == '='"), "../src/shared/fstab-util.c" , 94, __PRETTY_FUNCTION__); } while (0); | ||||
95 | x++; | ||||
96 | v = strndup(x, l - strlen(name) - 1); | ||||
97 | if (!v) | ||||
98 | return -ENOMEM12; | ||||
99 | } | ||||
100 | } | ||||
101 | } | ||||
102 | } | ||||
103 | } else { | ||||
104 | char **t, **s; | ||||
105 | |||||
106 | stor = strv_split(opts, ","); | ||||
107 | if (!stor) | ||||
108 | return -ENOMEM12; | ||||
109 | strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1)); | ||||
110 | if (!strv) | ||||
111 | return -ENOMEM12; | ||||
112 | |||||
113 | for (s = t = strv; *s; s++) { | ||||
114 | NULSTR_FOREACH(name, names)for ((name) = (names); (name) && *(name); (name) = strchr ((name), 0)+1) { | ||||
115 | x = startswith(*s, name); | ||||
116 | if (x && IN_SET(*x, '\0', '=')({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){'\0', '='})/sizeof(int)]; switch(*x) { case '\0': case '=': _found = 1; break; default: break; } _found; })) | ||||
117 | goto found; | ||||
118 | } | ||||
119 | |||||
120 | *t = *s; | ||||
121 | t++; | ||||
122 | continue; | ||||
123 | found: | ||||
124 | /* Keep the last occurence found */ | ||||
125 | n = name; | ||||
126 | if (value) { | ||||
127 | free(v); | ||||
128 | if (*x == '\0') | ||||
129 | v = NULL((void*)0); | ||||
130 | else { | ||||
131 | assert(*x == '=')do { if ((__builtin_expect(!!(!(*x == '=')),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*x == '='"), "../src/shared/fstab-util.c" , 131, __PRETTY_FUNCTION__); } while (0); | ||||
132 | x++; | ||||
133 | v = strdup(x); | ||||
134 | if (!v) | ||||
135 | return -ENOMEM12; | ||||
136 | } | ||||
137 | } | ||||
138 | } | ||||
139 | *t = NULL((void*)0); | ||||
140 | } | ||||
141 | |||||
142 | answer: | ||||
143 | if (namefound
| ||||
144 | *namefound = n; | ||||
145 | if (filtered
| ||||
146 | char *f; | ||||
147 | |||||
148 | f = strv_join(strv, ","); | ||||
149 | if (!f) | ||||
150 | return -ENOMEM12; | ||||
151 | |||||
152 | *filtered = f; | ||||
153 | } | ||||
154 | if (value
| ||||
155 | *value = TAKE_PTR(v)({ typeof(v) _ptr_ = (v); (v) = ((void*)0); _ptr_; }); | ||||
156 | |||||
157 | return !!n; | ||||
158 | } | ||||
159 | |||||
160 | int fstab_extract_values(const char *opts, const char *name, char ***values) { | ||||
161 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **optsv = NULL((void*)0), **res = NULL((void*)0); | ||||
162 | char **s; | ||||
163 | |||||
164 | assert(opts)do { if ((__builtin_expect(!!(!(opts)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("opts"), "../src/shared/fstab-util.c", 164 , __PRETTY_FUNCTION__); } while (0); | ||||
165 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/shared/fstab-util.c", 165 , __PRETTY_FUNCTION__); } while (0); | ||||
166 | assert(values)do { if ((__builtin_expect(!!(!(values)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("values"), "../src/shared/fstab-util.c", 166, __PRETTY_FUNCTION__); } while (0); | ||||
167 | |||||
168 | optsv = strv_split(opts, ","); | ||||
169 | if (!optsv) | ||||
170 | return -ENOMEM12; | ||||
171 | |||||
172 | STRV_FOREACH(s, optsv)for ((s) = (optsv); (s) && *(s); (s)++) { | ||||
173 | char *arg; | ||||
174 | int r; | ||||
175 | |||||
176 | arg = startswith(*s, name); | ||||
177 | if (!arg || *arg != '=') | ||||
178 | continue; | ||||
179 | r = strv_extend(&res, arg + 1); | ||||
180 | if (r < 0) | ||||
181 | return r; | ||||
182 | } | ||||
183 | |||||
184 | *values = TAKE_PTR(res)({ typeof(res) _ptr_ = (res); (res) = ((void*)0); _ptr_; }); | ||||
185 | |||||
186 | return !!*values; | ||||
187 | } | ||||
188 | |||||
189 | int fstab_find_pri(const char *options, int *ret) { | ||||
190 | _cleanup_free___attribute__((cleanup(freep))) char *opt = NULL((void*)0); | ||||
191 | int r; | ||||
192 | unsigned pri; | ||||
193 | |||||
194 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/shared/fstab-util.c", 194 , __PRETTY_FUNCTION__); } while (0); | ||||
| |||||
195 | |||||
196 | r = fstab_filter_options(options, "pri\0", NULL((void*)0), &opt, NULL((void*)0)); | ||||
197 | if (r
| ||||
198 | return r; | ||||
199 | if (r
| ||||
200 | return 0; | ||||
201 | |||||
202 | r = safe_atou(opt, &pri); | ||||
| |||||
203 | if (r < 0) | ||||
204 | return r; | ||||
205 | |||||
206 | if ((int) pri < 0) | ||||
207 | return -ERANGE34; | ||||
208 | |||||
209 | *ret = (int) pri; | ||||
210 | return 1; | ||||
211 | } | ||||
212 | |||||
213 | static char *unquote(const char *s, const char* quotes) { | ||||
214 | size_t l; | ||||
215 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/shared/fstab-util.c", 215, __PRETTY_FUNCTION__); } while (0); | ||||
216 | |||||
217 | /* This is rather stupid, simply removes the heading and | ||||
218 | * trailing quotes if there is one. Doesn't care about | ||||
219 | * escaping or anything. | ||||
220 | * | ||||
221 | * DON'T USE THIS FOR NEW CODE ANYMORE! */ | ||||
222 | |||||
223 | l = strlen(s); | ||||
224 | if (l < 2) | ||||
225 | return strdup(s); | ||||
226 | |||||
227 | if (strchr(quotes, s[0]) && s[l-1] == s[0]) | ||||
228 | return strndup(s+1, l-2); | ||||
229 | |||||
230 | return strdup(s); | ||||
231 | } | ||||
232 | |||||
233 | static char *tag_to_udev_node(const char *tagvalue, const char *by) { | ||||
234 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0), *u = NULL((void*)0); | ||||
235 | size_t enc_len; | ||||
236 | |||||
237 | u = unquote(tagvalue, QUOTES"\"\'"); | ||||
238 | if (!u) | ||||
239 | return NULL((void*)0); | ||||
240 | |||||
241 | enc_len = strlen(u) * 4 + 1; | ||||
242 | t = new(char, enc_len)((char*) malloc_multiply(sizeof(char), (enc_len))); | ||||
243 | if (!t) | ||||
244 | return NULL((void*)0); | ||||
245 | |||||
246 | if (encode_devnode_name(u, t, enc_len) < 0) | ||||
247 | return NULL((void*)0); | ||||
248 | |||||
249 | return strjoin("/dev/disk/by-", by, "/", t)strjoin_real(("/dev/disk/by-"), by, "/", t, ((void*)0)); | ||||
250 | } | ||||
251 | |||||
252 | char *fstab_node_to_udev_node(const char *p) { | ||||
253 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/shared/fstab-util.c", 253, __PRETTY_FUNCTION__); } while (0); | ||||
254 | |||||
255 | if (startswith(p, "LABEL=")) | ||||
256 | return tag_to_udev_node(p+6, "label"); | ||||
257 | |||||
258 | if (startswith(p, "UUID=")) | ||||
259 | return tag_to_udev_node(p+5, "uuid"); | ||||
260 | |||||
261 | if (startswith(p, "PARTUUID=")) | ||||
262 | return tag_to_udev_node(p+9, "partuuid"); | ||||
263 | |||||
264 | if (startswith(p, "PARTLABEL=")) | ||||
265 | return tag_to_udev_node(p+10, "partlabel"); | ||||
266 | |||||
267 | return strdup(p); | ||||
268 | } |