diff options
Diffstat (limited to 'mdk-stage1/tools.c')
-rw-r--r-- | mdk-stage1/tools.c | 516 |
1 files changed, 188 insertions, 328 deletions
diff --git a/mdk-stage1/tools.c b/mdk-stage1/tools.c index a921883a8..2e27688ea 100644 --- a/mdk-stage1/tools.c +++ b/mdk-stage1/tools.c @@ -1,7 +1,7 @@ /* - * Guillaume Cottenceau (gc@mandrakesoft.com) + * Guillaume Cottenceau (gc) * - * Copyright 2000 MandrakeSoft + * Copyright 2000 Mandriva * * This software may be freely redistributed under the terms of the GNU * public license. @@ -26,13 +26,14 @@ #include <sys/stat.h> #include <fcntl.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <dirent.h> #include <sys/types.h> -#include <bzlib.h> #include <sys/mount.h> #include <sys/poll.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <linux/fd.h> #include "stage1.h" #include "log.h" #include "mount.h" @@ -40,172 +41,41 @@ #include "automatic.h" #include "tools.h" +#include "utils.h" +#include "params.h" +#include "probing.h" +#include "modules.h" +#include "lomount.h" - -static struct param_elem params[50]; -static int param_number = 0; - -void process_cmdline(void) +int image_has_stage2() { - char buf[512]; - int fd, size, i; - - log_message("opening /proc/cmdline... "); - - if ((fd = open("/proc/cmdline", O_RDONLY)) == -1) - fatal_error("could not open /proc/cmdline"); - - size = read(fd, buf, sizeof(buf)); - buf[size-1] = '\0'; // -1 to eat the \n - close(fd); - - log_message("\t%s", buf); - - i = 0; - while (buf[i] != '\0') { - char *name, *value = NULL; - int j = i; - while (buf[i] != ' ' && buf[i] != '=' && buf[i] != '\0') - i++; - if (i == j) { - i++; - continue; - } - name = memdup(&buf[j], i-j + 1); - name[i-j] = '\0'; - - if (buf[i] == '=') { - int k = i+1; - i++; - while (buf[i] != ' ' && buf[i] != '\0') - i++; - value = memdup(&buf[k], i-k + 1); - value[i-k] = '\0'; - } - - params[param_number].name = name; - params[param_number].value = value; - param_number++; - if (!strcmp(name, "expert")) set_param(MODE_EXPERT); - 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, "noauto")) set_param(MODE_NOAUTO); - if (!strcmp(name, "special_stage2")) set_param(MODE_SPECIAL_STAGE2); - if (!strcmp(name, "automatic")) { - set_param(MODE_AUTOMATIC); - grab_automatic_params(value); - } - if (buf[i] == '\0') - break; - i++; - } - - log_message("\tgot %d args", param_number); + return access(COMPRESSED_FILE_REL(IMAGE_LOCATION "/"), R_OK) == 0 || + access(IMAGE_LOCATION "/" LIVE_LOCATION_REL, R_OK) == 0; } - -int stage1_mode = 0; - -int get_param(int i) +enum return_type create_IMAGE_LOCATION(char *location_full) { -#ifdef SPAWN_INTERACTIVE - static int fd = 0; - char buf[5000]; - char * ptr; - int nb; - - if (fd <= 0) { - fd = open(interactive_fifo, O_RDONLY); - if (fd == -1) - return (stage1_mode & i); - fcntl(fd, F_SETFL, O_NONBLOCK); - } + struct stat statbuf; + int offset = strncmp(location_full, IMAGE_LOCATION_DIR, sizeof(IMAGE_LOCATION_DIR) - 1) == 0 ? sizeof(IMAGE_LOCATION_DIR) - 1 : 0; + char *with_arch = asprintf_("%s/%s", location_full, ARCH); - if (fd > 0) { - if ((nb = read(fd, buf, sizeof(buf))) > 0) { - buf[nb] = '\0'; - ptr = buf; - while ((ptr = strstr(ptr, "+ "))) { - if (!strncmp(ptr+2, "expert", 6)) set_param(MODE_EXPERT); - if (!strncmp(ptr+2, "rescue", 6)) set_param(MODE_RESCUE); - ptr++; - } - ptr = buf; - while ((ptr = strstr(ptr, "- "))) { - if (!strncmp(ptr+2, "expert", 6)) unset_param(MODE_EXPERT); - if (!strncmp(ptr+2, "rescue", 6)) unset_param(MODE_RESCUE); - ptr++; - } - } - } -#endif + log_message("trying %s", with_arch); - return (stage1_mode & i); -} + if (stat(with_arch, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) + location_full = with_arch; -char * get_param_valued(char *param_name) -{ - int i; - for (i = 0; i < param_number ; i++) - if (!strcmp(params[i].name, param_name)) - return params[i].value; + log_message("assuming %s is a mirror tree", location_full + offset); - return NULL; -} - -void set_param_valued(char *param_name, char *param_value) -{ - params[param_number].name = param_name; - params[param_number].value = param_value; - param_number++; -} - -void set_param(int i) -{ - stage1_mode |= i; - if (i == MODE_RESCUE) { - set_param_valued("special_stage2", "rescue"); - set_param(MODE_SPECIAL_STAGE2); - } -} - -void unset_param(int i) -{ - stage1_mode &= ~i; -} - -// warning, many things rely on the fact that: -// - when failing it returns 0 -// - it stops on first non-digit char -int charstar_to_int(char * s) -{ - int number = 0; - while (*s && isdigit(*s)) { - number = (number * 10) + (*s - '0'); - s++; - } - return number; -} - -int total_memory(void) -{ - int value; - struct stat statr; - if (stat("/proc/kcore", &statr)) - return 0; - - /* drakx powered: use /proc/kcore and rounds every 4 Mbytes */ - value = 4 * ((int)((float)statr.st_size / 1024 / 1024 / 4 + 0.5)); - log_message("Total Memory: %d Mbytes", value); + unlink(IMAGE_LOCATION); + if (symlink(location_full + offset, IMAGE_LOCATION) != 0) + return RETURN_ERROR; - return value; + return RETURN_OK; } - int ramdisk_possible(void) { - if (total_memory() > (IS_RESCUE ? MEM_LIMIT_RESCUE : MEM_LIMIT_RAMDISK)) + if (total_memory() > (IS_RESCUE ? MEM_LIMIT_RESCUE : MEM_LIMIT_DRAKX)) return 1; else { log_message("warning, ramdisk is not possible due to low mem!"); @@ -213,223 +83,213 @@ int ramdisk_possible(void) } } - -static void save_stuff_for_rescue(void) +int compressed_image_preload(void) { - void save_this_file(char * file) { - char buf[5000]; - int fd_r, fd_w, i; - char location[100]; - - if ((fd_r = open(file, O_RDONLY)) < 0) { - log_message("can't open %s for read", file); - return; - } - strcpy(location, STAGE2_LOCATION); - strcat(location, file); - if ((fd_w = open(location, O_WRONLY)) < 0) { - log_message("can't open %s for write", location); - close(fd_r); - return; - } - if ((i = read(fd_r, buf, sizeof(buf))) <= 0) { - log_message("can't read from %s", file); - close(fd_r); close(fd_w); - return; - } - if (write(fd_w, buf, i) != i) - log_message("can't write %d bytes to %s", i, location); - close(fd_r); close(fd_w); - log_message("saved file %s for rescue (%d bytes)", file, i); + if (total_memory() > (IS_RESCUE ? MEM_LIMIT_RESCUE_PRELOAD : MEM_LIMIT_DRAKX_PRELOAD)) + return 1; + else { + log_message("warning, not preloading compressed due to low mem"); + return 0; } - save_this_file("/etc/resolv.conf"); } - -enum return_type load_ramdisk_fd(int ramdisk_fd, int size) +enum return_type save_fd(int from_fd, char * to, void (*callback_func)(int overall)) { - BZFILE * st2; - char * ramdisk = "/dev/ram3"; /* warning, verify that this file exists in the initrd, and that root=/dev/ram3 is actually passed to the kernel at boot time */ - int ram_fd; - char buffer[32768]; - int z_errnum; - char * wait_msg = "Loading program into memory..."; - int bytes_read = 0; - int actually; - int seems_ok = 0; - - st2 = BZ2_bzdopen(ramdisk_fd, "r"); - - if (!st2) { - log_message("Opening compressed ramdisk: %s", BZ2_bzerror(st2, &z_errnum)); - stg1_error_message("Could not open compressed ramdisk file."); - return RETURN_ERROR; - } - - ram_fd = open(ramdisk, O_WRONLY); - if (ram_fd == -1) { - log_perror(ramdisk); - stg1_error_message("Could not open ramdisk device file."); - return RETURN_ERROR; - } - - init_progression(wait_msg, size); - - while ((actually = BZ2_bzread(st2, buffer, sizeof(buffer))) > 0) { - seems_ok = 1; - if (write(ram_fd, buffer, actually) != actually) { - log_perror("writing ramdisk"); - remove_wait_message(); - return RETURN_ERROR; + FILE * f_to; + size_t quantity __attribute__((aligned(16))), overall = 0; + char buf[4096] __attribute__((aligned(4096))); + int ret = RETURN_ERROR; + + if (!(f_to = fopen(to, "w"))) { + log_perror(to); + goto close_from; + } + + do { + quantity = read(from_fd, buf, sizeof(buf)); + if (quantity > 0) { + if (fwrite(buf, 1, quantity, f_to) != quantity) { + log_message("short write (%s)", strerror(errno)); + goto cleanup; + } + } else if (quantity == -1) { + log_message("an error occured: %s", strerror(errno)); + goto cleanup; } - update_progression((int)((bytes_read += actually) / RAMDISK_COMPRESSION_RATIO)); - } - if (!seems_ok) { - log_message("reading compressed ramdisk: %s", BZ2_bzerror(st2, &z_errnum)); - BZ2_bzclose(st2); /* opened by gzdopen, but also closes the associated fd */ - close(ram_fd); - remove_wait_message(); - stg1_error_message("Could not uncompress second stage ramdisk. " - "This is probably an hardware error while reading the data. " - "(this may be caused by a hardware failure or a Linux kernel bug)"); - return RETURN_ERROR; - } + if (callback_func) { + overall += quantity; + callback_func(overall); + } + } while (quantity); - end_progression(); + ret = RETURN_OK; - BZ2_bzclose(st2); /* opened by gzdopen, but also closes the associated fd */ - close(ram_fd); + cleanup: + fclose(f_to); + close_from: + close(from_fd); - if (my_mount(ramdisk, STAGE2_LOCATION, "ext2", 1)) - return RETURN_ERROR; + return ret; +} + +enum return_type copy_file(char * from, char * to, void (*callback_func)(int overall)) +{ + int from_fd; - set_param(MODE_RAMDISK); + log_message("copy_file: %s -> %s", from, to); - if (IS_RESCUE) { - save_stuff_for_rescue(); - if (umount(STAGE2_LOCATION)) { - log_perror(ramdisk); - return RETURN_ERROR; - } - return RETURN_OK; /* fucksike, I lost several hours wondering why the kernel won't see the rescue if it is alreay mounted */ - } + from_fd = open(from, O_RDONLY); + if (from_fd != -1) { + return save_fd(from_fd, to, callback_func); + } else { + log_perror(from); + return RETURN_ERROR; + } +} +enum return_type mount_compressed_image(char *compressed_image, char *location_mount) +{ + if (lomount(compressed_image, location_mount, NULL, 1)) { + stg1_error_message("Could not mount compressed loopback :(."); + return RETURN_ERROR; + } return RETURN_OK; } - -char * get_ramdisk_realname(void) +enum return_type preload_mount_compressed_fd(int compressed_fd, int image_size, char *image_name, char *location_mount) { - char img_name[500]; - char * stg2_name = get_param_valued("special_stage2"); - char * begin_img = RAMDISK_LOCATION; - char * end_img = "_stage2.bz2"; - - if (!stg2_name) - stg2_name = "mdkinst"; - - if (IS_RESCUE) - stg2_name = "rescue"; + int ret; + char *compressed_tmpfs = asprintf_("/tmp/%s", image_name); + char *buf = "Loading program into memory..."; + init_progression(buf, image_size); + ret = save_fd(compressed_fd, compressed_tmpfs, update_progression); + end_progression(); + if (ret != RETURN_OK) + return ret; - strcpy(img_name, begin_img); - strcat(img_name, stg2_name); - strcat(img_name, end_img); - - return strdup(img_name); + return mount_compressed_image(compressed_tmpfs, location_mount); } - -enum return_type load_ramdisk(void) +enum return_type mount_compressed_image_may_preload(char *image_name, char *location_mount, int preload) { - int st2_fd; - struct stat statr; - char img_name[500]; - - strcpy(img_name, IMAGE_LOCATION); - strcat(img_name, get_ramdisk_realname()); + char *compressed_image = asprintf_("%s/%s", COMPRESSED_LOCATION, image_name); - log_message("trying to load %s as a ramdisk", img_name); + log_message("mount_compressed_may_preload: %s into %s (preload = %d)", compressed_image, location_mount, preload); - st2_fd = open(img_name, O_RDONLY); /* to be able to see the progression */ + if (access(compressed_image, R_OK) != 0) return RETURN_ERROR; - if (st2_fd == -1) { - log_message("open ramdisk file (%s) failed", img_name); - stg1_error_message("Could not open compressed ramdisk file (%s).", img_name); - return RETURN_ERROR; + if (preload) { + int compressed_fd = open(compressed_image, O_RDONLY); + if (compressed_fd != -1) { + return preload_mount_compressed_fd(compressed_fd, file_size(compressed_image), image_name, location_mount); + } else { + log_perror(compressed_image); + return RETURN_ERROR; + } + } else { + return mount_compressed_image(compressed_image, location_mount); } +} - if (stat(img_name, &statr)) - return RETURN_ERROR; - else - return load_ramdisk_fd(st2_fd, statr.st_size); +enum return_type may_load_compressed_image(void) +{ + if (!IS_RESCUE && access(IMAGE_LOCATION "/" LIVE_LOCATION_REL, R_OK) == 0) { + /* LIVE install */ + return RETURN_OK; + } else { + /* compressed install */ + return mount_compressed_image_may_preload(COMPRESSED_NAME(""), STAGE2_LOCATION, compressed_image_preload()); + } } -/* pixel's */ -void * memdup(void *src, size_t size) +enum return_type load_compressed_fd(int fd, int size) { - void * r; - r = malloc(size); - memcpy(r, src, size); - return r; + return preload_mount_compressed_fd(fd, size, COMPRESSED_NAME(""), STAGE2_LOCATION); } +int try_mount(char * dev, char * location) +{ + char device_fullname[50]; + snprintf(device_fullname, sizeof(device_fullname), "/dev/%s", dev); + + if (my_mount(device_fullname, location, "auto", 0) == -1) { + return 1; + } -static char ** my_env = NULL; -static int env_size = 0; + return 0; +} -void handle_env(char ** env) +#ifndef DISABLE_DISK +int get_disks(char *** names, char *** models) { - char ** ptr = env; + char ** ptr; + int count = 0; + + my_modprobe("ide_disk", ANY_DRIVER_TYPE, NULL); + my_modprobe("sd_mod", ANY_DRIVER_TYPE, NULL); + + get_medias(DISK, names, models, BUS_ANY); + + ptr = *names; while (ptr && *ptr) { + count++; ptr++; - env_size++; } - my_env = malloc(sizeof(char *) * 100); - memcpy(my_env, env, sizeof(char *) * (env_size+1)); -} -char ** grab_env(void) { - return my_env; + return count; } +#endif -void add_to_env(char * name, char * value) +#ifndef DISABLE_CDROM +int get_cdroms(char *** names, char *** models) { - char tmp[500]; - sprintf(tmp, "%s=%s", name, value); - my_env[env_size] = strdup(tmp); - env_size++; - my_env[env_size] = NULL; -} + char ** ptr; + int count = 0; + my_modprobe("ide_cd_mod", ANY_DRIVER_TYPE, NULL); + my_modprobe("sr_mod", ANY_DRIVER_TYPE, NULL); -char ** list_directory(char * direct) -{ - char * tmp[50000]; /* in /dev there can be many many files.. */ - int i = 0; - struct dirent *ep; - DIR *dp = opendir(direct); - while (dp && (ep = readdir(dp))) { - if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, "..")) { - tmp[i] = strdup(ep->d_name); - i++; - } + get_medias(CDROM, names, models, BUS_ANY); + + ptr = *names; + while (ptr && *ptr) { + count++; + ptr++; } - if (dp) - closedir(dp); - tmp[i] = NULL; - return memdup(tmp, sizeof(char*) * (i+1)); -} + return count; +} +#endif -int string_array_length(char ** a) +char * floppy_device(void) { - int i = 0; - if (!a) - return -1; - while (a && *a) { - a++; - i++; - } - return i; + char ** names, ** models; + int fd; + my_modprobe("floppy", ANY_DRIVER_TYPE, NULL); + fd = open("/dev/fd0", O_RDONLY|O_NONBLOCK); + if (fd != -1) { + char drivtyp[17]; + if (!ioctl(fd, FDGETDRVTYP, (void *)drivtyp)) { + struct floppy_drive_struct ds; + log_message("/dev/fd0 type: %s", drivtyp); + if (!ioctl(fd, FDPOLLDRVSTAT, &ds)) { + log_message("\ttrack: %d", ds.track); + if (ds.track >= 0) { + close(fd); + return "/dev/fd0"; + } + } + } else { + log_perror("can't FDGETDRVTYP /dev/fd0"); + } + close(fd); + } + log_message("seems that you don't have a regular floppy drive"); + my_modprobe("sd_mod", ANY_DRIVER_TYPE, NULL); + get_medias(FLOPPY, &names, &models, BUS_ANY); + if (names && *names) + return asprintf_("/dev/%s", *names); + else + return NULL; } |