Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/switch_root.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 2979 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* vi: set sw=4 ts=4: */
2     /* Copyright 2005 Rob Landley <rob@landley.net>
3     *
4     * Switch from rootfs to another filesystem as the root of the mount tree.
5     *
6     * Licensed under GPL version 2, see file LICENSE in this tarball for details.
7     */
8    
9 niro 816 #include "libbb.h"
10 niro 532 #include <sys/vfs.h>
11    
12     // Make up for header deficiencies.
13     #ifndef RAMFS_MAGIC
14 niro 816 #define RAMFS_MAGIC ((unsigned)0x858458f6)
15 niro 532 #endif
16    
17     #ifndef TMPFS_MAGIC
18 niro 816 #define TMPFS_MAGIC ((unsigned)0x01021994)
19 niro 532 #endif
20    
21     #ifndef MS_MOVE
22 niro 816 #define MS_MOVE 8192
23 niro 532 #endif
24    
25     // Recursively delete contents of rootfs.
26 niro 816 static void delete_contents(const char *directory, dev_t rootdev)
27 niro 532 {
28     DIR *dir;
29     struct dirent *d;
30     struct stat st;
31    
32     // Don't descend into other filesystems
33 niro 816 if (lstat(directory, &st) || st.st_dev != rootdev)
34     return;
35 niro 532
36     // Recursively delete the contents of directories.
37     if (S_ISDIR(st.st_mode)) {
38 niro 816 dir = opendir(directory);
39     if (dir) {
40 niro 532 while ((d = readdir(dir))) {
41 niro 816 char *newdir = d->d_name;
42 niro 532
43     // Skip . and ..
44 niro 816 if (DOT_OR_DOTDOT(newdir))
45 niro 532 continue;
46    
47     // Recurse to delete contents
48 niro 816 newdir = concat_path_file(directory, newdir);
49     delete_contents(newdir, rootdev);
50     free(newdir);
51 niro 532 }
52     closedir(dir);
53    
54     // Directory should now be empty. Zap it.
55     rmdir(directory);
56     }
57    
58     // It wasn't a directory. Zap it.
59     } else unlink(directory);
60     }
61    
62 niro 816 int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
63     int switch_root_main(int argc UNUSED_PARAM, char **argv)
64 niro 532 {
65 niro 816 char *newroot, *console = NULL;
66 niro 532 struct stat st1, st2;
67     struct statfs stfs;
68 niro 816 dev_t rootdev;
69 niro 532
70     // Parse args (-c console)
71 niro 816 opt_complementary = "-2"; // minimum 2 params
72     getopt32(argv, "+c:", &console); // '+': stop parsing at first non-option
73     argv += optind;
74 niro 532
75     // Change to new root directory and verify it's a different fs.
76 niro 816 newroot = *argv++;
77 niro 532
78 niro 816 xchdir(newroot);
79     if (lstat(".", &st1) || lstat("/", &st2) || st1.st_dev == st2.st_dev) {
80 niro 532 bb_error_msg_and_die("bad newroot %s", newroot);
81     }
82 niro 816 rootdev = st2.st_dev;
83 niro 532
84     // Additional sanity checks: we're about to rm -rf /, so be REALLY SURE
85     // we mean it. (I could make this a CONFIG option, but I would get email
86 niro 816 // from all the people who WILL eat their filesystems.)
87     if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs)
88     || (((unsigned)stfs.f_type != RAMFS_MAGIC) && ((unsigned)stfs.f_type != TMPFS_MAGIC))
89     || (getpid() != 1)
90     ) {
91 niro 532 bb_error_msg_and_die("not rootfs");
92     }
93    
94     // Zap everything out of rootdev
95 niro 816 delete_contents("/", rootdev);
96 niro 532
97     // Overmount / with newdir and chroot into it. The chdir is needed to
98     // recalculate "." and ".." links.
99 niro 816 if (mount(".", "/", NULL, MS_MOVE, NULL))
100     bb_error_msg_and_die("error moving root");
101     xchroot(".");
102     xchdir("/");
103 niro 532
104     // If a new console specified, redirect stdin/stdout/stderr to that.
105     if (console) {
106     close(0);
107 niro 816 xopen(console, O_RDWR);
108     xdup2(0, 1);
109     xdup2(0, 2);
110 niro 532 }
111    
112     // Exec real init. (This is why we must be pid 1.)
113 niro 816 execv(argv[0], argv);
114     bb_perror_msg_and_die("bad init %s", argv[0]);
115 niro 532 }