diff --git a/Makefile b/Makefile index 712bf32..9d96e7f 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ RELEASE = $(shell $(RPM) -q --qf '[%{RELEASE} ]' --specfile $(RPMSPEC) |cut -f1 TARFILE = $(PACKAGE)-$(VERSION).tar.bz2 TARDIR = $(shell $(RPM) --define 'name $(PACKAGE)' --eval %_sourcedir) -METHODS = full medias network +METHODS = full medias network live DESTDIR = BINSDIR ?= /usr/lib/propagator/bin @@ -104,17 +104,21 @@ endif # stage1 itself STAGE1SRC = stage1.c log.c tools.c modules.c probing.c mount.c automatic.c frontend-common.c MEDIASRC = cdrom.c disk.c lomount.c +LIVESRC = live.c NETWORKSRC = network.c nfsmount.c dhcp.c url.c dns.c adsl.c ALLSRC = $(INITSRC) $(STAGE1SRC) $(MEDIASRC) $(NETWORKSRC) ############################################################################### -STAGE1OBJS-MEDIA = $(subst .c,-MEDIA.o,$(STAGE1SRC) $(MEDIASRC)) +STAGE1OBJS-LIVE = $(subst .c,-LIVE.o,$(STAGE1SRC) $(LIVESRC) $(MEDIASRC)) +LIVE_DEFS = -DDISABLE_NETWORK -DDISABLE_DISK -DAUTO_METHOD=\""live"\" + +STAGE1OBJS-MEDIA = $(subst .c,-MEDIA.o,$(STAGE1SRC) $(MEDIASRC) $(LIVESRC)) MEDIA_DEFS = -DDISABLE_NETWORK -DAUTO_METHOD=\""cdrom"\" ##-DAUTO_METHOD=\""disk"\" STAGE1OBJS-NETWORK = $(subst .c,-NETWORK.o,$(STAGE1SRC) $(NETWORKSRC)) -NETWORK_DEFS = -DDISABLE_CDROM -DDISABLE_DISK +NETWORK_DEFS = -DDISABLE_CDROM -DDISABLE_DISK -DDISABLE_LIVE -STAGE1OBJS-FULL = $(subst .c,-FULL.o,$(STAGE1SRC) $(MEDIASRC) $(NETWORKSRC)) +STAGE1OBJS-FULL = $(subst .c,-FULL.o,$(STAGE1SRC) $(MEDIASRC) $(LIVESRC) $(NETWORKSRC)) USBNET_DEFS = -DENABLE_USBNET USBSTORAGE_DEFS = -DENABLE_USBSTORAGE @@ -154,6 +158,10 @@ stage1-full: $(STAGE1OBJS-FULL) $(STAGE1_OWN_LIBS) $(STAGE1_NETWORK_LIBS) $(FRON $(CC) -o $@ $^ $(LDFLAGS_STAGE1) $(STRIPCMD) $@ +stage1-live: $(STAGE1OBJS-LIVE) $(STAGE1_OWN_LIBS) $(FRONTEND_LINK) $(STAGE1_LIBC) + $(CC) -o $@ $^ $(LDFLAGS_STAGE1) + $(STRIPCMD) $@ + $(INITOBJS): %.o: %.c $(COMPILE) $(INIT_DEFS) -c $< @@ -163,6 +171,9 @@ $(STAGE1OBJS-MEDIA): %-MEDIA.o: %.c $(STAGE1OBJS-NETWORK): %-NETWORK.o: %.c $(COMPILE) $(INCLUDES) $(NETWORK_DEFS) $(USBNET_DEFS) -c $< -o $@ +$(STAGE1OBJS-LIVE): %-LIVE.o: %.c + $(COMPILE) $(INCLUDES) $(LIVE_DEFS) $(USBSTORAGE_DEFS) -c $< -o $@ + $(STAGE1OBJS-FULL): %-FULL.o: %.c $(COMPILE) $(INCLUDES) $(USBNET_DEFS) $(USBSTORAGE_DEFS) -c $< -o $@ @@ -193,6 +204,8 @@ endif *-FULL.o: %-FULL.o: %.o +*-LIVE.o: %-LIVE.o: %.o + install: all mkdir -p $(DESTDIR)$(BINSDIR) install -m0755 init $(DESTDIR)$(BINSDIR) diff --git a/config-stage1.h b/config-stage1.h index bb2f703..9f4fda4 100644 --- a/config-stage1.h +++ b/config-stage1.h @@ -19,7 +19,7 @@ #include "version.h" /* If we have more than that amount of memory (in Mbytes), we assume we can load the second stage as a ramdisk */ -#define MEM_LIMIT_RAMDISK 80 +#define MEM_LIMIT_RAMDISK 150 /* If we have more than that amount of memory (in Mbytes), we assume we can load the rescue as a ramdisk */ #define MEM_LIMIT_RESCUE 56 @@ -33,6 +33,8 @@ #define RAMDISK_LOCATION "/ALTLinux/base/" #define IMAGE_LOCATION "/tmp/image" #define STAGE2_LOCATION "/tmp/stage2" +#define LIVECD_LOCATION "/ALTLinux/altlinux.clp" +#define LIVEIMAGE_LOCATION "/tmp/live" //#define STAGE2_BINNAME "predator" #define STAGE2_BINNAME "install2" @@ -43,9 +45,10 @@ #ifdef DISABLE_DISK #ifdef DISABLE_CDROM +#ifdef DISABLE_LIVE #define DISABLE_MEDIAS #endif #endif - +#endif #endif diff --git a/init.c b/init.c index bd37103..86c1123 100644 --- a/init.c +++ b/init.c @@ -425,7 +425,6 @@ int main(int argc, char **argv) char * child_argv[2]; child_argv[0] = "/sbin/stage1"; child_argv[1] = NULL; - sleep(10); execve(child_argv[0], child_argv, env); printf("error in exec of stage1 :-(\n"); return 0; @@ -444,8 +443,16 @@ int main(int argc, char **argv) printf("\n"); abnormal_termination = 1; } else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_rescue) { + char * child_argv[2]; + child_argv[0] = "/sbin/init"; + child_argv[1] = NULL; kill(klog_pid, 9); - printf("exiting init -- giving hand to rescue\n"); + printf("exiting init -- giving hand to livecd\n"); + chdir("/tmp/live"); + pivot_root(".","old_root"); + chroot("."); + umount("old_root"); + execve(child_argv[0], child_argv, env); return 0; } else printf("install succeeded\n"); diff --git a/live.c b/live.c new file mode 100644 index 0000000..7b0882b --- /dev/null +++ b/live.c @@ -0,0 +1,257 @@ +/* + * Anton Farygin (rider@altlinux.com) + * + * Copyright 2004 ALT Linux + * + * 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. + * + */ + +/* + * Portions from Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * Portions from Erik Troan (ewt@redhat.com) + * + * Copyright 1996 Red Hat Software + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "stage1.h" +#include "frontend.h" +#include "modules.h" +#include "probing.h" +#include "log.h" +#include "mount.h" + +#include "live.h" + + +static int mount_that_cd_device(char * dev_name) +{ + char device_fullname[50]; + + strcpy(device_fullname, "/dev/"); + strcat(device_fullname, dev_name); + + return my_mount(device_fullname, IMAGE_LOCATION, "iso9660", 0); +} + +int do_losetup(char * device, char * target) +{ + int loopfd, targfd; + struct loop_info loopInfo; + loopfd = open( device, O_RDONLY ); + if ( loopfd < 0 ) + { + log_message( "losetup: error opening %s: %s", device, strerror(errno) ); + return -1; + } + + targfd = open( target, O_RDONLY ); + if ( targfd < 0 ) + { + log_message( "losetup: error opening %s: %s", target, strerror(errno) ); + close( loopfd ); + return -1; + } + + if ( ioctl(loopfd, LOOP_SET_FD, targfd) < 0 ) + { + log_message( "losetup: error setting up loopback device: %s", strerror(errno) ); + close( loopfd ); + close( targfd ); + return -1; + } + + memset(&loopInfo, 0, sizeof(loopInfo)); + strcpy(loopInfo.lo_name, target); + + if ( ioctl(loopfd, LOOP_SET_STATUS, &loopInfo) < 0 ) + log_message( "losetup: error setting up loopback device: %s", strerror(errno) ); + + close( loopfd ); + close( targfd ); + return 0; +} + +static int mount_image(char * dev_name) +{ + char device_fullname[50]; + strcpy(device_fullname, "/dev/"); + strcat(device_fullname, dev_name); + log_message("Setup %s for " IMAGE_LOCATION LIVECD_LOCATION, device_fullname); + if (do_losetup(device_fullname, IMAGE_LOCATION LIVECD_LOCATION) == -1) + fatal_error("could not setup loopback for live cd image"); + mkdir(LIVEIMAGE_LOCATION,0755); + return my_mount(device_fullname, LIVEIMAGE_LOCATION, "ext2", 0); +} + + +static int test_that_livecd() +{ + return access(IMAGE_LOCATION LIVECD_LOCATION, R_OK); +} + + +static enum return_type try_with_live_device(char * dev_name, char * dev_model); + +static enum return_type do_with_live_device(char * dev_name, char * dev_model) +{ + pid_t preparepid, childpid; + int end_child; + int wait_status; + + if (test_that_livecd()) { + enum return_type results; + umount(IMAGE_LOCATION); + results = ask_yes_no("That CDROM disc does not seem to be a " DISTRIB_NAME " LIVE CD.\nRetry with another disc?"); + if (results == RETURN_OK) + return try_with_live_device(dev_name, dev_model); + return results; + } + + log_message("found a " DISTRIB_NAME " LIVE-CD, good news!"); + mount_image("cloop"); +#if 0 + if (!(preparepid = fork())) { + /* child */ + char * child_argv[2]; + char * args[3] = { "prepare_live.sh", NULL, }; + char * envp[32] = { "HOME=/root", "TERM=linux", NULL, }; + chroot("/tmp/live"); + sleep(10); + execve("/root/prepare_live.sh",args,envp); + printf("error in exec of prepare_live.sh :-(\n"); + return 0; + } + + while (!end_child) { + childpid = wait4(-1, &wait_status, 0, NULL); + if (childpid == preparepid) + end_child = 1; + } +#endif + method_name = strdup("live"); + return RETURN_OK; +} + +static enum return_type try_with_live_device(char * dev_name, char * dev_model) +{ + wait_message("Trying to access a CDROM disc (drive %s)", dev_model); + + if (mount_that_cd_device(dev_name) == -1) { + enum return_type results; + char msg[500]; + unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */ + remove_wait_message(); + + snprintf(msg, sizeof(msg), "I can't access a " DISTRIB_NAME " liveCD disc in your CDROM drive (%s).\nRetry?", dev_model); + results = ask_yes_no(msg); + if (results == RETURN_OK) + return try_with_live_device(dev_name, dev_model); + return results; + } + remove_wait_message(); + + return do_with_live_device(dev_name, dev_model); +} + +enum return_type live_prepare(void) +{ + char ** medias, ** ptr, ** medias_models; + char * choice; + int i, count = 0; + enum return_type results; + + my_insmod("ide-cd", ANY_DRIVER_TYPE, NULL); + my_insmod("sr_mod", ANY_DRIVER_TYPE, NULL); + my_insmod("zlib_inflate", ANY_DRIVER_TYPE, NULL); + my_insmod("cloop", ANY_DRIVER_TYPE, NULL); + + get_medias(CDROM, &medias, &medias_models); + + ptr = medias; + while (ptr && *ptr) { + count++; + ptr++; + } + + if (count == 0) { + stg1_error_message("No CDROM device found."); + i = ask_insmod(SCSI_ADAPTERS); + if (i == RETURN_BACK) + return RETURN_BACK; + return live_prepare(); + } + + if (count == 1) { + results = try_with_live_device(*medias, *medias_models); + if (results == RETURN_OK) + return RETURN_OK; + i = ask_insmod(SCSI_ADAPTERS); + if (i == RETURN_BACK) + return RETURN_BACK; + return live_prepare(); + } + + if (IS_AUTOMATIC) { + char ** model = medias_models; + ptr = medias; + while (ptr && *ptr) { + wait_message("Trying to access " DISTRIB_NAME " LIVE CD disc (drive %s)", *model); + if (mount_that_cd_device(*ptr) != -1) { + if (!test_that_livecd()) { + remove_wait_message(); + return do_with_live_device(*ptr, *model); + } + else + umount(IMAGE_LOCATION); + } + remove_wait_message(); + ptr++; + model++; + } + unset_param(MODE_AUTOMATIC); + return live_prepare(); + } + else { + results = ask_from_list_comments("Please choose the CDROM drive to use for the livecd.", medias, medias_models, &choice); + if (results == RETURN_OK) { + char ** model = medias_models; + ptr = medias; + while (ptr && *ptr && model && *model) { + if (!strcmp(*ptr, choice)) + break; + ptr++; + model++; + } + results = try_with_live_device(choice, *model); + } else + return results; + } + + if (results == RETURN_OK) + return RETURN_OK; + if (results == RETURN_BACK) + return live_prepare(); + + i = ask_insmod(SCSI_ADAPTERS); + if (i == RETURN_BACK) + return RETURN_BACK; + return live_prepare(); +} diff --git a/live.h b/live.h new file mode 100644 index 0000000..3c0394f --- /dev/null +++ b/live.h @@ -0,0 +1,33 @@ +/* + * Anton Farygin (rider@altlinux.com) + * + * Copyright 2004 ALT Linux + * + * 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. + * + */ + +/* + * Portions from Guillaume Cottenceau (gc@mandrakesoft.com) + * + * Copyright 2000 MandrakeSoft + * + * Portions from Erik Troan (ewt@redhat.com) + * + * Copyright 1996 Red Hat Software + * + */ + +#ifndef _LIVE_H_ +#define _LIVE_H_ + +#include "stage1.h" + +enum return_type live_prepare(void); + +#endif diff --git a/stage1.c b/stage1.c index 8d859a6..151f661 100644 --- a/stage1.c +++ b/stage1.c @@ -301,6 +301,9 @@ static enum return_type method_select_and_prepare(void) #ifndef DISABLE_CDROM char * cdrom_install = "CDROM drive"; char * cdrom_install_auto = "cdrom"; #endif +#ifndef DISABLE_LIVE + char * live_install = "CDROM LIVECD"; char * live_install_auto = "live"; +#endif #ifndef DISABLE_NETWORK char * network_nfs_install = "NFS server"; char * network_nfs_install_auto = "nfs"; char * network_ftp_install = "FTP server"; char * network_ftp_install_auto = "ftp"; @@ -316,6 +319,9 @@ static enum return_type method_select_and_prepare(void) #ifndef DISABLE_CDROM means[i] = cdrom_install; means_auto[i++] = cdrom_install_auto; #endif +#ifndef DISABLE_LIVE + means[i] = live_install; means_auto[i++] = live_install_auto; +#endif #ifndef DISABLE_DISK means[i] = disk_install; means_auto[i++] = disk_install_auto; #endif @@ -332,6 +338,11 @@ static enum return_type method_select_and_prepare(void) if (!strcmp(choice, cdrom_install)) results = cdrom_prepare(); #endif + +#ifndef DISABLE_LIVE + if (!strcmp(choice, live_install)) + results = live_prepare(); +#endif #ifndef DISABLE_DISK if (!strcmp(choice, disk_install)) @@ -415,34 +426,29 @@ int main(int argc, char **argv, char **env) if (ret != RETURN_OK) fatal_error("could not select an installation method"); - if (!IS_RAMDISK) { - if (symlink(IMAGE_LOCATION LIVE_LOCATION, STAGE2_LOCATION) != 0) { - perror("symlink"); - printf("symlink from " IMAGE_LOCATION LIVE_LOCATION " to " STAGE2_LOCATION " failed"); - fatal_error(strerror(errno)); - } - } - - if (symlink(STAGE2_LOCATION "/usr", "/usr") != 0) { - perror("symlink"); - printf("symlink from " STAGE2_LOCATION "/usr to /usr failed"); - fatal_error(strerror(errno)); - } - - if (symlink(STAGE2_LOCATION "/lib", "/lib") != 0) { - perror("symlink"); - printf("symlink from " STAGE2_LOCATION "/lib to /lib failed"); - fatal_error(strerror(errno)); - } - if (interactive_pid != 0) kill(interactive_pid, 9); - if (IS_RESCUE) + if (IS_RESCUE || IS_LIVE) return 66; + if (IS_TESTING) return 0; + + if (symlink(STAGE2_LOCATION "/usr", "/usr") != 0) { + perror("symlink"); + printf("symlink from " STAGE2_LOCATION "/usr to /usr failed"); + fatal_error(strerror(errno)); + } + + if (symlink(STAGE2_LOCATION "/lib", "/lib") != 0) { + perror("symlink"); + printf("symlink from " STAGE2_LOCATION "/lib to /lib failed"); + fatal_error(strerror(errno)); + } + + argptr = stage2_args; *argptr++ = "/usr/bin/"STAGE2_BINNAME; *argptr++ = "--method"; diff --git a/stage1.h b/stage1.h index c3b74cf..3dfb717 100644 --- a/stage1.h +++ b/stage1.h @@ -33,6 +33,7 @@ extern char * interactive_fifo; #define MODE_TESTING (1 << 0) #define MODE_EXPERT (1 << 1) +#define MODE_LIVE (1 << 2) #define MODE_RESCUE (1 << 3) #define MODE_AUTOMATIC (1 << 4) #define MODE_LOWMEM (1 << 5) @@ -44,6 +45,7 @@ extern char * interactive_fifo; #define IS_TESTING (get_param(MODE_TESTING)) #define IS_EXPERT (get_param(MODE_EXPERT)) #define IS_RESCUE (get_param(MODE_RESCUE)) +#define IS_LIVE (get_param(MODE_LIVE)) #define IS_AUTOMATIC (get_param(MODE_AUTOMATIC)) #define IS_LOWMEM (get_param(MODE_LOWMEM)) #define IS_SPECIAL_STAGE2 (get_param(MODE_SPECIAL_STAGE2)) diff --git a/tools.c b/tools.c index 8156b5e..202e124 100644 --- a/tools.c +++ b/tools.c @@ -90,6 +90,7 @@ void process_cmdline(void) if (!strcmp(name, "changedisk")) set_param(MODE_CHANGEDISK); if (!strcmp(name, "updatemodules")) set_param(MODE_UPDATEMODULES); if (!strcmp(name, "rescue")) set_param(MODE_RESCUE); + if (!strcmp(name, "live")) set_param(MODE_LIVE); if (!strcmp(name, "special_stage2")) set_param(MODE_SPECIAL_STAGE2); if (!strcmp(name, "lowmem")) set_param(MODE_LOWMEM); if (!strcmp(name, "automatic")) {