]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/strv.c
Merge pull request #1475 from steelman/analyze-without-hostnamed
[thirdparty/systemd.git] / src / basic / strv.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
60918275
LP
22#include <stdlib.h>
23#include <stdarg.h>
24#include <string.h>
2e6c9e6b 25#include <errno.h>
60918275
LP
26
27#include "util.h"
28#include "strv.h"
29
30char *strv_find(char **l, const char *name) {
5f9a22c3
LP
31 char **i;
32
60918275
LP
33 assert(name);
34
5f9a22c3
LP
35 STRV_FOREACH(i, l)
36 if (streq(*i, name))
37 return *i;
60918275
LP
38
39 return NULL;
40}
41
a4bfb399
LP
42char *strv_find_prefix(char **l, const char *name) {
43 char **i;
44
45 assert(name);
46
47 STRV_FOREACH(i, l)
48 if (startswith(*i, name))
49 return *i;
50
51 return NULL;
52}
53
28849dba
LP
54char *strv_find_startswith(char **l, const char *name) {
55 char **i, *e;
56
57 assert(name);
58
59 /* Like strv_find_prefix, but actually returns only the
60 * suffix, not the whole item */
61
62 STRV_FOREACH(i, l) {
63 e = startswith(*i, name);
64 if (e)
65 return e;
66 }
67
68 return NULL;
69}
70
dd9c7723 71void strv_clear(char **l) {
60918275
LP
72 char **k;
73
74 if (!l)
75 return;
76
77 for (k = l; *k; k++)
78 free(*k);
79
dd9c7723
TG
80 *l = NULL;
81}
82
33c2ce7b 83char **strv_free(char **l) {
dd9c7723 84 strv_clear(l);
60918275 85 free(l);
33c2ce7b 86 return NULL;
60918275
LP
87}
88
2fd9ae2e 89char **strv_copy(char * const *l) {
60918275
LP
90 char **r, **k;
91
1fd8d04e
LP
92 k = r = new(char*, strv_length(l) + 1);
93 if (!r)
60918275
LP
94 return NULL;
95
ede27aab 96 if (l)
1fd8d04e
LP
97 for (; *l; k++, l++) {
98 *k = strdup(*l);
99 if (!*k) {
100 strv_free(r);
101 return NULL;
102 }
103 }
60918275
LP
104
105 *k = NULL;
106 return r;
60918275
LP
107}
108
2fd9ae2e 109unsigned strv_length(char * const *l) {
60918275
LP
110 unsigned n = 0;
111
112 if (!l)
113 return 0;
114
115 for (; *l; l++)
116 n++;
117
118 return n;
119}
120
257eca1a 121char **strv_new_ap(const char *x, va_list ap) {
60918275
LP
122 const char *s;
123 char **a;
124 unsigned n = 0, i = 0;
257eca1a
LP
125 va_list aq;
126
07719a21
LP
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
60918275 132 if (x) {
07719a21 133 n = x == (const char*) -1 ? 0 : 1;
60918275 134
257eca1a 135 va_copy(aq, ap);
07719a21
LP
136 while ((s = va_arg(aq, const char*))) {
137 if (s == (const char*) -1)
138 continue;
139
60918275 140 n++;
07719a21
LP
141 }
142
257eca1a 143 va_end(aq);
60918275
LP
144 }
145
07719a21
LP
146 a = new(char*, n+1);
147 if (!a)
60918275
LP
148 return NULL;
149
150 if (x) {
07719a21
LP
151 if (x != (const char*) -1) {
152 a[i] = strdup(x);
153 if (!a[i])
154 goto fail;
155 i++;
60918275
LP
156 }
157
60918275 158 while ((s = va_arg(ap, const char*))) {
07719a21
LP
159
160 if (s == (const char*) -1)
161 continue;
162
163 a[i] = strdup(s);
164 if (!a[i])
60918275
LP
165 goto fail;
166
167 i++;
168 }
60918275
LP
169 }
170
171 a[i] = NULL;
257eca1a 172
60918275
LP
173 return a;
174
175fail:
1fd8d04e 176 strv_free(a);
60918275
LP
177 return NULL;
178}
034c6ed7 179
257eca1a
LP
180char **strv_new(const char *x, ...) {
181 char **r;
182 va_list ap;
183
184 va_start(ap, x);
185 r = strv_new_ap(x, ap);
186 va_end(ap);
187
188 return r;
189}
190
e3e45d4f
SP
191int strv_extend_strv(char ***a, char **b) {
192 int r;
193 char **s;
07719a21 194
e3e45d4f
SP
195 STRV_FOREACH(s, b) {
196 r = strv_extend(a, *s);
197 if (r < 0)
198 return r;
07719a21 199 }
034c6ed7 200
e3e45d4f 201 return 0;
5f9a22c3
LP
202}
203
e3e45d4f
SP
204int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
205 int r;
206 char **s;
5f9a22c3 207
e3e45d4f
SP
208 STRV_FOREACH(s, b) {
209 char *v;
5f9a22c3 210
e3e45d4f
SP
211 v = strappend(*s, suffix);
212 if (!v)
213 return -ENOMEM;
5f9a22c3 214
e3e45d4f
SP
215 r = strv_push(a, v);
216 if (r < 0) {
217 free(v);
218 return r;
8ea913b2 219 }
8ea913b2 220 }
5f9a22c3 221
e3e45d4f 222 return 0;
5f9a22c3
LP
223}
224
225char **strv_split(const char *s, const char *separator) {
a2a5291b 226 const char *word, *state;
5f9a22c3
LP
227 size_t l;
228 unsigned n, i;
229 char **r;
230
231 assert(s);
232
233 n = 0;
a2a5291b 234 FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
5f9a22c3
LP
235 n++;
236
1fd8d04e
LP
237 r = new(char*, n+1);
238 if (!r)
5f9a22c3
LP
239 return NULL;
240
241 i = 0;
a2a5291b
ZJS
242 FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
243 r[i] = strndup(word, l);
1fd8d04e 244 if (!r[i]) {
5f9a22c3
LP
245 strv_free(r);
246 return NULL;
247 }
248
1fd8d04e
LP
249 i++;
250 }
251
5f9a22c3
LP
252 r[i] = NULL;
253 return r;
254}
255
26d04f86
LP
256char **strv_split_newlines(const char *s) {
257 char **l;
258 unsigned n;
259
260 assert(s);
261
262 /* Special version of strv_split() that splits on newlines and
263 * suppresses an empty string at the end */
264
265 l = strv_split(s, NEWLINE);
266 if (!l)
267 return NULL;
268
269 n = strv_length(l);
270 if (n <= 0)
271 return l;
272
ece174c5 273 if (isempty(l[n - 1]))
a1e58e8e 274 l[n - 1] = mfree(l[n - 1]);
26d04f86
LP
275
276 return l;
277}
278
8adaf7bd 279int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
f88e6be5 280 _cleanup_strv_free_ char **l = NULL;
8dd4c05b 281 size_t n = 0, allocated = 0;
f88e6be5
LP
282 int r;
283
284 assert(t);
285 assert(s);
286
287 for (;;) {
288 _cleanup_free_ char *word = NULL;
289
8adaf7bd 290 r = extract_first_word(&s, &word, separators, flags);
f88e6be5
LP
291 if (r < 0)
292 return r;
ece174c5 293 if (r == 0)
f88e6be5
LP
294 break;
295
296 if (!GREEDY_REALLOC(l, allocated, n + 2))
297 return -ENOMEM;
298
299 l[n++] = word;
300 word = NULL;
301
302 l[n] = NULL;
303 }
304
8dd4c05b 305 if (!l) {
f88e6be5 306 l = new0(char*, 1);
8dd4c05b
LP
307 if (!l)
308 return -ENOMEM;
309 }
f88e6be5
LP
310
311 *t = l;
312 l = NULL;
313
8dd4c05b 314 return (int) n;
f88e6be5
LP
315}
316
5f9a22c3
LP
317char *strv_join(char **l, const char *separator) {
318 char *r, *e;
319 char **s;
320 size_t n, k;
321
322 if (!separator)
323 separator = " ";
324
325 k = strlen(separator);
326
327 n = 0;
328 STRV_FOREACH(s, l) {
329 if (n != 0)
330 n += k;
331 n += strlen(*s);
332 }
333
1fd8d04e
LP
334 r = new(char, n+1);
335 if (!r)
5f9a22c3
LP
336 return NULL;
337
338 e = r;
339 STRV_FOREACH(s, l) {
340 if (e != r)
341 e = stpcpy(e, separator);
342
343 e = stpcpy(e, *s);
344 }
345
8d49745c
LP
346 *e = 0;
347
5f9a22c3
LP
348 return r;
349}
350
a6fde353
ZJS
351char *strv_join_quoted(char **l) {
352 char *buf = NULL;
353 char **s;
354 size_t allocated = 0, len = 0;
355
356 STRV_FOREACH(s, l) {
357 /* assuming here that escaped string cannot be more
358 * than twice as long, and reserving space for the
359 * separator and quotes.
360 */
361 _cleanup_free_ char *esc = NULL;
362 size_t needed;
363
364 if (!GREEDY_REALLOC(buf, allocated,
365 len + strlen(*s) * 2 + 3))
366 goto oom;
367
368 esc = cescape(*s);
369 if (!esc)
370 goto oom;
371
372 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
373 len > 0 ? " " : "", esc);
374 assert(needed < allocated - len);
375 len += needed;
376 }
377
378 if (!buf)
379 buf = malloc0(1);
380
381 return buf;
382
383 oom:
384 free(buf);
385 return NULL;
386}
387
4468addc 388int strv_push(char ***l, char *value) {
5926ccca 389 char **c;
97569e15 390 unsigned n, m;
5926ccca
LP
391
392 if (!value)
393 return 0;
394
82dde599 395 n = strv_length(*l);
97569e15 396
98940a3c 397 /* Increase and check for overflow */
97569e15
LP
398 m = n + 2;
399 if (m < n)
400 return -ENOMEM;
401
14f27b4e 402 c = realloc_multiply(*l, sizeof(char*), m);
4468addc 403 if (!c)
82dde599 404 return -ENOMEM;
82dde599 405
4468addc 406 c[n] = value;
82dde599
LP
407 c[n+1] = NULL;
408
5926ccca
LP
409 *l = c;
410 return 0;
411}
412
98940a3c
LP
413int strv_push_pair(char ***l, char *a, char *b) {
414 char **c;
415 unsigned n, m;
416
417 if (!a && !b)
418 return 0;
419
420 n = strv_length(*l);
421
422 /* increase and check for overflow */
423 m = n + !!a + !!b + 1;
424 if (m < n)
425 return -ENOMEM;
426
427 c = realloc_multiply(*l, sizeof(char*), m);
428 if (!c)
429 return -ENOMEM;
430
431 if (a)
432 c[n++] = a;
433 if (b)
434 c[n++] = b;
435 c[n] = NULL;
436
437 *l = c;
438 return 0;
439}
440
9a00f57a
LP
441int strv_push_prepend(char ***l, char *value) {
442 char **c;
97569e15 443 unsigned n, m, i;
9a00f57a
LP
444
445 if (!value)
446 return 0;
447
448 n = strv_length(*l);
97569e15
LP
449
450 /* increase and check for overflow */
451 m = n + 2;
452 if (m < n)
453 return -ENOMEM;
454
455 c = new(char*, m);
9a00f57a
LP
456 if (!c)
457 return -ENOMEM;
458
459 for (i = 0; i < n; i++)
460 c[i+1] = (*l)[i];
461
462 c[0] = value;
463 c[n+1] = NULL;
464
465 free(*l);
466 *l = c;
467
468 return 0;
469}
470
6e18964d
ZJS
471int strv_consume(char ***l, char *value) {
472 int r;
473
474 r = strv_push(l, value);
475 if (r < 0)
476 free(value);
477
9a00f57a
LP
478 return r;
479}
480
98940a3c
LP
481int strv_consume_pair(char ***l, char *a, char *b) {
482 int r;
483
484 r = strv_push_pair(l, a, b);
485 if (r < 0) {
486 free(a);
487 free(b);
488 }
489
490 return r;
491}
492
9a00f57a
LP
493int strv_consume_prepend(char ***l, char *value) {
494 int r;
495
496 r = strv_push_prepend(l, value);
497 if (r < 0)
498 free(value);
499
6e18964d
ZJS
500 return r;
501}
502
4468addc
LP
503int strv_extend(char ***l, const char *value) {
504 char *v;
4468addc
LP
505
506 if (!value)
507 return 0;
508
509 v = strdup(value);
510 if (!v)
511 return -ENOMEM;
512
6e18964d 513 return strv_consume(l, v);
4468addc
LP
514}
515
5f9a22c3 516char **strv_uniq(char **l) {
cba8922f
LP
517 char **i;
518
5f9a22c3
LP
519 /* Drops duplicate entries. The first identical string will be
520 * kept, the others dropped */
521
cba8922f 522 STRV_FOREACH(i, l)
5f9a22c3
LP
523 strv_remove(i+1, *i);
524
525 return l;
526}
527
e1dd6790
LP
528bool strv_is_uniq(char **l) {
529 char **i;
530
531 STRV_FOREACH(i, l)
532 if (strv_find(i+1, *i))
533 return false;
534
535 return true;
536}
537
5f9a22c3
LP
538char **strv_remove(char **l, const char *s) {
539 char **f, **t;
540
541 if (!l)
542 return NULL;
543
5d6ab905
LP
544 assert(s);
545
546 /* Drops every occurrence of s in the string list, edits
547 * in-place. */
5f9a22c3 548
e3e45d4f
SP
549 for (f = t = l; *f; f++)
550 if (streq(*f, s))
71ecc858 551 free(*f);
e3e45d4f
SP
552 else
553 *(t++) = *f;
71ecc858
LP
554
555 *t = NULL;
556 return l;
557}
558
21bc923a
LP
559char **strv_parse_nulstr(const char *s, size_t l) {
560 const char *p;
561 unsigned c = 0, i = 0;
562 char **v;
563
564 assert(s || l <= 0);
565
566 if (l <= 0)
49b832c5 567 return new0(char*, 1);
21bc923a
LP
568
569 for (p = s; p < s + l; p++)
570 if (*p == 0)
571 c++;
572
573 if (s[l-1] != 0)
574 c++;
575
1fd8d04e
LP
576 v = new0(char*, c+1);
577 if (!v)
21bc923a
LP
578 return NULL;
579
580 p = s;
581 while (p < s + l) {
582 const char *e;
583
584 e = memchr(p, 0, s + l - p);
585
1fd8d04e
LP
586 v[i] = strndup(p, e ? e - p : s + l - p);
587 if (!v[i]) {
21bc923a
LP
588 strv_free(v);
589 return NULL;
590 }
591
1fd8d04e
LP
592 i++;
593
21bc923a
LP
594 if (!e)
595 break;
596
597 p = e + 1;
598 }
599
600 assert(i == c);
601
602 return v;
603}
0c85a4f3 604
fabe5c0e
LP
605char **strv_split_nulstr(const char *s) {
606 const char *i;
607 char **r = NULL;
608
609 NULSTR_FOREACH(i, s)
610 if (strv_extend(&r, i) < 0) {
611 strv_free(r);
612 return NULL;
613 }
614
615 if (!r)
616 return strv_new(NULL, NULL);
617
618 return r;
619}
620
0c85a4f3 621bool strv_overlap(char **a, char **b) {
e3e45d4f 622 char **i;
0c85a4f3 623
e3e45d4f
SP
624 STRV_FOREACH(i, a)
625 if (strv_contains(b, *i))
626 return true;
0c85a4f3
LP
627
628 return false;
629}
857a493d
LP
630
631static int str_compare(const void *_a, const void *_b) {
632 const char **a = (const char**) _a, **b = (const char**) _b;
633
634 return strcmp(*a, *b);
635}
636
637char **strv_sort(char **l) {
638
639 if (strv_isempty(l))
640 return l;
641
642 qsort(l, strv_length(l), sizeof(char*), str_compare);
643 return l;
644}
7c2d8094 645
0f84a72e
DH
646bool strv_equal(char **a, char **b) {
647 if (!a || !b)
648 return a == b;
649
650 for ( ; *a || *b; ++a, ++b)
651 if (!streq_ptr(*a, *b))
652 return false;
653
654 return true;
655}
656
7c2d8094
TA
657void strv_print(char **l) {
658 char **s;
659
7c2d8094
TA
660 STRV_FOREACH(s, l)
661 puts(*s);
662}
4de33e7f
LP
663
664int strv_extendf(char ***l, const char *format, ...) {
665 va_list ap;
666 char *x;
667 int r;
668
669 va_start(ap, format);
670 r = vasprintf(&x, format, ap);
671 va_end(ap);
672
673 if (r < 0)
674 return -ENOMEM;
675
676 return strv_consume(l, x);
677}
e1dd6790
LP
678
679char **strv_reverse(char **l) {
680 unsigned n, i;
681
682 n = strv_length(l);
683 if (n <= 1)
684 return l;
685
686 for (i = 0; i < n / 2; i++) {
687 char *t;
688
689 t = l[i];
690 l[i] = l[n-1-i];
691 l[n-1-i] = t;
692 }
693
694 return l;
695}
bceccd5e 696
04c14b25
RM
697char **strv_shell_escape(char **l, const char *bad) {
698 char **s;
699
700 /* Escapes every character in every string in l that is in bad,
701 * edits in-place, does not roll-back on error. */
702
703 STRV_FOREACH(s, l) {
704 char *v;
705
706 v = shell_escape(*s, bad);
707 if (!v)
708 return NULL;
709
710 free(*s);
711 *s = v;
712 }
713
714 return l;
715}
716
2404701e 717bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
bceccd5e
ZJS
718 char* const* p;
719
720 STRV_FOREACH(p, patterns)
721 if (fnmatch(*p, s, 0) == 0)
722 return true;
723
724 return false;
725}
fe382237
LP
726
727char ***strv_free_free(char ***l) {
728 char ***i;
729
730 if (!l)
731 return NULL;
732
733 for (i = l; *i; i++)
734 strv_free(*i);
735
736 free(l);
737 return NULL;
738}
e3ead6bb
LP
739
740char **strv_skip(char **l, size_t n) {
741
742 while (n > 0) {
743 if (strv_isempty(l))
744 return l;
745
746 l++, n--;
747 }
748
749 return l;
750}
8dd4c05b
LP
751
752int strv_extend_n(char ***l, const char *value, size_t n) {
753 size_t i, j, k;
754 char **nl;
755
756 assert(l);
757
758 if (!value)
759 return 0;
760 if (n == 0)
761 return 0;
762
763 /* Adds the value value n times to l */
764
765 k = strv_length(*l);
766
767 nl = realloc(*l, sizeof(char*) * (k + n + 1));
768 if (!nl)
769 return -ENOMEM;
770
771 *l = nl;
772
773 for (i = k; i < k + n; i++) {
774 nl[i] = strdup(value);
775 if (!nl[i])
776 goto rollback;
777 }
778
779 nl[i] = NULL;
780 return 0;
781
782rollback:
783 for (j = k; j < i; i++)
784 free(nl[j]);
785
786 nl[k] = NULL;
5b700370 787 return -ENOMEM;
8dd4c05b 788}