File: | build-scan/../src/shared/fstab-util.c |
Warning: | line 244, column 24 Potential leak of memory pointed to by 'u' |
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 < 0) | |||
198 | return r; | |||
199 | if (r == 0 || !opt) | |||
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 | } |