• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/fstools/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 #include <sys/wait.h>
 18 
 19 #include <errno.h>
 20 #include <stdio.h>
 21 #include <unistd.h>
 22 #include <string.h>
 23 
 24 #include "libfstools.h"
 25 
 26 /* this is a raw syscall - man 2 pivot_root */
 27 extern int pivot_root(const char *new_root, const char *put_old);
 28 
 29 /**
 30  * mount_move - move mounted point to the new location
 31  *
 32  * @oldroot: directory that is current location of mount point
 33  * @newroot: new directory for the mount point
 34  */
 35 int
 36 mount_move(const char *oldroot, const char *newroot, const char *dir)
 37 {
 38 #ifndef MS_MOVE
 39 #define MS_MOVE (1 << 13)
 40 #endif
 41         struct stat s;
 42         char olddir[64];
 43         char newdir[64];
 44         int ret;
 45 
 46         snprintf(olddir, sizeof(olddir), "%s%s", oldroot, dir);
 47         snprintf(newdir, sizeof(newdir), "%s%s", newroot, dir);
 48 
 49         if (stat(olddir, &s) || !S_ISDIR(s.st_mode))
 50                 return -1;
 51 
 52         if (stat(newdir, &s) || !S_ISDIR(s.st_mode))
 53                 return -1;
 54 
 55         ret = mount(olddir, newdir, NULL, MS_NOATIME | MS_MOVE, NULL);
 56 
 57 /*      if (ret)
 58                 ULOG_ERR("failed %s %s: %m\n", olddir, newdir);*/
 59 
 60         return ret;
 61 }
 62 
 63 int
 64 pivot(char *new, char *old)
 65 {
 66         char pivotdir[64];
 67         int ret;
 68 
 69         if (mount_move("", new, "/proc"))
 70                 return -1;
 71 
 72         snprintf(pivotdir, sizeof(pivotdir), "%s%s", new, old);
 73 
 74         ret = pivot_root(new, pivotdir);
 75 
 76         if (ret < 0) {
 77                 ULOG_ERR("pivot_root failed %s %s: %m\n", new, pivotdir);
 78                 return -1;
 79         }
 80 
 81         mount_move(old, "", "/dev");
 82         mount_move(old, "", "/tmp");
 83         mount_move(old, "", "/sys");
 84         mount_move(old, "", "/overlay");
 85 
 86         return 0;
 87 }
 88 
 89 /**
 90  * fopivot - switch to overlay using passed dir as upper one
 91  *
 92  * @rw_root: writable directory that will be used as upper dir
 93  * @ro_root: directory where old root will be put
 94  */
 95 int
 96 fopivot(char *rw_root, char *ro_root)
 97 {
 98         char overlay[64], mount_options[64], upperdir[64], workdir[64], upgrade[64], upgrade_dest[64];
 99         struct stat st;
100 
101         if (find_filesystem("overlay")) {
102                 ULOG_ERR("BUG: no suitable fs found\n");
103                 return -1;
104         }
105 
106         snprintf(overlay, sizeof(overlay), "overlayfs:%s", rw_root);
107         snprintf(upperdir, sizeof(upperdir), "%s/upper", rw_root);
108         snprintf(workdir, sizeof(workdir), "%s/work", rw_root);
109         snprintf(upgrade, sizeof(upgrade), "%s/sysupgrade.tgz", rw_root);
110         snprintf(upgrade_dest, sizeof(upgrade_dest), "%s/sysupgrade.tgz", upperdir);
111         snprintf(mount_options, sizeof(mount_options), "lowerdir=/,upperdir=%s,workdir=%s",
112                  upperdir, workdir);
113 
114         /*
115          * Overlay FS v23 and later requires both a upper and
116          * a work directory, both on the same filesystem, but
117          * not part of the same subtree.
118          * We can't really deal with these constraints without
119          * creating two new subdirectories in /overlay.
120          */
121         if (mkdir(upperdir, 0755) == -1 && errno != EEXIST)
122                 return -1;
123 
124         if (mkdir(workdir, 0755) == -1 && errno != EEXIST)
125                 return -1;
126 
127         if (stat(upgrade, &st) == 0)
128                 rename(upgrade, upgrade_dest);
129 
130         if (mount(overlay, "/mnt", "overlay", MS_NOATIME, mount_options)) {
131                 ULOG_ERR("mount failed: %m, options %s\n", mount_options);
132                 return -1;
133         }
134 
135         return pivot("/mnt", ro_root);
136 }
137 
138 /**
139  * ramoverlay - use RAM to store filesystem changes on top of RO root
140  */
141 int
142 ramoverlay(void)
143 {
144         mkdir("/tmp/root", 0755);
145         mount("tmpfs", "/tmp/root", "tmpfs", MS_NOATIME, "mode=0755");
146 
147         return fopivot("/tmp/root", "/rom");
148 }
149 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt