diff options
author | John Crispin <blogic@openwrt.org> | 2014-04-03 18:38:18 +0100 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2014-04-03 23:03:46 +0100 |
commit | 8603b6f2e7782437f3af16778b231ec9c1045f09 (patch) | |
tree | 909dae619547c6595d7c1a0a16451079d4c46249 /libfstools/mount.c | |
parent | dbd3dc58391b750d9ad8403e89f79457bd49dc90 (diff) | |
download | fstools-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.c | 110 |
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"); +} |