Contents of /trunk/mkinitrd-magellan/busybox/util-linux/switch_root.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 2900 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 2900 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* 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 | #include "busybox.h" |
10 | #include <sys/vfs.h> |
11 | |
12 | |
13 | // Make up for header deficiencies. |
14 | |
15 | #ifndef RAMFS_MAGIC |
16 | #define RAMFS_MAGIC 0x858458f6 |
17 | #endif |
18 | |
19 | #ifndef TMPFS_MAGIC |
20 | #define TMPFS_MAGIC 0x01021994 |
21 | #endif |
22 | |
23 | #ifndef MS_MOVE |
24 | #define MS_MOVE 8192 |
25 | #endif |
26 | |
27 | dev_t rootdev; |
28 | |
29 | // Recursively delete contents of rootfs. |
30 | |
31 | static void delete_contents(char *directory) |
32 | { |
33 | DIR *dir; |
34 | struct dirent *d; |
35 | struct stat st; |
36 | |
37 | // Don't descend into other filesystems |
38 | if (lstat(directory, &st) || st.st_dev != rootdev) return; |
39 | |
40 | // Recursively delete the contents of directories. |
41 | if (S_ISDIR(st.st_mode)) { |
42 | if((dir = opendir(directory))) { |
43 | while ((d = readdir(dir))) { |
44 | char *newdir=d->d_name; |
45 | |
46 | // Skip . and .. |
47 | if(*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2]))) |
48 | continue; |
49 | |
50 | // Recurse to delete contents |
51 | newdir = alloca(strlen(directory) + strlen(d->d_name) + 2); |
52 | sprintf(newdir, "%s/%s", directory, d->d_name); |
53 | delete_contents(newdir); |
54 | } |
55 | closedir(dir); |
56 | |
57 | // Directory should now be empty. Zap it. |
58 | rmdir(directory); |
59 | } |
60 | |
61 | // It wasn't a directory. Zap it. |
62 | |
63 | } else unlink(directory); |
64 | } |
65 | |
66 | int switch_root_main(int argc, char *argv[]) |
67 | { |
68 | char *newroot, *console=NULL; |
69 | struct stat st1, st2; |
70 | struct statfs stfs; |
71 | |
72 | // Parse args (-c console) |
73 | |
74 | opt_complementary = "-2"; |
75 | getopt32(argc, argv, "c:", &console); |
76 | |
77 | // Change to new root directory and verify it's a different fs. |
78 | |
79 | newroot=argv[optind++]; |
80 | |
81 | if (chdir(newroot) || lstat(".", &st1) || lstat("/", &st2) || |
82 | st1.st_dev == st2.st_dev) |
83 | { |
84 | bb_error_msg_and_die("bad newroot %s", newroot); |
85 | } |
86 | rootdev=st2.st_dev; |
87 | |
88 | // Additional sanity checks: we're about to rm -rf /, so be REALLY SURE |
89 | // we mean it. (I could make this a CONFIG option, but I would get email |
90 | // from all the people who WILL eat their filesystemss.) |
91 | |
92 | if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs) || |
93 | (stfs.f_type != RAMFS_MAGIC && stfs.f_type != TMPFS_MAGIC) || |
94 | getpid() != 1) |
95 | { |
96 | bb_error_msg_and_die("not rootfs"); |
97 | } |
98 | |
99 | // Zap everything out of rootdev |
100 | |
101 | delete_contents("/"); |
102 | |
103 | // Overmount / with newdir and chroot into it. The chdir is needed to |
104 | // recalculate "." and ".." links. |
105 | |
106 | if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".") || chdir("/")) |
107 | bb_error_msg_and_die("moving root"); |
108 | |
109 | // If a new console specified, redirect stdin/stdout/stderr to that. |
110 | |
111 | if (console) { |
112 | close(0); |
113 | if(open(console, O_RDWR) < 0) |
114 | bb_error_msg_and_die("bad console '%s'", console); |
115 | dup2(0, 1); |
116 | dup2(0, 2); |
117 | } |
118 | |
119 | // Exec real init. (This is why we must be pid 1.) |
120 | execv(argv[optind], argv+optind); |
121 | bb_error_msg_and_die("bad init '%s'", argv[optind]); |
122 | } |