]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/strv.c
relicense to LGPLv2.1 (with exceptions)
[thirdparty/systemd.git] / src / shared / strv.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "util.h"
29 #include "strv.h"
30
31 char *strv_find(char **l, const char *name) {
32 char **i;
33
34 assert(name);
35
36 STRV_FOREACH(i, l)
37 if (streq(*i, name))
38 return *i;
39
40 return NULL;
41 }
42
43 char *strv_find_prefix(char **l, const char *name) {
44 char **i;
45
46 assert(name);
47
48 STRV_FOREACH(i, l)
49 if (startswith(*i, name))
50 return *i;
51
52 return NULL;
53 }
54
55 void strv_free(char **l) {
56 char **k;
57
58 if (!l)
59 return;
60
61 for (k = l; *k; k++)
62 free(*k);
63
64 free(l);
65 }
66
67 char **strv_copy(char **l) {
68 char **r, **k;
69
70 k = r = new(char*, strv_length(l)+1);
71 if (!k)
72 return NULL;
73
74 if (l)
75 for (; *l; k++, l++)
76 if (!(*k = strdup(*l)))
77 goto fail;
78
79 *k = NULL;
80 return r;
81
82 fail:
83 for (k--; k >= r; k--)
84 free(*k);
85
86 free(r);
87
88 return NULL;
89 }
90
91 unsigned strv_length(char **l) {
92 unsigned n = 0;
93
94 if (!l)
95 return 0;
96
97 for (; *l; l++)
98 n++;
99
100 return n;
101 }
102
103 char **strv_new_ap(const char *x, va_list ap) {
104 const char *s;
105 char **a;
106 unsigned n = 0, i = 0;
107 va_list aq;
108
109 if (x) {
110 n = 1;
111
112 va_copy(aq, ap);
113 while (va_arg(aq, const char*))
114 n++;
115 va_end(aq);
116 }
117
118 if (!(a = new(char*, n+1)))
119 return NULL;
120
121 if (x) {
122 if (!(a[i] = strdup(x))) {
123 free(a);
124 return NULL;
125 }
126
127 i++;
128
129 while ((s = va_arg(ap, const char*))) {
130 if (!(a[i] = strdup(s)))
131 goto fail;
132
133 i++;
134 }
135 }
136
137 a[i] = NULL;
138
139 return a;
140
141 fail:
142
143 for (; i > 0; i--)
144 if (a[i-1])
145 free(a[i-1]);
146
147 free(a);
148
149 return NULL;
150 }
151
152 char **strv_new(const char *x, ...) {
153 char **r;
154 va_list ap;
155
156 va_start(ap, x);
157 r = strv_new_ap(x, ap);
158 va_end(ap);
159
160 return r;
161 }
162
163 char **strv_merge(char **a, char **b) {
164 char **r, **k;
165
166 if (!a)
167 return strv_copy(b);
168
169 if (!b)
170 return strv_copy(a);
171
172 if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
173 return NULL;
174
175 for (k = r; *a; k++, a++)
176 if (!(*k = strdup(*a)))
177 goto fail;
178 for (; *b; k++, b++)
179 if (!(*k = strdup(*b)))
180 goto fail;
181
182 *k = NULL;
183 return r;
184
185 fail:
186 for (k--; k >= r; k--)
187 free(*k);
188
189 free(r);
190
191 return NULL;
192 }
193
194 char **strv_merge_concat(char **a, char **b, const char *suffix) {
195 char **r, **k;
196
197 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
198
199 if (!b)
200 return strv_copy(a);
201
202 r = new(char*, strv_length(a) + strv_length(b) + 1);
203 if (!r)
204 return NULL;
205
206 k = r;
207 if (a)
208 for (; *a; k++, a++) {
209 *k = strdup(*a);
210 if (!*k)
211 goto fail;
212 }
213
214 for (; *b; k++, b++) {
215 *k = strappend(*b, suffix);
216 if (!*k)
217 goto fail;
218 }
219
220 *k = NULL;
221 return r;
222
223 fail:
224 for (k--; k >= r; k--)
225 free(*k);
226
227 free(r);
228
229 return NULL;
230
231 }
232
233 char **strv_split(const char *s, const char *separator) {
234 char *state;
235 char *w;
236 size_t l;
237 unsigned n, i;
238 char **r;
239
240 assert(s);
241
242 n = 0;
243 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
244 n++;
245
246 if (!(r = new(char*, n+1)))
247 return NULL;
248
249 i = 0;
250 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
251 if (!(r[i++] = strndup(w, l))) {
252 strv_free(r);
253 return NULL;
254 }
255
256 r[i] = NULL;
257 return r;
258 }
259
260 char **strv_split_quoted(const char *s) {
261 char *state;
262 char *w;
263 size_t l;
264 unsigned n, i;
265 char **r;
266
267 assert(s);
268
269 n = 0;
270 FOREACH_WORD_QUOTED(w, l, s, state)
271 n++;
272
273 if (!(r = new(char*, n+1)))
274 return NULL;
275
276 i = 0;
277 FOREACH_WORD_QUOTED(w, l, s, state)
278 if (!(r[i++] = cunescape_length(w, l))) {
279 strv_free(r);
280 return NULL;
281 }
282
283 r[i] = NULL;
284 return r;
285 }
286
287 char *strv_join(char **l, const char *separator) {
288 char *r, *e;
289 char **s;
290 size_t n, k;
291
292 if (!separator)
293 separator = " ";
294
295 k = strlen(separator);
296
297 n = 0;
298 STRV_FOREACH(s, l) {
299 if (n != 0)
300 n += k;
301 n += strlen(*s);
302 }
303
304 if (!(r = new(char, n+1)))
305 return NULL;
306
307 e = r;
308 STRV_FOREACH(s, l) {
309 if (e != r)
310 e = stpcpy(e, separator);
311
312 e = stpcpy(e, *s);
313 }
314
315 *e = 0;
316
317 return r;
318 }
319
320 char **strv_append(char **l, const char *s) {
321 char **r, **k;
322
323 if (!l)
324 return strv_new(s, NULL);
325
326 if (!s)
327 return strv_copy(l);
328
329 r = new(char*, strv_length(l)+2);
330 if (!r)
331 return NULL;
332
333 for (k = r; *l; k++, l++)
334 if (!(*k = strdup(*l)))
335 goto fail;
336
337 if (!(*(k++) = strdup(s)))
338 goto fail;
339
340 *k = NULL;
341 return r;
342
343 fail:
344 for (k--; k >= r; k--)
345 free(*k);
346
347 free(r);
348
349 return NULL;
350 }
351
352 char **strv_uniq(char **l) {
353 char **i;
354
355 /* Drops duplicate entries. The first identical string will be
356 * kept, the others dropped */
357
358 STRV_FOREACH(i, l)
359 strv_remove(i+1, *i);
360
361 return l;
362 }
363
364 char **strv_remove(char **l, const char *s) {
365 char **f, **t;
366
367 if (!l)
368 return NULL;
369
370 assert(s);
371
372 /* Drops every occurrence of s in the string list, edits
373 * in-place. */
374
375 for (f = t = l; *f; f++) {
376
377 if (streq(*f, s)) {
378 free(*f);
379 continue;
380 }
381
382 *(t++) = *f;
383 }
384
385 *t = NULL;
386 return l;
387 }
388
389 char **strv_remove_prefix(char **l, const char *s) {
390 char **f, **t;
391
392 if (!l)
393 return NULL;
394
395 assert(s);
396
397 /* Drops every occurrence of a string prefixed with s in the
398 * string list, edits in-place. */
399
400 for (f = t = l; *f; f++) {
401
402 if (startswith(*f, s)) {
403 free(*f);
404 continue;
405 }
406
407 *(t++) = *f;
408 }
409
410 *t = NULL;
411 return l;
412 }
413
414 static int env_append(char **r, char ***k, char **a) {
415 assert(r);
416 assert(k);
417
418 if (!a)
419 return 0;
420
421 /* Add the entries of a to *k unless they already exist in *r
422 * in which case they are overridden instead. This assumes
423 * there is enough space in the r array. */
424
425 for (; *a; a++) {
426 char **j;
427 size_t n;
428
429 n = strcspn(*a, "=");
430
431 if ((*a)[n] == '=')
432 n++;
433
434 for (j = r; j < *k; j++)
435 if (strncmp(*j, *a, n) == 0)
436 break;
437
438 if (j >= *k)
439 (*k)++;
440 else
441 free(*j);
442
443 if (!(*j = strdup(*a)))
444 return -ENOMEM;
445 }
446
447 return 0;
448 }
449
450 char **strv_env_merge(unsigned n_lists, ...) {
451 size_t n = 0;
452 char **l, **k, **r;
453 va_list ap;
454 unsigned i;
455
456 /* Merges an arbitrary number of environment sets */
457
458 va_start(ap, n_lists);
459 for (i = 0; i < n_lists; i++) {
460 l = va_arg(ap, char**);
461 n += strv_length(l);
462 }
463 va_end(ap);
464
465 if (!(r = new(char*, n+1)))
466 return NULL;
467
468 k = r;
469
470 va_start(ap, n_lists);
471 for (i = 0; i < n_lists; i++) {
472 l = va_arg(ap, char**);
473 if (env_append(r, &k, l) < 0)
474 goto fail;
475 }
476 va_end(ap);
477
478 *k = NULL;
479
480 return r;
481
482 fail:
483 va_end(ap);
484
485 for (k--; k >= r; k--)
486 free(*k);
487
488 free(r);
489
490 return NULL;
491 }
492
493 static bool env_match(const char *t, const char *pattern) {
494 assert(t);
495 assert(pattern);
496
497 /* pattern a matches string a
498 * a matches a=
499 * a matches a=b
500 * a= matches a=
501 * a=b matches a=b
502 * a= does not match a
503 * a=b does not match a=
504 * a=b does not match a
505 * a=b does not match a=c */
506
507 if (streq(t, pattern))
508 return true;
509
510 if (!strchr(pattern, '=')) {
511 size_t l = strlen(pattern);
512
513 return strncmp(t, pattern, l) == 0 && t[l] == '=';
514 }
515
516 return false;
517 }
518
519 char **strv_env_delete(char **x, unsigned n_lists, ...) {
520 size_t n, i = 0;
521 char **k, **r;
522 va_list ap;
523
524 /* Deletes every entry from x that is mentioned in the other
525 * string lists */
526
527 n = strv_length(x);
528
529 r = new(char*, n+1);
530 if (!r)
531 return NULL;
532
533 STRV_FOREACH(k, x) {
534 unsigned v;
535
536 va_start(ap, n_lists);
537 for (v = 0; v < n_lists; v++) {
538 char **l, **j;
539
540 l = va_arg(ap, char**);
541 STRV_FOREACH(j, l)
542 if (env_match(*k, *j))
543 goto skip;
544 }
545 va_end(ap);
546
547 r[i] = strdup(*k);
548 if (!r[i]) {
549 strv_free(r);
550 return NULL;
551 }
552
553 i++;
554 continue;
555
556 skip:
557 va_end(ap);
558 }
559
560 r[i] = NULL;
561
562 assert(i <= n);
563
564 return r;
565 }
566
567 char **strv_env_unset(char **l, const char *p) {
568
569 char **f, **t;
570
571 if (!l)
572 return NULL;
573
574 assert(p);
575
576 /* Drops every occurrence of the env var setting p in the
577 * string list. edits in-place. */
578
579 for (f = t = l; *f; f++) {
580
581 if (env_match(*f, p)) {
582 free(*f);
583 continue;
584 }
585
586 *(t++) = *f;
587 }
588
589 *t = NULL;
590 return l;
591 }
592
593 char **strv_env_set(char **x, const char *p) {
594
595 char **k, **r;
596 char* m[2] = { (char*) p, NULL };
597
598 /* Overrides the env var setting of p, returns a new copy */
599
600 if (!(r = new(char*, strv_length(x)+2)))
601 return NULL;
602
603 k = r;
604 if (env_append(r, &k, x) < 0)
605 goto fail;
606
607 if (env_append(r, &k, m) < 0)
608 goto fail;
609
610 *k = NULL;
611
612 return r;
613
614 fail:
615 for (k--; k >= r; k--)
616 free(*k);
617
618 free(r);
619
620 return NULL;
621
622 }
623
624 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
625 char **i;
626
627 assert(name);
628
629 STRV_FOREACH(i, l)
630 if (strncmp(*i, name, k) == 0 &&
631 (*i)[k] == '=')
632 return *i + k + 1;
633
634 return NULL;
635 }
636
637 char *strv_env_get(char **l, const char *name) {
638 return strv_env_get_with_length(l, name, strlen(name));
639 }
640
641 char **strv_env_clean(char **l) {
642 char **r, **ret;
643
644 for (r = ret = l; *l; l++) {
645 const char *equal;
646
647 equal = strchr(*l, '=');
648
649 if (equal && equal[1] == 0) {
650 free(*l);
651 continue;
652 }
653
654 *(r++) = *l;
655 }
656
657 *r = NULL;
658
659 return ret;
660 }
661
662 char **strv_parse_nulstr(const char *s, size_t l) {
663 const char *p;
664 unsigned c = 0, i = 0;
665 char **v;
666
667 assert(s || l <= 0);
668
669 if (l <= 0)
670 return strv_new(NULL, NULL);
671
672 for (p = s; p < s + l; p++)
673 if (*p == 0)
674 c++;
675
676 if (s[l-1] != 0)
677 c++;
678
679 if (!(v = new0(char*, c+1)))
680 return NULL;
681
682 p = s;
683 while (p < s + l) {
684 const char *e;
685
686 e = memchr(p, 0, s + l - p);
687
688 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
689 strv_free(v);
690 return NULL;
691 }
692
693 if (!e)
694 break;
695
696 p = e + 1;
697 }
698
699 assert(i == c);
700
701 return v;
702 }
703
704 bool strv_overlap(char **a, char **b) {
705 char **i, **j;
706
707 STRV_FOREACH(i, a) {
708 STRV_FOREACH(j, b) {
709 if (streq(*i, *j))
710 return true;
711 }
712 }
713
714 return false;
715 }