summaryrefslogtreecommitdiff
path: root/libfstools/mount.c
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2014-04-03 18:38:18 +0100
committerJohn Crispin <blogic@openwrt.org>2014-04-03 23:03:46 +0100
commit8603b6f2e7782437f3af16778b231ec9c1045f09 (patch)
tree909dae619547c6595d7c1a0a16451079d4c46249 /libfstools/mount.c
parentdbd3dc58391b750d9ad8403e89f79457bd49dc90 (diff)
downloadfstools-8603b6f2e7782437f3af16778b231ec9c1045f09.tar.gz
move files around
Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'libfstools/mount.c')
-rw-r--r--libfstools/mount.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/libfstools/mount.c b/libfstools/mount.c
new file mode 100644
index 0000000..e7b57f0
--- /dev/null
+++ b/libfstools/mount.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "../fs-state.h"
+
+/* this is a raw syscall - man 2 pivot_root */
+extern int pivot_root(const char *new_root, const char *put_old);
+
+int
+mount_move(char *oldroot, char *newroot, char *dir)
+{
+#ifndef MS_MOVE
+#define MS_MOVE (1 << 13)
+#endif
+ struct stat s;
+ char olddir[64];
+ char newdir[64];
+ int ret;
+
+ snprintf(olddir, sizeof(olddir), "%s%s", oldroot, dir);
+ snprintf(newdir, sizeof(newdir), "%s%s", newroot, dir);
+
+ if (stat(olddir, &s) || !S_ISDIR(s.st_mode))
+ return -1;
+
+ if (stat(newdir, &s) || !S_ISDIR(s.st_mode))
+ return -1;
+
+ ret = mount(olddir, newdir, NULL, MS_NOATIME | MS_MOVE, NULL);
+
+/* if (ret)
+ fprintf(stderr, "failed %s %s: %s\n", olddir, newdir, strerror(errno));*/
+
+ return ret;
+}
+
+int
+pivot(char *new, char *old)
+{
+ char pivotdir[64];
+ int ret;
+
+ if (mount_move("", new, "/proc"))
+ return -1;
+
+ snprintf(pivotdir, sizeof(pivotdir), "%s%s", new, old);
+
+ ret = pivot_root(new, pivotdir);
+
+ if (ret < 0) {
+ fprintf(stderr, "pivot_root failed %s %s: %s\n", new, pivotdir, strerror(errno));
+ return -1;
+ }
+
+ mount_move(old, "", "/dev");
+ mount_move(old, "", "/tmp");
+ mount_move(old, "", "/sys");
+ mount_move(old, "", "/overlay");
+
+ return 0;
+}
+
+int
+fopivot(char *rw_root, char *ro_root)
+{
+ char overlay[64], lowerdir[64];
+
+ if (find_filesystem("overlay")) {
+ fprintf(stderr, "BUG: no suitable fs found\n");
+ return -1;
+ }
+
+ snprintf(overlay, sizeof(overlay), "overlayfs:%s", rw_root);
+ snprintf(lowerdir, sizeof(lowerdir), "lowerdir=/,upperdir=%s", rw_root);
+
+ if (mount(overlay, "/mnt", "overlayfs", MS_NOATIME, lowerdir)) {
+ fprintf(stderr, "mount failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return pivot("/mnt", ro_root);
+}
+
+int
+ramoverlay(void)
+{
+ mkdir("/tmp/root", 0755);
+ mount("tmpfs", "/tmp/root", "tmpfs", MS_NOATIME, "mode=0755");
+
+ return fopivot("/tmp/root", "/rom");
+}