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