chiark / gitweb /
sysusers: fix selinux context of backup files
[elogind.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 * const *l) {
68         char **r, **k;
69
70         k = r = new(char*, strv_length(l) + 1);
71         if (!r)
72                 return NULL;
73
74         if (l)
75                 for (; *l; k++, l++) {
76                         *k = strdup(*l);
77                         if (!*k) {
78                                 strv_free(r);
79                                 return NULL;
80                         }
81                 }
82
83         *k = NULL;
84         return r;
85 }
86
87 unsigned strv_length(char * const *l) {
88         unsigned n = 0;
89
90         if (!l)
91                 return 0;
92
93         for (; *l; l++)
94                 n++;
95
96         return n;
97 }
98
99 char **strv_new_ap(const char *x, va_list ap) {
100         const char *s;
101         char **a;
102         unsigned n = 0, i = 0;
103         va_list aq;
104
105         /* As a special trick we ignore all listed strings that equal
106          * (const char*) -1. This is supposed to be used with the
107          * STRV_IFNOTNULL() macro to include possibly NULL strings in
108          * the string list. */
109
110         if (x) {
111                 n = x == (const char*) -1 ? 0 : 1;
112
113                 va_copy(aq, ap);
114                 while ((s = va_arg(aq, const char*))) {
115                         if (s == (const char*) -1)
116                                 continue;
117
118                         n++;
119                 }
120
121                 va_end(aq);
122         }
123
124         a = new(char*, n+1);
125         if (!a)
126                 return NULL;
127
128         if (x) {
129                 if (x != (const char*) -1) {
130                         a[i] = strdup(x);
131                         if (!a[i])
132                                 goto fail;
133                         i++;
134                 }
135
136                 while ((s = va_arg(ap, const char*))) {
137
138                         if (s == (const char*) -1)
139                                 continue;
140
141                         a[i] = strdup(s);
142                         if (!a[i])
143                                 goto fail;
144
145                         i++;
146                 }
147         }
148
149         a[i] = NULL;
150
151         return a;
152
153 fail:
154         strv_free(a);
155         return NULL;
156 }
157
158 char **strv_new(const char *x, ...) {
159         char **r;
160         va_list ap;
161
162         va_start(ap, x);
163         r = strv_new_ap(x, ap);
164         va_end(ap);
165
166         return r;
167 }
168
169 int strv_extend_strv(char ***a, char **b) {
170         int r;
171         char **s;
172
173         STRV_FOREACH(s, b) {
174                 r = strv_extend(a, *s);
175                 if (r < 0)
176                         return r;
177         }
178
179         return 0;
180 }
181
182 int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
183         int r;
184         char **s;
185
186         STRV_FOREACH(s, b) {
187                 char *v;
188
189                 v = strappend(*s, suffix);
190                 if (!v)
191                         return -ENOMEM;
192
193                 r = strv_push(a, v);
194                 if (r < 0) {
195                         free(v);
196                         return r;
197                 }
198         }
199
200         return 0;
201 }
202
203 char **strv_split(const char *s, const char *separator) {
204         char *state;
205         char *w;
206         size_t l;
207         unsigned n, i;
208         char **r;
209
210         assert(s);
211
212         n = 0;
213         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
214                 n++;
215
216         r = new(char*, n+1);
217         if (!r)
218                 return NULL;
219
220         i = 0;
221         FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
222                 r[i] = strndup(w, l);
223                 if (!r[i]) {
224                         strv_free(r);
225                         return NULL;
226                 }
227
228                 i++;
229         }
230
231         r[i] = NULL;
232         return r;
233 }
234
235 char **strv_split_quoted(const char *s) {
236         char *state;
237         char *w;
238         size_t l;
239         unsigned n, i;
240         char **r;
241
242         assert(s);
243
244         n = 0;
245         FOREACH_WORD_QUOTED(w, l, s, state)
246                 n++;
247
248         r = new(char*, n+1);
249         if (!r)
250                 return NULL;
251
252         i = 0;
253         FOREACH_WORD_QUOTED(w, l, s, state) {
254                 r[i] = cunescape_length(w, l);
255                 if (!r[i]) {
256                         strv_free(r);
257                         return NULL;
258                 }
259                 i++;
260         }
261
262         r[i] = NULL;
263         return r;
264 }
265
266 char **strv_split_newlines(const char *s) {
267         char **l;
268         unsigned n;
269
270         assert(s);
271
272         /* Special version of strv_split() that splits on newlines and
273          * suppresses an empty string at the end */
274
275         l = strv_split(s, NEWLINE);
276         if (!l)
277                 return NULL;
278
279         n = strv_length(l);
280         if (n <= 0)
281                 return l;
282
283         if (isempty(l[n-1])) {
284                 free(l[n-1]);
285                 l[n-1] = NULL;
286         }
287
288         return l;
289 }
290
291 char *strv_join(char **l, const char *separator) {
292         char *r, *e;
293         char **s;
294         size_t n, k;
295
296         if (!separator)
297                 separator = " ";
298
299         k = strlen(separator);
300
301         n = 0;
302         STRV_FOREACH(s, l) {
303                 if (n != 0)
304                         n += k;
305                 n += strlen(*s);
306         }
307
308         r = new(char, n+1);
309         if (!r)
310                 return NULL;
311
312         e = r;
313         STRV_FOREACH(s, l) {
314                 if (e != r)
315                         e = stpcpy(e, separator);
316
317                 e = stpcpy(e, *s);
318         }
319
320         *e = 0;
321
322         return r;
323 }
324
325 char *strv_join_quoted(char **l) {
326         char *buf = NULL;
327         char **s;
328         size_t allocated = 0, len = 0;
329
330         STRV_FOREACH(s, l) {
331                 /* assuming here that escaped string cannot be more
332                  * than twice as long, and reserving space for the
333                  * separator and quotes.
334                  */
335                 _cleanup_free_ char *esc = NULL;
336                 size_t needed;
337
338                 if (!GREEDY_REALLOC(buf, allocated,
339                                     len + strlen(*s) * 2 + 3))
340                         goto oom;
341
342                 esc = cescape(*s);
343                 if (!esc)
344                         goto oom;
345
346                 needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
347                                   len > 0 ? " " : "", esc);
348                 assert(needed < allocated - len);
349                 len += needed;
350         }
351
352         if (!buf)
353                 buf = malloc0(1);
354
355         return buf;
356
357  oom:
358         free(buf);
359         return NULL;
360 }
361
362 int strv_push(char ***l, char *value) {
363         char **c;
364         unsigned n;
365
366         if (!value)
367                 return 0;
368
369         n = strv_length(*l);
370         c = realloc(*l, sizeof(char*) * (n + 2));
371         if (!c)
372                 return -ENOMEM;
373
374         c[n] = value;
375         c[n+1] = NULL;
376
377         *l = c;
378         return 0;
379 }
380
381 int strv_push_prepend(char ***l, char *value) {
382         char **c;
383         unsigned n, i;
384
385         if (!value)
386                 return 0;
387
388         n = strv_length(*l);
389         c = new(char*, n + 2);
390         if (!c)
391                 return -ENOMEM;
392
393         for (i = 0; i < n; i++)
394                 c[i+1] = (*l)[i];
395
396         c[0] = value;
397         c[n+1] = NULL;
398
399         free(*l);
400         *l = c;
401
402         return 0;
403 }
404
405 int strv_consume(char ***l, char *value) {
406         int r;
407
408         r = strv_push(l, value);
409         if (r < 0)
410                 free(value);
411
412         return r;
413 }
414
415 int strv_consume_prepend(char ***l, char *value) {
416         int r;
417
418         r = strv_push_prepend(l, value);
419         if (r < 0)
420                 free(value);
421
422         return r;
423 }
424
425 int strv_extend(char ***l, const char *value) {
426         char *v;
427
428         if (!value)
429                 return 0;
430
431         v = strdup(value);
432         if (!v)
433                 return -ENOMEM;
434
435         return strv_consume(l, v);
436 }
437
438 char **strv_uniq(char **l) {
439         char **i;
440
441         /* Drops duplicate entries. The first identical string will be
442          * kept, the others dropped */
443
444         STRV_FOREACH(i, l)
445                 strv_remove(i+1, *i);
446
447         return l;
448 }
449
450 char **strv_remove(char **l, const char *s) {
451         char **f, **t;
452
453         if (!l)
454                 return NULL;
455
456         assert(s);
457
458         /* Drops every occurrence of s in the string list, edits
459          * in-place. */
460
461         for (f = t = l; *f; f++)
462                 if (streq(*f, s))
463                         free(*f);
464                 else
465                         *(t++) = *f;
466
467         *t = NULL;
468         return l;
469 }
470
471 char **strv_parse_nulstr(const char *s, size_t l) {
472         const char *p;
473         unsigned c = 0, i = 0;
474         char **v;
475
476         assert(s || l <= 0);
477
478         if (l <= 0)
479                 return new0(char*, 1);
480
481         for (p = s; p < s + l; p++)
482                 if (*p == 0)
483                         c++;
484
485         if (s[l-1] != 0)
486                 c++;
487
488         v = new0(char*, c+1);
489         if (!v)
490                 return NULL;
491
492         p = s;
493         while (p < s + l) {
494                 const char *e;
495
496                 e = memchr(p, 0, s + l - p);
497
498                 v[i] = strndup(p, e ? e - p : s + l - p);
499                 if (!v[i]) {
500                         strv_free(v);
501                         return NULL;
502                 }
503
504                 i++;
505
506                 if (!e)
507                         break;
508
509                 p = e + 1;
510         }
511
512         assert(i == c);
513
514         return v;
515 }
516
517 char **strv_split_nulstr(const char *s) {
518         const char *i;
519         char **r = NULL;
520
521         NULSTR_FOREACH(i, s)
522                 if (strv_extend(&r, i) < 0) {
523                         strv_free(r);
524                         return NULL;
525                 }
526
527         if (!r)
528                 return strv_new(NULL, NULL);
529
530         return r;
531 }
532
533 bool strv_overlap(char **a, char **b) {
534         char **i;
535
536         STRV_FOREACH(i, a)
537                 if (strv_contains(b, *i))
538                         return true;
539
540         return false;
541 }
542
543 static int str_compare(const void *_a, const void *_b) {
544         const char **a = (const char**) _a, **b = (const char**) _b;
545
546         return strcmp(*a, *b);
547 }
548
549 char **strv_sort(char **l) {
550
551         if (strv_isempty(l))
552                 return l;
553
554         qsort(l, strv_length(l), sizeof(char*), str_compare);
555         return l;
556 }
557
558 void strv_print(char **l) {
559         char **s;
560
561         STRV_FOREACH(s, l)
562                 puts(*s);
563 }
564
565 int strv_extendf(char ***l, const char *format, ...) {
566         va_list ap;
567         char *x;
568         int r;
569
570         va_start(ap, format);
571         r = vasprintf(&x, format, ap);
572         va_end(ap);
573
574         if (r < 0)
575                 return -ENOMEM;
576
577         return strv_consume(l, x);
578 }