]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/utils.c
cgmanager: free line at end of check_supports_multiple_controllers
[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>
0a4be28d 42#include <sys/prctl.h>
e3642c43 43
3ce74686 44#include "utils.h"
e3642c43 45#include "log.h"
025ed0f3 46#include "lxclock.h"
51d0854c 47#include "namespace.h"
e3642c43 48
5d6ef228
SG
49#ifndef PR_SET_MM
50#define PR_SET_MM 35
51#endif
52
553347e4
TA
53#ifndef PR_SET_MM_ARG_START
54#define PR_SET_MM_ARG_START 8
55#endif
56
57#ifndef PR_SET_MM_ARG_END
58#define PR_SET_MM_ARG_END 9
59#endif
60
61#ifndef PR_SET_MM_ENV_START
62#define PR_SET_MM_ENV_START 10
63#endif
64
65#ifndef PR_SET_MM_ENV_END
66#define PR_SET_MM_ENV_END 11
67#endif
68
e3642c43
DL
69lxc_log_define(lxc_utils, lxc);
70
18aa217b
SH
71static int _recursive_rmdir_onedev(char *dirname, dev_t pdev,
72 const char *exclude, int level)
60bf62d4
SH
73{
74 struct dirent dirent, *direntp;
75 DIR *dir;
76 int ret, failed=0;
77 char pathname[MAXPATHLEN];
18aa217b 78 bool hadexclude = false;
60bf62d4
SH
79
80 dir = opendir(dirname);
81 if (!dir) {
82 ERROR("%s: failed to open %s", __func__, dirname);
4355ab5f 83 return -1;
60bf62d4
SH
84 }
85
86 while (!readdir_r(dir, &dirent, &direntp)) {
87 struct stat mystat;
88 int rc;
89
90 if (!direntp)
91 break;
92
93 if (!strcmp(direntp->d_name, ".") ||
94 !strcmp(direntp->d_name, ".."))
95 continue;
96
97 rc = snprintf(pathname, MAXPATHLEN, "%s/%s", dirname, direntp->d_name);
98 if (rc < 0 || rc >= MAXPATHLEN) {
99 ERROR("pathname too long");
100 failed=1;
101 continue;
102 }
18aa217b
SH
103
104 if (!level && exclude && !strcmp(direntp->d_name, exclude)) {
105 ret = rmdir(pathname);
106 if (ret < 0) {
107 switch(errno) {
108 case ENOTEMPTY:
109 INFO("Not deleting snapshots");
110 hadexclude = true;
111 break;
112 case ENOTDIR:
113 ret = unlink(pathname);
114 if (ret)
115 INFO("%s: failed to remove %s", __func__, pathname);
116 break;
117 default:
118 SYSERROR("%s: failed to rmdir %s", __func__, pathname);
119 failed = 1;
120 break;
121 }
122 }
123 continue;
124 }
125
60bf62d4
SH
126 ret = lstat(pathname, &mystat);
127 if (ret) {
128 ERROR("%s: failed to stat %s", __func__, pathname);
129 failed=1;
130 continue;
131 }
132 if (mystat.st_dev != pdev)
133 continue;
134 if (S_ISDIR(mystat.st_mode)) {
18aa217b 135 if (_recursive_rmdir_onedev(pathname, pdev, exclude, level+1) < 0)
60bf62d4
SH
136 failed=1;
137 } else {
138 if (unlink(pathname) < 0) {
139 ERROR("%s: failed to delete %s", __func__, pathname);
140 failed=1;
141 }
142 }
143 }
144
145 if (rmdir(dirname) < 0) {
18aa217b
SH
146 if (!hadexclude) {
147 ERROR("%s: failed to delete %s", __func__, dirname);
148 failed=1;
149 }
60bf62d4
SH
150 }
151
025ed0f3 152 ret = closedir(dir);
025ed0f3 153 if (ret) {
60bf62d4
SH
154 ERROR("%s: failed to close directory %s", __func__, dirname);
155 failed=1;
156 }
157
4355ab5f 158 return failed ? -1 : 0;
60bf62d4
SH
159}
160
4355ab5f 161/* returns 0 on success, -1 if there were any failures */
18aa217b 162extern int lxc_rmdir_onedev(char *path, const char *exclude)
60bf62d4
SH
163{
164 struct stat mystat;
165
166 if (lstat(path, &mystat) < 0) {
167 ERROR("%s: failed to stat %s", __func__, path);
4355ab5f 168 return -1;
60bf62d4
SH
169 }
170
18aa217b 171 return _recursive_rmdir_onedev(path, mystat.st_dev, exclude, 0);
60bf62d4
SH
172}
173
6e4bb2e0
MN
174static int mount_fs(const char *source, const char *target, const char *type)
175{
176 /* the umount may fail */
177 if (umount(target))
178 WARN("failed to unmount %s : %s", target, strerror(errno));
179
180 if (mount(source, target, type, 0, NULL)) {
181 ERROR("failed to mount %s : %s", target, strerror(errno));
182 return -1;
183 }
184
185 DEBUG("'%s' mounted on '%s'", source, target);
186
187 return 0;
188}
189
ea0da529 190extern void lxc_setup_fs(void)
6e4bb2e0
MN
191{
192 if (mount_fs("proc", "/proc", "proc"))
ea0da529 193 INFO("failed to remount proc");
6e4bb2e0 194
721d262c 195 /* if we can't mount /dev/shm, continue anyway */
6e4bb2e0 196 if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
3283db09 197 INFO("failed to mount /dev/shm");
6e4bb2e0
MN
198
199 /* If we were able to mount /dev/shm, then /dev exists */
b91b1cd7 200 /* Sure, but it's read-only per config :) */
6e4bb2e0 201 if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
b91b1cd7 202 DEBUG("failed to create '/dev/mqueue'");
ea0da529 203 return;
6e4bb2e0
MN
204 }
205
5d4d3ebb 206 /* continue even without posix message queue support */
6e4bb2e0 207 if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
5d4d3ebb 208 INFO("failed to mount /dev/mqueue");
6e4bb2e0 209}
9ddaf3bf
JHS
210
211/* borrowed from iproute2 */
7c11d57a 212extern int get_u16(unsigned short *val, const char *arg, int base)
9ddaf3bf
JHS
213{
214 unsigned long res;
215 char *ptr;
216
217 if (!arg || !*arg)
218 return -1;
219
09bbd745 220 errno = 0;
9ddaf3bf 221 res = strtoul(arg, &ptr, base);
09bbd745 222 if (!ptr || ptr == arg || *ptr || res > 0xFFFF || errno != 0)
9ddaf3bf
JHS
223 return -1;
224
225 *val = res;
226
227 return 0;
228}
229
3ce74686 230extern int mkdir_p(const char *dir, mode_t mode)
1b09f2c0 231{
3ce74686
SH
232 const char *tmp = dir;
233 const char *orig = dir;
860fc865
RW
234 char *makeme;
235
236 do {
237 dir = tmp + strspn(tmp, "/");
238 tmp = dir + strcspn(dir, "/");
d74325c4 239 makeme = strndup(orig, dir - orig);
860fc865
RW
240 if (*makeme) {
241 if (mkdir(makeme, mode) && errno != EEXIST) {
959aee9c 242 SYSERROR("failed to create directory '%s'", makeme);
d74325c4 243 free(makeme);
860fc865
RW
244 return -1;
245 }
246 }
d74325c4 247 free(makeme);
860fc865 248 } while(tmp != dir);
1b09f2c0 249
98663823 250 return 0;
1b09f2c0 251}
2a59a681 252
89cd7793
QH
253extern void remove_trailing_slashes(char *p)
254{
255 int l = strlen(p);
256 while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
257 p[l] = '\0';
258}
259
d0386d66 260static char *copy_global_config_value(char *p)
2a59a681
SH
261{
262 int len = strlen(p);
263 char *retbuf;
264
265 if (len < 1)
266 return NULL;
267 if (p[len-1] == '\n') {
268 p[len-1] = '\0';
269 len--;
270 }
271 retbuf = malloc(len+1);
272 if (!retbuf)
273 return NULL;
274 strcpy(retbuf, p);
275 return retbuf;
276}
277
31a95fec 278#define DEFAULT_VG "lxc"
055af165 279#define DEFAULT_THIN_POOL "lxc"
31a95fec 280#define DEFAULT_ZFSROOT "lxc"
67e571de 281
593e8478 282const char *lxc_global_config_value(const char *option_name)
31a95fec 283{
74a3920a 284 static const char * const options[][2] = {
2e59ba02
SG
285 { "lxc.bdev.lvm.vg", DEFAULT_VG },
286 { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
287 { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT },
288 { "lxc.lxcpath", NULL },
289 { "lxc.default_config", NULL },
5e1c5795 290 { "lxc.cgroup.pattern", NULL },
2e59ba02 291 { "lxc.cgroup.use", NULL },
d0386d66
CS
292 { NULL, NULL },
293 };
4878dac4 294
93c379f0 295 /* placed in the thread local storage pool for non-bionic targets */
babbea4b
ÇO
296#ifdef HAVE_TLS
297 static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
298#else
91664352 299 static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
babbea4b 300#endif
48921d92
SH
301
302 /* user_config_path is freed as soon as it is used */
4878dac4 303 char *user_config_path = NULL;
48921d92
SH
304
305 /*
306 * The following variables are freed at bottom unconditionally.
307 * So NULL the value if it is to be returned to the caller
308 */
9e8be781 309 char *user_default_config_path = NULL;
4878dac4 310 char *user_lxc_path = NULL;
5e1c5795 311 char *user_cgroup_pattern = NULL;
4878dac4
SG
312
313 if (geteuid() > 0) {
6ed46d9e
AM
314 const char *user_home = getenv("HOME");
315 if (!user_home)
e99facec 316 user_home = "/";
4878dac4
SG
317
318 user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
9e8be781 319 user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
4878dac4
SG
320 user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
321
322 sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
9e8be781 323 sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
4878dac4 324 sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
89a4ec73 325 user_cgroup_pattern = strdup("lxc/%n");
4878dac4
SG
326 }
327 else {
328 user_config_path = strdup(LXC_GLOBAL_CONF);
9e8be781 329 user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
4878dac4 330 user_lxc_path = strdup(LXCPATH);
5e1c5795 331 user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
4878dac4
SG
332 }
333
74a3920a 334 const char * const (*ptr)[2];
d0386d66
CS
335 size_t i;
336 char buf[1024], *p, *p2;
337 FILE *fin = NULL;
338
339 for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
340 if (!strcmp(option_name, (*ptr)[0]))
341 break;
342 }
343 if (!(*ptr)[0]) {
4878dac4 344 free(user_config_path);
9e8be781 345 free(user_default_config_path);
4878dac4 346 free(user_lxc_path);
5e1c5795 347 free(user_cgroup_pattern);
d0386d66
CS
348 errno = EINVAL;
349 return NULL;
350 }
052616eb 351
052616eb 352 if (values[i]) {
4878dac4 353 free(user_config_path);
9e8be781 354 free(user_default_config_path);
4878dac4 355 free(user_lxc_path);
5e1c5795 356 free(user_cgroup_pattern);
babbea4b 357 return values[i];
052616eb 358 }
31a95fec 359
4878dac4
SG
360 fin = fopen_cloexec(user_config_path, "r");
361 free(user_config_path);
31a95fec
SH
362 if (fin) {
363 while (fgets(buf, 1024, fin)) {
364 if (buf[0] == '#')
365 continue;
d0386d66 366 p = strstr(buf, option_name);
31a95fec
SH
367 if (!p)
368 continue;
d0386d66
CS
369 /* see if there was just white space in front
370 * of the option name
371 */
372 for (p2 = buf; p2 < p; p2++) {
373 if (*p2 != ' ' && *p2 != '\t')
374 break;
375 }
376 if (p2 < p)
377 continue;
31a95fec
SH
378 p = strchr(p, '=');
379 if (!p)
380 continue;
d0386d66
CS
381 /* see if there was just white space after
382 * the option name
383 */
384 for (p2 += strlen(option_name); p2 < p; p2++) {
385 if (*p2 != ' ' && *p2 != '\t')
386 break;
387 }
388 if (p2 < p)
389 continue;
31a95fec
SH
390 p++;
391 while (*p && (*p == ' ' || *p == '\t')) p++;
392 if (!*p)
393 continue;
f407c5e4 394
f407c5e4
SG
395 if (strcmp(option_name, "lxc.lxcpath") == 0) {
396 free(user_lxc_path);
397 user_lxc_path = copy_global_config_value(p);
398 remove_trailing_slashes(user_lxc_path);
399 values[i] = user_lxc_path;
a1c9a9c9 400 user_lxc_path = NULL;
f407c5e4
SG
401 goto out;
402 }
403
404 values[i] = copy_global_config_value(p);
31a95fec
SH
405 goto out;
406 }
407 }
d0386d66 408 /* could not find value, use default */
9e8be781 409 if (strcmp(option_name, "lxc.lxcpath") == 0) {
f407c5e4 410 remove_trailing_slashes(user_lxc_path);
4878dac4 411 values[i] = user_lxc_path;
48921d92 412 user_lxc_path = NULL;
9e8be781
SG
413 }
414 else if (strcmp(option_name, "lxc.default_config") == 0) {
415 values[i] = user_default_config_path;
48921d92 416 user_default_config_path = NULL;
5e1c5795
KY
417 }
418 else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
419 values[i] = user_cgroup_pattern;
48921d92 420 user_cgroup_pattern = NULL;
9e8be781 421 }
48921d92 422 else
4878dac4 423 values[i] = (*ptr)[1];
48921d92 424
d0386d66
CS
425 /* special case: if default value is NULL,
426 * and there is no config, don't view that
427 * as an error... */
428 if (!values[i])
429 errno = 0;
31a95fec
SH
430
431out:
432 if (fin)
433 fclose(fin);
41f68357 434
48921d92
SH
435 free(user_cgroup_pattern);
436 free(user_default_config_path);
437 free(user_lxc_path);
438
babbea4b 439 return values[i];
31a95fec
SH
440}
441
44b9ae4b 442char *get_rundir()
9e60f51d 443{
97a696c6
SG
444 char *rundir;
445 const char *homedir;
9e60f51d 446
d6470e71 447 if (geteuid() == 0) {
c580b8d2 448 rundir = strdup(RUNTIME_PATH);
d6470e71
SG
449 return rundir;
450 }
97a696c6
SG
451
452 rundir = getenv("XDG_RUNTIME_DIR");
44b9ae4b
SG
453 if (rundir) {
454 rundir = strdup(rundir);
455 return rundir;
456 }
97a696c6 457
44b9ae4b
SG
458 INFO("XDG_RUNTIME_DIR isn't set in the environment.");
459 homedir = getenv("HOME");
460 if (!homedir) {
461 ERROR("HOME isn't set in the environment.");
462 return NULL;
97a696c6
SG
463 }
464
44b9ae4b
SG
465 rundir = malloc(sizeof(char) * (17 + strlen(homedir)));
466 sprintf(rundir, "%s/.cache/lxc/run/", homedir);
467
9e60f51d
DE
468 return rundir;
469}
470
9be53773
SH
471int wait_for_pid(pid_t pid)
472{
473 int status, ret;
474
475again:
476 ret = waitpid(pid, &status, 0);
477 if (ret == -1) {
71b9b8ed 478 if (errno == EINTR)
9be53773
SH
479 goto again;
480 return -1;
481 }
482 if (ret != pid)
483 goto again;
484 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
485 return -1;
486 return 0;
487}
c797a220
CS
488
489int lxc_wait_for_pid_status(pid_t pid)
490{
491 int status, ret;
492
493again:
494 ret = waitpid(pid, &status, 0);
495 if (ret == -1) {
496 if (errno == EINTR)
497 goto again;
498 return -1;
499 }
500 if (ret != pid)
501 goto again;
502 return status;
503}
92f023dc 504
650468bb 505ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
92f023dc 506{
650468bb 507 ssize_t ret;
92f023dc
CS
508again:
509 ret = write(fd, buf, count);
510 if (ret < 0 && errno == EINTR)
511 goto again;
512 return ret;
513}
514
650468bb 515ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
92f023dc 516{
650468bb 517 ssize_t ret;
92f023dc
CS
518again:
519 ret = read(fd, buf, count);
520 if (ret < 0 && errno == EINTR)
521 goto again;
522 return ret;
523}
524
650468bb 525ssize_t lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf)
92f023dc 526{
650468bb 527 ssize_t ret;
92f023dc
CS
528 ret = lxc_read_nointr(fd, buf, count);
529 if (ret <= 0)
530 return ret;
650468bb 531 if ((size_t)ret != count)
92f023dc
CS
532 return -1;
533 if (expected_buf && memcmp(buf, expected_buf, count) != 0) {
534 errno = EINVAL;
535 return -1;
536 }
537 return ret;
538}
3ce74686
SH
539
540#if HAVE_LIBGNUTLS
541#include <gnutls/gnutls.h>
542#include <gnutls/crypto.h>
41246cee
DE
543
544__attribute__((constructor))
545static void gnutls_lxc_init(void)
546{
547 gnutls_global_init();
548}
549
3ce74686
SH
550int sha1sum_file(char *fnam, unsigned char *digest)
551{
552 char *buf;
553 int ret;
554 FILE *f;
555 long flen;
556
557 if (!fnam)
558 return -1;
025ed0f3 559 f = fopen_cloexec(fnam, "r");
7be677a8 560 if (!f) {
3ce74686
SH
561 SYSERROR("Error opening template");
562 return -1;
563 }
564 if (fseek(f, 0, SEEK_END) < 0) {
565 SYSERROR("Error seeking to end of template");
dd1d77f9 566 fclose(f);
3ce74686
SH
567 return -1;
568 }
569 if ((flen = ftell(f)) < 0) {
570 SYSERROR("Error telling size of template");
dd1d77f9 571 fclose(f);
3ce74686
SH
572 return -1;
573 }
574 if (fseek(f, 0, SEEK_SET) < 0) {
575 SYSERROR("Error seeking to start of template");
dd1d77f9 576 fclose(f);
3ce74686
SH
577 return -1;
578 }
579 if ((buf = malloc(flen+1)) == NULL) {
580 SYSERROR("Out of memory");
dd1d77f9 581 fclose(f);
3ce74686
SH
582 return -1;
583 }
584 if (fread(buf, 1, flen, f) != flen) {
585 SYSERROR("Failure reading template");
586 free(buf);
dd1d77f9 587 fclose(f);
3ce74686
SH
588 return -1;
589 }
dd1d77f9 590 if (fclose(f) < 0) {
3ce74686
SH
591 SYSERROR("Failre closing template");
592 free(buf);
593 return -1;
594 }
595 buf[flen] = '\0';
596 ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
597 free(buf);
598 return ret;
599}
600#endif
61a1d519
CS
601
602char** lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup)
603{
604 va_list ap2;
605 size_t count = 1 + skip;
606 char **result;
607
608 /* first determine size of argument list, we don't want to reallocate
609 * constantly...
610 */
611 va_copy(ap2, ap);
612 while (1) {
613 char* arg = va_arg(ap2, char*);
614 if (!arg)
615 break;
616 count++;
617 }
618 va_end(ap2);
619
620 result = calloc(count, sizeof(char*));
621 if (!result)
622 return NULL;
623 count = skip;
624 while (1) {
625 char* arg = va_arg(ap, char*);
626 if (!arg)
627 break;
628 arg = do_strdup ? strdup(arg) : arg;
629 if (!arg)
630 goto oom;
631 result[count++] = arg;
632 }
633
634 /* calloc has already set last element to NULL*/
635 return result;
636
637oom:
638 free(result);
639 return NULL;
640}
641
642const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
643{
644 return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
645}
db27c8d7
CS
646
647FILE *fopen_cloexec(const char *path, const char *mode)
648{
649 int open_mode = 0;
650 int step = 0;
651 int fd;
652 int saved_errno = 0;
653 FILE *ret;
654
655 if (!strncmp(mode, "r+", 2)) {
656 open_mode = O_RDWR;
657 step = 2;
658 } else if (!strncmp(mode, "r", 1)) {
659 open_mode = O_RDONLY;
660 step = 1;
661 } else if (!strncmp(mode, "w+", 2)) {
662 open_mode = O_RDWR | O_TRUNC | O_CREAT;
663 step = 2;
664 } else if (!strncmp(mode, "w", 1)) {
665 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
666 step = 1;
667 } else if (!strncmp(mode, "a+", 2)) {
668 open_mode = O_RDWR | O_CREAT | O_APPEND;
669 step = 2;
670 } else if (!strncmp(mode, "a", 1)) {
671 open_mode = O_WRONLY | O_CREAT | O_APPEND;
672 step = 1;
673 }
674 for (; mode[step]; step++)
675 if (mode[step] == 'x')
676 open_mode |= O_EXCL;
677 open_mode |= O_CLOEXEC;
678
82371fdd 679 fd = open(path, open_mode, 0666);
db27c8d7
CS
680 if (fd < 0)
681 return NULL;
682
683 ret = fdopen(fd, mode);
684 saved_errno = errno;
685 if (!ret)
686 close(fd);
687 errno = saved_errno;
688 return ret;
689}
502657d5 690
ebec9176
AM
691extern struct lxc_popen_FILE *lxc_popen(const char *command)
692{
693 struct lxc_popen_FILE *fp = NULL;
694 int parent_end = -1, child_end = -1;
695 int pipe_fds[2];
696 pid_t child_pid;
697
698 int r = pipe2(pipe_fds, O_CLOEXEC);
699
700 if (r < 0) {
701 ERROR("pipe2 failure");
702 return NULL;
703 }
704
705 parent_end = pipe_fds[0];
706 child_end = pipe_fds[1];
707
708 child_pid = fork();
709
710 if (child_pid == 0) {
711 /* child */
712 int child_std_end = STDOUT_FILENO;
713
714 if (child_end != child_std_end) {
715 /* dup2() doesn't dup close-on-exec flag */
716 dup2(child_end, child_std_end);
717
718 /* it's safe not to close child_end here
719 * as it's marked close-on-exec anyway
720 */
721 } else {
722 /*
723 * The descriptor is already the one we will use.
724 * But it must not be marked close-on-exec.
725 * Undo the effects.
726 */
57d2be54
SG
727 if (fcntl(child_end, F_SETFD, 0) != 0) {
728 SYSERROR("Failed to remove FD_CLOEXEC from fd.");
729 exit(127);
730 }
ebec9176
AM
731 }
732
733 /*
734 * Unblock signals.
735 * This is the main/only reason
736 * why we do our lousy popen() emulation.
737 */
738 {
739 sigset_t mask;
740 sigfillset(&mask);
741 sigprocmask(SIG_UNBLOCK, &mask, NULL);
742 }
743
744 execl("/bin/sh", "sh", "-c", command, (char *) NULL);
745 exit(127);
746 }
747
748 /* parent */
749
750 close(child_end);
751 child_end = -1;
752
753 if (child_pid < 0) {
754 ERROR("fork failure");
755 goto error;
756 }
757
758 fp = calloc(1, sizeof(*fp));
759 if (!fp) {
760 ERROR("failed to allocate memory");
761 goto error;
762 }
763
764 fp->f = fdopen(parent_end, "r");
765 if (!fp->f) {
766 ERROR("fdopen failure");
767 goto error;
768 }
769
770 fp->child_pid = child_pid;
771
772 return fp;
773
774error:
775
776 if (fp) {
777 if (fp->f) {
778 fclose(fp->f);
779 parent_end = -1; /* so we do not close it second time */
780 }
781
782 free(fp);
783 }
784
ebec9176
AM
785 if (parent_end != -1)
786 close(parent_end);
787
788 return NULL;
789}
790
ebec9176
AM
791extern int lxc_pclose(struct lxc_popen_FILE *fp)
792{
793 FILE *f = NULL;
794 pid_t child_pid = 0;
795 int wstatus = 0;
796 pid_t wait_pid;
797
798 if (fp) {
799 f = fp->f;
800 child_pid = fp->child_pid;
801 /* free memory (we still need to close file stream) */
802 free(fp);
803 fp = NULL;
804 }
805
806 if (!f || fclose(f)) {
807 ERROR("fclose failure");
808 return -1;
809 }
810
811 do {
812 wait_pid = waitpid(child_pid, &wstatus, 0);
813 } while (wait_pid == -1 && errno == EINTR);
814
815 if (wait_pid == -1) {
816 ERROR("waitpid failure");
817 return -1;
818 }
819
820 return wstatus;
821}
822
502657d5
CS
823char *lxc_string_replace(const char *needle, const char *replacement, const char *haystack)
824{
825 ssize_t len = -1, saved_len = -1;
826 char *result = NULL;
827 size_t replacement_len = strlen(replacement);
828 size_t needle_len = strlen(needle);
829
830 /* should be executed exactly twice */
831 while (len == -1 || result == NULL) {
832 char *p;
833 char *last_p;
834 ssize_t part_len;
835
836 if (len != -1) {
837 result = calloc(1, len + 1);
838 if (!result)
839 return NULL;
840 saved_len = len;
841 }
842
843 len = 0;
844
845 for (last_p = (char *)haystack, p = strstr(last_p, needle); p; last_p = p, p = strstr(last_p, needle)) {
846 part_len = (ssize_t)(p - last_p);
847 if (result && part_len > 0)
848 memcpy(&result[len], last_p, part_len);
849 len += part_len;
850 if (result && replacement_len > 0)
851 memcpy(&result[len], replacement, replacement_len);
852 len += replacement_len;
853 p += needle_len;
854 }
855 part_len = strlen(last_p);
856 if (result && part_len > 0)
857 memcpy(&result[len], last_p, part_len);
858 len += part_len;
859 }
860
861 /* make sure we did the same thing twice,
862 * once for calculating length, the other
863 * time for copying data */
864 assert(saved_len == len);
865 /* make sure we didn't overwrite any buffer,
866 * due to calloc the string should be 0-terminated */
867 assert(result[len] == '\0');
868
869 return result;
870}
871
872bool lxc_string_in_array(const char *needle, const char **haystack)
873{
874 for (; haystack && *haystack; haystack++)
875 if (!strcmp(needle, *haystack))
876 return true;
877 return false;
878}
879
880char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix)
881{
882 char *result;
883 char **p;
884 size_t sep_len = strlen(sep);
885 size_t result_len = use_as_prefix * sep_len;
886
887 /* calculate new string length */
888 for (p = (char **)parts; *p; p++)
889 result_len += (p > (char **)parts) * sep_len + strlen(*p);
890
891 result = calloc(result_len + 1, 1);
892 if (!result)
893 return NULL;
894
895 if (use_as_prefix)
896 strcpy(result, sep);
897 for (p = (char **)parts; *p; p++) {
898 if (p > (char **)parts)
899 strcat(result, sep);
900 strcat(result, *p);
901 }
902
903 return result;
904}
905
906char **lxc_normalize_path(const char *path)
907{
908 char **components;
909 char **p;
910 size_t components_len = 0;
911 size_t pos = 0;
912
913 components = lxc_string_split(path, '/');
914 if (!components)
915 return NULL;
916 for (p = components; *p; p++)
917 components_len++;
918
919 /* resolve '.' and '..' */
920 for (pos = 0; pos < components_len; ) {
921 if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) {
922 /* eat this element */
923 free(components[pos]);
924 memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos));
925 components_len--;
926 } else if (!strcmp(components[pos], "..")) {
927 /* eat this and the previous element */
928 free(components[pos - 1]);
929 free(components[pos]);
930 memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos));
931 components_len -= 2;
932 pos--;
933 } else {
934 pos++;
935 }
936 }
937
938 return components;
939}
940
24b51482
CS
941char *lxc_append_paths(const char *first, const char *second)
942{
943 size_t len = strlen(first) + strlen(second) + 1;
944 const char *pattern = "%s%s";
945 char *result = NULL;
946
947 if (second[0] != '/') {
948 len += 1;
949 pattern = "%s/%s";
950 }
951
952 result = calloc(1, len);
953 if (!result)
954 return NULL;
955
956 snprintf(result, len, pattern, first, second);
957 return result;
958}
959
502657d5
CS
960bool lxc_string_in_list(const char *needle, const char *haystack, char _sep)
961{
962 char *token, *str, *saveptr = NULL;
963 char sep[2] = { _sep, '\0' };
964
965 if (!haystack || !needle)
966 return 0;
967
968 str = alloca(strlen(haystack)+1);
969 strcpy(str, haystack);
970 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
971 if (strcmp(needle, token) == 0)
972 return 1;
973 }
974
975 return 0;
976}
977
978char **lxc_string_split(const char *string, char _sep)
979{
980 char *token, *str, *saveptr = NULL;
981 char sep[2] = { _sep, '\0' };
982 char **result = NULL;
983 size_t result_capacity = 0;
984 size_t result_count = 0;
985 int r, saved_errno;
986
987 if (!string)
988 return calloc(1, sizeof(char *));
989
990 str = alloca(strlen(string)+1);
991 strcpy(str, string);
992 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
993 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
994 if (r < 0)
995 goto error_out;
996 result[result_count] = strdup(token);
997 if (!result[result_count])
998 goto error_out;
999 result_count++;
1000 }
1001
1002 /* if we allocated too much, reduce it */
1003 return realloc(result, (result_count + 1) * sizeof(char *));
1004error_out:
1005 saved_errno = errno;
1006 lxc_free_array((void **)result, free);
1007 errno = saved_errno;
1008 return NULL;
1009}
1010
1011char **lxc_string_split_and_trim(const char *string, char _sep)
1012{
1013 char *token, *str, *saveptr = NULL;
1014 char sep[2] = { _sep, '\0' };
1015 char **result = NULL;
1016 size_t result_capacity = 0;
1017 size_t result_count = 0;
1018 int r, saved_errno;
1019 size_t i = 0;
1020
1021 if (!string)
1022 return calloc(1, sizeof(char *));
1023
1024 str = alloca(strlen(string)+1);
1025 strcpy(str, string);
1026 for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
1027 while (token[0] == ' ' || token[0] == '\t')
1028 token++;
1029 i = strlen(token);
1030 while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
1031 token[i - 1] = '\0';
1032 i--;
1033 }
1034 r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
1035 if (r < 0)
1036 goto error_out;
1037 result[result_count] = strdup(token);
1038 if (!result[result_count])
1039 goto error_out;
1040 result_count++;
1041 }
1042
1043 /* if we allocated too much, reduce it */
1044 return realloc(result, (result_count + 1) * sizeof(char *));
1045error_out:
1046 saved_errno = errno;
1047 lxc_free_array((void **)result, free);
1048 errno = saved_errno;
1049 return NULL;
1050}
1051
1052void lxc_free_array(void **array, lxc_free_fn element_free_fn)
1053{
1054 void **p;
1055 for (p = array; p && *p; p++)
1056 element_free_fn(*p);
1057 free((void*)array);
1058}
1059
1060int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment)
1061{
1062 size_t new_capacity;
1063 void **new_array;
1064
1065 /* first time around, catch some trivial mistakes of the user
1066 * only initializing one of these */
1067 if (!*array || !*capacity) {
1068 *array = NULL;
1069 *capacity = 0;
1070 }
1071
1072 new_capacity = *capacity;
1073 while (new_size + 1 > new_capacity)
1074 new_capacity += capacity_increment;
1075 if (new_capacity != *capacity) {
1076 /* we have to reallocate */
1077 new_array = realloc(*array, new_capacity * sizeof(void *));
1078 if (!new_array)
1079 return -1;
1080 memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *));
1081 *array = new_array;
1082 *capacity = new_capacity;
1083 }
1084
1085 /* array has sufficient elements */
1086 return 0;
1087}
1088
1089size_t lxc_array_len(void **array)
1090{
1091 void **p;
1092 size_t result = 0;
1093
1094 for (p = array; p && *p; p++)
1095 result++;
1096
1097 return result;
1098}
1099
0e95426b
CS
1100int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool add_newline)
1101{
1102 int fd, saved_errno;
1103 ssize_t ret;
1104
1105 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0666);
1106 if (fd < 0)
1107 return -1;
1108 ret = lxc_write_nointr(fd, buf, count);
1109 if (ret < 0)
799f29ab 1110 goto out_error;
0e95426b
CS
1111 if ((size_t)ret != count)
1112 goto out_error;
1113 if (add_newline) {
1114 ret = lxc_write_nointr(fd, "\n", 1);
1115 if (ret != 1)
1116 goto out_error;
1117 }
1118 close(fd);
1119 return 0;
1120
1121out_error:
1122 saved_errno = errno;
1123 close(fd);
1124 errno = saved_errno;
1125 return -1;
1126}
1127
1128int lxc_read_from_file(const char *filename, void* buf, size_t count)
1129{
1130 int fd = -1, saved_errno;
1131 ssize_t ret;
1132
1133 fd = open(filename, O_RDONLY | O_CLOEXEC);
1134 if (fd < 0)
1135 return -1;
1136
1137 if (!buf || !count) {
1138 char buf2[100];
1139 size_t count2 = 0;
1140 while ((ret = read(fd, buf2, 100)) > 0)
1141 count2 += ret;
1142 if (ret >= 0)
1143 ret = count2;
1144 } else {
1145 memset(buf, 0, count);
1146 ret = read(fd, buf, count);
1147 }
1148
1149 if (ret < 0)
1150 ERROR("read %s: %s", filename, strerror(errno));
1151
1152 saved_errno = errno;
1153 close(fd);
1154 errno = saved_errno;
1155 return ret;
1156}
799f29ab
ÇO
1157
1158void **lxc_append_null_to_array(void **array, size_t count)
1159{
1160 void **temp;
1161
1162 /* Append NULL to the array */
1163 if (count) {
1164 temp = realloc(array, (count + 1) * sizeof(*array));
1165 if (!temp) {
1166 int i;
1167 for (i = 0; i < count; i++)
1168 free(array[i]);
1169 free(array);
1170 return NULL;
1171 }
1172 array = temp;
1173 array[count] = NULL;
1174 }
1175 return array;
1176}
508c263e
SH
1177
1178int randseed(bool srand_it)
1179{
1180 /*
1181 srand pre-seed function based on /dev/urandom
1182 */
1183 unsigned int seed=time(NULL)+getpid();
1184
1185 FILE *f;
1186 f = fopen("/dev/urandom", "r");
1187 if (f) {
1188 int ret = fread(&seed, sizeof(seed), 1, f);
1189 if (ret != 1)
1190 DEBUG("unable to fread /dev/urandom, %s, fallback to time+pid rand seed", strerror(errno));
1191 fclose(f);
1192 }
1193
1194 if (srand_it)
1195 srand(seed);
1196
1197 return seed;
1198}
5d897655
SH
1199
1200uid_t get_ns_uid(uid_t orig)
1201{
1202 char *line = NULL;
1203 size_t sz = 0;
1204 uid_t nsid, hostid, range;
1205 FILE *f = fopen("/proc/self/uid_map", "r");
1206 if (!f)
1207 return 0;
1208
1209 while (getline(&line, &sz, f) != -1) {
1210 if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
1211 continue;
1212 if (hostid <= orig && hostid + range > orig) {
1213 nsid += orig - hostid;
1214 goto found;
1215 }
1216 }
1217
1218 nsid = 0;
1219found:
1220 fclose(f);
1221 free(line);
1222 return nsid;
1223}
c476bdce
SH
1224
1225bool dir_exists(const char *path)
1226{
1227 struct stat sb;
1228 int ret;
1229
1230 ret = stat(path, &sb);
1231 if (ret < 0)
1232 // could be something other than eexist, just say no
1233 return false;
1234 return S_ISDIR(sb.st_mode);
1235}
93c379f0
ÇO
1236
1237/* Note we don't use SHA-1 here as we don't want to depend on HAVE_GNUTLS.
1238 * FNV has good anti collision properties and we're not worried
1239 * about pre-image resistance or one-way-ness, we're just trying to make
1240 * the name unique in the 108 bytes of space we have.
1241 */
1242uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
1243{
1244 unsigned char *bp;
1245
1246 for(bp = buf; bp < (unsigned char *)buf + len; bp++)
1247 {
1248 /* xor the bottom with the current octet */
1249 hval ^= (uint64_t)*bp;
1250
1251 /* gcc optimised:
1252 * multiply by the 64 bit FNV magic prime mod 2^64
1253 */
1254 hval += (hval << 1) + (hval << 4) + (hval << 5) +
1255 (hval << 7) + (hval << 8) + (hval << 40);
1256 }
1257
1258 return hval;
1259}
2c6f3fc9
SH
1260
1261/*
1262 * Detect whether / is mounted MS_SHARED. The only way I know of to
1263 * check that is through /proc/self/mountinfo.
1264 * I'm only checking for /. If the container rootfs or mount location
1265 * is MS_SHARED, but not '/', then you're out of luck - figuring that
1266 * out would be too much work to be worth it.
1267 */
1268#define LINELEN 4096
1269int detect_shared_rootfs(void)
1270{
1271 char buf[LINELEN], *p;
1272 FILE *f;
1273 int i;
1274 char *p2;
1275
1276 f = fopen("/proc/self/mountinfo", "r");
1277 if (!f)
1278 return 0;
1279 while (fgets(buf, LINELEN, f)) {
1280 for (p = buf, i=0; p && i < 4; i++)
b7f954bb 1281 p = strchr(p+1, ' ');
2c6f3fc9
SH
1282 if (!p)
1283 continue;
b7f954bb 1284 p2 = strchr(p+1, ' ');
2c6f3fc9
SH
1285 if (!p2)
1286 continue;
1287 *p2 = '\0';
1288 if (strcmp(p+1, "/") == 0) {
1289 // this is '/'. is it shared?
b7f954bb 1290 p = strchr(p2+1, ' ');
2c6f3fc9
SH
1291 if (p && strstr(p, "shared:")) {
1292 fclose(f);
1293 return 1;
1294 }
1295 }
1296 }
1297 fclose(f);
1298 return 0;
1299}
0e6e3a41 1300
51d0854c
DY
1301bool switch_to_ns(pid_t pid, const char *ns) {
1302 int fd, ret;
1303 char nspath[MAXPATHLEN];
1304
1305 /* Switch to new ns */
1306 ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns);
1307 if (ret < 0 || ret >= MAXPATHLEN)
1308 return false;
1309
1310 fd = open(nspath, O_RDONLY);
1311 if (fd < 0) {
1312 SYSERROR("failed to open %s", nspath);
1313 return false;
1314 }
1315
1316 ret = setns(fd, 0);
1317 if (ret) {
1318 SYSERROR("failed to set process %d to %s of %d.", pid, ns, fd);
1319 close(fd);
1320 return false;
1321 }
1322 close(fd);
1323 return true;
1324}
1325
b7f954bb
SH
1326/*
1327 * looking at fs/proc_namespace.c, it appears we can
1328 * actually expect the rootfs entry to very specifically contain
1329 * " - rootfs rootfs "
1330 * IIUC, so long as we've chrooted so that rootfs is not our root,
1331 * the rootfs entry should always be skipped in mountinfo contents.
1332 */
1333int detect_ramfs_rootfs(void)
1334{
1335 char buf[LINELEN], *p;
1336 FILE *f;
1337 int i;
1338 char *p2;
1339
1340 f = fopen("/proc/self/mountinfo", "r");
1341 if (!f)
1342 return 0;
1343 while (fgets(buf, LINELEN, f)) {
1344 for (p = buf, i=0; p && i < 4; i++)
1345 p = strchr(p+1, ' ');
1346 if (!p)
1347 continue;
1348 p2 = strchr(p+1, ' ');
1349 if (!p2)
1350 continue;
1351 *p2 = '\0';
1352 if (strcmp(p+1, "/") == 0) {
1353 // this is '/'. is it the ramfs?
1354 p = strchr(p2+1, '-');
1355 if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) {
1356 fclose(f);
1357 return 1;
1358 }
1359 }
1360 }
1361 fclose(f);
1362 return 0;
1363}
1364
9d9c111c 1365char *on_path(char *cmd, const char *rootfs) {
0e6e3a41
SG
1366 char *path = NULL;
1367 char *entry = NULL;
1368 char *saveptr = NULL;
1369 char cmdpath[MAXPATHLEN];
1370 int ret;
1371
1372 path = getenv("PATH");
1373 if (!path)
8afb3e61 1374 return NULL;
0e6e3a41
SG
1375
1376 path = strdup(path);
1377 if (!path)
8afb3e61 1378 return NULL;
0e6e3a41
SG
1379
1380 entry = strtok_r(path, ":", &saveptr);
1381 while (entry) {
9d9c111c
SH
1382 if (rootfs)
1383 ret = snprintf(cmdpath, MAXPATHLEN, "%s/%s/%s", rootfs, entry, cmd);
1384 else
1385 ret = snprintf(cmdpath, MAXPATHLEN, "%s/%s", entry, cmd);
0e6e3a41
SG
1386
1387 if (ret < 0 || ret >= MAXPATHLEN)
1388 goto next_loop;
1389
1390 if (access(cmdpath, X_OK) == 0) {
1391 free(path);
8afb3e61 1392 return strdup(cmdpath);
0e6e3a41
SG
1393 }
1394
1395next_loop:
b707e368 1396 entry = strtok_r(NULL, ":", &saveptr);
0e6e3a41
SG
1397 }
1398
1399 free(path);
8afb3e61 1400 return NULL;
0e6e3a41 1401}
76a26f55
SH
1402
1403bool file_exists(const char *f)
1404{
1405 struct stat statbuf;
1406
1407 return stat(f, &statbuf) == 0;
1408}
9d9c111c
SH
1409
1410/* historically lxc-init has been under /usr/lib/lxc and under
1411 * /usr/lib/$ARCH/lxc. It now lives as $prefix/sbin/init.lxc.
1412 */
1413char *choose_init(const char *rootfs)
1414{
1415 char *retv = NULL;
370ec268
SF
1416 const char *empty = "",
1417 *tmp;
9d9c111c
SH
1418 int ret, env_set = 0;
1419 struct stat mystat;
1420
1421 if (!getenv("PATH")) {
1422 if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 0))
1423 SYSERROR("Failed to setenv");
1424 env_set = 1;
1425 }
1426
1427 retv = on_path("init.lxc", rootfs);
1428
1429 if (env_set) {
1430 if (unsetenv("PATH"))
1431 SYSERROR("Failed to unsetenv");
1432 }
1433
1434 if (retv)
1435 return retv;
1436
1437 retv = malloc(PATH_MAX);
1438 if (!retv)
1439 return NULL;
1440
1441 if (rootfs)
370ec268 1442 tmp = rootfs;
9d9c111c 1443 else
370ec268
SF
1444 tmp = empty;
1445
1446 ret = snprintf(retv, PATH_MAX, "%s/%s/%s", tmp, SBINDIR, "/init.lxc");
9d9c111c
SH
1447 if (ret < 0 || ret >= PATH_MAX) {
1448 ERROR("pathname too long");
1449 goto out1;
1450 }
1451
1452 ret = stat(retv, &mystat);
1453 if (ret == 0)
1454 return retv;
1455
370ec268 1456 ret = snprintf(retv, PATH_MAX, "%s/%s/%s", tmp, LXCINITDIR, "/lxc/lxc-init");
9d9c111c
SH
1457 if (ret < 0 || ret >= PATH_MAX) {
1458 ERROR("pathname too long");
1459 goto out1;
1460 }
1461
1462 ret = stat(retv, &mystat);
1463 if (ret == 0)
1464 return retv;
1465
370ec268 1466 ret = snprintf(retv, PATH_MAX, "%s/usr/lib/lxc/lxc-init", tmp);
9d9c111c
SH
1467 if (ret < 0 || ret >= PATH_MAX) {
1468 ERROR("pathname too long");
1469 goto out1;
1470 }
1471 ret = stat(retv, &mystat);
1472 if (ret == 0)
1473 return retv;
1474
370ec268 1475 ret = snprintf(retv, PATH_MAX, "%s/sbin/lxc-init", tmp);
9d9c111c
SH
1476 if (ret < 0 || ret >= PATH_MAX) {
1477 ERROR("pathname too long");
1478 goto out1;
1479 }
1480 ret = stat(retv, &mystat);
1481 if (ret == 0)
1482 return retv;
1483
1484 /*
1485 * Last resort, look for the statically compiled init.lxc which we
1486 * hopefully bind-mounted in.
1487 * If we are called during container setup, and we get to this point,
1488 * then the init.lxc.static from the host will need to be bind-mounted
1489 * in. So we return NULL here to indicate that.
1490 */
1491 if (rootfs)
1492 goto out1;
1493
1494 ret = snprintf(retv, PATH_MAX, "/init.lxc.static");
1495 if (ret < 0 || ret >= PATH_MAX) {
1496 WARN("Nonsense - name /lxc.init.static too long");
1497 goto out1;
1498 }
1499 ret = stat(retv, &mystat);
1500 if (ret == 0)
1501 return retv;
1502
1503out1:
1504 free(retv);
1505 return NULL;
1506}
735f2c6e
TA
1507
1508int print_to_file(const char *file, const char *content)
1509{
1510 FILE *f;
1511 int ret = 0;
1512
1513 f = fopen(file, "w");
1514 if (!f)
1515 return -1;
1516 if (fprintf(f, "%s", content) != strlen(content))
1517 ret = -1;
1518 fclose(f);
1519 return ret;
1520}
e1daebd9
SH
1521
1522int is_dir(const char *path)
1523{
1524 struct stat statbuf;
1525 int ret = stat(path, &statbuf);
1526 if (ret == 0 && S_ISDIR(statbuf.st_mode))
1527 return 1;
1528 return 0;
1529}
6010a416
SG
1530
1531/*
1532 * Given the '-t' template option to lxc-create, figure out what to
1533 * do. If the template is a full executable path, use that. If it
1534 * is something like 'sshd', then return $templatepath/lxc-sshd.
1535 * On success return the template, on error return NULL.
1536 */
1537char *get_template_path(const char *t)
1538{
1539 int ret, len;
1540 char *tpath;
1541
1542 if (t[0] == '/' && access(t, X_OK) == 0) {
1543 tpath = strdup(t);
1544 return tpath;
1545 }
1546
1547 len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
1548 tpath = malloc(len);
1549 if (!tpath)
1550 return NULL;
1551 ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
1552 if (ret < 0 || ret >= len) {
1553 free(tpath);
1554 return NULL;
1555 }
1556 if (access(tpath, X_OK) < 0) {
1557 SYSERROR("bad template: %s", t);
1558 free(tpath);
1559 return NULL;
1560 }
1561
1562 return tpath;
1563}
0a4be28d
TA
1564
1565/*
1566 * Sets the process title to the specified title. Note:
1567 * 1. this function requires root to succeed
1568 * 2. it clears /proc/self/environ
1569 * 3. it may not succed (e.g. if title is longer than /proc/self/environ +
1570 * the original title)
1571 */
1572int setproctitle(char *title)
1573{
1574 char buf[2048], *tmp;
1575 FILE *f;
1576 int i, len, ret = 0;
1577 unsigned long arg_start, arg_end, env_start, env_end;
1578
1579 f = fopen_cloexec("/proc/self/stat", "r");
1580 if (!f) {
1581 return -1;
1582 }
1583
1584 tmp = fgets(buf, sizeof(buf), f);
1585 fclose(f);
1586 if (!tmp) {
1587 return -1;
1588 }
1589
1590 /* Skip the first 47 fields, column 48-51 are ARG_START and
1591 * ARG_END. */
1592 tmp = strchr(buf, ' ');
1593 for (i = 0; i < 46; i++) {
1594 if (!tmp)
1595 return -1;
1596 tmp = strchr(tmp+1, ' ');
1597 }
1598
73c1c887
SH
1599 if (!tmp)
1600 return -1;
1601
0a4be28d
TA
1602 i = sscanf(tmp, "%lu %lu %lu %lu", &arg_start, &arg_end, &env_start, &env_end);
1603 if (i != 4) {
1604 return -1;
1605 }
1606
96fe6d1d
TA
1607 /* Include the null byte here, because in the calculations below we
1608 * want to have room for it. */
1609 len = strlen(title) + 1;
1610
0a4be28d
TA
1611 /* We're truncating the environment, so we should use at most the
1612 * length of the argument + environment for the title. */
0a4be28d
TA
1613 if (len > env_end - arg_start) {
1614 arg_end = env_end;
1615 len = env_end - arg_start;
1616 } else {
1617 /* Only truncate the environment if we're actually going to
1618 * overwrite part of it. */
1619 if (len >= arg_end - arg_start) {
1620 env_start = env_end;
1621 }
1622 arg_end = arg_start + len;
1623 }
1624
96fe6d1d 1625 strcpy((char*)arg_start, title);
0a4be28d
TA
1626
1627 ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START, (long)arg_start, 0, 0);
1628 ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END, (long)arg_end, 0, 0);
1629 ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START, (long)env_start, 0, 0);
1630 ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END, (long)env_end, 0, 0);
1631
1632 return ret;
1633}