]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
Simplify switch_root.c a bit
authorVictor Lowther <victor.lowther@gmail.com>
Sat, 7 Mar 2009 04:32:37 +0000 (22:32 -0600)
committerVictor Lowther <victor.lowther@gmail.com>
Sat, 7 Mar 2009 04:32:37 +0000 (22:32 -0600)
Shift some required functionality from switch_root.c to init.

String manipulation and filtering, and testing for the existence of init
is easier in the init script than in C.

modules.d/99base/init
switch_root.c

index 3616adc5399d37b5a2df713b487656e1a16f1a2b..ddefebf29f5106cfc3466a36ffcb50d87e22ec21 100755 (executable)
@@ -96,7 +96,12 @@ source_all pre-pivot
 getarg break && emergency_shell
 kill $(pidof udevd)
 echo "Switching to real root filesystem $root"
-exec switch_root -n "$NEWROOT" || {
+initargs=""
+for x in $CMDLINE; do
+    [ "${x%%=*}" = "console" -o "${x%%=*}" = "BOOT_IMAGE" ] && continue
+    initargs="$initargs $x"
+done
+exec switch_root "$NEWROOT" "$INIT" $initargs || {
     # davej doesn't like initrd bugs
     echo "Something went very badly wrong in the initrd.  Please "
     echo "file a bug against mkinitrd."
index 638a66379cc2aebd78270487be77f7d67b058e12..be5720ed7de98886251e0c1ae3b8f2ac178ea4b6 100644 (file)
@@ -49,203 +49,11 @@ enum {
        err_usage,
 };
 
-static int readFD(int fd, char **buf)
-{
-       char *p;
-       size_t size = 16384;
-       int s = 0, filesize = 0;
-
-       if (!(*buf = calloc (16384, sizeof (char))))
-               return -1;
-
-       do {
-               p = *buf + filesize;
-               s = read(fd, p, 16384 - s);
-               if (s < 0)
-                       break;
-               filesize += s;
-               /* only exit for empty reads */
-               if (s == 0)
-                       break;
-               else if (s == 16384) {
-                       *buf = realloc(*buf, size + 16384);
-                       memset(*buf + size, '\0', 16384);
-                       size += s;
-                       s = 0;
-               } else {
-                       size += s;
-               }
-       } while (1);
-
-       *buf = realloc(*buf, filesize+1);
-       (*buf)[filesize] = '\0';
-
-       return *buf ? filesize : -1;
-}
-
-static char *getKernelCmdLine(void)
-{
-       static char *cmdline = NULL;
-       int fd = -1;
-       int errnum;
-
-       fd = open("./proc/cmdline", O_RDONLY);
-       if (fd < 0) {
-               errnum = errno;
-               fprintf(stderr, "Error: Could not open ./proc/cmdline: %m\n");
-               errno = errnum;
-               return NULL;
-       }
-       
-       if (readFD(fd, &cmdline) < 0) {
-               errnum = errno;
-               fprintf(stderr, "Error: could not read ./proc/cmdline: %m\n");
-               close(fd);
-               errno = errnum;
-               return NULL;
-       }
-       close(fd);
-
-       return cmdline;
-}
-
-/* get the start of a kernel arg "arg".  returns everything after it
- * (useful for things like getting the args to init=).  so if you only
- * want one arg, you need to terminate it at the n */
-static char *getKernelArg(char *arg)
-{
-       char *start;
-       char *cmdline;
-       int len;
-
-       cmdline = start = getKernelCmdLine();
-       if (start == NULL)
-               return NULL;
-
-       while (*start) {
-               if (isspace(*start)) {
-                       start++;
-                       continue;
-               }
-
-               len = strlen(arg);
-               /* don't return if it's a different argument that merely starts
-                * like this one. */
-               if (strncmp(start, arg, len) == 0) {
-                       if (start[len] == '=')
-                               return start + len + 1;
-                       if (!start[len] || isspace(start[len]))
-                               return start + len;
-               }
-               while (*++start && !isspace(*start))
-                       ;
-       }
-
-       return NULL;
-}
-
-#define MAX_INIT_ARGS 32
-static int build_init_args(char **init, char ***initargs_out)
-{
-       const char *initprogs[] = { "./sbin/init", "./etc/init",
-                                   "./bin/init", "./bin/sh", NULL };
-       const char *ignoreargs[] = { "console=", "BOOT_IMAGE=", NULL };
-       char *cmdline = NULL;
-       char **initargs;
-
-       int i = 0;
-
-       *init = getKernelArg("init");
-
-       if (*init == NULL) {
-               int j;
-               cmdline = getKernelCmdLine();
-               if (cmdline == NULL)
-                       return -1;
-
-               for (j = 0; initprogs[j] != NULL; j++) {
-                       if (!access(initprogs[j], X_OK)) {
-                               *init = strdup(initprogs[j]);
-                               break;
-                       }
-               }
-       }
-
-       initargs = (char **)calloc(MAX_INIT_ARGS+1, sizeof (char *));
-       if (initargs == NULL)
-               return -1;
-
-       if (cmdline && *init) {
-               initargs[i++] = *init;
-       } else {
-               cmdline = *init;
-               initargs[0] = NULL;
-       }
-
-       if (cmdline) {
-               char quote = '\0';
-               char *chptr;
-               char *start;
-
-               start = chptr = cmdline;
-               for (; (i < MAX_INIT_ARGS) && (*start != '\0'); i++) {
-                       while (*chptr && (*chptr != quote)) {
-                               if (isspace(*chptr) && quote == '\0')
-                                       break;
-                               if (*chptr == '"' || *chptr == '\'')
-                                       quote = *chptr;
-                               chptr++;
-                       }
-
-                       if (quote == '"' || quote == '\'')
-                               chptr++;
-                       if (*chptr != '\0')
-                               *(chptr++) = '\0';
-
-                       /* There are some magic parameters added *after*
-                        * everything you pass, including a console= from the 
-                        * x86_64 kernel and BOOT_IMAGE= by syslinux.  Bash
-                        * doesn't know what they mean, so it then exits, init 
-                        * gets killed, desaster ensues.  *sigh*.
-                        */
-                       int j;
-                       for (j = 0; ignoreargs[j] != NULL; j++) {
-                               if (cmdline == *init && !strncmp(start, ignoreargs[j], strlen(ignoreargs[j]))) {
-                                       if (!*chptr)
-                                               initargs[i] = NULL;
-                                       else
-                                               i--;
-                                       start = chptr;
-                                       break;
-                               }
-                       }
-                       if (start == chptr)
-                               continue;
-
-                       if (start[0] == '\0')
-                               i--;
-                       else
-                               initargs[i] = strdup(start);
-                       start = chptr;
-               }
-       }
-
-       if (initargs[i-1] != NULL)
-               initargs[i] = NULL;
-
-       *initargs_out = initargs;
-       
-
-       return 0;
-}
-
-static void switchroot(const char *newroot)
+static int switchroot(const char *newroot)
 {
        /*  Don't try to unmount the old "/", there's no way to do it. */
        const char *umounts[] = { "/dev", "/proc", "/sys", NULL };
-       char *init, **initargs;
        int errnum;
-       int rc;
        int i;
 
        for (i = 0; umounts[i] != NULL; i++) {
@@ -260,36 +68,32 @@ static void switchroot(const char *newroot)
                }
        }
 
-       chdir(newroot);
-
-       rc = build_init_args(&init, &initargs);
-       if (rc < 0)
-               return;
+       if (chdir(newroot) < 0) {
+         errnum=errno;
+         fprintf(stderr, "switchroot: chdir failed: %m\n");
+         errno=errnum;
+         return -1;
+       }
 
        if (mount(newroot, "/", NULL, MS_MOVE, NULL) < 0) {
                errnum = errno;
                fprintf(stderr, "switchroot: mount failed: %m\n");
                errno = errnum;
-               return;
+               return -1;
        }
 
        if (chroot(".")) {
                errnum = errno;
                fprintf(stderr, "switchroot: chroot failed: %m\n");
                errno = errnum;
-               return;
+               return -2;
        }
-
-       if (access(initargs[0], X_OK))
-               fprintf(stderr, "WARNING: can't access %s\n", initargs[0]);
-
-       execv(initargs[0], initargs);
-       return;
+       return 1;
 }
 
 static void usage(FILE *output)
 {
-       fprintf(output, "usage: switchroot {-n|--newroot} <newrootdir>\n");
+       fprintf(output, "usage: switchroot <newrootdir> <init> <args to init>\n");
        if (output == stderr)
                exit(err_usage);
        exit(ok);
@@ -297,32 +101,22 @@ static void usage(FILE *output)
 
 int main(int argc, char *argv[])
 {
-       int i;
-       char *newroot = NULL;
-
-       for (i = 1; i < argc; i++) {
-               if (!strcmp(argv[i], "--help")
-                               || !strcmp(argv[i], "-h")
-                               || !strcmp(argv[i], "--usage")) {
-                       usage(stdout);
-               } else if (!strcmp(argv[i], "-n")
-                               || !strcmp(argv[i], "--newroot")) {
-                       newroot = argv[++i];
-               } else if (!strncmp(argv[i], "--newroot=", 10)) {
-                       newroot = argv[i] + 10;
-               } else {
-                       usage(stderr);
-               }
-       }
-
-       if (newroot == NULL || newroot[0] == '\0') {
+       char *newroot = argv[1];
+       char *init = argv[2];
+       char **initargs = &argv[2];
+      
+       if (newroot == NULL || newroot[0] == '\0' ||
+           init == NULL || init[0] == '\0' ) {
                usage(stderr);
        }
 
-       switchroot(newroot);
-
-       fprintf(stderr, "switchroot has failed.  Sorry.\n");
-       return 1;
+       if (switchroot(newroot) < 0) {
+         fprintf(stderr, "switchroot has failed.  Sorry.\n");
+         return 1;
+       }
+       if (access(initargs[0], X_OK))
+         fprintf(stderr, "WARNING: can't access %s\n", initargs[0]);
+       execv(initargs[0], initargs);
 }
 
 /*