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