[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Updates to ash and busybox



> > > you how many times I've wish chroot was on the recue disk... You know,
> > > chroot could even be used for a reboot-free install -- just chroot to
> > > the newly installed partition...
> > 
> > Amazing convergance!  We were recently talking about having init have
> > the ability to exec/chroot?  If we had this, we could conceivably have
> > a "bootless installation" -- once you've installed the base system,
> > you could just chroot your init over to the target system, and keep
> > chugging...
> 
> This sounds like a good idea in principle, but it leads to a nasty problem.
> If you do this, you might use the newly installed system for days,
> configuring it, puttling lots of effort into it, and getting attached to it. 
> 
> And then you eventually reboot. And discover the install actually failed
> somehow and you can't boot of the hard disk at all. When I was looking at
> the Caldera install (which does this), I ran into this exact problem, and
> it's the kind of thing that would give a user (especially a new user who
> doesn't know how to correct it) a _very_ bad impression of debian.
> 
> It's great as an option. It's horrid as a default.
> 
> -- 
> see shy jo

I've been using this trick from more than one year and it works very well.
I have also illustrated the chroot solution in my proposal of Jul 10 1999
to this list about the debian automatic installation, but apparently nobody
noticed it.

This is how I can cut down the reboot time to five seconds in my dzinstall
bootdisk. The only problem I found is that squid can't be conviced to die if
started from the chroot. I hadn't the time able to investigate, but a good
kill -9 always solves the problem.

Chroot can also be used by the installer program to run any program just
installed in the target root. For example I use it to crypt the root passwd
using perl, which isn't in the boot floppies, and to run dpkg in the new
root from the installer to merge the Packages.cd file.

Regarding the danger of running from months in a chrooted environment you
can also ask or force a real reboot in a postinst install script. If the
user chooses not to reboot and than runs into troubles it is his fault.

Here is the patch for slink busybox to restart the init with chroot without
rebooting. Note that it uses USR2 as restart signal, so you can always do a
real reboot if you want.


*** utilities/busybox/busybox.def.h.orig	Thu Jan 21 11:21:44 1999
--- utilities/busybox/busybox.def.h	Thu Apr  8 14:47:48 1999
***************
*** 8,13 ****
--- 8,14 ----
  #define BB_CHGRP
  #define BB_CHMOD
  #define BB_CHOWN
+ #define BB_CHROOT
  #define BB_CLEAR
  #define BB_CP
  #define BB_DATE
*** utilities/busybox/init.c.orig	Fri Feb 19 01:07:22 1999
--- utilities/busybox/init.c	Mon Apr 19 11:47:39 1999
***************
*** 19,24 ****
--- 19,26 ----
  #include <linux/serial.h>	/* for serial_struct */
  #include <sys/ioctl.h>
  
+ const char		chroot_usage[] = "chroot directory [command...]\n\n"
+ 	"\trun command or interactive shell with special root directory.\n";
  const char		init_usage[] = "Used internally by the system.";
  char			console[16] = "";
  const char *	default_console = "/dev/tty1";
***************
*** 26,31 ****
--- 28,34 ----
  const char *	second_terminal = "/dev/tty2";
  const char *	log = "/dev/tty3";
  char * term_ptr = NULL;
+ const char ** save_argv = NULL;
  
  static void
  message(const char * terminal, const char * pattern, ...)
***************
*** 212,239 ****
  static void
  shutdown_system(int do_reboot)
  {
! 	static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0};
  
  	sync();
  	/* Allow Ctrl-Alt-Del to reboot system. */
  	reboot(RB_ENABLE_CAD);
  
  	/* Send signals to every process _except_ pid 1 */
! 	message(console, "Sending SIGHUP to all processes.\r\n");
  	kill(-1, SIGHUP);
  	sleep(2);
  	sync();
! 	message(console, "Sending SIGKILL to all processes.\r\n");
  	kill(-1, SIGKILL);
  	sleep(1);
! 	waitfor(run("/bin/umount", umount_args, console, 0));
  	sync();
  	bdflush(1, 0);
  	sync();
  	reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM);
  	exit(0);
  }
  
  static void
  halt_signal(int sig)
  {
--- 215,319 ----
  static void
  shutdown_system(int do_reboot)
  {
! 	static const char *const umount_args[] = { "/bin/umount", "-n", "-a", 0 };
! 	static const char *const umount_proc[] = { "/bin/umount", "-n", "/proc", 0 };
! 	static const char *const remount_root[] = { "/bin/mount", "-n", "-o", "remount,ro", "/target", 0 };
! 	struct stat statbuf;
! 
! 	if ((do_reboot == 2) && (stat("/target/sbin/init",&statbuf) != 0)) {
! 	    do_reboot = 1;
! 	}
  
  	sync();
  	/* Allow Ctrl-Alt-Del to reboot system. */
  	reboot(RB_ENABLE_CAD);
  
  	/* Send signals to every process _except_ pid 1 */
! 	message(console, "Sending SIGHUP to all processes...\r\n");
  	kill(-1, SIGHUP);
  	sleep(2);
  	sync();
! 	message(console, "Sending SIGKILL to all processes...\r\n");
  	kill(-1, SIGKILL);
  	sleep(1);
! 
! 	if ((do_reboot == 2) && (chdir("/target") == 0)) {
! 	    /* chdir prevents unmount of /target */
! 	    waitfor(run("/bin/umount", umount_args, console, 0));
! 	    waitfor(run("/bin/umount", umount_proc, console, 0));
! 	    chdir("/");
! 	    waitfor(run("/bin/mount", remount_root, console, 0));
! 	} else {
! 	    waitfor(run("/bin/umount", umount_args, console, 0));
! 	}
! 
  	sync();
+ 	message(console, "umount done.\r\n");
  	bdflush(1, 0);
  	sync();
+ 
+ 	/* Try to restart the system without doing a reboot */
+ 	if (do_reboot == 2) {
+ 	    static char *environment[] = {
+ 		"HOME=/",
+ 		"TERM=linux",
+ 		"BOOT_IMAGE=linux",
+ 		"vga=normal",
+ 		NULL
+ 	    };
+ 	    int rc, i;
+ 
+ 	    if ((chdir("/target") != 0) || (chroot("/target") != 0)) {
+ 		message(console, "Unable to chroot to /target, %s\r\n", 
+ 			strerror(errno));
+ 		goto do_reboot;
+ 	    }
+ 	    for (i=3; i<256; i++) {
+ 		close(i);
+ 	    }
+ 
+ 	    /* Exec the new init */
+ 	    message(console, "Restarting init...\r\n"); sleep(2);
+ 	    save_argv[0] = "/sbin/init";
+ 	    rc = execve("/sbin/init", (char **)save_argv,(char **)environment);
+ 
+ 	    /* Should not be reached */
+ 	    message(console, "Unable to exec /sbin/init, %s\r\n",
+ 		    strerror(errno));
+ 	}
+ 
+  do_reboot:
  	reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM);
  	exit(0);
  }
  
