]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/overlay.c
stringutils: include stdarg for va_list
[mirror_lxc.git] / src / lxc / storage / overlay.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE 1
26 #endif
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "conf.h"
33 #include "config.h"
34 #include "confile.h"
35 #include "log.h"
36 #include "lxccontainer.h"
37 #include "macro.h"
38 #include "overlay.h"
39 #include "rsync.h"
40 #include "storage.h"
41 #include "storage_utils.h"
42 #include "utils.h"
43
44 lxc_log_define(overlay, lxc);
45
46 static char *ovl_name;
47 static char *ovl_version[] = {"overlay", "overlayfs"};
48
49 static char *ovl_detect_name(void);
50 static int ovl_do_rsync(const char *src, const char *dest,
51 struct lxc_conf *conf);
52 static int ovl_remount_on_enodev(const char *lower, const char *target,
53 const char *name, unsigned long mountflags,
54 const void *options);
55
56 int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char *oldname,
57 const char *cname, const char *oldpath, const char *lxcpath,
58 int snap, uint64_t newsize, struct lxc_conf *conf)
59 {
60 int ret;
61 const char *src;
62
63 if (!snap) {
64 ERROR("The overlay storage driver can only be used for "
65 "snapshots");
66 return -22;
67 }
68
69 if (!orig->src || !orig->dest)
70 return -1;
71
72 new->dest = must_make_path(lxcpath, cname, "rootfs", NULL);
73
74 ret = mkdir_p(new->dest, 0755);
75 if (ret < 0 && errno != EEXIST) {
76 SYSERROR("Failed to create directory \"%s\"", new->dest);
77 return -1;
78 }
79
80 if (am_guest_unpriv()) {
81 ret = chown_mapped_root(new->dest, conf);
82 if (ret < 0)
83 WARN("Failed to update ownership of %s", new->dest);
84 }
85
86 if (strcmp(orig->type, "dir") == 0) {
87 char *delta, *lastslash;
88 char *work;
89 int ret, len, lastslashidx;
90
91 /* If we have "/var/lib/lxc/c2/rootfs" then delta will be
92 * "/var/lib/lxc/c2/delta0".
93 */
94 lastslash = strrchr(new->dest, '/');
95 if (!lastslash) {
96 ERROR("Failed to detect \"/\" in string \"%s\"",
97 new->dest);
98 return -22;
99 }
100
101 if (strlen(lastslash) < STRLITERALLEN("/rootfs")) {
102 ERROR("Failed to detect \"/rootfs\" in string \"%s\"",
103 new->dest);
104 return -22;
105 }
106
107 lastslash++;
108 lastslashidx = lastslash - new->dest;
109
110 delta = malloc(lastslashidx + 7);
111 if (!delta) {
112 ERROR("Failed to allocate memory");
113 return -1;
114 }
115
116 memcpy(delta, new->dest, lastslashidx + 1);
117 memcpy(delta + lastslashidx, "delta0", STRLITERALLEN("delta0"));
118 delta[lastslashidx + STRLITERALLEN("delta0")] = '\0';
119
120 ret = mkdir(delta, 0755);
121 if (ret < 0 && errno != EEXIST) {
122 SYSERROR("Failed to create directory \"%s\"", delta);
123 free(delta);
124 return -1;
125 }
126
127 if (am_guest_unpriv()) {
128 ret = chown_mapped_root(delta, conf);
129 if (ret < 0)
130 WARN("Failed to update ownership of %s", delta);
131 }
132
133 /* Make workdir for overlayfs.v22 or higher:
134 * The workdir will be
135 * /var/lib/lxc/c2/olwork
136 * and is used to prepare files before they are atomically
137 * switched to the overlay destination. Workdirs need to be on
138 * the same filesystem as the upperdir so it's OK for it to be
139 * empty.
140 */
141 work = malloc(lastslashidx + 7);
142 if (!work) {
143 ERROR("Failed to allocate memory");
144 free(delta);
145 return -1;
146 }
147
148 memcpy(work, new->dest, lastslashidx + 1);
149 memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
150 work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
151
152 ret = mkdir(work, 0755);
153 if (ret < 0) {
154 SYSERROR("Failed to create directory \"%s\"", work);
155 free(delta);
156 free(work);
157 return -1;
158 }
159
160 if (am_guest_unpriv()) {
161 ret = chown_mapped_root(work, conf);
162 if (ret < 0)
163 WARN("Failed to update ownership of %s", work);
164 }
165 free(work);
166
167 /* strlen("overlay:") = 8
168 * +
169 * strlen(delta)
170 * +
171 * :
172 * +
173 * strlen(src)
174 * +
175 * \0
176 */
177 src = lxc_storage_get_path(orig->src, orig->type);
178 len = 8 + strlen(delta) + 1 + strlen(src) + 1;
179 new->src = malloc(len);
180 if (!new->src) {
181 ERROR("Failed to allocate memory");
182 free(delta);
183 return -ENOMEM;
184 }
185
186 ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
187 free(delta);
188 if (ret < 0 || (size_t)ret >= len) {
189 ERROR("Failed to create string");
190 return -1;
191 }
192 } else if (!strcmp(orig->type, "overlayfs") ||
193 !strcmp(orig->type, "overlay")) {
194 char *clean_old_path, *clean_new_path;
195 char *lastslash, *ndelta, *nsrc, *odelta, *osrc, *s1, *s2, *s3,
196 *work;
197 int ret, lastslashidx;
198 size_t len, name_len;
199
200 osrc = strdup(orig->src);
201 if (!osrc) {
202 ERROR("Failed to duplicate string \"%s\"", orig->src);
203 return -22;
204 }
205
206 nsrc = osrc;
207 if (strncmp(osrc, "overlay:", 8) == 0)
208 nsrc += 8;
209 else if (strncmp(osrc, "overlayfs:", 10) == 0)
210 nsrc += 10;
211
212 odelta = strchr(nsrc, ':');
213 if (!odelta) {
214 ERROR("Failed to find \":\" in \"%s\"", nsrc);
215 free(osrc);
216 return -22;
217 }
218
219 *odelta = '\0';
220 odelta++;
221 ndelta = must_make_path(lxcpath, cname, "delta0", NULL);
222
223 ret = mkdir(ndelta, 0755);
224 if (ret < 0 && errno != EEXIST) {
225 SYSERROR("Failed to create directory \"%s\"", ndelta);
226 free(osrc);
227 free(ndelta);
228 return -1;
229 }
230
231 if (am_guest_unpriv()) {
232 ret = chown_mapped_root(ndelta, conf);
233 if (ret < 0)
234 WARN("Failed to update ownership of %s",
235 ndelta);
236 }
237
238 /* Make workdir for overlayfs.v22 or higher (See the comment
239 * further up.).
240 */
241 lastslash = strrchr(ndelta, '/');
242 if (!lastslash) {
243 ERROR("Failed to detect \"/\" in \"%s\"", ndelta);
244 free(osrc);
245 free(ndelta);
246 return -1;
247 }
248 lastslash++;
249 lastslashidx = lastslash - ndelta;
250
251 work = malloc(lastslashidx + 7);
252 if (!work) {
253 free(osrc);
254 free(ndelta);
255 ERROR("Failed to allocate memory");
256 return -1;
257 }
258
259 memcpy(work, ndelta, lastslashidx + 1);
260 memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
261 work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
262
263 ret = mkdir(work, 0755);
264 if (ret < 0 && errno != EEXIST) {
265 SYSERROR("Failed to create directory \"%s\"", ndelta);
266 free(osrc);
267 free(ndelta);
268 free(work);
269 return -1;
270 }
271
272 if (am_guest_unpriv()) {
273 ret = chown_mapped_root(work, conf);
274 if (ret < 0)
275 WARN("Failed to update ownership of %s", work);
276 }
277 free(work);
278
279 /* strlen("overlay:") = 8
280 * +
281 * strlen(delta)
282 * +
283 * :
284 * +
285 * strlen(src)
286 * +
287 * \0
288 */
289 len = 8 + strlen(ndelta) + 1 + strlen(nsrc) + 1;
290 new->src = malloc(len);
291 if (!new->src) {
292 free(osrc);
293 free(ndelta);
294 ERROR("Failed to allocate memory");
295 return -ENOMEM;
296 }
297 ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
298 if (ret < 0 || (size_t)ret >= len) {
299 ERROR("Failed to create string");
300 free(osrc);
301 free(ndelta);
302 return -1;
303 }
304
305 ret = ovl_do_rsync(odelta, ndelta, conf);
306 free(osrc);
307 free(ndelta);
308 if (ret < 0)
309 return -1;
310
311 /* When we create an overlay snapshot of an overlay container in
312 * the snapshot directory under "<lxcpath>/<name>/snaps/" we
313 * don't need to record a dependency. If we would restore would
314 * also fail.
315 */
316 clean_old_path = lxc_deslashify(oldpath);
317 if (!clean_old_path)
318 return -1;
319
320 clean_new_path = lxc_deslashify(lxcpath);
321 if (!clean_new_path) {
322 free(clean_old_path);
323 return -1;
324 }
325
326 s1 = strrchr(clean_old_path, '/');
327 if (!s1) {
328 ERROR("Failed to detect \"/\" in string \"%s\"", clean_old_path);
329 free(clean_old_path);
330 free(clean_new_path);
331 return -1;
332 }
333
334 s2 = strrchr(clean_new_path, '/');
335 if (!s2) {
336 ERROR("Failed to detect \"/\" in string \"%s\"", clean_new_path);
337 free(clean_old_path);
338 free(clean_new_path);
339 return -1;
340 }
341
342 if (!strncmp(s1, "/snaps", STRLITERALLEN("/snaps"))) {
343 s1 = clean_new_path;
344 s2 = clean_old_path;
345 s3 = (char *)cname;
346 } else if (!strncmp(s2, "/snaps", STRLITERALLEN("/snaps"))) {
347 s1 = clean_old_path;
348 s2 = clean_new_path;
349 s3 = (char *)oldname;
350 } else {
351 free(clean_old_path);
352 free(clean_new_path);
353 return 0;
354 }
355
356 len = strlen(s1);
357 if (!strncmp(s1, s2, len)) {
358 char *tmp;
359
360 tmp = (char *)(s2 + len + 1);
361 if (*tmp == '\0') {
362 free(clean_old_path);
363 free(clean_new_path);
364 return 0;
365 }
366
367 name_len = strlen(s3);
368 if (strncmp(s3, tmp, name_len)) {
369 free(clean_old_path);
370 free(clean_new_path);
371 return 0;
372 }
373
374 free(clean_old_path);
375 free(clean_new_path);
376 return LXC_CLONE_SNAPSHOT;
377 }
378
379 free(clean_old_path);
380 free(clean_new_path);
381 return 0;
382 } else {
383 ERROR("overlay clone of %s container is not yet supported",
384 orig->type);
385 /* Note, supporting this will require ovl_mount supporting
386 * mounting of the underlay. No big deal, just needs to be done.
387 */
388 return -1;
389 }
390
391 return 0;
392 }
393
394 /* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
395 * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
396 * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
397 */
398 int ovl_create(struct lxc_storage *bdev, const char *dest, const char *n,
399 struct bdev_specs *specs)
400 {
401 char *delta;
402 int ret;
403 size_t len, newlen;
404
405 len = strlen(dest);
406 if (len < 8 || strcmp(dest + len - 7, "/rootfs")) {
407 ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest);
408 return -1;
409 }
410
411 bdev->dest = strdup(dest);
412 if (!bdev->dest) {
413 ERROR("Failed to duplicate string \"%s\"", dest);
414 return -1;
415 }
416
417 delta = strdup(dest);
418 if (!delta) {
419 ERROR("Failed to allocate memory");
420 return -1;
421 }
422 memcpy(delta + len - 6, "delta0", STRLITERALLEN("delta0"));
423
424 ret = mkdir_p(delta, 0755);
425 if (ret < 0) {
426 SYSERROR("Failed to create directory \"%s\"", delta);
427 free(delta);
428 return -1;
429 }
430
431 /* overlay:lower:upper */
432 newlen = (2 * len) + strlen("overlay:") + 2;
433 bdev->src = malloc(newlen);
434 if (!bdev->src) {
435 ERROR("Failed to allocate memory");
436 free(delta);
437 return -1;
438 }
439
440 ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
441 if (ret < 0 || (size_t)ret >= newlen) {
442 ERROR("Failed to create string");
443 free(delta);
444 return -1;
445 }
446
447 ret = mkdir_p(bdev->dest, 0755);
448 if (ret < 0) {
449 SYSERROR("Failed to create directory \"%s\"", bdev->dest);
450 free(delta);
451 return -1;
452 }
453
454 free(delta);
455 return 0;
456 }
457
458 int ovl_destroy(struct lxc_storage *orig)
459 {
460 char *upper = orig->src;
461
462 /* For an overlay container the rootfs is considered immutable
463 * and cannot be removed when restoring from a snapshot.
464 */
465 if (orig->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)
466 return 0;
467
468 if (strncmp(upper, "overlay:", 8) == 0)
469 upper += 8;
470 else if (strncmp(upper, "overlayfs:", 10) == 0)
471 upper += 10;
472
473 upper = strchr(upper, ':');
474 if (!upper)
475 return -22;
476 upper++;
477
478 return lxc_rmdir_onedev(upper, NULL);
479 }
480
481 bool ovl_detect(const char *path)
482 {
483 if (!strncmp(path, "overlay:", 8))
484 return true;
485
486 if (!strncmp(path, "overlayfs:", 10))
487 return true;
488
489 return false;
490 }
491
492 int ovl_mount(struct lxc_storage *bdev)
493 {
494 char *tmp, *options, *dup, *lower, *upper;
495 char *options_work, *work, *lastslash;
496 int lastslashidx;
497 size_t len, len2;
498 unsigned long mntflags;
499 char *mntdata;
500 int ret, ret2;
501
502 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
503 return -22;
504
505 if (!bdev->src || !bdev->dest)
506 return -22;
507
508 if (!ovl_name)
509 ovl_name = ovl_detect_name();
510
511 /* Separately mount it first:
512 * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
513 */
514 dup = strdup(bdev->src);
515 if (!dup) {
516 ERROR("Failed to allocate memory");
517 return -1;
518 }
519 upper = dup;
520 lower = dup;
521
522 if (strncmp(dup, "overlay:", 8) == 0)
523 lower += 8;
524 else if (strncmp(dup, "overlayfs:", 10) == 0)
525 lower += 10;
526 if (upper != lower)
527 upper = lower;
528
529 /* support multiple lower layers */
530 while ((tmp = strstr(upper, ":/"))) {
531 tmp++;
532 upper = tmp;
533 }
534
535 upper--;
536 if (upper == lower) {
537 free(dup);
538 return -22;
539 }
540 *upper = '\0';
541 upper++;
542
543 /* if delta doesn't yet exist, create it */
544 ret = mkdir_p(upper, 0755);
545 if (ret < 0 && errno != EEXIST) {
546 SYSERROR("Failed to create directory \"%s\"", upper);
547 free(dup);
548 return -22;
549 }
550
551 /* overlayfs.v22 or higher needs workdir option:
552 * if upper is
553 * /var/lib/lxc/c2/delta0
554 * then workdir is
555 * /var/lib/lxc/c2/olwork
556 */
557 lastslash = strrchr(upper, '/');
558 if (!lastslash) {
559 ERROR("Failed to detect \"/\" in string \"%s\"", upper);
560 free(dup);
561 return -22;
562 }
563
564 lastslash++;
565 lastslashidx = lastslash - upper;
566
567 work = malloc(lastslashidx + 7);
568 if (!work) {
569 ERROR("Failed to allocate memory");
570 free(dup);
571 return -22;
572 }
573
574 memcpy(work, upper, lastslashidx + 1);
575 memcpy(work + lastslashidx, "olwork", STRLITERALLEN("olwork"));
576 work[lastslashidx + STRLITERALLEN("olwork")] = '\0';
577
578 ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
579 if (ret < 0) {
580 ERROR("Failed to parse mount options");
581 free(mntdata);
582 free(dup);
583 free(work);
584 return -22;
585 }
586
587 ret = mkdir_p(work, 0755);
588 if (ret < 0 && errno != EEXIST) {
589 SYSERROR("Failed to create directory \"%s\"", work);
590 free(mntdata);
591 free(dup);
592 free(work);
593 return -22;
594 }
595
596 /*
597 * TODO:
598 * We should check whether bdev->src is a blockdev but for now only
599 * support overlays of a basic directory
600 */
601
602 if (mntdata) {
603 len = strlen(lower) + strlen(upper) +
604 strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
605 options = alloca(len);
606 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s",
607 upper, lower, mntdata);
608
609 len2 = strlen(lower) + strlen(upper) + strlen(work) +
610 strlen("upperdir=,lowerdir=,workdir=") +
611 strlen(mntdata) + 1;
612 options_work = alloca(len2);
613 ret2 = snprintf(options, len2,
614 "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper,
615 lower, work, mntdata);
616 } else {
617 len = strlen(lower) + strlen(upper) +
618 strlen("upperdir=,lowerdir=") + 1;
619 options = alloca(len);
620 ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper,
621 lower);
622
623 len2 = strlen(lower) + strlen(upper) + strlen(work) +
624 strlen("upperdir=,lowerdir=,workdir=") + 1;
625 options_work = alloca(len2);
626 ret2 = snprintf(options_work, len2,
627 "upperdir=%s,lowerdir=%s,workdir=%s", upper,
628 lower, work);
629 }
630
631 if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
632 ERROR("Failed to create string");
633 free(mntdata);
634 free(dup);
635 free(work);
636 return -1;
637 }
638
639 /* Assume we need a workdir as we are on a overlay version >= v22. */
640 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
641 MS_MGC_VAL | mntflags, options_work);
642 if (ret < 0) {
643 SYSINFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
644 "Retrying without workdir",
645 lower, bdev->dest, options_work);
646
647 /* Assume we cannot use a workdir as we are on a version <= v21.
648 */
649 ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
650 MS_MGC_VAL | mntflags, options);
651 if (ret < 0)
652 SYSERROR("Failed to mount \"%s\" on \"%s\" with options \"%s\"",
653 lower, bdev->dest, options);
654 else
655 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
656 lower, bdev->dest, options);
657 } else {
658 INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower,
659 bdev->dest, options_work);
660 }
661
662 free(dup);
663 free(work);
664 return ret;
665 }
666
667 int ovl_umount(struct lxc_storage *bdev)
668 {
669 int ret;
670
671 if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
672 return -22;
673
674 if (!bdev->src || !bdev->dest)
675 return -22;
676
677 ret = umount(bdev->dest);
678 if (ret < 0)
679 SYSERROR("Failed to unmount \"%s\"", bdev->dest);
680 else
681 TRACE("Unmounted \"%s\"", bdev->dest);
682
683 return ret;
684 }
685
686 const char *ovl_get_lower(const char *rootfs_path)
687 {
688 const char *s1 = rootfs_path;
689
690 if (strncmp(rootfs_path, "overlay:", 8) == 0)
691 s1 += 8;
692 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
693 s1 += 10;
694
695 s1 = strstr(s1, ":/");
696 if (!s1)
697 return NULL;
698 s1++;
699
700 return s1;
701 }
702
703 char *ovl_get_rootfs(const char *rootfs_path, size_t *rootfslen)
704 {
705 char *rootfsdir = NULL;
706 char *s1 = NULL;
707 char *s2 = NULL;
708 char *s3 = NULL;
709
710 if (!rootfs_path || !rootfslen)
711 return NULL;
712
713 s1 = strdup(rootfs_path);
714 if (!s1)
715 return NULL;
716
717 s2 = s1;
718 if (strncmp(rootfs_path, "overlay:", 8) == 0)
719 s2 += 8;
720 else if (strncmp(rootfs_path, "overlayfs:", 10) == 0)
721 s2 += 10;
722
723 s3 = strstr(s2, ":/");
724 if (s3)
725 *s3 = '\0';
726
727 rootfsdir = strdup(s2);
728 free(s1);
729 if (!rootfsdir)
730 return NULL;
731
732 *rootfslen = strlen(rootfsdir);
733
734 return rootfsdir;
735 }
736
737 int ovl_mkdir(const struct mntent *mntent, const struct lxc_rootfs *rootfs,
738 const char *lxc_name, const char *lxc_path)
739 {
740 char lxcpath[PATH_MAX];
741 char **opts;
742 int ret;
743 size_t arrlen, i, len, rootfslen;
744 int fret = -1;
745 size_t dirlen = 0;
746 char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
747 *workdir = NULL;
748
749 /* When rootfs == NULL we have a container without a rootfs. */
750 if (rootfs && rootfs->path)
751 rootfs_path = rootfs->path;
752
753 opts = lxc_string_split(mntent->mnt_opts, ',');
754 if (opts)
755 arrlen = lxc_array_len((void **)opts);
756 else
757 goto err;
758
759 for (i = 0; i < arrlen; i++) {
760 if (strstr(opts[i], "upperdir=") &&
761 (strlen(opts[i]) > (len = strlen("upperdir="))))
762 upperdir = opts[i] + len;
763 else if (strstr(opts[i], "workdir=") &&
764 (strlen(opts[i]) > (len = strlen("workdir="))))
765 workdir = opts[i] + len;
766 }
767
768 if (rootfs_path) {
769 ret = snprintf(lxcpath, PATH_MAX, "%s/%s", lxc_path, lxc_name);
770 if (ret < 0 || ret >= PATH_MAX)
771 goto err;
772
773 rootfs_dir = ovl_get_rootfs(rootfs_path, &rootfslen);
774 if (!rootfs_dir)
775 goto err;
776
777 dirlen = strlen(lxcpath);
778 }
779
780 /*
781 * We neither allow users to create upperdirs and workdirs outside the
782 * containerdir nor inside the rootfs. The latter might be debatable.
783 * When we have a container without a rootfs we skip the checks.
784 */
785 ret = 0;
786 if (upperdir) {
787 if (!rootfs_path)
788 ret = mkdir_p(upperdir, 0755);
789 else if (!strncmp(upperdir, lxcpath, dirlen) &&
790 strncmp(upperdir, rootfs_dir, rootfslen))
791 ret = mkdir_p(upperdir, 0755);
792
793 if (ret < 0)
794 SYSWARN("Failed to create directory \"%s\"", upperdir);
795 }
796
797 ret = 0;
798 if (workdir) {
799 if (!rootfs_path)
800 ret = mkdir_p(workdir, 0755);
801 else if (!strncmp(workdir, lxcpath, dirlen) &&
802 strncmp(workdir, rootfs_dir, rootfslen))
803 ret = mkdir_p(workdir, 0755);
804
805 if (ret < 0)
806 SYSWARN("Failed to create directory \"%s\"", workdir);
807 }
808
809 fret = 0;
810
811 err:
812 free(rootfs_dir);
813 lxc_free_array((void **)opts, free);
814 return fret;
815 }
816
817 /* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
818 * with overlay lxc.mount.entry entries we need to update absolute paths for
819 * upper- and workdir. This update is done in two locations:
820 * lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
821 * independent of each other since lxc_conf->mountlist may contain more mount
822 * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
823 */
824 int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
825 const char *lxc_name, const char *newpath,
826 const char *newname)
827 {
828 char new_upper[PATH_MAX], new_work[PATH_MAX], old_upper[PATH_MAX],
829 old_work[PATH_MAX];
830 size_t i;
831 struct lxc_list *iterator;
832 char *cleanpath = NULL;
833 int fret = -1;
834 int ret = 0;
835 const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
836
837 cleanpath = strdup(newpath);
838 if (!cleanpath)
839 goto err;
840
841 remove_trailing_slashes(cleanpath);
842
843 /*
844 * We have to update lxc_conf->unexpanded_config separately from
845 * lxc_conf->mount_list.
846 */
847 for (i = 0; i < sizeof(ovl_dirs) / sizeof(ovl_dirs[0]); i++) {
848 if (!clone_update_unexp_ovl_paths(lxc_conf, lxc_path, newpath,
849 lxc_name, newname,
850 ovl_dirs[i]))
851 goto err;
852 }
853
854 ret =
855 snprintf(old_work, PATH_MAX, "workdir=%s/%s", lxc_path, lxc_name);
856 if (ret < 0 || ret >= PATH_MAX)
857 goto err;
858
859 ret =
860 snprintf(new_work, PATH_MAX, "workdir=%s/%s", cleanpath, newname);
861 if (ret < 0 || ret >= PATH_MAX)
862 goto err;
863
864 lxc_list_for_each(iterator, &lxc_conf->mount_list) {
865 char *mnt_entry = NULL, *new_mnt_entry = NULL, *tmp = NULL,
866 *tmp_mnt_entry = NULL;
867
868 mnt_entry = iterator->elem;
869
870 if (strstr(mnt_entry, "overlay"))
871 tmp = "upperdir";
872 if (!tmp)
873 continue;
874
875 ret = snprintf(old_upper, PATH_MAX, "%s=%s/%s", tmp, lxc_path,
876 lxc_name);
877 if (ret < 0 || ret >= PATH_MAX)
878 goto err;
879
880 ret = snprintf(new_upper, PATH_MAX, "%s=%s/%s", tmp,
881 cleanpath, newname);
882 if (ret < 0 || ret >= PATH_MAX)
883 goto err;
884
885 if (strstr(mnt_entry, old_upper)) {
886 tmp_mnt_entry =
887 lxc_string_replace(old_upper, new_upper, mnt_entry);
888 }
889
890 if (strstr(mnt_entry, old_work)) {
891 if (tmp_mnt_entry)
892 new_mnt_entry = lxc_string_replace(
893 old_work, new_work, tmp_mnt_entry);
894 else
895 new_mnt_entry = lxc_string_replace(
896 old_work, new_work, mnt_entry);
897 }
898
899 if (new_mnt_entry) {
900 free(iterator->elem);
901 iterator->elem = strdup(new_mnt_entry);
902 } else if (tmp_mnt_entry) {
903 free(iterator->elem);
904 iterator->elem = strdup(tmp_mnt_entry);
905 }
906
907 free(new_mnt_entry);
908 free(tmp_mnt_entry);
909 }
910
911 fret = 0;
912 err:
913 free(cleanpath);
914 return fret;
915 }
916
917 static int ovl_remount_on_enodev(const char *lower, const char *target,
918 const char *name, unsigned long mountflags,
919 const void *options)
920 {
921 int ret;
922 ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
923 if (ret < 0 && errno == ENODEV) /* Try other module name. */
924 ret = mount(lower, target,
925 ovl_name == ovl_version[0] ? ovl_version[1]
926 : ovl_version[0],
927 MS_MGC_VAL | mountflags, options);
928 return ret;
929 }
930
931 static char *ovl_detect_name(void)
932 {
933 FILE *f;
934 char *v = ovl_version[0];
935 char *line = NULL;
936 size_t len = 0;
937
938 f = fopen("/proc/filesystems", "r");
939 if (!f)
940 return v;
941
942 while (getline(&line, &len, f) != -1) {
943 if (strcmp(line, "nodev\toverlayfs\n") == 0) {
944 v = ovl_version[1];
945 break;
946 }
947 }
948
949 fclose(f);
950 free(line);
951 return v;
952 }
953
954 static int ovl_do_rsync(const char *src, const char *dest,
955 struct lxc_conf *conf)
956 {
957 int ret = -1;
958 struct rsync_data_char rdata = {0};
959 char cmd_output[PATH_MAX] = {0};
960
961 rdata.src = (char *)src;
962 rdata.dest = (char *)dest;
963 if (am_guest_unpriv())
964 ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata,
965 "lxc_rsync_exec_wrapper");
966 else
967 ret = run_command(cmd_output, sizeof(cmd_output),
968 lxc_rsync_exec_wrapper, (void *)&rdata);
969 if (ret < 0)
970 ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src, dest,
971 cmd_output[0] != '\0' ? ": " : "",
972 cmd_output[0] != '\0' ? cmd_output : "");
973
974 return ret;
975 }