]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/strv.c
tree-wide: port more code to use send_one_fd() and receive_one_fd()
[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
LP
280 size_t n = 0, allocated = 0;
281 _cleanup_strv_free_ char **l = NULL;
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
305 if (!l)
306 l = new0(char*, 1);
307
308 *t = l;
309 l = NULL;
310
311 return 0;
312}
313
5f9a22c3
LP
314char *strv_join(char **l, const char *separator) {
315 char *r, *e;
316 char **s;
317 size_t n, k;
318
319 if (!separator)
320 separator = " ";
321
322 k = strlen(separator);
323
324 n = 0;
325 STRV_FOREACH(s, l) {
326 if (n != 0)
327 n += k;
328 n += strlen(*s);
329 }
330
1fd8d04e
LP
331 r = new(char, n+1);
332 if (!r)
5f9a22c3
LP
333 return NULL;
334
335 e = r;
336 STRV_FOREACH(s, l) {
337 if (e != r)
338 e = stpcpy(e, separator);
339
340 e = stpcpy(e, *s);
341 }
342
8d49745c
LP
343 *e = 0;
344
5f9a22c3
LP
345 return r;
346}
347
a6fde353
ZJS
348char *strv_join_quoted(char **l) {
349 char *buf = NULL;
350 char **s;
351 size_t allocated = 0, len = 0;
352
353 STRV_FOREACH(s, l) {
354 /* assuming here that escaped string cannot be more
355 * than twice as long, and reserving space for the
356 * separator and quotes.
357 */
358 _cleanup_free_ char *esc = NULL;
359 size_t needed;
360
361 if (!GREEDY_REALLOC(buf, allocated,
362 len + strlen(*s) * 2 + 3))
363 goto oom;
364
365 esc = cescape(*s);
366 if (!esc)
367 goto oom;
368
369 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
370 len > 0 ? " " : "", esc);
371 assert(needed < allocated - len);
372 len += needed;
373 }
374
375 if (!buf)
376 buf = malloc0(1);
377
378 return buf;
379
380 oom:
381 free(buf);
382 return NULL;
383}
384
4468addc 385int strv_push(char ***l, char *value) {
5926ccca 386 char **c;
97569e15 387 unsigned n, m;
5926ccca
LP
388
389 if (!value)
390 return 0;
391
82dde599 392 n = strv_length(*l);
97569e15 393
98940a3c 394 /* Increase and check for overflow */
97569e15
LP
395 m = n + 2;
396 if (m < n)
397 return -ENOMEM;
398
14f27b4e 399 c = realloc_multiply(*l, sizeof(char*), m);
4468addc 400 if (!c)
82dde599 401 return -ENOMEM;
82dde599 402
4468addc 403 c[n] = value;
82dde599
LP
404 c[n+1] = NULL;
405
5926ccca
LP
406 *l = c;
407 return 0;
408}
409
98940a3c
LP
410int strv_push_pair(char ***l, char *a, char *b) {
411 char **c;
412 unsigned n, m;
413
414 if (!a && !b)
415 return 0;
416
417 n = strv_length(*l);
418
419 /* increase and check for overflow */
420 m = n + !!a + !!b + 1;
421 if (m < n)
422 return -ENOMEM;
423
424 c = realloc_multiply(*l, sizeof(char*), m);
425 if (!c)
426 return -ENOMEM;
427
428 if (a)
429 c[n++] = a;
430 if (b)
431 c[n++] = b;
432 c[n] = NULL;
433
434 *l = c;
435 return 0;
436}
437
9a00f57a
LP
438int strv_push_prepend(char ***l, char *value) {
439 char **c;
97569e15 440 unsigned n, m, i;
9a00f57a
LP
441
442 if (!value)
443 return 0;
444
445 n = strv_length(*l);
97569e15
LP
446
447 /* increase and check for overflow */
448 m = n + 2;
449 if (m < n)
450 return -ENOMEM;
451
452 c = new(char*, m);
9a00f57a
LP
453 if (!c)
454 return -ENOMEM;
455
456 for (i = 0; i < n; i++)
457 c[i+1] = (*l)[i];
458
459 c[0] = value;
460 c[n+1] = NULL;
461
462 free(*l);
463 *l = c;
464
465 return 0;
466}
467
6e18964d
ZJS
468int strv_consume(char ***l, char *value) {
469 int r;
470
471 r = strv_push(l, value);
472 if (r < 0)
473 free(value);
474
9a00f57a
LP
475 return r;
476}
477
98940a3c
LP
478int strv_consume_pair(char ***l, char *a, char *b) {
479 int r;
480
481 r = strv_push_pair(l, a, b);
482 if (r < 0) {
483 free(a);
484 free(b);
485 }
486
487 return r;
488}
489
9a00f57a
LP
490int strv_consume_prepend(char ***l, char *value) {
491 int r;
492
493 r = strv_push_prepend(l, value);
494 if (r < 0)
495 free(value);
496
6e18964d
ZJS
497 return r;
498}
499
4468addc
LP
500int strv_extend(char ***l, const char *value) {
501 char *v;
4468addc
LP
502
503 if (!value)
504 return 0;
505
506 v = strdup(value);
507 if (!v)
508 return -ENOMEM;
509
6e18964d 510 return strv_consume(l, v);
4468addc
LP
511}
512
5f9a22c3 513char **strv_uniq(char **l) {
cba8922f
LP
514 char **i;
515
5f9a22c3
LP
516 /* Drops duplicate entries. The first identical string will be
517 * kept, the others dropped */
518
cba8922f 519 STRV_FOREACH(i, l)
5f9a22c3
LP
520 strv_remove(i+1, *i);
521
522 return l;
523}
524
e1dd6790
LP
525bool strv_is_uniq(char **l) {
526 char **i;
527
528 STRV_FOREACH(i, l)
529 if (strv_find(i+1, *i))
530 return false;
531
532 return true;
533}
534
5f9a22c3
LP
535char **strv_remove(char **l, const char *s) {
536 char **f, **t;
537
538 if (!l)
539 return NULL;
540
5d6ab905
LP
541 assert(s);
542
543 /* Drops every occurrence of s in the string list, edits
544 * in-place. */
5f9a22c3 545
e3e45d4f
SP
546 for (f = t = l; *f; f++)
547 if (streq(*f, s))
71ecc858 548 free(*f);
e3e45d4f
SP
549 else
550 *(t++) = *f;
71ecc858
LP
551
552 *t = NULL;
553 return l;
554}
555
21bc923a
LP
556char **strv_parse_nulstr(const char *s, size_t l) {
557 const char *p;
558 unsigned c = 0, i = 0;
559 char **v;
560
561 assert(s || l <= 0);
562
563 if (l <= 0)
49b832c5 564 return new0(char*, 1);
21bc923a
LP
565
566 for (p = s; p < s + l; p++)
567 if (*p == 0)
568 c++;
569
570 if (s[l-1] != 0)
571 c++;
572
1fd8d04e
LP
573 v = new0(char*, c+1);
574 if (!v)
21bc923a
LP
575 return NULL;
576
577 p = s;
578 while (p < s + l) {
579 const char *e;
580
581 e = memchr(p, 0, s + l - p);
582
1fd8d04e
LP
583 v[i] = strndup(p, e ? e - p : s + l - p);
584 if (!v[i]) {
21bc923a
LP
585 strv_free(v);
586 return NULL;
587 }
588
1fd8d04e
LP
589 i++;
590
21bc923a
LP
591 if (!e)
592 break;
593
594 p = e + 1;
595 }
596
597 assert(i == c);
598
599 return v;
600}
0c85a4f3 601
fabe5c0e
LP
602char **strv_split_nulstr(const char *s) {
603 const char *i;
604 char **r = NULL;
605
606 NULSTR_FOREACH(i, s)
607 if (strv_extend(&r, i) < 0) {
608 strv_free(r);
609 return NULL;
610 }
611
612 if (!r)
613 return strv_new(NULL, NULL);
614
615 return r;
616}
617
0c85a4f3 618bool strv_overlap(char **a, char **b) {
e3e45d4f 619 char **i;
0c85a4f3 620
e3e45d4f
SP
621 STRV_FOREACH(i, a)
622 if (strv_contains(b, *i))
623 return true;
0c85a4f3
LP
624
625 return false;
626}
857a493d
LP
627
628static int str_compare(const void *_a, const void *_b) {
629 const char **a = (const char**) _a, **b = (const char**) _b;
630
631 return strcmp(*a, *b);
632}
633
634char **strv_sort(char **l) {
635
636 if (strv_isempty(l))
637 return l;
638
639 qsort(l, strv_length(l), sizeof(char*), str_compare);
640 return l;
641}
7c2d8094 642
0f84a72e
DH
643bool strv_equal(char **a, char **b) {
644 if (!a || !b)
645 return a == b;
646
647 for ( ; *a || *b; ++a, ++b)
648 if (!streq_ptr(*a, *b))
649 return false;
650
651 return true;
652}
653
7c2d8094
TA
654void strv_print(char **l) {
655 char **s;
656
7c2d8094
TA
657 STRV_FOREACH(s, l)
658 puts(*s);
659}
4de33e7f
LP
660
661int strv_extendf(char ***l, const char *format, ...) {
662 va_list ap;
663 char *x;
664 int r;
665
666 va_start(ap, format);
667 r = vasprintf(&x, format, ap);
668 va_end(ap);
669
670 if (r < 0)
671 return -ENOMEM;
672
673 return strv_consume(l, x);
674}
e1dd6790
LP
675
676char **strv_reverse(char **l) {
677 unsigned n, i;
678
679 n = strv_length(l);
680 if (n <= 1)
681 return l;
682
683 for (i = 0; i < n / 2; i++) {
684 char *t;
685
686 t = l[i];
687 l[i] = l[n-1-i];
688 l[n-1-i] = t;
689 }
690
691 return l;
692}
bceccd5e 693
04c14b25
RM
694char **strv_shell_escape(char **l, const char *bad) {
695 char **s;
696
697 /* Escapes every character in every string in l that is in bad,
698 * edits in-place, does not roll-back on error. */
699
700 STRV_FOREACH(s, l) {
701 char *v;
702
703 v = shell_escape(*s, bad);
704 if (!v)
705 return NULL;
706
707 free(*s);
708 *s = v;
709 }
710
711 return l;
712}
713
2404701e 714bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
bceccd5e
ZJS
715 char* const* p;
716
717 STRV_FOREACH(p, patterns)
718 if (fnmatch(*p, s, 0) == 0)
719 return true;
720
721 return false;
722}