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