From c4321813f9f3cd4136203d52c0f20343d7722228 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 19 Oct 2013 21:30:12 +0100 Subject: stage1: Move the symlink creation from stage1 to init. In order to run stage1 we now need to do things a little differently, namely that we move the symlinking fixups into 'init' itself which we will actually call as a kind of fake switch_root implementation to avoid hacking dracut too much[1]. As we run stage1 during dracut's 'mount' phase we should not do the symlink hacks so early otherwise it will mess up the rest of the dracut initqueue processing. Currently, the initrd's /usr is nuked and then symlinked, but to allow for easier debugging I now just bind mount the stage2 /usr over the top which allows us to unmount it again easily enough if we want to go back. We no longer touch the /bin, /sbin or /lib[64] symlinks as these are relative and simply bind mounting /usr is enough to fix all of them. 1. This scheme will have to change if we eventually swtich to a systemd based dracut invocation. --- mdk-stage1/NEWS | 1 + mdk-stage1/init.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++---- mdk-stage1/stage1.c | 31 ------------------ mdk-stage1/tools.c | 59 ---------------------------------- mdk-stage1/tools.h | 2 -- mdk-stage1/utils.c | 8 ----- mdk-stage1/utils.h | 2 -- 7 files changed, 87 insertions(+), 108 deletions(-) (limited to 'mdk-stage1') diff --git a/mdk-stage1/NEWS b/mdk-stage1/NEWS index 3c65b1bd5..8f2846cbd 100644 --- a/mdk-stage1/NEWS +++ b/mdk-stage1/NEWS @@ -1,3 +1,4 @@ +- do initrd symlinking in 'init' rather than 'stage1' (stage1 is now run earlier) - build init and stage1 as a shared library (due to bugs in directory handling in dietlibc as exposed in libkmod but also because glibc is already include in dracut) diff --git a/mdk-stage1/init.c b/mdk-stage1/init.c index 3f912c2ac..6d571a62a 100644 --- a/mdk-stage1/init.c +++ b/mdk-stage1/init.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -378,7 +379,86 @@ int in_reboot(void) return 0; } -int exit_value_proceed = 66; +int recursive_remove(char *file); +int recursive_remove(char *file) +{ + struct stat sb; + + if (lstat(file, &sb) != 0) { + printf("failed to stat %s: %d\n", file, errno); + return -1; + } + + /* only descend into subdirectories if device is same as dir */ + if (S_ISDIR(sb.st_mode)) { + char * strBuf = alloca(strlen(file) + 1024); + DIR * dir; + struct dirent * d; + + if (!(dir = opendir(file))) { + printf("error opening %s: %d\n", file, errno); + return -1; + } + while ((d = readdir(dir))) { + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + strcpy(strBuf, file); + strcat(strBuf, "/"); + strcat(strBuf, d->d_name); + + if (recursive_remove(strBuf) != 0) { + closedir(dir); + return -1; + } + } + closedir(dir); + + if (rmdir(file)) { + printf("failed to rmdir %s: %d\n", file, errno); + return -1; + } + } else { + if (unlink(file) != 0) { + printf("failed to remove %s: %d\n", file, errno); + return -1; + } + } + return 0; +} + + +int create_initial_fs_symlinks(char* symlinks) +{ + FILE *f; + char buf[5000]; + + if (!(f = fopen(symlinks, "rb"))) { + printf("Error opening symlink definitions file '%s'\n", symlinks); + return -1; + } + while (fgets(buf, sizeof(buf), f)) { + char oldpath[500], newpath[500]; + struct stat sb; + + buf[strlen(buf)-1] = '\0'; // trim \n + if (sscanf(buf, "%s %s", oldpath, newpath) != 2) { + sprintf(oldpath, "%s%s", STAGE2_LOCATION, buf); + sprintf(newpath, "%s", buf); + } + if (lstat(newpath, &sb) == 0) + recursive_remove(newpath); + printf("Creating symlink %s -> %s\n", oldpath, newpath); + if (symlink(oldpath, newpath)) { + printf("Error creating symlink\n"); + return -1; + } + } + fclose(f); + return 0; +} + + int exit_value_restart = 0x35; int main(int argc, char **argv) @@ -454,12 +534,12 @@ int main(int argc, char **argv) if (!testing) doklog(); - /* Go into normal init mode - keep going, and then do a orderly shutdown - when: + if (create_initial_fs_symlinks(STAGE2_LOCATION "/usr/share/symlinks") != 0) + fatal_error("Fatal error finishing initialization (could not create symlinks)."); + + if (mount(STAGE2_LOCATION "/usr", "/usr", "none", MS_BIND|MS_RDONLY, NULL)) + fatal_error("Unable to bind mount /usr filesystem from rescue or installer stage2"); - 1) install exits - 2) we receive a SIGHUP - */ do { if (counter == 1) { diff --git a/mdk-stage1/stage1.c b/mdk-stage1/stage1.c index ee24bf0a1..4439b7d37 100644 --- a/mdk-stage1/stage1.c +++ b/mdk-stage1/stage1.c @@ -344,39 +344,8 @@ static void method_select_and_prepare(void) } #endif -static enum return_type create_initial_fs_symlinks(char* symlinks) -{ - FILE *f; - char buf[5000]; - - if (scall(!(f = fopen(symlinks, "rb")), "fopen")) - return RETURN_ERROR; - while (fgets(buf, sizeof(buf), f)) { - char oldpath[500], newpath[500]; - buf[strlen(buf)-1] = '\0'; // trim \n - if (sscanf(buf, "%s %s", oldpath, newpath) != 2) { - sprintf(oldpath, "%s%s", STAGE2_LOCATION, buf); - sprintf(newpath, "%s", buf); - } - recursiveRemove_if_it_exists(newpath); - log_message("creating symlink %s -> %s", oldpath, newpath); - if (scall(symlink(oldpath, newpath), "symlink")) - return RETURN_ERROR; - } - fclose(f); - return RETURN_OK; -} - void finish_preparing(void) { - recursiveRemove("/init"); - - if (create_initial_fs_symlinks(STAGE2_LOCATION "/usr/share/symlinks") != RETURN_OK) - stg1_fatal_message("Fatal error finishing initialization."); - - /* /tmp/syslog is used by the second init, so it must be copied now, not in stage2 */ - /* we remove it to ensure the old one is not copied over it in stage2 */ - #ifdef SPAWN_SHELL if (shell_pid != 0) { int fd; diff --git a/mdk-stage1/tools.c b/mdk-stage1/tools.c index aca40c971..78108d6a9 100644 --- a/mdk-stage1/tools.c +++ b/mdk-stage1/tools.c @@ -148,65 +148,6 @@ enum return_type copy_file(char * from, char * to, void (*callback_func)(int ove } } -enum return_type recursiveRemove(char *file) -{ - struct stat sb; - - if (lstat(file, &sb) != 0) { - log_message("failed to stat %s: %d", file, errno); - return RETURN_ERROR; - } - - /* only descend into subdirectories if device is same as dir */ - if (S_ISDIR(sb.st_mode)) { - char * strBuf = alloca(strlen(file) + 1024); - DIR * dir; - struct dirent * d; - - if (!(dir = opendir(file))) { - log_message("error opening %s: %d", file, errno); - return RETURN_ERROR; - } - while ((d = readdir(dir))) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - - strcpy(strBuf, file); - strcat(strBuf, "/"); - strcat(strBuf, d->d_name); - - if (recursiveRemove(strBuf) != 0) { - closedir(dir); - return RETURN_ERROR; - } - } - closedir(dir); - - if (rmdir(file)) { - log_message("failed to rmdir %s: %d", file, errno); - return RETURN_ERROR; - } - } else { - if (unlink(file) != 0) { - log_message("failed to remove %s: %d", file, errno); - return RETURN_ERROR; - } - } - return RETURN_OK; -} - -enum return_type recursiveRemove_if_it_exists(char *file) -{ - struct stat sb; - - if (lstat(file, &sb) != 0) { - /* if file doesn't exist, simply return OK */ - return RETURN_OK; - } - - return recursiveRemove(file); -} - enum return_type mount_compressed_image(char *compressed_image, char *location_mount) { if (lomount(compressed_image, location_mount, NULL, 1)) { diff --git a/mdk-stage1/tools.h b/mdk-stage1/tools.h index 1b08e42ca..87c0c1d49 100644 --- a/mdk-stage1/tools.h +++ b/mdk-stage1/tools.h @@ -29,8 +29,6 @@ int image_has_stage2(); enum return_type create_IMAGE_LOCATION(char *location_full); int ramdisk_possible(void); enum return_type copy_file(char * from, char * to, void (*callback_func)(int overall)); -enum return_type recursiveRemove(char *file); -enum return_type recursiveRemove_if_it_exists(char *file); enum return_type preload_mount_compressed_fd(int compressed_fd, int image_size, char *image_name, char *location_mount); enum return_type mount_compressed_image(char *compressed_image, char *location_mount); enum return_type mount_compressed_image_may_preload(char *image_name, char *location_mount, int preload); diff --git a/mdk-stage1/utils.c b/mdk-stage1/utils.c index af5ee9af3..d861877e4 100644 --- a/mdk-stage1/utils.c +++ b/mdk-stage1/utils.c @@ -162,14 +162,6 @@ char * asprintf_(const char *msg, ...) return strdup(""); } -int scall_(int retval, char * msg, char * file, int line) -{ - char tmp[5000]; - sprintf(tmp, "%s(%s:%d) failed", msg, file, line); - if (retval) - log_perror(tmp); - return retval; -} void lowercase(char *s) { diff --git a/mdk-stage1/utils.h b/mdk-stage1/utils.h index d42c52d06..b8a77b0ad 100644 --- a/mdk-stage1/utils.h +++ b/mdk-stage1/utils.h @@ -27,9 +27,7 @@ void add_to_env(char * name, char * value); char ** list_directory(char * direct); int string_array_length(char ** a); char * asprintf_(const char *msg, ...); -int scall_(int retval, char * msg, char * file, int line); char *my_dirname(char *path); -#define scall(retval, msg) scall_(retval, msg, __FILE__, __LINE__) void lowercase(char *s); #define ptr_begins_static_str(pointer,static_str) (!strncmp(pointer,static_str,sizeof(static_str)-1)) -- cgit v1.2.1