]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/utils.c
lxc-checkconfig: Fix parsing on vserver kernels
[mirror_lxc.git] / src / lxc / utils.c
CommitLineData
e3642c43
DL
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
e3642c43
DL
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e3642c43
DL
22 */
23
052616eb
ÇO
24#include "config.h"
25
e3642c43
DL
26#include <errno.h>
27#include <unistd.h>
d983b93c
MN
28#include <stdlib.h>
29#include <stddef.h>
61a1d519 30#include <string.h>
e3642c43
DL
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <sys/mman.h>
d983b93c 34#include <sys/param.h>
6e4bb2e0 35#include <sys/mount.h>
d983b93c
MN
36#include <dirent.h>
37#include <fcntl.h>
1b09f2c0 38#include <libgen.h>
9be53773
SH
39#include <sys/types.h>
40#include <sys/wait.h>
502657d5 41#include <assert.h>
e3642c43 42
3ce74686 43#include "utils.h"
e3642c43 44#include "log.h"
025ed0f3 45#include "lxclock.h"
e3642c43 46
052616eb
ÇO
47#define MAX_STACKDEPTH 25
48
e3642c43
DL
49lxc_log_define(lxc_utils, lxc);
50
60bf62d4
SH
51static int _recursive_rmdir_onedev(char *dirname, dev_t pdev)
52{
53 struct dirent dirent, *direntp;
54 DIR *dir;
55 int ret, failed=0;
56 char pathname[MAXPATHLEN];
57
58 dir = opendir(dirname);
59 if (!dir) {
60 ERROR("%s: failed to open %s", __func__, dirname);
4355ab5f 61 return -1;
60bf62d4
SH
62 }
63
64 while (!readdir_r(dir, &dirent, &direntp)) {
65 struct stat mystat;
66 int rc;
67
68 if (!direntp)
69 break;
70
71 if (!strcmp(direntp->d_name, ".") ||
72 !strcmp(direntp->d_name, ".."))
73 continue;
74
75 rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name);
76 if (rc < 0 || rc >= MAXPATHLEN) {
77 ERROR("pathname too long");
78 failed=1;
79 continue;
80 }
81 ret = lstat(pathname, &mystat);
82 if (ret) {
83 ERROR("%s: failed to stat %s", __func__, pathname);
84 failed=1;
85 continue;
86 }
87 if (mystat.st_dev != pdev)
88 continue;
89 if (S_ISDIR(mystat.st_mode)) {
4355ab5f 90 if (_recursive_rmdir_onedev(pathname, pdev) < 0)
60bf62d4
SH
91 failed=1;
92 } else {
93 if (unlink(pathname) < 0) {
94 ERROR("%s: failed to delete %s", __func__, pathname);
95 failed=1;
96 }
97 }
98 }
99
100 if (rmdir(dirname) < 0) {
101 ERROR("%s: failed to delete %s", __func__, dirname);
102 failed=1;
103 }
104
025ed0f3 105 ret = closedir(dir);
025ed0f3 106 if (ret) {
60bf62d4
SH
107 ERROR("%s: failed to close directory %s", __func__, dirname);
108 failed=1;
109 }
110
4355ab5f 111 return failed ? -1 : 0;
60bf62d4
SH
112}
113
4355ab5f 114/* returns 0 on success, -1 if there were any failures */
60bf62d4
SH
115extern int lxc_rmdir_onedev(char *path)
116{
117 struct stat mystat;
118
119 if (lstat(path, &mystat) < 0) {
120 ERROR("%s: failed to stat %s", __func__, path);
4355ab5f 121 return -1;
60bf62d4
SH
122 }
123
124 return _recursive_rmdir_onedev(path, mystat.st_dev);
125}
126
6e4bb2e0
MN
127static int mount_fs(const char *source, const char *target, const char *type)
128{
129 /* the umount may fail */
130 if (umount(target))
131 WARN("failed to unmount %s : %s", target, strerror(errno));
132
133 if (mount(source, target, type, 0, NULL)) {
134 ERROR("failed to mount %s : %s", target, strerror(errno));
135 return -1;
136 }
137
138 DEBUG("'%s' mounted on '%s'", source, target);
139
140 return 0;
141}
142
ea0da529 143extern void lxc_setup_fs(void)
6e4bb2e0
MN
144{
145 if (mount_fs("proc", "/proc", "proc"))
ea0da529 146 INFO("failed to remount proc");
6e4bb2e0 147
721d262c 148 /* if we can't mount /dev/shm, continue anyway */
6e4bb2e0 149 if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
3283db09 150 INFO("failed to mount /dev/shm");
6e4bb2e0
MN
151
152 /* If we were able to mount /dev/shm, then /dev exists */
b91b1cd7 153 /* Sure, but it's read-only per config :) */
6e4bb2e0 154 if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
b91b1cd7 155 DEBUG("failed to create '/dev/mqueue'");
ea0da529 156 return;
6e4bb2e0
MN
157 }
158
5d4d3ebb 159 /* continue even without posix message queue support */
6e4bb2e0 160 if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
5d4d3ebb 161 INFO("failed to mount /dev/mqueue");
6e4bb2e0 162}
9ddaf3bf
JHS
163
164/* borrowed from iproute2 */
7c11d57a 165extern int get_u16(unsigned short *val, const char *arg, int base)
9ddaf3bf
JHS
166{
167 unsigned long res;
168 char *ptr;
169
170 if (!arg || !*arg)
171 return -1;
172
09bbd745 173 errno = 0;
9ddaf3bf 174 res = strtoul(arg, &ptr, base);
09bbd745 175 if (!ptr || ptr == arg || *ptr || res > 0xFFFF || errno != 0)
9ddaf3bf
JHS
176 return -1;
177
178 *val = res;
179
180 return 0;
181}
182
3ce74686 183extern int mkdir_p(const char *dir, mode_t mode)
1b09f2c0 184{
3ce74686
SH
185 const char *tmp = dir;
186 const char *orig = dir;
860fc865
RW
187 char *makeme;
188
189 do {
190 dir = tmp + strspn(tmp, "/");
191 tmp = dir + strcspn(dir, "/");
d74325c4 192 makeme = strndup(orig, dir - orig);
860fc865
RW
193 if (*makeme) {
194 if (mkdir(makeme, mode) && errno != EEXIST) {
959aee9c 195 SYSERROR("failed to create directory '%s'", makeme);
d74325c4 196 free(makeme);
860fc865
RW
197 return -1;
198 }
199 }
d74325c4 200 free(makeme);
860fc865 201 } while(tmp != dir);
1b09f2c0 202
98663823 203 return 0;
1b09f2c0 204}
2a59a681 205
89cd7793
QH
206extern void remove_trailing_slashes(char *p)
207{
208 int l = strlen(p);
209 while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
210 p[l] = '\0';
211}
212
d0386d66 213static char *copy_global_config_value(char *p)
2a59a681
SH
214{
215 int len = strlen(p);
216 char *retbuf;
217
218 if (len < 1)
219 return NULL;
220 if (p[len-1] == '\n') {
221 p[len-1] = '\0';
222 len--;
223 }
224 retbuf = malloc(len+1);
225 if (!retbuf)
226 return NULL;
227 strcpy(retbuf, p);
228 return retbuf;
229}
230
31a95fec 231#define DEFAULT_VG "lxc"
055af165 232#define DEFAULT_THIN_POOL "lxc"
31a95fec 233#define DEFAULT_ZFSROOT "lxc"
67e571de 234
593e8478 235const char *lxc_global_config_value(const char *option_name)
31a95fec 236{
74a3920a 237 static const char * const options[][2] = {
2e59ba02
SG
238 { "lxc.bdev.lvm.vg", DEFAULT_VG },
239 { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
240 { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT },
241 { "lxc.lxcpath", NULL },
242 { "lxc.default_config", NULL },
243 { "lxc.cgroup.pattern", DEFAULT_CGROUP_PATTERN },
244 { "lxc.cgroup.use", NULL },
d0386d66
CS
245 { NULL, NULL },
246 };
4878dac4 247
93c379f0 248 /* placed in the thread local storage pool for non-bionic targets */
babbea4b
ÇO
249#ifdef HAVE_TLS
250 static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
251#else
91664352 252 static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
babbea4b 253#endif
4878dac4 254 char *user_config_path = NULL;
9e8be781 255 char *user_default_config_path = NULL;
4878dac4 256 char *user_lxc_path = NULL;
4878dac4
SG
257
258 if (geteuid() > 0) {
6ed46d9e
AM
259 const char *user_home = getenv("HOME");
260 if (!user_home)
e99facec 261 user_home = "/";
4878dac4
SG
262
263 user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
9e8be781 264 user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
4878dac4
SG
265 user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
266
267 sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
9e8be781 268 sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
4878dac4 269 sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
4878dac4
SG
270 }
271 else {
272 user_config_path = strdup(LXC_GLOBAL_CONF);
9e8be781 273 user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
4878dac4
SG
274 user_lxc_path = strdup(LXCPATH);
275 }
276
74a3920a 277 const char * const (*ptr)[2];
d0386d66
CS
278 size_t i;
279 char buf[1024], *p, *p2;
280 FILE *fin = NULL;
281
282 for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
283 if (!strcmp(option_name, (*ptr)[0]))
284 break;
285 }
286 if (!(*ptr)[0]) {
4878dac4 287 free(user_config_path);
9e8be781 288 free(user_default_config_path);
4878dac4 289 free(user_lxc_path);
d0386d66
CS
290 errno = EINVAL;
291 return NULL;
292 }
052616eb 293
052616eb 294 if (values[i]) {
4878dac4 295 free(user_config_path);
9e8be781 296 free(user_default_config_path);
4878dac4 297 free(user_lxc_path);
babbea4b 298 return values[i];
052616eb 299 }
31a95fec 300
4878dac4
SG
301 fin = fopen_cloexec(user_config_path, "r");
302 free(user_config_path);
31a95fec
SH
303 if (fin) {
304 while (fgets(buf, 1024, fin)) {
305 if (buf[0] == '#')
306 continue;
d0386d66 307 p = strstr(buf, option_name);
31a95fec
SH
308 if (!p)
309 continue;
d0386d66
CS
310 /* see if there was just white space in front
311 * of the option name
312 */
313 for (p2 = buf; p2 < p; p2++) {
314 if (*p2 != ' ' && *p2 != '\t')
315 break;
316 }
317 if (p2 < p)
318 continue;
31a95fec
SH
319 p = strchr(p, '=');
320 if (!p)
321 continue;
d0386d66
CS
322 /* see if there was just white space after
323 * the option name
324 */
325 for (p2 += strlen(option_name); p2 < p; p2++) {
326 if (*p2 != ' ' && *p2 != '\t')
327 break;
328 }
329 if (p2 < p)
330 continue;
31a95fec
SH
331 p++;
332 while (*p && (*p == ' ' || *p == '\t')) p++;
333 if (!*p)
334 continue;
f407c5e4 335
9e8be781 336 free(user_default_config_path);
f407c5e4
SG
337
338 if (strcmp(option_name, "lxc.lxcpath") == 0) {
339 free(user_lxc_path);
340 user_lxc_path = copy_global_config_value(p);
341 remove_trailing_slashes(user_lxc_path);
342 values[i] = user_lxc_path;
343 goto out;
344 }
345
346 values[i] = copy_global_config_value(p);
4878dac4 347 free(user_lxc_path);
31a95fec
SH
348 goto out;
349 }
350 }
d0386d66 351 /* could not find value, use default */
9e8be781 352 if (strcmp(option_name, "lxc.lxcpath") == 0) {
f407c5e4 353 remove_trailing_slashes(user_lxc_path);
4878dac4 354 values[i] = user_lxc_path;
9e8be781
SG
355 free(user_default_config_path);
356 }
357 else if (strcmp(option_name, "lxc.default_config") == 0) {
358 values[i] = user_default_config_path;
359 free(user_lxc_path);
360 }
4878dac4 361 else {
9e8be781 362 free(user_default_config_path);
4878dac4
SG
363 free(user_lxc_path);
364 values[i] = (*ptr)[1];
365 }
d0386d66
CS
366 /* special case: if default value is NULL,
367 * and there is no config, don't view that
368 * as an error... */
369 if (!values[i])
370 errno = 0;
31a95fec
SH
371
372out:
373 if (fin)
374 fclose(fin);
41f68357 375
babbea4b 376 return values[i];
31a95fec
SH
377}
378
9e60f51d
DE
379const char *get_rundir()
380{
381 const char *rundir;
382
383 rundir = getenv("XDG_RUNTIME_DIR");
384 if (geteuid() == 0 || rundir == NULL)
061ba5d0 385 rundir = RUNTIME_PATH;
9e60f51d
DE
386 return rundir;
387}
388
9be53773
SH
389int wait_for_pid(pid_t pid)
390{
391 int status, ret;
392
393again:
394 ret = waitpid(pid, &status, 0);
395 if (ret == -1) {
71b9b8ed 396 if (errno == EINTR)
9be53773
SH
397 goto again;
398 return -1;
399 }
400 if (ret != pid)
401 goto again;
402 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
403 return -1;
404 return 0;
405}
c797a220
CS
406
407int lxc_wait_for_pid_status(pid_t pid)
408{
409 int status, ret;
410
411again:
412 ret = waitpid(pid, &status, 0);
413 if (ret == -1) {
414 if (errno == EINTR)
415 goto again;
416 return -1;
417 }
418 if (ret != pid)
419 goto again;
420 return status;
421}
92f023dc 422
650468bb 423ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
92f023dc 424{
650468bb 425 ssize_t ret;
92f023dc
CS
426again:
427 ret = write(fd, buf, count);
428 if (ret < 0 && errno == EINTR)
429 goto again;
430 return ret;
431}
432
650468bb 433ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
92f023dc 434{
650468bb 435 ssize_t ret;
92f023dc
CS
436again:
437 ret = read(fd, buf, count);
438 if (ret < 0 && errno == EINTR)
439 goto again;
440 return ret;
441}
442
650468bb 443ssize_t lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf)
92f023dc 444{
650468bb 445 ssize_t ret;
92f023dc
CS
446 ret = lxc_read_nointr(fd, buf, count);
447 if (ret <= 0)
448 return ret;
650468bb 449 if ((size_t)ret != count)
92f023dc
CS
450 return -1;
451 if (expected_buf && memcmp(buf, expected_buf, count) != 0) {
452 errno = EINVAL;
453 return -1;
454 }
455 return ret;
456}
3ce74686
SH
457
458#if HAVE_LIBGNUTLS
459#include <gnutls/gnutls.h>
460#include <gnutls/crypto.h>
41246cee
DE
461
462__attribute__((constructor))
463static void gnutls_lxc_init(void)
464{
465 gnutls_global_init();
466}
467
3ce74686
SH
468int sha1sum_file(char *fnam, unsigned char *digest)
469{
470 char *buf;
471 int ret;
472 FILE *f;
473 long flen;
474
475 if (!fnam)
476 return -1;
025ed0f3 477 f = fopen_cloexec(fnam, "r");
7be677a8 478 if (!f) {
3ce74686
SH
479 SYSERROR("Error opening template");
480 return -1;
481 }
482 if (fseek(f, 0, SEEK_END) < 0) {
483 SYSERROR("Error seeking to end of template");
dd1d77f9 484 fclose(f);
3ce74686
SH
485 return -1;
486 }
487 if ((flen = ftell(f)) < 0) {
488 SYSERROR("Error telling size of template");
dd1d77f9 489 fclose(f);
3ce74686
SH
490 return -1;
491 }
492 if (fseek(f, 0, SEEK_SET) < 0) {
493 SYSERROR("Error seeking to start of template");
dd1d77f9 494 fclose(f);
3ce74686
SH
495 return -1;
496 }
497 if ((buf = malloc(flen+1)) == NULL) {
498 SYSERROR("Out of memory");
dd1d77f9 499 fclose(f);
3ce74686
SH
500 return -1;
501 }
502 if (fread(buf, 1, flen, f) != flen) {
503 SYSERROR("Failure reading template");
504 free(buf);
dd1d77f9 505 fclose(f);
3ce74686
SH
506 return -1;
507 }
dd1d77f9 508 if (fclose(f) < 0) {
3ce74686
SH
509 SYSERROR("Failre closing template");
510 free(buf);
511 return -1;
512 }
513 buf[flen] = '\0';
514 ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
515 free(buf);
516 return ret;
517}
518#endif
61a1d519
CS
519
520char** lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup)
521{
522 va_list ap2;
523 size_t count = 1 + skip;
524 char **result;
525
526 /* first determine size of argument list, we don't want to reallocate
527 * constantly...
528 */
529 va_copy(ap2, ap);
530 while (1) {
531 char* arg = va_arg(ap2, char*);
532 if (!arg)
533 break;
534 count++;
535 }
536 va_end(ap2);
537
538 result = calloc(count, sizeof(char*));
539 if (!result)
540 return NULL;
541 count = skip;
542 while (1) {
543 char* arg = va_arg(ap, char*);
544 if (!arg)
545 break;
546 arg = do_strdup ? strdup(arg) : arg;
547 if (!arg)
548 goto oom;
549 result[count++] = arg;
550 }
551
552 /* calloc has already set last element to NULL*/
553 return result;
554
555oom:
556 free(result);
557 return NULL;
558}
559
560const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
561{
562 return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
563}
db27c8d7
CS
564
565FILE *fopen_cloexec(const char *path, const char *mode)
566{
567 int open_mode = 0;
568 int step = 0;
569 int fd;
570 int saved_errno = 0;
571 FILE *ret;
572
573 if (!strncmp(mode, "r+", 2)) {
574 open_mode = O_RDWR;
575 step = 2;
576 } else if (!strncmp(mode, "r", 1)) {
577 open_mode = O_RDONLY;
578 step = 1;
579 } else if (!strncmp(mode, "w+", 2)) {
580 open_mode = O_RDWR | O_TRUNC | O_CREAT;
581 step = 2;
582 } else if (!strncmp(mode, "w", 1)) {
583 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
584 step = 1;
585 } else if (!strncmp(mode, "a+", 2)) {
586 open_mode = O_RDWR | O_CREAT | O_APPEND;
587 step = 2;
588 } else if (!strncmp(mode, "a", 1)) {
589 open_mode = O_WRONLY | O_CREAT | O_APPEND;
590 step = 1;
591 }
592 for (; mode[step]; step++)
593 if (mode[step] == 'x')
594 open_mode |= O_EXCL;
595 open_mode |= O_CLOEXEC;
596
82371fdd 597 fd = open(path, open_mode, 0666);
db27c8d7
CS
598 if (fd < 0)
599 return NULL;
600
601 ret = fdopen(fd, mode);
602 saved_errno = errno;
603 if (!ret)
604 close(fd);
605 errno = saved_errno;
606 return ret;
607}
502657d5 608
ebec9176
AM
609extern struct lxc_popen_FILE *lxc_popen(const char *command)
610{
611 struct lxc_popen_FILE *fp = NULL;
612 int parent_end = -1, child_end = -1;
613 int pipe_fds[2];
614 pid_t child_pid;
615
616 int r = pipe2(pipe_fds, O_CLOEXEC);
617
618 if (r < 0) {
619 ERROR("pipe2 failure");
620 return NULL;
621 }
622
623 parent_end = pipe_fds[0];
624 child_end = pipe_fds[1];
625
626 child_pid = fork();
627
628 if (child_pid == 0) {
629 /* child */
630 int child_std_end = STDOUT_FILENO;
631
632 if (child_end != child_std_end) {
633 /* dup2() doesn't dup close-on-exec flag */
634 dup2(child_end, child_std_end);
635
636 /* it's safe not to close child_end here
637 * as it's marked close-on-exec anyway
638 */
639 } else {
640 /*
641 * The descriptor is already the one we will use.
642 * But it must not be marked close-on-exec.
643 * Undo the effects.
644 */
57d2be54
SG
645 if (fcntl(child_end, F_SETFD, 0) != 0) {
646 SYSERROR("Failed to remove FD_CLOEXEC from fd.");
647 exit(127);
648 }
ebec9176
AM
649 }
650
651 /*
652 * Unblock signals.
653 * This is the main/only reason
654 * why we do our lousy popen() emulation.
655 */
656 {
657 sigset_t mask;
658 sigfillset(&mask);
659 sigprocmask(SIG_UNBLOCK, &mask, NULL);
660 }
661
662 execl("/bin/sh", "sh", "-c", command, (char *) NULL);
663 exit(127);
664 }
665
666 /* parent */
667
668 close(child_end);
669 child_end = -1;
670
671 if (child_pid < 0) {
672 ERROR("fork failure");
673 goto error;
674 }
675
676 fp = calloc(1, sizeof(*fp));
677 if (!fp) {
678 ERROR("failed to allocate memory");
679 goto error;
680 }
681
682 fp->f = fdopen(parent_end, "r");
683 if (!fp->f) {
684 ERROR("fdopen failure");
685 goto error;
686 }
687
688 fp->child_pid = child_pid;
689
690 return fp;
691
692error:
693
694 if (fp) {
695 if (fp->f) {
696 fclose(fp->f);
697 parent_end = -1; /* so we do not close it second time */
698 }
699
700 free(fp);
701 }
702
ebec9176
AM
703 if (parent_end != -1)
704 close(parent_end);
705
706 return NULL;
707}
708
ebec9176
AM
709extern int lxc_pclose(struct lxc_popen_FILE *fp)
710{
711 FILE *f = NULL;
712 pid_t child_pid = 0;
713 int wstatus = 0;
714 pid_t wait_pid;
715
716 if (fp) {
717 f = fp->f;
718 child_pid = fp->child_pid;
719 /* free memory (we still need to close file stream) */
720 free(fp);
721 fp = NULL;
722 }
723
724 if (!f || fclose(f)) {
725 ERROR("fclose failure");
726 return -1;
727 }
728
729 do {
730 wait_pid = waitpid(child_pid, &wstatus, 0);
731 } while (wait_pid == -1 && errno == EINTR);
732
733 if (wait_pid == -1) {
734 ERROR("waitpid failure");
735 return -1;
736 }
737
738 return wstatus;
739}
740
502657d5
CS
741char *lxc_string_replace(const char *needle, const char *replacement, const char *haystack)
742{
743 ssize_t len = -1, saved_len = -1;
744 char *result = NULL;
745 size_t replacement_len = strlen(replacement);
746 size_t needle_len = strlen(needle);
747
748 /* should be executed exactly twice */
749 while (len == -1 || result == NULL) {
750 char *p;
751 char *last_p;
752 ssize_t part_len;
753
754 if (len != -1) {
755 result = calloc(1, len + 1);
756 if (!result)
757 return NULL;
758 saved_len = len;
759 }
760
761 len = 0;
762
763 for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) {
764 part_len = (ssize_t)(p - last_p);
765 if (result && part_len > 0)
766 memcpy(&result[len], last_p, part_len);
767 len += part_len;
768 if (result && replacement_len > 0)
769 memcpy(&result[len], replacement, replacement_len);
770 len += replacement_len;
771 p += needle_len;
772 }
773 part_len = strlen(last_p);
774 if (result && part_len > 0)
775 memcpy(&result[len], last_p, part_len);
776 len += part_len;
777 }
778
779 /* make sure we did the same thing twice,
780 * once for calculating length, the other
781 * time for copying data */
782 assert(saved_len == len);
783 /* make sure we didn't overwrite any buffer,
784 * due to calloc the string should be 0-terminated */
785 assert(result[len] == '\0');
786
787 return result;
788}
789
790bool lxc_string_in_array(const char *needle, const char **haystack)
791{
792 for (; haystack && *haystack; haystack++)
793 if (!strcmp(needle, *haystack))
794 return true;
795 return false;
796}
797
798char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
799{
800 char *result;
801 char **p;
802 size_t sep_len = strlen(sep);
803 size_t result_len = use_as_prefix * sep_len;
804
805 /* calculate new string length */
806 for (p = (char **)parts; *p; p++)
807 result_len += (p > (char **)parts) * sep_len + strlen(*p);
808
809 result = calloc(result_len + 1, 1);
810 if (!result)
811 return NULL;
812
813 if (use_as_prefix)
814 strcpy(result, sep);
815 for (p = (char **)parts; *p; p++) {
816 if (p > (char **)parts)
817 strcat(result, sep);
818 strcat(result, *p);
819 }
820
821 return result;
822}
823
824char **lxc_normalize_path(const char *path)
825{
826 char **components;
827 char **p;
828 size_t components_len = 0;
829 size_t pos = 0;
830
831 components = lxc_string_split(path, '/');
832 if (!components)
833 return NULL;
834 for (p = components; *p; p++)
835 components_len++;
836
837 /* resolve '.' and '..' */
838 for (pos = 0; pos < components_len; ) {
839 if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) {
840 /* eat this element */
841 free(components[pos]);
842 memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos));
843 components_len--;
844 } else if (!strcmp(components[pos], "..")) {
845 /* eat this and the previous element */
846 free(components[pos - 1]);
847 free(components[pos]);
848 memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos));
849 components_len -= 2;
850 pos--;
851 } else {
852 pos++;
853 }
854 }
855
856 return components;
857}
858
24b51482
CS
859char *lxc_append_paths(const char *first, const char *second)
860{
861 size_t len = strlen(first) + strlen(second) + 1;
862 const char *pattern = "%s%s";
863 char *result = NULL;
864
865 if (second[0] != '/') {
866 len += 1;
867 pattern = "%s/%s";
868 }
869
870 result = calloc(1, len);
871 if (!result)
872 return NULL;
873
874 snprintf(result, len, pattern, first, second);
875 return result;
876}
877
502657d5
CS
878bool lxc_string_in_list(const char *needle, const char *haystack, char _sep)
879{
880 char *token, *str, *saveptr = NULL;
881 char sep[2] = { _sep, '\0' };
882
883 if (!haystack || !needle)
884 return 0;
885
886 str = alloca(strlen(haystack)+1);
887 strcpy(str, haystack);
888 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
889 if (strcmp(needle, token) == 0)
890 return 1;
891 }
892
893 return 0;
894}
895
896char **lxc_string_split(const char *string, char _sep)
897{
898 char *token, *str, *saveptr = NULL;
899 char sep[2] = { _sep, '\0' };
900 char **result = NULL;
901 size_t result_capacity = 0;
902 size_t result_count = 0;
903 int r, saved_errno;
904
905 if (!string)
906 return calloc(1, sizeof(char *));
907
908 str = alloca(strlen(string)+1);
909 strcpy(str, string);
910 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
911 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
912 if (r < 0)
913 goto error_out;
914 result[result_count] = strdup(token);
915 if (!result[result_count])
916 goto error_out;
917 result_count++;
918 }
919
920 /* if we allocated too much, reduce it */
921 return realloc(result, (result_count + 1) * sizeof(char *));
922error_out:
923 saved_errno = errno;
924 lxc_free_array((void **)result, free);
925 errno = saved_errno;
926 return NULL;
927}
928
929char **lxc_string_split_and_trim(const char *string, char _sep)
930{
931 char *token, *str, *saveptr = NULL;
932 char sep[2] = { _sep, '\0' };
933 char **result = NULL;
934 size_t result_capacity = 0;
935 size_t result_count = 0;
936 int r, saved_errno;
937 size_t i = 0;
938
939 if (!string)
940 return calloc(1, sizeof(char *));
941
942 str = alloca(strlen(string)+1);
943 strcpy(str, string);
944 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
945 while (token[0] == ' ' || token[0] == '\t')
946 token++;
947 i = strlen(token);
948 while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
949 token[i - 1] = '\0';
950 i--;
951 }
952 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
953 if (r < 0)
954 goto error_out;
955 result[result_count] = strdup(token);
956 if (!result[result_count])
957 goto error_out;
958 result_count++;
959 }
960
961 /* if we allocated too much, reduce it */
962 return realloc(result, (result_count + 1) * sizeof(char *));
963error_out:
964 saved_errno = errno;
965 lxc_free_array((void **)result, free);
966 errno = saved_errno;
967 return NULL;
968}
969
970void lxc_free_array(void **array, lxc_free_fn element_free_fn)
971{
972 void **p;
973 for (p = array; p && *p; p++)
974 element_free_fn(*p);
975 free((void*)array);
976}
977
978int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment)
979{
980 size_t new_capacity;
981 void **new_array;
982
983 /* first time around, catch some trivial mistakes of the user
984 * only initializing one of these */
985 if (!*array || !*capacity) {
986 *array = NULL;
987 *capacity = 0;
988 }
989
990 new_capacity = *capacity;
991 while (new_size + 1 > new_capacity)
992 new_capacity += capacity_increment;
993 if (new_capacity != *capacity) {
994 /* we have to reallocate */
995 new_array = realloc(*array, new_capacity * sizeof(void *));
996 if (!new_array)
997 return -1;
998 memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *));
999 *array = new_array;
1000 *capacity = new_capacity;
1001 }
1002
1003 /* array has sufficient elements */
1004 return 0;
1005}
1006
1007size_t lxc_array_len(void **array)
1008{
1009 void **p;
1010 size_t result = 0;
1011
1012 for (p = array; p && *p; p++)
1013 result++;
1014
1015 return result;
1016}
1017
0e95426b
CS
1018int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool add_newline)
1019{
1020 int fd, saved_errno;
1021 ssize_t ret;
1022
1023 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
1024 if (fd < 0)
1025 return -1;
1026 ret = lxc_write_nointr(fd, buf, count);
1027 if (ret < 0)
799f29ab 1028 goto out_error;
0e95426b
CS
1029 if ((size_t)ret != count)
1030 goto out_error;
1031 if (add_newline) {
1032 ret = lxc_write_nointr(fd, "\n", 1);
1033 if (ret != 1)
1034 goto out_error;
1035 }
1036 close(fd);
1037 return 0;
1038
1039out_error:
1040 saved_errno = errno;
1041 close(fd);
1042 errno = saved_errno;
1043 return -1;
1044}
1045
1046int lxc_read_from_file(const char *filename, void* buf, size_t count)
1047{
1048 int fd = -1, saved_errno;
1049 ssize_t ret;
1050
1051 fd = open(filename, O_RDONLY | O_CLOEXEC);
1052 if (fd < 0)
1053 return -1;
1054
1055 if (!buf || !count) {
1056 char buf2[100];
1057 size_t count2 = 0;
1058 while ((ret = read(fd, buf2, 100)) > 0)
1059 count2 += ret;
1060 if (ret >= 0)
1061 ret = count2;
1062 } else {
1063 memset(buf, 0, count);
1064 ret = read(fd, buf, count);
1065 }
1066
1067 if (ret < 0)
1068 ERROR("read %s: %s", filename, strerror(errno));
1069
1070 saved_errno = errno;
1071 close(fd);
1072 errno = saved_errno;
1073 return ret;
1074}
799f29ab
ÇO
1075
1076void **lxc_append_null_to_array(void **array, size_t count)
1077{
1078 void **temp;
1079
1080 /* Append NULL to the array */
1081 if (count) {
1082 temp = realloc(array, (count + 1) * sizeof(*array));
1083 if (!temp) {
1084 int i;
1085 for (i = 0; i < count; i++)
1086 free(array[i]);
1087 free(array);
1088 return NULL;
1089 }
1090 array = temp;
1091 array[count] = NULL;
1092 }
1093 return array;
1094}
508c263e
SH
1095
1096int randseed(bool srand_it)
1097{
1098 /*
1099 srand pre-seed function based on /dev/urandom
1100 */
1101 unsigned int seed=time(NULL)+getpid();
1102
1103 FILE *f;
1104 f = fopen("/dev/urandom", "r");
1105 if (f) {
1106 int ret = fread(&seed, sizeof(seed), 1, f);
1107 if (ret != 1)
1108 DEBUG("unable to fread /dev/urandom, %s, fallback to time+pid rand seed", strerror(errno));
1109 fclose(f);
1110 }
1111
1112 if (srand_it)
1113 srand(seed);
1114
1115 return seed;
1116}
5d897655
SH
1117
1118uid_t get_ns_uid(uid_t orig)
1119{
1120 char *line = NULL;
1121 size_t sz = 0;
1122 uid_t nsid, hostid, range;
1123 FILE *f = fopen("/proc/self/uid_map", "r");
1124 if (!f)
1125 return 0;
1126
1127 while (getline(&line, &sz, f) != -1) {
1128 if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
1129 continue;
1130 if (hostid <= orig && hostid + range > orig) {
1131 nsid += orig - hostid;
1132 goto found;
1133 }
1134 }
1135
1136 nsid = 0;
1137found:
1138 fclose(f);
1139 free(line);
1140 return nsid;
1141}
c476bdce
SH
1142
1143bool dir_exists(const char *path)
1144{
1145 struct stat sb;
1146 int ret;
1147
1148 ret = stat(path, &sb);
1149 if (ret < 0)
1150 // could be something other than eexist, just say no
1151 return false;
1152 return S_ISDIR(sb.st_mode);
1153}
93c379f0
ÇO
1154
1155/* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS.
1156 * FNV has good anti collision properties and we're not worried
1157 * about pre-image resistance or one-way-ness, we're just trying to make
1158 * the name unique in the 108 bytes of space we have.
1159 */
1160uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
1161{
1162 unsigned char *bp;
1163
1164 for(bp = buf; bp < (unsigned char *)buf + len; bp++)
1165 {
1166 /* xor the bottom with the current octet */
1167 hval ^= (uint64_t)*bp;
1168
1169 /* gcc optimised:
1170 * multiply by the 64 bit FNV magic prime mod 2^64
1171 */
1172 hval += (hval << 1) + (hval << 4) + (hval << 5) +
1173 (hval << 7) + (hval << 8) + (hval << 40);
1174 }
1175
1176 return hval;
1177}