diff options
-rw-r--r-- | mdk-stage1/.cvsignore | 1 | ||||
-rw-r--r-- | mdk-stage1/Makefile | 4 | ||||
-rw-r--r-- | mdk-stage1/frontend.h | 2 | ||||
-rw-r--r-- | mdk-stage1/newt-frontend.c | 4 | ||||
-rw-r--r-- | mdk-stage1/rescue-gui.c | 206 | ||||
-rw-r--r-- | mdk-stage1/stdio-frontend.c | 4 | ||||
-rw-r--r-- | rescue/Makefile | 2 | ||||
-rwxr-xr-x | rescue/guessmounts | 30 | ||||
-rwxr-xr-x | rescue/install_bootloader | 47 | ||||
-rwxr-xr-x | rescue/lsparts | 124 | ||||
-rwxr-xr-x | rescue/make_rescue_img | 4 | ||||
-rw-r--r-- | rescue/tree/etc/issue | 3 | ||||
-rwxr-xr-x | rescue/tree/etc/rc.sysinit | 9 |
13 files changed, 422 insertions, 18 deletions
diff --git a/mdk-stage1/.cvsignore b/mdk-stage1/.cvsignore index 36f56f6b5..af2397e4b 100644 --- a/mdk-stage1/.cvsignore +++ b/mdk-stage1/.cvsignore @@ -9,3 +9,4 @@ debug.log mkinitrd_helper.tar.bz2 hack_* stage1-usbnet +rescue-gui diff --git a/mdk-stage1/Makefile b/mdk-stage1/Makefile index 3b1482724..1e4b25653 100644 --- a/mdk-stage1/Makefile +++ b/mdk-stage1/Makefile @@ -236,6 +236,10 @@ tar-mkinitrd_helper: clean tar cfj mkinitrd_helper.tar.bz2 mkinitrd_helper-subdir --exclude CVS rm -rf mkinitrd_helper-subdir +rescue-gui: rescue-gui.o frontend-common.o $(FRONTEND_LINK) $(STAGE1_LIBC) + $(CC) $(LDFLAGS_STAGE1) -o $@ $^ + $(STRIPCMD) $@ + .depend: $(CPP) $(CFLAGS) -M $(ALLSRC) > .depend diff --git a/mdk-stage1/frontend.h b/mdk-stage1/frontend.h index 167291798..9c2609281 100644 --- a/mdk-stage1/frontend.h +++ b/mdk-stage1/frontend.h @@ -41,6 +41,8 @@ enum return_type ask_from_list(char *msg, char ** elems, char ** choice); enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice); enum return_type ask_from_entries(char *msg, char ** questions, char *** answers, int entry_size, void (*callback_func)(char ** strings)); +void suspend_to_console(void); +void resume_from_suspend(void); void verror_message(char *msg, va_list ap); void vinfo_message(char *msg, va_list ap); diff --git a/mdk-stage1/newt-frontend.c b/mdk-stage1/newt-frontend.c index e0bc7c5ce..15221c91f 100644 --- a/mdk-stage1/newt-frontend.c +++ b/mdk-stage1/newt-frontend.c @@ -390,3 +390,7 @@ enum return_type ask_from_entries(char *msg, char ** questions, char *** answers return RETURN_OK; } + + +void suspend_to_console(void) { newtSuspend(); } +void resume_from_suspend(void) { newtResume(); } diff --git a/mdk-stage1/rescue-gui.c b/mdk-stage1/rescue-gui.c new file mode 100644 index 000000000..bed0b403c --- /dev/null +++ b/mdk-stage1/rescue-gui.c @@ -0,0 +1,206 @@ +/* + * Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2001 MandrakeSoft + * + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> +#define _USE_BSD +#include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <sys/mount.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/unistd.h> +#include <sys/select.h> + +#include "config-stage1.h" +#include "frontend.h" +#include "tools.h" + +char * env[] = { + "PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sbin:/mnt/usr/sbin:/mnt/bin:/mnt/usr/bin", + "LD_LIBRARY_PATH=/lib:/usr/lib:/mnt/lib:/mnt/usr/lib:/usr/X11R6/lib:/mnt/usr/X11R6/lib", + "HOME=/", + "TERM=linux", + "TERMINFO=/etc/terminfo", + NULL +}; + +void pause(void) { unsigned char t; fflush(stdout); read(0, &t, 1); } + + +/* ------ UUURGH this is duplicated from `init.c', don't edit here........ */ +static inline _syscall3(int, reboot, int, magic, int, magic2, int, flag); +#define LOOP_CLR_FD 0x4C01 +void del_loop(char *device) +{ + int fd; + if ((fd = open(device, O_RDONLY, 0)) < 0) { + printf("del_loop open failed\n"); + return; + } + + if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { + printf("del_loop ioctl failed"); + return; + } + + close(fd); +} +struct filesystem { char * dev; char * name; char * fs; int mounted; }; +void unmount_filesystems(void) +{ + int fd, size; + char buf[65535]; /* this should be big enough */ + char *p; + struct filesystem fs[500]; + int numfs = 0; + int i, nb; + + printf("unmounting filesystems...\n"); + + fd = open("/proc/mounts", O_RDONLY, 0); + if (fd < 1) { + printf("ERROR: failed to open /proc/mounts"); + sleep(2); + return; + } + + size = read(fd, buf, sizeof(buf) - 1); + buf[size] = '\0'; + + close(fd); + + p = buf; + while (*p) { + fs[numfs].mounted = 1; + fs[numfs].dev = p; + while (*p != ' ') p++; + *p++ = '\0'; + fs[numfs].name = p; + while (*p != ' ') p++; + *p++ = '\0'; + fs[numfs].fs = p; + while (*p != ' ') p++; + *p++ = '\0'; + while (*p != '\n') p++; + p++; + if (strcmp(fs[numfs].name, "/") != 0) numfs++; /* skip if root, no need to take initrd root in account */ + } + + /* Pixel's ultra-optimized sorting algorithm: + multiple passes trying to umount everything until nothing moves + anymore (a.k.a holy shotgun method) */ + do { + nb = 0; + for (i = 0; i < numfs; i++) { + /*printf("trying with %s\n", fs[i].name);*/ + if (fs[i].mounted && umount(fs[i].name) == 0) { + if (strncmp(fs[i].dev + sizeof("/dev/") - 1, "loop", + sizeof("loop") - 1) == 0) + del_loop(fs[i].dev); + + printf("\t%s\n", fs[i].name); + fs[i].mounted = 0; + nb++; + } + } + } while (nb); + + for (i = nb = 0; i < numfs; i++) + if (fs[i].mounted) { + printf("\t%s umount failed\n", fs[i].name); + if (strcmp(fs[i].fs, "ext2") == 0) nb++; /* don't count not-ext2 umount failed */ + } + + if (nb) { + printf("failed to umount some filesystems\n"); + while (1); + } +} +/* ------ UUURGH -- end */ + + +int main(int argc, char **argv) +{ + enum return_type results; + + char install_bootloader[] = "Re-install Boot Loader"; + char mount_parts[] = "Mount your partitions under /mnt"; + char go_to_console[] = "Go to console"; + char reboot_[] = "Reboot"; + + char * actions[] = { install_bootloader, mount_parts, go_to_console, reboot_, NULL }; + char * choice; + + init_frontend("Welcome to " DISTRIB_NAME " Rescue (" VERSION ") " __DATE__ " " __TIME__); + + do { + int pid; + char * binary = NULL; + + choice = ""; + results = ask_from_list("Please choose the desired action.", actions, &choice); + + if (ptr_begins_static_str(choice, install_bootloader)) { + binary = "/usr/bin/install_bootloader"; + } + if (ptr_begins_static_str(choice, mount_parts)) { + binary = "/usr/bin/guessmounts"; + } + if (ptr_begins_static_str(choice, reboot_)) { + finish_frontend(); + unmount_filesystems(); + printf("rebooting system\n"); + sleep(2); + reboot(0xfee1dead, 672274793, 0x01234567); + } + + if (binary) { + int wait_status; + suspend_to_console(); + if (!(pid = fork())) { + + char * child_argv[2]; + child_argv[0] = binary; + child_argv[1] = NULL; + + execve(child_argv[0], child_argv, env); + printf("Can't execute binary (%s)\n<press Enter>\n", binary); + pause(); + + return 33; + } + while (wait4(-1, &wait_status, 0, NULL) != pid) {}; + printf("<press Enter to return to Rescue GUI>"); + pause(); + resume_from_suspend(); + if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) { + error_message("Program exited abnormally (return code %d).", WEXITSTATUS(wait_status)); + if (WIFSIGNALED(wait_status)) + error_message("(received signal %d)", WTERMSIG(wait_status)); + } + } + + } while (results == RETURN_OK && !ptr_begins_static_str(choice, go_to_console)); + + finish_frontend(); + printf("Bye.\n"); + + return 0; +} diff --git a/mdk-stage1/stdio-frontend.c b/mdk-stage1/stdio-frontend.c index 0eda5d76c..83e8fd76d 100644 --- a/mdk-stage1/stdio-frontend.c +++ b/mdk-stage1/stdio-frontend.c @@ -360,3 +360,7 @@ enum return_type ask_from_entries(char *msg, char ** questions, char *** answers return RETURN_OK; } } + + +void suspend_to_console(void) {} +void resume_from_suspend(void) {} diff --git a/rescue/Makefile b/rescue/Makefile index 59de38f3d..d236ac579 100644 --- a/rescue/Makefile +++ b/rescue/Makefile @@ -7,7 +7,7 @@ ROOTDEST = /export install: rescue_stage2.bz2 cp -f $< $(ROOTDEST)/Mandrake/base -rescue_stage2.bz2: kernel_read_part list list.$(ARCH) drvinst guessmounts make_rescue_img +rescue_stage2.bz2: kernel_read_part list list.$(ARCH) drvinst guessmounts lsparts make_rescue_img ./make_rescue_img clean: diff --git a/rescue/guessmounts b/rescue/guessmounts index e2c9f2c55..5adb33d92 100755 --- a/rescue/guessmounts +++ b/rescue/guessmounts @@ -1,5 +1,4 @@ #!/usr/bin/perl - # # Guillaume Cottenceau (gc@mandrakesoft.com) # @@ -15,9 +14,13 @@ sub cat_ { local *F; open F, $_[0] or $_[1] ? die "cat of file $_[0] failed: $!\n" : return; my @l = <F>; wantarray ? @l : join '', @l } +sub chomp_ { my @l = map { my $l = $_; chomp $l; $l } @_; wantarray ? @l : $l[0] } + + +my @mounts = cat_('/proc/mounts'); +grep { (split)[1] =~ m|^/mnt$| } @mounts and print("/mnt is already mounted (according to /proc/mounts)\n"), exit 0; -#- start system('drvinst'); #- class2text seems broken, I can't detect easily only modules for SCSI storage :-( print "\nPlease wait, trying to find your root device...\n"; @@ -38,8 +41,10 @@ M: foreach (@parts) { for my $fs ('ext3', 'ext2', 'reiserfs', 'xfs', 'jfs') { my $where = $target; if (!system("mount -t $fs $dev $where 2>/dev/null")) { - if (-f "$where/etc/fstab") { - print "Found a probable root partition on $dev (type $fs)\n"; + if (-r "$where/etc/fstab" && -r "$where/etc/mandrake-release") { + print "=> found a Mandrake root partition on $dev\n=> type $fs, version `", + chomp_(cat_ "$where/etc/mandrake-release"), + "'\n"; @fstab = cat_("$where/etc/fstab"); $root = $dev; last M; @@ -52,7 +57,7 @@ M: foreach (@parts) { } if ($root) { - print "\nMounting other partition from fstab on $target...\n"; + print "\nMounting other partitions from fstab on $target...\n"; foreach (@fstab) { my ($dev, $where, $type, $opts) = split; next if (!$type || $dev eq 'none' || $opts =~ /noauto/ || @@ -63,17 +68,24 @@ if ($root) { $opts = join(',', grep { !/codepage=/ && !/iocharset/ } split(',', $opts)); #- vfat opts, we don't have the modules in rescue $where = "$target$where"; -d $where || mkdir($where) or die "couldn't create $where\n"; - print "Mounting $dev on $where type $type\n"; + print "\t$dev on $where type $type\n"; system("mount -t $type $dev $where -o $opts"); } - print "Your partitions are mounted on $target.\n". - "For example you can use 'chroot $target' to simulate your system.\n". - "(you can reinstall lilo that way if necessary).\n\n"; + print "\nYour system is ready on $target.\n\n"; +} else { + die "Could not find your root device :-(.\n"; } + #------------------------------------------------- #- $Log$ +#- Revision 1.4 2001/10/24 22:34:01 gc +#- - add a GUI to the rescue +#- - provide guessmounts with better efficiency and output, go to console, and reboot +#- - provide install_bootloader which runs lilo from /mnt if it seems safe +#- - add lsparts to rescue, which prints partitions with detected types +#- #- Revision 1.3 2001/09/07 18:22:54 gc #- ext3, xfs, jfs #- diff --git a/rescue/install_bootloader b/rescue/install_bootloader new file mode 100755 index 000000000..8bbd6886c --- /dev/null +++ b/rescue/install_bootloader @@ -0,0 +1,47 @@ +#!/usr/bin/perl +# +# Guillaume Cottenceau (gc@mandrakesoft.com) +# +# Copyright 2001 MandrakeSoft +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +sub cat_ { local *F; open F, $_[0] or $_[1] ? die "cat of file $_[0] failed: $!\n" : return; my @l = <F>; wantarray ? @l : join '', @l } +sub chomp_ { my @l = map { my $l = $_; chomp $l; $l } @_; wantarray ? @l : $l[0] } + +system('guessmounts') and die; + +#- this is dangerous, try to take care +my @mounts = cat_('/proc/mounts'); +grep { (split)[1] =~ m|^/mnt$| } @mounts or die "Your root device isn't mounted on /mnt (according to /proc/mounts)\n"; +-x '/mnt/sbin/lilo' or die "/mnt/sbin/lilo isn't executable, exiting.\n"; +-r '/mnt/etc/lilo.conf' or die "/mnt/etc/lilo.conf isn't readable, exiting.\n"; +cat_('/mnt/etc/mandrake-release') =~ /Mandrake/ or die "/mnt/etc/mandrake-release doesn't contain 'Mandrake', exiting.\n"; + +print "About to re-install Boot Loader of following Mandrake distro:\n\t", + chomp_(cat_ "/mnt/etc/mandrake-release"), + "\n=> ok? <press Enter to continue, 'n' and Enter to cancel> "; +<STDIN> =~ /^n/i and exit 0; + +exec '/mnt/sbin/lilo', '-r', '/mnt'; + +die "error: couldn't exec /mnt/sbin/lilo.\n"; + + +#------------------------------------------------- +#- $Log$ +#- Revision 1.1 2001/10/24 22:34:01 gc +#- - add a GUI to the rescue +#- - provide guessmounts with better efficiency and output, go to console, and reboot +#- - provide install_bootloader which runs lilo from /mnt if it seems safe +#- - add lsparts to rescue, which prints partitions with detected types +#- +#- +#- diff --git a/rescue/lsparts b/rescue/lsparts new file mode 100755 index 000000000..c73e1ad21 --- /dev/null +++ b/rescue/lsparts @@ -0,0 +1,124 @@ +#!/usr/bin/perl +# +# Main author Pascal Rigaux (pixel@mandrakesoft.com) +# Put together by Guillaume Cottenceau (gc@mandrakesoft.com) +# +# Copyright 1999,2000,2001 MandrakeSoft +# +# This software may be freely redistributed under the terms of the GNU +# public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# This code is extracted from DrakX, the Mandrake Linux graphical installer. +# http://www.mandrakelinux.com/drakx/ +# Open development rulz, find CVS here: +# http://www.mandrakelinux.com/cgi-bin/cvsweb.cgi/gi/ +# +# Detects partition types using signatures +# + +sub cat_ { local *F; open F, $_[0] or $_[1] ? die "cat of file $_[0] failed: $!\n" : return; my @l = <F>; wantarray ? @l : join '', @l } + +sub arch() { + my $t = `uname -m`; + chomp $t; + $t; +} + +# from Perl Cookbook / Pleac +# http://pleac.sourceforge.net/pleac_perl/numbers.html#AEN121 +sub commify { + my $text = reverse $_[0]; + $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; + return scalar reverse $text; +} + +my @partitions_signatures = ( + [ 0x8e, 0, "HM\1\0" ], + [ 0x83, 0x438, "\x53\xEF" ], + [ 0x183, 0x10034, "ReIsErFs" ], + [ 0x183, 0x10034, "ReIsEr2Fs" ], + [ 0x283, 0, 'XFSB', 0x200, 'XAGF', 0x400, 'XAGI' ], + [ 0x383, 0x8000, 'JFS1' ], + [ 0x82, 4086, "SWAP-SPACE" ], + [ 0x82, 4086, "SWAPSPACE2" ], + [ 0x7, 0x1FE, "\x55\xAA", 0x3, "NTFS" ], + [ 0xc, 0x1FE, "\x55\xAA", 0x52, "FAT32" ], +arch() !~ /^sparc/ ? ( + [ 0x6, 0x1FE, "\x55\xAA", 0x36, "FAT" ], +) : (), +); + +sub typeFromMagic { + my $f = shift; + local *F; sysopen F, $f, 0 or return; + + my $tmp; + M: foreach (@partitions_signatures) { + my ($name, @l) = @$_; + while (@l) { + my ($offset, $signature) = splice(@l, 0, 2); + sysseek(F, $offset, 0) or next M; + sysread(F, $tmp, length $signature); + $tmp eq $signature or next M; + } + return $name; + } + return -1; +} + +my %type2name = ( + 0x1 => 'DOS 12-bit FAT', + 0x4 => 'DOS 16-bit FAT (up to 32M)', + 0x5 => 'DOS 3.3+ Extended Partition', + 0x6 => 'DOS FAT16', + 0x7 => 'NTFS (or HPFS)', + 0xb => 'Win98 FAT32', + 0xc => 'Win98 FAT32, LBA-mapped', + 0xe => 'Win95: DOS 16-bit FAT, LBA-mapped', + 0xf => 'Win95: Extended partition, LBA-mapped', + 0x82 => 'Linux Swap', + 0x83 => 'Ext2', + 0x183 => 'ReiserFS', + 0x283 => 'XFS', + 0x383 => 'JFS', + 0x85 => 'Linux extended partition', + 0x87 => 'NTFS volume set', + 0x8e => 'Linux LVM', + -1 => 'unknown' + ); + + +my $params = join '', @ARGV; + +$params =~ /-h/ and die "usage: lsparts [-v]\n"; +$params =~ /-v/ and $verbose = 1; + + +my (undef, undef, @parts) = cat_('/proc/partitions'); + +P: foreach (@parts) { + my (undef, undef, $blocks, $dev) = split or next; + my %skip_conditions = ( + "Skipping <$dev> because too little blocks ($blocks)" => ($blocks <= 1), + "Skipping <$dev> because doesn't end with a number (e.g. seems to not be a partition)" => ($dev !~ /\d$/), + ); + $skip_conditions{$_} and ($verbose and print(STDERR $_, "\n")), next P foreach keys %skip_conditions; + my $type = typeFromMagic("/dev/$dev"); + $type and printf "$dev: %6s Mbytes, type <0x%x> (%s)\n", commify($blocks >> 10), $type, $type2name{$type}; +} + + +#------------------------------------------------- +#- $Log$ +#- Revision 1.1 2001/10/24 22:34:01 gc +#- - add a GUI to the rescue +#- - provide guessmounts with better efficiency and output, go to console, and reboot +#- - provide install_bootloader which runs lilo from /mnt if it seems safe +#- - add lsparts to rescue, which prints partitions with detected types +#- +# diff --git a/rescue/make_rescue_img b/rescue/make_rescue_img index e3bb4e8ed..e6c744e53 100755 --- a/rescue/make_rescue_img +++ b/rescue/make_rescue_img @@ -86,6 +86,10 @@ _ "cp ../all.modules/$main/modules.dep $tmp/modules"; installown("drvinst", "/usr/bin"); installown("guessmounts", "/usr/bin"); +installown("install_bootloader", "/usr/bin"); +installown("lsparts", "/usr/bin"); +_ "cd ../mdk-stage1 && make rescue-gui"; +installown("../mdk-stage1/rescue-gui", "/usr/bin"); __ "strip $tmp/{lib,bin,sbin}/* $tmp/usr/{bin,sbin}/* 2>/dev/null"; diff --git a/rescue/tree/etc/issue b/rescue/tree/etc/issue index 55da5cd1e..a38b2f1a3 100644 --- a/rescue/tree/etc/issue +++ b/rescue/tree/etc/issue @@ -18,9 +18,10 @@ [1;30;44m [43m [40m [47m [40m [43m [40m[2C [0m[255D -Mandrake Linux release 8.1 (Cooker) +Mandrake Linux release 8.2 (Cooker) Use [1;33;40mloadkeys[0m to change your keyboard layout (eg: loadkeys fr) Use [1;33;40mmodprobe[0m to load modules (eg: modprobe snd-card-fm801) Use [1;33;40mdrvinst[0m to install drivers according to detected devices +Use [1;33;40mlsparts[0m to list your partitions with types diff --git a/rescue/tree/etc/rc.sysinit b/rescue/tree/etc/rc.sysinit index c33983cca..444e0c064 100755 --- a/rescue/tree/etc/rc.sysinit +++ b/rescue/tree/etc/rc.sysinit @@ -41,11 +41,6 @@ grep -q oem /proc/cmdline && exec /etc/oem -f /sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 /sbin/route add 127.0.0.1 lo -if ! grep -q noguessmounts /proc/cmdline; then - echo "I will try now to guess your mountpoints;" - echo -e "If any problems, reboot and enter \\033[1;37mrescue noguessmounts\\033[0;39m to disable this." - echo "" - guessmounts - echo "Press <enter> to continue" - read +if ! grep -q expert /proc/cmdline; then + rescue-gui fi |