summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Guthrie <colin@mageia.org>2013-10-19 21:30:12 +0100
committerColin Guthrie <colin@mageia.org>2013-10-29 20:29:07 +0000
commitc4321813f9f3cd4136203d52c0f20343d7722228 (patch)
treeba1cbb296d3d490142d670f88a2a76452a87829d
parent7213bee2f13e551bffb7754846726833e196719b (diff)
downloaddrakx-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.
-rw-r--r--mdk-stage1/NEWS1
-rw-r--r--mdk-stage1/init.c92
-rw-r--r--mdk-stage1/stage1.c31
-rw-r--r--mdk-stage1/tools.c59
-rw-r--r--mdk-stage1/tools.h2
-rw-r--r--mdk-stage1/utils.c8
-rw-r--r--mdk-stage1/utils.h2
7 files changed, 87 insertions, 108 deletions
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 <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) {
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))