| 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 | } |