Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.532  
changed lines
  Added in v.816