libfstools: be more consistent with other existing code
[project/fstools.git] / libfstools / mount.c
1 /*
2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/mount.h>
17
18 #include <errno.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <string.h>
22
23 #include "libfstools.h"
24
25 /* this is a raw syscall - man 2 pivot_root */
26 extern int pivot_root(const char *new_root, const char *put_old);
27
28 int
29 mount_move(char *oldroot, char *newroot, char *dir)
30 {
31 #ifndef MS_MOVE
32 #define MS_MOVE (1 << 13)
33 #endif
34 struct stat s;
35 char olddir[64];
36 char newdir[64];
37 int ret;
38
39 snprintf(olddir, sizeof(olddir), "%s%s", oldroot, dir);
40 snprintf(newdir, sizeof(newdir), "%s%s", newroot, dir);
41
42 if (stat(olddir, &s) || !S_ISDIR(s.st_mode))
43 return -1;
44
45 if (stat(newdir, &s) || !S_ISDIR(s.st_mode))
46 return -1;
47
48 ret = mount(olddir, newdir, NULL, MS_NOATIME | MS_MOVE, NULL);
49
50 /* if (ret)
51 fprintf(stderr, "failed %s %s: %s\n", olddir, newdir, strerror(errno));*/
52
53 return ret;
54 }
55
56 int
57 pivot(char *new, char *old)
58 {
59 char pivotdir[64];
60 int ret;
61
62 if (mount_move("", new, "/proc"))
63 return -1;
64
65 snprintf(pivotdir, sizeof(pivotdir), "%s%s", new, old);
66
67 ret = pivot_root(new, pivotdir);
68
69 if (ret < 0) {
70 fprintf(stderr, "pivot_root failed %s %s: %s\n", new, pivotdir, strerror(errno));
71 return -1;
72 }
73
74 mount_move(old, "", "/dev");
75 mount_move(old, "", "/tmp");
76 mount_move(old, "", "/sys");
77 mount_move(old, "", "/overlay");
78
79 return 0;
80 }
81
82 int
83 fopivot(char *rw_root, char *ro_root)
84 {
85 char overlay[64], lowerdir[64];
86
87 if (find_filesystem("overlay")) {
88 fprintf(stderr, "BUG: no suitable fs found\n");
89 return -1;
90 }
91
92 snprintf(overlay, sizeof(overlay), "overlayfs:%s", rw_root);
93 snprintf(lowerdir, sizeof(lowerdir), "lowerdir=/,upperdir=%s", rw_root);
94
95 if (mount(overlay, "/mnt", "overlayfs", MS_NOATIME, lowerdir)) {
96 fprintf(stderr, "mount failed: %s\n", strerror(errno));
97 return -1;
98 }
99
100 return pivot("/mnt", ro_root);
101 }
102
103 int
104 ramoverlay(void)
105 {
106 mkdir("/tmp/root", 0755);
107 mount("tmpfs", "/tmp/root", "tmpfs", MS_NOATIME, "mode=0755");
108
109 return fopivot("/tmp/root", "/rom");
110 }