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 2010 Lennart Poettering
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 <stdlib.h>
23 : #include <stdarg.h>
24 : #include <string.h>
25 : #include <errno.h>
26 :
27 : #include "util.h"
28 : #include "strv.h"
29 :
30 1698 : char *strv_find(char **l, const char *name) {
31 : char **i;
32 :
33 1698 : assert(name);
34 :
35 4484 : STRV_FOREACH(i, l)
36 3059 : if (streq(*i, name))
37 273 : return *i;
38 :
39 1425 : return NULL;
40 : }
41 :
42 5 : char *strv_find_prefix(char **l, const char *name) {
43 : char **i;
44 :
45 5 : assert(name);
46 :
47 11 : STRV_FOREACH(i, l)
48 9 : if (startswith(*i, name))
49 3 : return *i;
50 :
51 2 : return NULL;
52 : }
53 :
54 5 : char *strv_find_startswith(char **l, const char *name) {
55 : char **i, *e;
56 :
57 5 : assert(name);
58 :
59 : /* Like strv_find_prefix, but actually returns only the
60 : * suffix, not the whole item */
61 :
62 11 : STRV_FOREACH(i, l) {
63 9 : e = startswith(*i, name);
64 9 : if (e)
65 3 : return e;
66 : }
67 :
68 2 : return NULL;
69 : }
70 :
71 36658 : void strv_clear(char **l) {
72 : char **k;
73 :
74 36658 : if (!l)
75 35987 : return;
76 :
77 3193 : for (k = l; *k; k++)
78 2522 : free(*k);
79 :
80 671 : *l = NULL;
81 : }
82 :
83 36658 : char **strv_free(char **l) {
84 36658 : strv_clear(l);
85 36658 : free(l);
86 36658 : return NULL;
87 : }
88 :
89 20 : char **strv_copy(char * const *l) {
90 : char **r, **k;
91 :
92 20 : k = r = new(char*, strv_length(l) + 1);
93 20 : if (!r)
94 0 : return NULL;
95 :
96 20 : if (l)
97 430 : for (; *l; k++, l++) {
98 411 : *k = strdup(*l);
99 411 : if (!*k) {
100 0 : strv_free(r);
101 0 : return NULL;
102 : }
103 : }
104 :
105 20 : *k = NULL;
106 20 : return r;
107 : }
108 :
109 3368 : unsigned strv_length(char * const *l) {
110 3368 : unsigned n = 0;
111 :
112 3368 : if (!l)
113 2713 : return 0;
114 :
115 3480 : for (; *l; l++)
116 2825 : n++;
117 :
118 655 : return n;
119 : }
120 :
121 66 : char **strv_new_ap(const char *x, va_list ap) {
122 : const char *s;
123 : char **a;
124 66 : unsigned n = 0, i = 0;
125 : va_list aq;
126 :
127 : /* As a special trick we ignore all listed strings that equal
128 : * (const char*) -1. This is supposed to be used with the
129 : * STRV_IFNOTNULL() macro to include possibly NULL strings in
130 : * the string list. */
131 :
132 66 : if (x) {
133 63 : n = x == (const char*) -1 ? 0 : 1;
134 :
135 63 : va_copy(aq, ap);
136 254 : while ((s = va_arg(aq, const char*))) {
137 128 : if (s == (const char*) -1)
138 2 : continue;
139 :
140 126 : n++;
141 : }
142 :
143 63 : va_end(aq);
144 : }
145 :
146 66 : a = new(char*, n+1);
147 66 : if (!a)
148 0 : return NULL;
149 :
150 66 : if (x) {
151 63 : if (x != (const char*) -1) {
152 62 : a[i] = strdup(x);
153 62 : if (!a[i])
154 0 : goto fail;
155 62 : i++;
156 : }
157 :
158 254 : while ((s = va_arg(ap, const char*))) {
159 :
160 128 : if (s == (const char*) -1)
161 2 : continue;
162 :
163 126 : a[i] = strdup(s);
164 126 : if (!a[i])
165 0 : goto fail;
166 :
167 126 : i++;
168 : }
169 : }
170 :
171 66 : a[i] = NULL;
172 :
173 66 : return a;
174 :
175 : fail:
176 0 : strv_free(a);
177 0 : return NULL;
178 : }
179 :
180 64 : char **strv_new(const char *x, ...) {
181 : char **r;
182 : va_list ap;
183 :
184 64 : va_start(ap, x);
185 64 : r = strv_new_ap(x, ap);
186 64 : va_end(ap);
187 :
188 64 : return r;
189 : }
190 :
191 8 : int strv_extend_strv(char ***a, char **b) {
192 : int r;
193 : char **s;
194 :
195 69 : STRV_FOREACH(s, b) {
196 61 : r = strv_extend(a, *s);
197 61 : if (r < 0)
198 0 : return r;
199 : }
200 :
201 8 : return 0;
202 : }
203 :
204 2 : int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
205 : int r;
206 : char **s;
207 :
208 6 : STRV_FOREACH(s, b) {
209 : char *v;
210 :
211 4 : v = strappend(*s, suffix);
212 4 : if (!v)
213 0 : return -ENOMEM;
214 :
215 4 : r = strv_push(a, v);
216 4 : if (r < 0) {
217 0 : free(v);
218 0 : return r;
219 : }
220 : }
221 :
222 2 : return 0;
223 : }
224 :
225 103 : char **strv_split(const char *s, const char *separator) {
226 : const char *word, *state;
227 : size_t l;
228 : unsigned n, i;
229 : char **r;
230 :
231 103 : assert(s);
232 :
233 103 : n = 0;
234 240 : FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
235 137 : n++;
236 :
237 103 : r = new(char*, n+1);
238 103 : if (!r)
239 0 : return NULL;
240 :
241 103 : i = 0;
242 240 : FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
243 137 : r[i] = strndup(word, l);
244 137 : if (!r[i]) {
245 0 : strv_free(r);
246 0 : return NULL;
247 : }
248 :
249 137 : i++;
250 : }
251 :
252 103 : r[i] = NULL;
253 103 : return r;
254 : }
255 :
256 1 : char **strv_split_newlines(const char *s) {
257 : char **l;
258 : unsigned n;
259 :
260 1 : assert(s);
261 :
262 : /* Special version of strv_split() that splits on newlines and
263 : * suppresses an empty string at the end */
264 :
265 1 : l = strv_split(s, NEWLINE);
266 1 : if (!l)
267 0 : return NULL;
268 :
269 1 : n = strv_length(l);
270 1 : if (n <= 0)
271 0 : return l;
272 :
273 1 : if (isempty(l[n-1])) {
274 0 : free(l[n-1]);
275 0 : l[n-1] = NULL;
276 : }
277 :
278 1 : return l;
279 : }
280 :
281 26 : int strv_split_quoted(char ***t, const char *s, UnquoteFlags flags) {
282 26 : size_t n = 0, allocated = 0;
283 52 : _cleanup_strv_free_ char **l = NULL;
284 : int r;
285 :
286 26 : assert(t);
287 26 : assert(s);
288 :
289 : for (;;) {
290 116 : _cleanup_free_ char *word = NULL;
291 :
292 58 : r = unquote_first_word(&s, &word, flags);
293 58 : if (r < 0)
294 7 : return r;
295 51 : if (r == 0)
296 19 : break;
297 :
298 32 : if (!GREEDY_REALLOC(l, allocated, n + 2))
299 0 : return -ENOMEM;
300 :
301 32 : l[n++] = word;
302 32 : word = NULL;
303 :
304 32 : l[n] = NULL;
305 32 : }
306 :
307 19 : if (!l)
308 4 : l = new0(char*, 1);
309 :
310 19 : *t = l;
311 19 : l = NULL;
312 :
313 19 : return 0;
314 : }
315 :
316 231 : char *strv_join(char **l, const char *separator) {
317 : char *r, *e;
318 : char **s;
319 : size_t n, k;
320 :
321 231 : if (!separator)
322 1 : separator = " ";
323 :
324 231 : k = strlen(separator);
325 :
326 231 : n = 0;
327 484 : STRV_FOREACH(s, l) {
328 253 : if (n != 0)
329 104 : n += k;
330 253 : n += strlen(*s);
331 : }
332 :
333 231 : r = new(char, n+1);
334 231 : if (!r)
335 0 : return NULL;
336 :
337 231 : e = r;
338 484 : STRV_FOREACH(s, l) {
339 253 : if (e != r)
340 104 : e = stpcpy(e, separator);
341 :
342 253 : e = stpcpy(e, *s);
343 : }
344 :
345 231 : *e = 0;
346 :
347 231 : return r;
348 : }
349 :
350 5 : char *strv_join_quoted(char **l) {
351 5 : char *buf = NULL;
352 : char **s;
353 5 : size_t allocated = 0, len = 0;
354 :
355 19 : STRV_FOREACH(s, l) {
356 : /* assuming here that escaped string cannot be more
357 : * than twice as long, and reserving space for the
358 : * separator and quotes.
359 : */
360 28 : _cleanup_free_ char *esc = NULL;
361 : size_t needed;
362 :
363 14 : if (!GREEDY_REALLOC(buf, allocated,
364 : len + strlen(*s) * 2 + 3))
365 0 : goto oom;
366 :
367 14 : esc = cescape(*s);
368 14 : if (!esc)
369 0 : goto oom;
370 :
371 14 : needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
372 : len > 0 ? " " : "", esc);
373 14 : assert(needed < allocated - len);
374 14 : len += needed;
375 : }
376 :
377 5 : if (!buf)
378 1 : buf = malloc0(1);
379 :
380 5 : return buf;
381 :
382 : oom:
383 0 : free(buf);
384 0 : return NULL;
385 : }
386 :
387 696 : int strv_push(char ***l, char *value) {
388 : char **c;
389 : unsigned n, m;
390 :
391 696 : if (!value)
392 0 : return 0;
393 :
394 696 : n = strv_length(*l);
395 :
396 : /* Increase and check for overflow */
397 696 : m = n + 2;
398 696 : if (m < n)
399 0 : return -ENOMEM;
400 :
401 696 : c = realloc_multiply(*l, sizeof(char*), m);
402 696 : if (!c)
403 0 : return -ENOMEM;
404 :
405 696 : c[n] = value;
406 696 : c[n+1] = NULL;
407 :
408 696 : *l = c;
409 696 : return 0;
410 : }
411 :
412 1 : int strv_push_pair(char ***l, char *a, char *b) {
413 : char **c;
414 : unsigned n, m;
415 :
416 1 : if (!a && !b)
417 0 : return 0;
418 :
419 1 : n = strv_length(*l);
420 :
421 : /* increase and check for overflow */
422 1 : m = n + !!a + !!b + 1;
423 1 : if (m < n)
424 0 : return -ENOMEM;
425 :
426 1 : c = realloc_multiply(*l, sizeof(char*), m);
427 1 : if (!c)
428 0 : return -ENOMEM;
429 :
430 1 : if (a)
431 1 : c[n++] = a;
432 1 : if (b)
433 1 : c[n++] = b;
434 1 : c[n] = NULL;
435 :
436 1 : *l = c;
437 1 : return 0;
438 : }
439 :
440 2 : int strv_push_prepend(char ***l, char *value) {
441 : char **c;
442 : unsigned n, m, i;
443 :
444 2 : if (!value)
445 0 : return 0;
446 :
447 2 : n = strv_length(*l);
448 :
449 : /* increase and check for overflow */
450 2 : m = n + 2;
451 2 : if (m < n)
452 0 : return -ENOMEM;
453 :
454 2 : c = new(char*, m);
455 2 : if (!c)
456 0 : return -ENOMEM;
457 :
458 9 : for (i = 0; i < n; i++)
459 7 : c[i+1] = (*l)[i];
460 :
461 2 : c[0] = value;
462 2 : c[n+1] = NULL;
463 :
464 2 : free(*l);
465 2 : *l = c;
466 :
467 2 : return 0;
468 : }
469 :
470 681 : int strv_consume(char ***l, char *value) {
471 : int r;
472 :
473 681 : r = strv_push(l, value);
474 681 : if (r < 0)
475 0 : free(value);
476 :
477 681 : return r;
478 : }
479 :
480 0 : int strv_consume_pair(char ***l, char *a, char *b) {
481 : int r;
482 :
483 0 : r = strv_push_pair(l, a, b);
484 0 : if (r < 0) {
485 0 : free(a);
486 0 : free(b);
487 : }
488 :
489 0 : return r;
490 : }
491 :
492 1 : int strv_consume_prepend(char ***l, char *value) {
493 : int r;
494 :
495 1 : r = strv_push_prepend(l, value);
496 1 : if (r < 0)
497 0 : free(value);
498 :
499 1 : return r;
500 : }
501 :
502 263 : int strv_extend(char ***l, const char *value) {
503 : char *v;
504 :
505 263 : if (!value)
506 0 : return 0;
507 :
508 263 : v = strdup(value);
509 263 : if (!v)
510 0 : return -ENOMEM;
511 :
512 263 : return strv_consume(l, v);
513 : }
514 :
515 94 : char **strv_uniq(char **l) {
516 : char **i;
517 :
518 : /* Drops duplicate entries. The first identical string will be
519 : * kept, the others dropped */
520 :
521 240 : STRV_FOREACH(i, l)
522 146 : strv_remove(i+1, *i);
523 :
524 94 : return l;
525 : }
526 :
527 4 : bool strv_is_uniq(char **l) {
528 : char **i;
529 :
530 8 : STRV_FOREACH(i, l)
531 5 : if (strv_find(i+1, *i))
532 1 : return false;
533 :
534 3 : return true;
535 : }
536 :
537 146 : char **strv_remove(char **l, const char *s) {
538 : char **f, **t;
539 :
540 146 : if (!l)
541 0 : return NULL;
542 :
543 146 : assert(s);
544 :
545 : /* Drops every occurrence of s in the string list, edits
546 : * in-place. */
547 :
548 363 : for (f = t = l; *f; f++)
549 217 : if (streq(*f, s))
550 16 : free(*f);
551 : else
552 201 : *(t++) = *f;
553 :
554 146 : *t = NULL;
555 146 : return l;
556 : }
557 :
558 6 : char **strv_parse_nulstr(const char *s, size_t l) {
559 : const char *p;
560 6 : unsigned c = 0, i = 0;
561 : char **v;
562 :
563 6 : assert(s || l <= 0);
564 :
565 6 : if (l <= 0)
566 0 : return new0(char*, 1);
567 :
568 135 : for (p = s; p < s + l; p++)
569 129 : if (*p == 0)
570 15 : c++;
571 :
572 6 : if (s[l-1] != 0)
573 1 : c++;
574 :
575 6 : v = new0(char*, c+1);
576 6 : if (!v)
577 0 : return NULL;
578 :
579 6 : p = s;
580 27 : while (p < s + l) {
581 : const char *e;
582 :
583 16 : e = memchr(p, 0, s + l - p);
584 :
585 16 : v[i] = strndup(p, e ? e - p : s + l - p);
586 16 : if (!v[i]) {
587 0 : strv_free(v);
588 0 : return NULL;
589 : }
590 :
591 16 : i++;
592 :
593 16 : if (!e)
594 1 : break;
595 :
596 15 : p = e + 1;
597 : }
598 :
599 6 : assert(i == c);
600 :
601 6 : return v;
602 : }
603 :
604 7 : char **strv_split_nulstr(const char *s) {
605 : const char *i;
606 7 : char **r = NULL;
607 :
608 29 : NULSTR_FOREACH(i, s)
609 22 : if (strv_extend(&r, i) < 0) {
610 0 : strv_free(r);
611 0 : return NULL;
612 : }
613 :
614 7 : if (!r)
615 0 : return strv_new(NULL, NULL);
616 :
617 7 : return r;
618 : }
619 :
620 2 : bool strv_overlap(char **a, char **b) {
621 : char **i;
622 :
623 6 : STRV_FOREACH(i, a)
624 5 : if (strv_contains(b, *i))
625 1 : return true;
626 :
627 1 : return false;
628 : }
629 :
630 4608 : static int str_compare(const void *_a, const void *_b) {
631 4608 : const char **a = (const char**) _a, **b = (const char**) _b;
632 :
633 4608 : return strcmp(*a, *b);
634 : }
635 :
636 15 : char **strv_sort(char **l) {
637 :
638 15 : if (strv_isempty(l))
639 0 : return l;
640 :
641 15 : qsort(l, strv_length(l), sizeof(char*), str_compare);
642 15 : return l;
643 : }
644 :
645 10 : bool strv_equal(char **a, char **b) {
646 10 : if (!a || !b)
647 2 : return a == b;
648 :
649 26 : for ( ; *a || *b; ++a, ++b)
650 20 : if (!streq_ptr(*a, *b))
651 2 : return false;
652 :
653 6 : return true;
654 : }
655 :
656 3 : void strv_print(char **l) {
657 : char **s;
658 :
659 14 : STRV_FOREACH(s, l)
660 11 : puts(*s);
661 3 : }
662 :
663 2 : int strv_extendf(char ***l, const char *format, ...) {
664 : va_list ap;
665 : char *x;
666 : int r;
667 :
668 2 : va_start(ap, format);
669 2 : r = vasprintf(&x, format, ap);
670 2 : va_end(ap);
671 :
672 2 : if (r < 0)
673 0 : return -ENOMEM;
674 :
675 2 : return strv_consume(l, x);
676 : }
677 :
678 4 : char **strv_reverse(char **l) {
679 : unsigned n, i;
680 :
681 4 : n = strv_length(l);
682 4 : if (n <= 1)
683 2 : return l;
684 :
685 4 : for (i = 0; i < n / 2; i++) {
686 : char *t;
687 :
688 2 : t = l[i];
689 2 : l[i] = l[n-1-i];
690 2 : l[n-1-i] = t;
691 : }
692 :
693 2 : return l;
694 : }
695 :
696 1 : bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
697 : char* const* p;
698 :
699 2 : STRV_FOREACH(p, patterns)
700 1 : if (fnmatch(*p, s, 0) == 0)
701 0 : return true;
702 :
703 1 : return false;
704 : }
|