summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/init.c')
-rw-r--r--mdk-stage1/init.c177
1 files changed, 123 insertions, 54 deletions
diff --git a/mdk-stage1/init.c b/mdk-stage1/init.c
index 3f912c2ac..7cec1076b 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>
@@ -56,7 +57,6 @@ static inline long reboot(unsigned int command)
#endif
-#define BINARY "/sbin/stage1"
#define BINARY_STAGE2 "/usr/bin/runinstall2"
@@ -378,7 +378,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)
@@ -386,7 +465,6 @@ int main(int argc, char **argv)
pid_t installpid, childpid;
int wait_status;
int fd;
- int counter = 0;
int abnormal_termination = 0;
if (argc > 1 && argv[1][0] >= '0' && argv[1][0] <= '9') {
@@ -404,24 +482,6 @@ int main(int argc, char **argv)
printf("*** TESTING MODE *** (pid is %d)\n", getpid());
- if (!testing) {
- if (mount("/proc", "/proc", "proc", 0, NULL))
- fatal_error("Unable to mount proc filesystem");
- if (mount("none", "/sys", "sysfs", 0, NULL))
- fatal_error("Unable to mount sysfs filesystem");
- if (mount("none", "/sys/kernel/debug", "debugfs", MS_NOSUID, "mode=0755"))
- fatal_error("Unable to mount debugfs filesystem");
- if (mount("none", "/dev", "devtmpfs", 0, NULL))
- fatal_error("Unable to mount dev filesystem");
- mkdir("/dev/pts", 0755);
- if (mount("/dev/pts", "/dev/pts", "devpts", MS_NOSUID|MS_NOEXEC, "gid=5,mode=0620"))
- fatal_error("Unable to mount /dev/pts devpts filesystem");
- mkdir("/dev/shm", 0755);
- if (mount("/dev/shm", "/dev/shm", "tmpfs", MS_NOSUID|MS_NODEV, "mode=1777"))
- fatal_error("Unable to mount /dev/shm tmpfs filesystem");
- }
-
-
/* ignore Control-C and keyboard stop signals */
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
@@ -454,57 +514,66 @@ 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).");
- 1) install exits
- 2) we receive a SIGHUP
- */
+ /* kernel modules and firmware is needed by stage2, so move them to the root */
+ if (rename("/usr/lib/modules", "/modules"))
+ fatal_error("Cannot rename modules folder");
- do {
- if (counter == 1) {
- printf("proceeding, please wait...\n");
- }
+ if (rename("/usr/lib/firmware", "/firmware"))
+ fatal_error("Cannot rename firmware folder");
- if (!(installpid = fork())) {
- /* child */
- char * child_argv[2];
- child_argv[0] = counter == 0 ? BINARY : BINARY_STAGE2;
- child_argv[1] = NULL;
+ /* Add some symlinks so stage1 is still valid on it's own - not strictly needed */
+ if (symlink("/modules", "/usr/lib/modules"))
+ fatal_error("Cannot symlink modules folder");
- execve(child_argv[0], child_argv, env);
- printf("error in exec of %s :-( [%d]\n", child_argv[0], errno);
- return 0;
- }
+ if (symlink("/firmware", "/usr/lib/firmware"))
+ fatal_error("Cannot symlink firmware folder");
- do {
- childpid = wait4(-1, &wait_status, 0, NULL);
- } while (childpid != installpid);
+ 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");
- counter++;
- } while (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_restart);
- /* allow Ctrl Alt Del to reboot */
- reboot(LINUX_REBOOT_CMD_CAD_ON);
+ if (access("/run/drakx/run-init", R_OK) == 0) {
+ /* This is typically used in rescue mode */
+ char * child_argv[2] = { "/sbin/init", NULL };
- if (in_reboot()) {
- // any exitcode is valid if we're in_reboot
- } else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_proceed) {
kill(klog_pid, 9);
printf("proceeding, please wait...\n");
+ execve(child_argv[0], child_argv, env);
+ fatal_error("failed to exec /sbin/init");
+ }
+
+ /* This is installer mode */
+ do {
+ printf("proceeding, please wait...\n");
- {
- char * child_argv[2] = { "/sbin/init", NULL };
+ if (!(installpid = fork())) {
+ /* child */
+ char * child_argv[2] = { BINARY_STAGE2, NULL };
execve(child_argv[0], child_argv, env);
+ printf("error in exec of %s :-( [%d]\n", child_argv[0], errno);
+ return 0;
}
- fatal_error("failed to exec /sbin/init");
- } else if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) {
+
+ do {
+ childpid = wait4(-1, &wait_status, 0, NULL);
+ } while (childpid != installpid);
+ } while (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_restart);
+
+ /* allow Ctrl Alt Del to reboot */
+ reboot(LINUX_REBOOT_CMD_CAD_ON);
+
+ if (in_reboot()) {
+ // any exitcode is valid if we're in_reboot
+ } else if (!WIFEXITED(wait_status) || WEXITSTATUS(wait_status) != 0) {
printf("exited abnormally :-( ");
if (WIFSIGNALED(wait_status))
printf("-- received signal %d", WTERMSIG(wait_status));
printf("\n");
abnormal_termination = 1;
- }
+ }
if (!abnormal_termination) {
int i;