+ int
+ chroot_main(struct FileInfo * fi, int argc, char * * argv)
+ {
+     static char *environment[] = {
+ 	"HOME=/",
+ 	"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
+ 	"SHELL=/bin/sh",
+ 	"TERM=linux",
+ 	"USER=root",
+ 	0
+     };
+ 
+     if (chroot(argv[1]) != 0) {
+ 	printf("Unable to chroot to %s, %s\r\n", argv[1], strerror(errno));
+ 	return -1;
+     } else {
+ 	if (argc > 2) {
+ 	    argc -= 2;
+ 	    argv += 2;
+ 	    argv[argc+1] = NULL;
+ 	    return execve(argv[0], (char **) argv, (char **) environment);
+ 	} else {
+ 	    return 0;
+ 	}
+     }
+ }
+ 
  static void
  halt_signal(int sig)
  {
***************
*** 247,252 ****
--- 327,338 ----
  }
  
  static void
+ restart_signal(int sig)
+ {
+ 	shutdown_system(2);
+ }
+ 
+ static void
  exit_signal(int sig)
  {
    
***************
*** 288,294 ****
  	setsid();
  
  	signal(SIGUSR1, halt_signal);
! 	signal(SIGUSR2, reboot_signal);
  	signal(SIGINT, reboot_signal);
  	signal(SIGTERM, exit_signal);
  
--- 374,380 ----
  	setsid();
  
  	signal(SIGUSR1, halt_signal);
! 	signal(SIGUSR2, restart_signal);
  	signal(SIGINT, reboot_signal);
  	signal(SIGTERM, exit_signal);
  
***************
*** 296,301 ****
--- 382,388 ----
  
  	message(log, "%s: started. ", argv[0]);
  
+ 	save_argv = (const char **) argv;
  	for ( j = 1; j < argc; j++ ) {
  		if ( strcmp(argv[j], "single") == 0 ) {
  			run_rc = 0;
*** utilities/busybox/internal.h.orig	Thu Jan 21 11:21:44 1999
--- utilities/busybox/internal.h	Thu Apr  8 14:40:51 1999
***************
*** 64,69 ****
--- 64,70 ----
  extern int chgrp_main(struct FileInfo * i, int argc, char * * argv);
  extern int chmod_main(struct FileInfo * i, int argc, char * * argv);
  extern int chown_main(struct FileInfo * i, int argc, char * * argv);
+ extern int chroot_main(struct FileInfo * i, int argc, char * * argv);
  extern int clear_main(struct FileInfo * i, int argc, char * * argv);
  extern int date_main(struct FileInfo * i, int argc, char * * argv);
  extern int dd_main(struct FileInfo * i, int argc, char * * argv);
***************
*** 142,147 ****
--- 143,149 ----
  extern const char	chgrp_usage[];
  extern const char	chmod_usage[];
  extern const char	chown_usage[];
+ extern const char	chroot_usage[];
  extern const char	clear_usage[];
  extern const char	cp_usage[];
  extern const char	date_usage[];
*** utilities/busybox/main.c.orig	Thu Jan 21 11:21:44 1999
--- utilities/busybox/main.c	Thu Apr  8 14:40:02 1999
***************
*** 20,25 ****
--- 20,28 ----
  #ifdef BB_CHOWN	//bin
  { "chown",	chown_main, 0, chown_usage,			2, -1 },
  #endif
+ #ifdef BB_CHROOT	//sbin
+ { "chroot",     chroot_main, 0, chroot_usage,	                1, -1 },
+ #endif
  #ifdef BB_CLEAR	//usr/bin
  { "clear",	clear_main, 0, clear_usage,			0, 0 },
  #endif

-- 
Massimo Dal Zotto

+----------------------------------------------------------------------+
|  Massimo Dal Zotto               email: dz@cs.unitn.it               |
|  Via Marconi, 141                phone: ++39-0461534251              |
|  38057 Pergine Valsugana (TN)      www: http://www.cs.unitn.it/~dz/  |
|  Italy                             pgp: finger dz@tango.cs.unitn.it  |
+----------------------------------------------------------------------+


Reply to: