]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/utils.c
log: Don't crash when name is NULL
[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) {
195 SYSERROR("failed to create directory '%s'\n", 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
babbea4b
ÇO
248 /* placed in the thread local storage pool for non-bionic targets */
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)
385 rundir = "/run";
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 */
645 fcntl(child_end, F_SETFD, 0);
646 }
647
648 /*
649 * Unblock signals.
650 * This is the main/only reason
651 * why we do our lousy popen() emulation.
652 */
653 {
654 sigset_t mask;
655 sigfillset(&mask);
656 sigprocmask(SIG_UNBLOCK, &mask, NULL);
657 }
658
659 execl("/bin/sh", "sh", "-c", command, (char *) NULL);
660 exit(127);
661 }
662
663 /* parent */
664
665 close(child_end);
666 child_end = -1;
667
668 if (child_pid < 0) {
669 ERROR("fork failure");
670 goto error;
671 }
672
673 fp = calloc(1, sizeof(*fp));
674 if (!fp) {
675 ERROR("failed to allocate memory");
676 goto error;
677 }
678
679 fp->f = fdopen(parent_end, "r");
680 if (!fp->f) {
681 ERROR("fdopen failure");
682 goto error;
683 }
684
685 fp->child_pid = child_pid;
686
687 return fp;
688
689error:
690
691 if (fp) {
692 if (fp->f) {
693 fclose(fp->f);
694 parent_end = -1; /* so we do not close it second time */
695 }
696
697 free(fp);
698 }
699
ebec9176
AM
700 if (parent_end != -1)
701 close(parent_end);
702
703 return NULL;
704}
705
ebec9176
AM
706extern int lxc_pclose(struct lxc_popen_FILE *fp)
707{
708 FILE *f = NULL;
709 pid_t child_pid = 0;
710 int wstatus = 0;
711 pid_t wait_pid;
712
713 if (fp) {
714 f = fp->f;
715 child_pid = fp->child_pid;
716 /* free memory (we still need to close file stream) */
717 free(fp);
718 fp = NULL;
719 }
720
721 if (!f || fclose(f)) {
722 ERROR("fclose failure");
723 return -1;
724 }
725
726 do {
727 wait_pid = waitpid(child_pid, &wstatus, 0);
728 } while (wait_pid == -1 && errno == EINTR);
729
730 if (wait_pid == -1) {
731 ERROR("waitpid failure");
732 return -1;
733 }
734
735 return wstatus;
736}
737
502657d5
CS
738char *lxc_string_replace(const char *needle, const char *replacement, const char *haystack)
739{
740 ssize_t len = -1, saved_len = -1;
741 char *result = NULL;
742 size_t replacement_len = strlen(replacement);
743 size_t needle_len = strlen(needle);
744
745 /* should be executed exactly twice */
746 while (len == -1 || result == NULL) {
747 char *p;
748 char *last_p;
749 ssize_t part_len;
750
751 if (len != -1) {
752 result = calloc(1, len + 1);
753 if (!result)
754 return NULL;
755 saved_len = len;
756 }
757
758 len = 0;
759
760 for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) {
761 part_len = (ssize_t)(p - last_p);
762 if (result && part_len > 0)
763 memcpy(&result[len], last_p, part_len);
764 len += part_len;
765 if (result && replacement_len > 0)
766 memcpy(&result[len], replacement, replacement_len);
767 len += replacement_len;
768 p += needle_len;
769 }
770 part_len = strlen(last_p);
771 if (result && part_len > 0)
772 memcpy(&result[len], last_p, part_len);
773 len += part_len;
774 }
775
776 /* make sure we did the same thing twice,
777 * once for calculating length, the other
778 * time for copying data */
779 assert(saved_len == len);
780 /* make sure we didn't overwrite any buffer,
781 * due to calloc the string should be 0-terminated */
782 assert(result[len] == '\0');
783
784 return result;
785}
786
787bool lxc_string_in_array(const char *needle, const char **haystack)
788{
789 for (; haystack && *haystack; haystack++)
790 if (!strcmp(needle, *haystack))
791 return true;
792 return false;
793}
794
795char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
796{
797 char *result;
798 char **p;
799 size_t sep_len = strlen(sep);
800 size_t result_len = use_as_prefix * sep_len;
801
802 /* calculate new string length */
803 for (p = (char **)parts; *p; p++)
804 result_len += (p > (char **)parts) * sep_len + strlen(*p);
805
806 result = calloc(result_len + 1, 1);
807 if (!result)
808 return NULL;
809
810 if (use_as_prefix)
811 strcpy(result, sep);
812 for (p = (char **)parts; *p; p++) {
813 if (p > (char **)parts)
814 strcat(result, sep);
815 strcat(result, *p);
816 }
817
818 return result;
819}
820
821char **lxc_normalize_path(const char *path)
822{
823 char **components;
824 char **p;
825 size_t components_len = 0;
826 size_t pos = 0;
827
828 components = lxc_string_split(path, '/');
829 if (!components)
830 return NULL;
831 for (p = components; *p; p++)
832 components_len++;
833
834 /* resolve '.' and '..' */
835 for (pos = 0; pos < components_len; ) {
836 if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) {
837 /* eat this element */
838 free(components[pos]);
839 memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos));
840 components_len--;
841 } else if (!strcmp(components[pos], "..")) {
842 /* eat this and the previous element */
843 free(components[pos - 1]);
844 free(components[pos]);
845 memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos));
846 components_len -= 2;
847 pos--;
848 } else {
849 pos++;
850 }
851 }
852
853 return components;
854}
855
24b51482
CS
856char *lxc_append_paths(const char *first, const char *second)
857{
858 size_t len = strlen(first) + strlen(second) + 1;
859 const char *pattern = "%s%s";
860 char *result = NULL;
861
862 if (second[0] != '/') {
863 len += 1;
864 pattern = "%s/%s";
865 }
866
867 result = calloc(1, len);
868 if (!result)
869 return NULL;
870
871 snprintf(result, len, pattern, first, second);
872 return result;
873}
874
502657d5
CS
875bool lxc_string_in_list(const char *needle, const char *haystack, char _sep)
876{
877 char *token, *str, *saveptr = NULL;
878 char sep[2] = { _sep, '\0' };
879
880 if (!haystack || !needle)
881 return 0;
882
883 str = alloca(strlen(haystack)+1);
884 strcpy(str, haystack);
885 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
886 if (strcmp(needle, token) == 0)
887 return 1;
888 }
889
890 return 0;
891}
892
893char **lxc_string_split(const char *string, char _sep)
894{
895 char *token, *str, *saveptr = NULL;
896 char sep[2] = { _sep, '\0' };
897 char **result = NULL;
898 size_t result_capacity = 0;
899 size_t result_count = 0;
900 int r, saved_errno;
901
902 if (!string)
903 return calloc(1, sizeof(char *));
904
905 str = alloca(strlen(string)+1);
906 strcpy(str, string);
907 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
908 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
909 if (r < 0)
910 goto error_out;
911 result[result_count] = strdup(token);
912 if (!result[result_count])
913 goto error_out;
914 result_count++;
915 }
916
917 /* if we allocated too much, reduce it */
918 return realloc(result, (result_count + 1) * sizeof(char *));
919error_out:
920 saved_errno = errno;
921 lxc_free_array((void **)result, free);
922 errno = saved_errno;
923 return NULL;
924}
925
926char **lxc_string_split_and_trim(const char *string, char _sep)
927{
928 char *token, *str, *saveptr = NULL;
929 char sep[2] = { _sep, '\0' };
930 char **result = NULL;
931 size_t result_capacity = 0;
932 size_t result_count = 0;
933 int r, saved_errno;
934 size_t i = 0;
935
936 if (!string)
937 return calloc(1, sizeof(char *));
938
939 str = alloca(strlen(string)+1);
940 strcpy(str, string);
941 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
942 while (token[0] == ' ' || token[0] == '\t')
943 token++;
944 i = strlen(token);
945 while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
946 token[i - 1] = '\0';
947 i--;
948 }
949 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
950 if (r < 0)
951 goto error_out;
952 result[result_count] = strdup(token);
953 if (!result[result_count])
954 goto error_out;
955 result_count++;
956 }
957
958 /* if we allocated too much, reduce it */
959 return realloc(result, (result_count + 1) * sizeof(char *));
960error_out:
961 saved_errno = errno;
962 lxc_free_array((void **)result, free);
963 errno = saved_errno;
964 return NULL;
965}
966
967void lxc_free_array(void **array, lxc_free_fn element_free_fn)
968{
969 void **p;
970 for (p = array; p && *p; p++)
971 element_free_fn(*p);
972 free((void*)array);
973}
974
975int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment)
976{
977 size_t new_capacity;
978 void **new_array;
979
980 /* first time around, catch some trivial mistakes of the user
981 * only initializing one of these */
982 if (!*array || !*capacity) {
983 *array = NULL;
984 *capacity = 0;
985 }
986
987 new_capacity = *capacity;
988 while (new_size + 1 > new_capacity)
989 new_capacity += capacity_increment;
990 if (new_capacity != *capacity) {
991 /* we have to reallocate */
992 new_array = realloc(*array, new_capacity * sizeof(void *));
993 if (!new_array)
994 return -1;
995 memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *));
996 *array = new_array;
997 *capacity = new_capacity;
998 }
999
1000 /* array has sufficient elements */
1001 return 0;
1002}
1003
1004size_t lxc_array_len(void **array)
1005{
1006 void **p;
1007 size_t result = 0;
1008
1009 for (p = array; p && *p; p++)
1010 result++;
1011
1012 return result;
1013}
1014
0e95426b
CS
1015int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool add_newline)
1016{
1017 int fd, saved_errno;
1018 ssize_t ret;
1019
1020 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
1021 if (fd < 0)
1022 return -1;
1023 ret = lxc_write_nointr(fd, buf, count);
1024 if (ret < 0)
799f29ab 1025 goto out_error;
0e95426b
CS
1026 if ((size_t)ret != count)
1027 goto out_error;
1028 if (add_newline) {
1029 ret = lxc_write_nointr(fd, "\n", 1);
1030 if (ret != 1)
1031 goto out_error;
1032 }
1033 close(fd);
1034 return 0;
1035
1036out_error:
1037 saved_errno = errno;
1038 close(fd);
1039 errno = saved_errno;
1040 return -1;
1041}
1042
1043int lxc_read_from_file(const char *filename, void* buf, size_t count)
1044{
1045 int fd = -1, saved_errno;
1046 ssize_t ret;
1047
1048 fd = open(filename, O_RDONLY | O_CLOEXEC);
1049 if (fd < 0)
1050 return -1;
1051
1052 if (!buf || !count) {
1053 char buf2[100];
1054 size_t count2 = 0;
1055 while ((ret = read(fd, buf2, 100)) > 0)
1056 count2 += ret;
1057 if (ret >= 0)
1058 ret = count2;
1059 } else {
1060 memset(buf, 0, count);
1061 ret = read(fd, buf, count);
1062 }
1063
1064 if (ret < 0)
1065 ERROR("read %s: %s", filename, strerror(errno));
1066
1067 saved_errno = errno;
1068 close(fd);
1069 errno = saved_errno;
1070 return ret;
1071}
799f29ab
ÇO
1072
1073void **lxc_append_null_to_array(void **array, size_t count)
1074{
1075 void **temp;
1076
1077 /* Append NULL to the array */
1078 if (count) {
1079 temp = realloc(array, (count + 1) * sizeof(*array));
1080 if (!temp) {
1081 int i;
1082 for (i = 0; i < count; i++)
1083 free(array[i]);
1084 free(array);
1085 return NULL;
1086 }
1087 array = temp;
1088 array[count] = NULL;
1089 }
1090 return array;
1091}
508c263e
SH
1092
1093int randseed(bool srand_it)
1094{
1095 /*
1096 srand pre-seed function based on /dev/urandom
1097 */
1098 unsigned int seed=time(NULL)+getpid();
1099
1100 FILE *f;
1101 f = fopen("/dev/urandom", "r");
1102 if (f) {
1103 int ret = fread(&seed, sizeof(seed), 1, f);
1104 if (ret != 1)
1105 DEBUG("unable to fread /dev/urandom, %s, fallback to time+pid rand seed", strerror(errno));
1106 fclose(f);
1107 }
1108
1109 if (srand_it)
1110 srand(seed);
1111
1112 return seed;
1113}
5d897655
SH
1114
1115uid_t get_ns_uid(uid_t orig)
1116{
1117 char *line = NULL;
1118 size_t sz = 0;
1119 uid_t nsid, hostid, range;
1120 FILE *f = fopen("/proc/self/uid_map", "r");
1121 if (!f)
1122 return 0;
1123
1124 while (getline(&line, &sz, f) != -1) {
1125 if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
1126 continue;
1127 if (hostid <= orig && hostid + range > orig) {
1128 nsid += orig - hostid;
1129 goto found;
1130 }
1131 }
1132
1133 nsid = 0;
1134found:
1135 fclose(f);
1136 free(line);
1137 return nsid;
1138}
c476bdce
SH
1139
1140bool dir_exists(const char *path)
1141{
1142 struct stat sb;
1143 int ret;
1144
1145 ret = stat(path, &sb);
1146 if (ret < 0)
1147 // could be something other than eexist, just say no
1148 return false;
1149 return S_ISDIR(sb.st_mode);
1150}