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