]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/tools/tool_utils.c
secure coding: #2 strcpy => strlcpy
[mirror_lxc.git] / src / lxc / tools / tool_utils.c
CommitLineData
9267beba
CB
1/* liblxcapi
2 *
3 * Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2018 Canonical Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
8d313ae1 20#define _GNU_SOURCE
9267beba 21#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
8d313ae1 22#include <ctype.h>
4b7c0ef8 23#include <dirent.h>
9267beba 24#include <errno.h>
23500ef5 25#include <fcntl.h>
9267beba 26#include <limits.h>
23500ef5 27#include <sched.h>
9267beba
CB
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <strings.h>
32#include <unistd.h>
33#include <linux/sched.h>
d567a9a7 34#include <sys/mount.h>
9267beba 35#include <sys/prctl.h>
0cb3e3a6 36#include <sys/stat.h>
9267beba
CB
37#include <sys/types.h>
38#include <sys/wait.h>
39
2e607d1c
KY
40#include "config.h"
41
9267beba
CB
42#if HAVE_SYS_PERSONALITY_H
43#include <sys/personality.h>
44#endif
45
46#include <lxc/lxccontainer.h>
47
d567a9a7 48#include "arguments.h"
9267beba
CB
49#include "tool_utils.h"
50
43f984ea
DJ
51#ifndef HAVE_STRLCPY
52#include "include/strlcpy.h"
53#endif
54
9267beba
CB
55int lxc_fill_elevated_privileges(char *flaglist, int *flags)
56{
57 char *token, *saveptr = NULL;
58 int i, aflag;
59 struct {
60 const char *token;
61 int flag;
62 } all_privs[] = {
63 { "CGROUP", LXC_ATTACH_MOVE_TO_CGROUP },
64 { "CAP", LXC_ATTACH_DROP_CAPABILITIES },
65 { "LSM", LXC_ATTACH_LSM_EXEC },
66 { NULL, 0 }
67 };
68
69 if (!flaglist) {
70 /* For the sake of backward compatibility, drop all privileges
71 * if none is specified.
72 */
73 for (i = 0; all_privs[i].token; i++)
74 *flags |= all_privs[i].flag;
75
76 return 0;
77 }
78
79 token = strtok_r(flaglist, "|", &saveptr);
80 while (token) {
81 aflag = -1;
82 for (i = 0; all_privs[i].token; i++)
83 if (!strcmp(all_privs[i].token, token))
84 aflag = all_privs[i].flag;
85 if (aflag < 0)
86 return -1;
87
88 *flags |= aflag;
89
90 token = strtok_r(NULL, "|", &saveptr);
91 }
92
93 return 0;
94}
95
96signed long lxc_config_parse_arch(const char *arch)
97{
98#if HAVE_SYS_PERSONALITY_H
99 size_t i;
100 struct per_name {
101 char *name;
102 unsigned long per;
103 } pername[] = {
104 { "x86", PER_LINUX32 },
105 { "linux32", PER_LINUX32 },
106 { "i386", PER_LINUX32 },
107 { "i486", PER_LINUX32 },
108 { "i586", PER_LINUX32 },
109 { "i686", PER_LINUX32 },
110 { "athlon", PER_LINUX32 },
111 { "mips", PER_LINUX32 },
112 { "mipsel", PER_LINUX32 },
113 { "ppc", PER_LINUX32 },
114 { "arm", PER_LINUX32 },
115 { "armv7l", PER_LINUX32 },
116 { "armhf", PER_LINUX32 },
117 { "armel", PER_LINUX32 },
118 { "powerpc", PER_LINUX32 },
119 { "linux64", PER_LINUX },
120 { "x86_64", PER_LINUX },
121 { "amd64", PER_LINUX },
122 { "mips64", PER_LINUX },
123 { "mips64el", PER_LINUX },
124 { "ppc64", PER_LINUX },
125 { "ppc64le", PER_LINUX },
126 { "ppc64el", PER_LINUX },
127 { "powerpc64", PER_LINUX },
128 { "s390x", PER_LINUX },
129 { "aarch64", PER_LINUX },
130 { "arm64", PER_LINUX },
131 };
132 size_t len = sizeof(pername) / sizeof(pername[0]);
133
134 for (i = 0; i < len; i++) {
135 if (!strcmp(pername[i].name, arch))
136 return pername[i].per;
137 }
138#endif
139
140 return -1;
141}
142
9267beba
CB
143const static struct ns_info {
144 const char *proc_name;
145 int clone_flag;
146} ns_info[LXC_NS_MAX] = {
147 [LXC_NS_USER] = { "user", CLONE_NEWUSER },
148 [LXC_NS_MNT] = { "mnt", CLONE_NEWNS },
149 [LXC_NS_PID] = { "pid", CLONE_NEWPID },
150 [LXC_NS_UTS] = { "uts", CLONE_NEWUTS },
151 [LXC_NS_IPC] = { "ipc", CLONE_NEWIPC },
152 [LXC_NS_NET] = { "net", CLONE_NEWNET },
153 [LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP }
154};
155
156int lxc_namespace_2_cloneflag(const char *namespace)
157{
158 int i;
159 for (i = 0; i < LXC_NS_MAX; i++)
160 if (!strcasecmp(ns_info[i].proc_name, namespace))
161 return ns_info[i].clone_flag;
162
163 fprintf(stderr, "Invalid namespace name \"%s\"", namespace);
164 return -EINVAL;
165}
166
167int lxc_fill_namespace_flags(char *flaglist, int *flags)
168{
169 char *token, *saveptr = NULL;
170 int aflag;
171
172 if (!flaglist) {
173 fprintf(stderr, "At least one namespace is needed\n");
174 return -1;
175 }
176
177 token = strtok_r(flaglist, "|", &saveptr);
178 while (token) {
179
180 aflag = lxc_namespace_2_cloneflag(token);
181 if (aflag < 0)
182 return -1;
183
184 *flags |= aflag;
185
186 token = strtok_r(NULL, "|", &saveptr);
187 }
188
189 return 0;
190}
191
192#if HAVE_LIBCAP
193
194#ifndef PR_CAPBSET_READ
195#define PR_CAPBSET_READ 23
196#endif
197
198int lxc_caps_init(void)
199{
200 uid_t uid = getuid();
201 gid_t gid = getgid();
202 uid_t euid = geteuid();
203
204 if (!uid)
205 return 0;
206
207 if (uid && !euid) {
208 if (prctl(PR_SET_KEEPCAPS, 1)) {
209 fprintf(stderr, "%s - Failed to set PR_SET_KEEPCAPS\n", strerror(errno));
210 return -1;
211 }
212
213 if (setresgid(gid, gid, gid)) {
214 fprintf(stderr, "%s - Failed to change gid to %d\n", strerror(errno), gid);
215 return -1;
216 }
217
218 if (setresuid(uid, uid, uid)) {
219 fprintf(stderr, "%s - Failed to change uid to %d\n", strerror(errno), uid);
220 return -1;
221 }
222
223 if (lxc_caps_up()) {
224 fprintf(stderr, "%s - Failed to restore capabilities\n", strerror(errno));
225 return -1;
226 }
227 }
228
229 return 0;
230}
231
232int lxc_caps_up(void)
233{
234 cap_t caps;
235 cap_value_t cap;
236 int ret;
237
238 /* when we are run as root, we don't want to play
239 * with the capabilities */
240 if (!getuid())
241 return 0;
242
243 caps = cap_get_proc();
244 if (!caps) {
245 fprintf(stderr, "%s - Failed to cap_get_proc\n", strerror(errno));
246 return -1;
247 }
248
249 for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
250 cap_flag_value_t flag;
251
252 ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
253 if (ret) {
254 if (errno == EINVAL) {
255 break;
256 } else {
257 fprintf(stderr, "%s- Failed to call cap_get_flag\n", strerror(errno));
258 goto out;
259 }
260 }
261
262 ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
263 if (ret) {
264 fprintf(stderr, "%s - Failed to call cap_set_flag", strerror(errno));
265 goto out;
266 }
267 }
268
269 ret = cap_set_proc(caps);
270 if (ret) {
271 fprintf(stderr, "%s - Failed to cap_set_proc", strerror(errno));
272 goto out;
273 }
274
275out:
276 cap_free(caps);
277 return 0;
278}
279
280#endif
281
78485176
CB
282int wait_for_pid(pid_t pid)
283{
284 int status, ret;
285
286again:
287 ret = waitpid(pid, &status, 0);
288 if (ret == -1) {
289 if (errno == EINTR)
290 goto again;
291 return -1;
292 }
293 if (ret != pid)
294 goto again;
295 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
296 return -1;
297 return 0;
298}
299
9267beba
CB
300int lxc_wait_for_pid_status(pid_t pid)
301{
302 int status, ret;
303
304again:
305 ret = waitpid(pid, &status, 0);
306 if (ret == -1) {
307 if (errno == EINTR)
308 goto again;
309 return -1;
310 }
311 if (ret != pid)
312 goto again;
313 return status;
314}
315
8d313ae1
CB
316int lxc_safe_uint(const char *numstr, unsigned int *converted)
317{
318 char *err = NULL;
319 unsigned long int uli;
320
321 while (isspace(*numstr))
322 numstr++;
323
324 if (*numstr == '-')
325 return -EINVAL;
326
327 errno = 0;
328 uli = strtoul(numstr, &err, 0);
329 if (errno == ERANGE && uli == ULONG_MAX)
330 return -ERANGE;
331
332 if (err == numstr || *err != '\0')
333 return -EINVAL;
334
335 if (uli > UINT_MAX)
336 return -ERANGE;
337
338 *converted = (unsigned int)uli;
339 return 0;
340}
341
9267beba
CB
342int lxc_safe_int(const char *numstr, int *converted)
343{
344 char *err = NULL;
345 signed long int sli;
346
347 errno = 0;
348 sli = strtol(numstr, &err, 0);
349 if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
350 return -ERANGE;
351
352 if (errno != 0 && sli == 0)
353 return -EINVAL;
354
355 if (err == numstr || *err != '\0')
356 return -EINVAL;
357
358 if (sli > INT_MAX || sli < INT_MIN)
359 return -ERANGE;
360
361 *converted = (int)sli;
362 return 0;
363}
364
365int lxc_safe_long(const char *numstr, long int *converted)
366{
367 char *err = NULL;
368 signed long int sli;
369
370 errno = 0;
371 sli = strtol(numstr, &err, 0);
372 if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
373 return -ERANGE;
374
375 if (errno != 0 && sli == 0)
376 return -EINVAL;
377
378 if (err == numstr || *err != '\0')
379 return -EINVAL;
380
381 *converted = sli;
382 return 0;
383}
0cb3e3a6
CB
384
385void lxc_free_array(void **array, lxc_free_fn element_free_fn)
386{
387 void **p;
388 for (p = array; p && *p; p++)
389 element_free_fn(*p);
390 free((void*)array);
391}
392
393int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment)
394{
395 size_t new_capacity;
396 void **new_array;
397
398 /* first time around, catch some trivial mistakes of the user
399 * only initializing one of these */
400 if (!*array || !*capacity) {
401 *array = NULL;
402 *capacity = 0;
403 }
404
405 new_capacity = *capacity;
406 while (new_size + 1 > new_capacity)
407 new_capacity += capacity_increment;
408 if (new_capacity != *capacity) {
409 /* we have to reallocate */
410 new_array = realloc(*array, new_capacity * sizeof(void *));
411 if (!new_array)
412 return -1;
413 memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *));
414 *array = new_array;
415 *capacity = new_capacity;
416 }
417
418 /* array has sufficient elements */
419 return 0;
420}
421
422char **lxc_string_split(const char *string, char _sep)
423{
424 char *token, *str, *saveptr = NULL;
425 char sep[2] = {_sep, '\0'};
426 char **tmp = NULL, **result = NULL;
427 size_t result_capacity = 0;
428 size_t result_count = 0;
43f984ea 429 size_t len;
0cb3e3a6
CB
430 int r, saved_errno;
431
432 if (!string)
433 return calloc(1, sizeof(char *));
434
43f984ea
DJ
435 len = strlen(string);
436 str = alloca(len + 1);
437 (void)strlcpy(str, string, len + 1);
438
0cb3e3a6
CB
439 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
440 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
441 if (r < 0)
442 goto error_out;
443 result[result_count] = strdup(token);
444 if (!result[result_count])
445 goto error_out;
446 result_count++;
447 }
448
449 /* if we allocated too much, reduce it */
450 tmp = realloc(result, (result_count + 1) * sizeof(char *));
451 if (!tmp)
452 goto error_out;
453 result = tmp;
454 /* Make sure we don't return uninitialized memory. */
455 if (result_count == 0)
456 *result = NULL;
457 return result;
458error_out:
459 saved_errno = errno;
460 lxc_free_array((void **)result, free);
461 errno = saved_errno;
462 return NULL;
463}
464
465char **lxc_normalize_path(const char *path)
466{
467 char **components;
468 char **p;
469 size_t components_len = 0;
470 size_t pos = 0;
471
472 components = lxc_string_split(path, '/');
473 if (!components)
474 return NULL;
475 for (p = components; *p; p++)
476 components_len++;
477
478 /* resolve '.' and '..' */
479 for (pos = 0; pos < components_len; ) {
480 if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) {
481 /* eat this element */
482 free(components[pos]);
483 memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos));
484 components_len--;
485 } else if (!strcmp(components[pos], "..")) {
486 /* eat this and the previous element */
487 free(components[pos - 1]);
488 free(components[pos]);
489 memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos));
490 components_len -= 2;
491 pos--;
492 } else {
493 pos++;
494 }
495 }
496
497 return components;
498}
499
500char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
501{
502 char *result;
503 char **p;
504 size_t sep_len = strlen(sep);
505 size_t result_len = use_as_prefix * sep_len;
506
507 /* calculate new string length */
508 for (p = (char **)parts; *p; p++)
509 result_len += (p > (char **)parts) * sep_len + strlen(*p);
510
511 result = calloc(result_len + 1, 1);
512 if (!result)
513 return NULL;
514
515 if (use_as_prefix)
43f984ea
DJ
516 (void)strlcpy(result, sep, result_len + 1);
517
0cb3e3a6
CB
518 for (p = (char **)parts; *p; p++) {
519 if (p > (char **)parts)
520 strcat(result, sep);
521 strcat(result, *p);
522 }
523
524 return result;
525}
526
527int is_dir(const char *path)
528{
529 struct stat statbuf;
530 int ret = stat(path, &statbuf);
531 if (ret == 0 && S_ISDIR(statbuf.st_mode))
532 return 1;
533 return 0;
534}
535
536size_t lxc_array_len(void **array)
537{
538 void **p;
539 size_t result = 0;
540
541 for (p = array; p && *p; p++)
542 result++;
543
544 return result;
545}
e6294545
CB
546
547/*
548 * Given the '-t' template option to lxc-create, figure out what to
549 * do. If the template is a full executable path, use that. If it
550 * is something like 'sshd', then return $templatepath/lxc-sshd.
551 * On success return the template, on error return NULL.
552 */
553char *get_template_path(const char *t)
554{
555 int ret, len;
556 char *tpath;
557
558 if (t[0] == '/' && access(t, X_OK) == 0) {
559 tpath = strdup(t);
560 return tpath;
561 }
562
563 len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
564 tpath = malloc(len);
565 if (!tpath)
566 return NULL;
567 ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
568 if (ret < 0 || ret >= len) {
569 free(tpath);
570 return NULL;
571 }
572 if (access(tpath, X_OK) < 0) {
573 fprintf(stderr, "Bad template: %s\n", t);
574 free(tpath);
575 return NULL;
576 }
577
578 return tpath;
579}
580
581int mkdir_p(const char *dir, mode_t mode)
582{
583 const char *tmp = dir;
584 const char *orig = dir;
585 char *makeme;
586
587 do {
588 dir = tmp + strspn(tmp, "/");
589 tmp = dir + strcspn(dir, "/");
590 makeme = strndup(orig, dir - orig);
591 if (*makeme) {
592 if (mkdir(makeme, mode) && errno != EEXIST) {
593 fprintf(stderr, "Failed to create directory \"%s\"\n", makeme);
594 free(makeme);
595 return -1;
596 }
597 }
598 free(makeme);
599 } while(tmp != dir);
600
601 return 0;
602}
e3347eef
CB
603
604bool file_exists(const char *f)
605{
606 struct stat statbuf;
607
608 return stat(f, &statbuf) == 0;
609}
23500ef5
CB
610
611bool switch_to_ns(pid_t pid, const char *ns) {
612 int fd, ret;
613 char nspath[TOOL_MAXPATHLEN];
614
615 /* Switch to new ns */
616 ret = snprintf(nspath, TOOL_MAXPATHLEN, "/proc/%d/ns/%s", pid, ns);
617 if (ret < 0 || ret >= TOOL_MAXPATHLEN)
618 return false;
619
620 fd = open(nspath, O_RDONLY);
621 if (fd < 0) {
622 fprintf(stderr, "Failed to open %s\n", nspath);
623 return false;
624 }
625
626 ret = setns(fd, 0);
627 if (ret) {
628 fprintf(stderr, "Failed to set process %d to %s of %d\n", pid, ns, fd);
629 close(fd);
630 return false;
631 }
632 close(fd);
633 return true;
634}
791e7a73
CB
635
636static bool complete_word(char ***result, char *start, char *end, size_t *cap, size_t *cnt)
637{
638 int r;
639
640 r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16);
641 if (r < 0)
642 return false;
643 (*result)[*cnt] = strndup(start, end - start);
644 if (!(*result)[*cnt])
645 return false;
646 (*cnt)++;
647
648 return true;
649}
650
651/*
652 * Given a a string 'one two "three four"', split into three words,
653 * one, two, and "three four"
654 */
655char **lxc_string_split_quoted(char *string)
656{
657 char *nextword = string, *p, state;
658 char **result = NULL;
659 size_t result_capacity = 0;
660 size_t result_count = 0;
661
662 if (!string || !*string)
663 return calloc(1, sizeof(char *));
664
665 // TODO I'm *not* handling escaped quote
666 state = ' ';
667 for (p = string; *p; p++) {
668 switch(state) {
669 case ' ':
670 if (isspace(*p))
671 continue;
672 else if (*p == '"' || *p == '\'') {
673 nextword = p;
674 state = *p;
675 continue;
676 }
677 nextword = p;
678 state = 'a';
679 continue;
680 case 'a':
681 if (isspace(*p)) {
682 complete_word(&result, nextword, p, &result_capacity, &result_count);
683 state = ' ';
684 continue;
685 }
686 continue;
687 case '"':
688 case '\'':
689 if (*p == state) {
690 complete_word(&result, nextword+1, p, &result_capacity, &result_count);
691 state = ' ';
692 continue;
693 }
694 continue;
695 }
696 }
697
698 if (state == 'a')
699 complete_word(&result, nextword, p, &result_capacity, &result_count);
700
701 return realloc(result, (result_count + 1) * sizeof(char *));
702}
703
704int lxc_char_left_gc(const char *buffer, size_t len)
705{
706 size_t i;
707 for (i = 0; i < len; i++) {
708 if (buffer[i] == ' ' ||
709 buffer[i] == '\t')
710 continue;
711 return i;
712 }
713 return 0;
714}
715
716int lxc_char_right_gc(const char *buffer, size_t len)
717{
718 int i;
719 for (i = len - 1; i >= 0; i--) {
720 if (buffer[i] == ' ' ||
721 buffer[i] == '\t' ||
722 buffer[i] == '\n' ||
723 buffer[i] == '\0')
724 continue;
725 return i + 1;
726 }
727 return 0;
728}
729
730struct new_config_item *parse_line(char *buffer)
731{
732 char *dot, *key, *line, *linep, *value;
733 int ret = 0;
734 char *dup = buffer;
735 struct new_config_item *new = NULL;
736
737 linep = line = strdup(dup);
738 if (!line)
739 return NULL;
740
741 line += lxc_char_left_gc(line, strlen(line));
742
743 /* martian option - don't add it to the config itself */
744 if (strncmp(line, "lxc.", 4))
745 goto on_error;
746
747 ret = -1;
748 dot = strchr(line, '=');
749 if (!dot) {
750 fprintf(stderr, "Invalid configuration item: %s\n", line);
751 goto on_error;
752 }
753
754 *dot = '\0';
755 value = dot + 1;
756
757 key = line;
758 key[lxc_char_right_gc(key, strlen(key))] = '\0';
759
760 value += lxc_char_left_gc(value, strlen(value));
761 value[lxc_char_right_gc(value, strlen(value))] = '\0';
762
763 if (*value == '\'' || *value == '\"') {
764 size_t len;
765
766 len = strlen(value);
767 if (len > 1 && value[len - 1] == *value) {
768 value[len - 1] = '\0';
769 value++;
770 }
771 }
772
773 ret = -1;
774 new = malloc(sizeof(struct new_config_item));
775 if (!new)
776 goto on_error;
777
778 new->key = strdup(key);
779 new->val = strdup(value);
780 if (!new->val || !new->key)
781 goto on_error;
782 ret = 0;
783
784on_error:
785 free(linep);
786 if (ret < 0 && new) {
787 free(new->key);
788 free(new->val);
789 free(new);
790 new = NULL;
791 }
792
793 return new;
794}
795
796int lxc_config_define_add(struct lxc_list *defines, char *arg)
797{
798 struct lxc_list *dent;
799
800 dent = malloc(sizeof(struct lxc_list));
801 if (!dent)
802 return -1;
803
804 dent->elem = parse_line(arg);
74269047
C
805 if (!dent->elem) {
806 free(dent);
791e7a73 807 return -1;
74269047
C
808 }
809
791e7a73
CB
810 lxc_list_add_tail(defines, dent);
811 return 0;
812}
813
e2eae703 814bool lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c)
791e7a73
CB
815{
816 struct lxc_list *it;
e2eae703 817 bool bret = true;
791e7a73
CB
818
819 lxc_list_for_each(it, defines) {
820 struct new_config_item *new_item = it->elem;
e2eae703
FA
821 bret = c->set_config_item(c, new_item->key, new_item->val);
822 if (!bret)
791e7a73
CB
823 break;
824 }
825
826 lxc_config_define_free(defines);
e2eae703 827 return bret;
791e7a73
CB
828}
829
830void lxc_config_define_free(struct lxc_list *defines)
831{
832 struct lxc_list *it, *next;
833
834 lxc_list_for_each_safe(it, defines, next) {
835 struct new_config_item *new_item = it->elem;
836 free(new_item->key);
837 free(new_item->val);
838 lxc_list_del(it);
839 free(it);
840 }
841}
8765242a
CB
842
843int lxc_read_from_file(const char *filename, void* buf, size_t count)
844{
845 int fd = -1, saved_errno;
846 ssize_t ret;
847
848 fd = open(filename, O_RDONLY | O_CLOEXEC);
849 if (fd < 0)
850 return -1;
851
852 if (!buf || !count) {
853 char buf2[100];
854 size_t count2 = 0;
855 while ((ret = read(fd, buf2, 100)) > 0)
856 count2 += ret;
857 if (ret >= 0)
858 ret = count2;
859 } else {
860 memset(buf, 0, count);
861 ret = read(fd, buf, count);
862 }
863
864 saved_errno = errno;
865 close(fd);
866 errno = saved_errno;
867 return ret;
868}
4b7c0ef8
CB
869
870char **lxc_string_split_and_trim(const char *string, char _sep)
871{
872 char *token, *str, *saveptr = NULL;
873 char sep[2] = { _sep, '\0' };
874 char **result = NULL;
875 size_t result_capacity = 0;
876 size_t result_count = 0;
877 int r, saved_errno;
878 size_t i = 0;
43f984ea 879 size_t len;
4b7c0ef8
CB
880
881 if (!string)
882 return calloc(1, sizeof(char *));
883
43f984ea
DJ
884 len = strlen(string);
885 str = alloca(len + 1);
886 (void)strlcpy(str, string, len + 1);
887
4b7c0ef8
CB
888 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
889 while (token[0] == ' ' || token[0] == '\t')
890 token++;
891 i = strlen(token);
892 while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
893 token[i - 1] = '\0';
894 i--;
895 }
896 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
897 if (r < 0)
898 goto error_out;
899 result[result_count] = strdup(token);
900 if (!result[result_count])
901 goto error_out;
902 result_count++;
903 }
904
905 /* if we allocated too much, reduce it */
906 return realloc(result, (result_count + 1) * sizeof(char *));
907error_out:
908 saved_errno = errno;
909 lxc_free_array((void **)result, free);
910 errno = saved_errno;
911 return NULL;
912}
913
914char *lxc_append_paths(const char *first, const char *second)
915{
916 int ret;
917 size_t len;
918 char *result = NULL;
919 const char *pattern = "%s%s";
920
921 len = strlen(first) + strlen(second) + 1;
922 if (second[0] != '/') {
923 len += 1;
924 pattern = "%s/%s";
925 }
926
927 result = calloc(1, len);
928 if (!result)
929 return NULL;
930
931 ret = snprintf(result, len, pattern, first, second);
932 if (ret < 0 || (size_t)ret >= len) {
933 free(result);
934 return NULL;
935 }
936
937 return result;
938}
939
940bool dir_exists(const char *path)
941{
942 struct stat sb;
943 int ret;
944
945 ret = stat(path, &sb);
946 if (ret < 0)
947 /* Could be something other than eexist, just say "no". */
948 return false;
949 return S_ISDIR(sb.st_mode);
950}
951
952char *lxc_string_replace(const char *needle, const char *replacement,
953 const char *haystack)
954{
955 ssize_t len = -1, saved_len = -1;
956 char *result = NULL;
957 size_t replacement_len = strlen(replacement);
958 size_t needle_len = strlen(needle);
959
960 /* should be executed exactly twice */
961 while (len == -1 || result == NULL) {
962 char *p;
963 char *last_p;
964 ssize_t part_len;
965
966 if (len != -1) {
967 result = calloc(1, len + 1);
968 if (!result)
969 return NULL;
970 saved_len = len;
971 }
972
973 len = 0;
974
975 for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) {
976 part_len = (ssize_t)(p - last_p);
977 if (result && part_len > 0)
978 memcpy(&result[len], last_p, part_len);
979 len += part_len;
980 if (result && replacement_len > 0)
981 memcpy(&result[len], replacement, replacement_len);
982 len += replacement_len;
983 p += needle_len;
984 }
985 part_len = strlen(last_p);
986 if (result && part_len > 0)
987 memcpy(&result[len], last_p, part_len);
988 len += part_len;
989 }
990
991 /* make sure we did the same thing twice,
992 * once for calculating length, the other
993 * time for copying data */
994 if (saved_len != len) {
995 free(result);
996 return NULL;
997 }
998 /* make sure we didn't overwrite any buffer,
999 * due to calloc the string should be 0-terminated */
1000 if (result[len] != '\0') {
1001 free(result);
1002 return NULL;
1003 }
1004
1005 return result;
1006}
1007
1008ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
1009{
1010 ssize_t ret;
1011again:
1012 ret = write(fd, buf, count);
1013 if (ret < 0 && errno == EINTR)
1014 goto again;
1015 return ret;
1016}
1017
1018char *get_rundir()
1019{
1020 char *rundir;
1021 const char *homedir;
1022
1023 if (geteuid() == 0) {
1024 rundir = strdup(RUNTIME_PATH);
1025 return rundir;
1026 }
1027
1028 rundir = getenv("XDG_RUNTIME_DIR");
1029 if (rundir) {
1030 rundir = strdup(rundir);
1031 return rundir;
1032 }
1033
1034 homedir = getenv("HOME");
1035 if (!homedir)
1036 return NULL;
1037
1038 rundir = malloc(sizeof(char) * (17 + strlen(homedir)));
1039 sprintf(rundir, "%s/.cache/lxc/run/", homedir);
1040
1041 return rundir;
1042}
1043
1044char *must_copy_string(const char *entry)
1045{
1046 char *ret;
1047
1048 if (!entry)
1049 return NULL;
1050 do {
1051 ret = strdup(entry);
1052 } while (!ret);
1053
1054 return ret;
1055}
1056
1057
1058void *must_realloc(void *orig, size_t sz)
1059{
1060 void *ret;
1061
1062 do {
1063 ret = realloc(orig, sz);
1064 } while (!ret);
1065
1066 return ret;
1067}
1068
1069char *must_make_path(const char *first, ...)
1070{
1071 va_list args;
1072 char *cur, *dest;
1073 size_t full_len = strlen(first);
1074
1075 dest = must_copy_string(first);
1076
1077 va_start(args, first);
1078 while ((cur = va_arg(args, char *)) != NULL) {
1079 full_len += strlen(cur);
1080 if (cur[0] != '/')
1081 full_len++;
1082 dest = must_realloc(dest, full_len + 1);
1083 if (cur[0] != '/')
1084 strcat(dest, "/");
1085 strcat(dest, cur);
1086 }
1087 va_end(args);
1088
1089 return dest;
1090}
1091
1092int rm_r(char *dirname)
1093{
1094 int ret;
1095 struct dirent *direntp;
1096 DIR *dir;
1097 int r = 0;
1098
1099 dir = opendir(dirname);
1100 if (!dir)
1101 return -1;
1102
1103 while ((direntp = readdir(dir))) {
1104 char *pathname;
1105 struct stat mystat;
1106
4b7c0ef8
CB
1107 if (!strcmp(direntp->d_name, ".") ||
1108 !strcmp(direntp->d_name, ".."))
1109 continue;
1110
1111 pathname = must_make_path(dirname, direntp->d_name, NULL);
1112
1113 ret = lstat(pathname, &mystat);
1114 if (ret < 0) {
1115 r = -1;
1116 goto next;
1117 }
1118
1119 if (!S_ISDIR(mystat.st_mode))
1120 goto next;
1121
1122 ret = rm_r(pathname);
1123 if (ret < 0)
1124 r = -1;
1125 next:
1126 free(pathname);
1127 }
1128
1129 ret = rmdir(dirname);
1130 if (ret < 0)
1131 r = -1;
1132
1133 ret = closedir(dir);
1134 if (ret < 0)
1135 r = -1;
1136
1137 return r;
1138}
1139
1140ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
1141{
1142 ssize_t ret;
1143again:
1144 ret = read(fd, buf, count);
1145 if (ret < 0 && errno == EINTR)
1146 goto again;
1147 return ret;
1148}
d567a9a7
CB
1149
1150static int mount_fs(const char *source, const char *target, const char *type)
1151{
1152 /* the umount may fail */
1153 if (umount(target) < 0)
1154
1155 if (mount(source, target, type, 0, NULL) < 0)
1156 return -1;
1157
1158 return 0;
1159}
1160
1161void lxc_setup_fs(void)
1162{
1163 (void)mount_fs("proc", "/proc", "proc");
1164
1165 /* if /dev has been populated by us, /dev/shm does not exist */
1166 if (access("/dev/shm", F_OK))
1167 (void)mkdir("/dev/shm", 0777);
1168
1169 /* if we can't mount /dev/shm, continue anyway */
1170 (void)mount_fs("shmfs", "/dev/shm", "tmpfs");
1171
1172 /* If we were able to mount /dev/shm, then /dev exists */
1173 /* Sure, but it's read-only per config :) */
1174 if (access("/dev/mqueue", F_OK))
1175 (void)mkdir("/dev/mqueue", 0666);
1176
1177 /* continue even without posix message queue support */
1178 (void)mount_fs("mqueue", "/dev/mqueue", "mqueue");
1179}
1180
1181struct clone_arg {
1182 int (*fn)(void *);
1183 void *arg;
1184};
1185
1186static int do_clone(void *arg)
1187{
1188 struct clone_arg *clone_arg = arg;
1189 return clone_arg->fn(clone_arg->arg);
1190}
1191
1192pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
1193{
1194 struct clone_arg clone_arg = {
1195 .fn = fn,
1196 .arg = arg,
1197 };
1198
1199 size_t stack_size = lxc_getpagesize();
1200 void *stack = alloca(stack_size);
1201 pid_t ret;
1202
1203#ifdef __ia64__
1204 ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg);
1205#else
1206 ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg);
1207#endif
1208 return ret;
1209}