diff options
author | Colin Guthrie <colin@mageia.org> | 2013-10-19 21:30:12 +0100 |
---|---|---|
committer | Colin Guthrie <colin@mageia.org> | 2013-10-29 20:29:07 +0000 |
commit | c4321813f9f3cd4136203d52c0f20343d7722228 (patch) | |
tree | ba1cbb296d3d490142d670f88a2a76452a87829d /mdk-stage1/init.c | |
parent | 7213bee2f13e551bffb7754846726833e196719b (diff) | |
download | drakx-c4321813f9f3cd4136203d52c0f20343d7722228.tar drakx-c4321813f9f3cd4136203d52c0f20343d7722228.tar.gz drakx-c4321813f9f3cd4136203d52c0f20343d7722228.tar.bz2 drakx-c4321813f9f3cd4136203d52c0f20343d7722228.tar.xz drakx-c4321813f9f3cd4136203d52c0f20343d7722228.zip |
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.
Diffstat (limited to 'mdk-stage1/init.c')
-rw-r--r-- | mdk-stage1/init.c | 92 |
1 files changed, 86 insertions, 6 deletions
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 <stdlib.h> #include <unistd.h> #include <stdio.h> +#include <dirent.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> @@ -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) { |