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