X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=helper%2Finit.c;h=34a84507598e58ec303cf4316b69673dc07cc1df;hb=6d9051df32b90c6a4fe6ca1ff9e771b7dfe004fa;hp=7b6b94efe7894c2c36bba3d7b16901ba26706545;hpb=6ab9465001dfaa52edc5992ee71f2e9aecc2085d;p=febootstrap.git diff --git a/helper/init.c b/helper/init.c index 7b6b94e..34a8450 100644 --- a/helper/init.c +++ b/helper/init.c @@ -19,8 +19,7 @@ /* This very minimal init "script" goes in the mini-initrd used to * boot the ext2-based appliance. Note we have no shell, so we cannot * use system(3) to run external commands. In fact, we don't have - * very much at all, except this program, insmod.static, and some - * kernel modules. + * very much at all, except this program, and some kernel modules. */ #include @@ -30,17 +29,40 @@ #include #include #include +#include #include #include #include #include #include +#include + +extern long init_module (void *, unsigned long, const char *); + +/* translation taken from module-init-tools/insmod.c */ +static const char *moderror(int err) +{ + switch (err) { + case ENOEXEC: + return "Invalid module format"; + case ENOENT: + return "Unknown symbol in module"; + case ESRCH: + return "Module has wrong symbol version"; + case EINVAL: + return "Invalid parameters"; + default: + return strerror(err); + } +} + /* Leave this enabled for now. When we get more confident in the boot * process we can turn this off or make it configurable. */ #define verbose 1 +static void mount_proc (void); static void print_uptime (void); static void insmod (const char *filename); static void show_directory (const char *dir); @@ -50,6 +72,8 @@ static char line[1024]; int main () { + mount_proc (); + print_uptime (); fprintf (stderr, "febootstrap: ext2 mini initrd starting up\n"); @@ -66,12 +90,6 @@ main () exit (EXIT_FAILURE); } - /* A perennial problem is that /sbin/insmod.static is not - * executable. Just make it executable. It's easier than fixing - * everyone's distro. - */ - chmod ("/sbin/insmod.static", 0755); - FILE *fp = fopen ("/modules", "r"); if (fp == NULL) { perror ("fopen: /modules"); @@ -81,7 +99,16 @@ main () size_t n = strlen (line); if (n > 0 && line[n-1] == '\n') line[--n] = '\0'; - insmod (line); + + /* XXX Because of the way we construct the module list, the + * "modules" file can contain non-existent modules. Ignore those + * for now. Really we should add them as missing dependencies. + * See ext2initrd.c:ext2_make_initrd(). + */ + if (access (line, R_OK) == 0) + insmod (line); + else + fprintf (stderr, "skipped %s, module is missing\n", line); } fclose (fp); @@ -175,26 +202,53 @@ static void insmod (const char *filename) { if (verbose) - fprintf (stderr, "febootstrap: insmod %s\n", filename); + fprintf (stderr, "febootstrap: internal insmod %s\n", filename); - pid_t pid = fork (); - if (pid == -1) { - perror ("insmod: fork"); + int fd = open (filename, O_RDONLY); + if (fd == -1) { + fprintf (stderr, "insmod: open: %s: %m\n", filename); exit (EXIT_FAILURE); } - - if (pid == 0) { /* Child. */ - execl ("/insmod.static", "insmod.static", filename, NULL); - perror ("insmod: execl"); - _exit (EXIT_FAILURE); + struct stat st; + if (fstat (fd, &st) == -1) { + perror ("insmod: fstat"); + exit (EXIT_FAILURE); + } + char buf[st.st_size]; + long offset = 0; + do { + long rc = read (fd, buf + offset, st.st_size - offset); + if (rc == -1) { + perror ("insmod: read"); + exit (EXIT_FAILURE); + } + offset += rc; + } while (offset < st.st_size); + close (fd); + + if (init_module (buf, st.st_size, "") != 0) { + fprintf (stderr, "insmod: init_module: %s: %s\n", filename, moderror (errno)); + /* However ignore the error because this can just happen because + * of a missing device. + */ } +} + +/* Mount /proc unless it's mounted already. */ +static void +mount_proc (void) +{ + if (access ("/proc/uptime", R_OK) == -1) { + mkdir ("/proc", 0755); + + if (verbose) + fprintf (stderr, "febootstrap: mounting /proc\n"); - /* Parent. */ - int status; - if (wait (&status) == -1 || - WEXITSTATUS (status) != 0) - perror ("insmod: wait"); - /* but ignore the error, some will be because the device is not found */ + if (mount ("proc", "/proc", "proc", 0, "") == -1) { + perror ("mount: /proc"); + /* Non-fatal. */ + } + } } /* Print contents of /proc/uptime. */ @@ -254,9 +308,9 @@ show_directory (const char *dirname) } while ((d = readdir (dir)) != NULL) { - fprintf (stderr, "%5d %c %-16s", d->d_ino, dirtype (d->d_type), d->d_name); + fprintf (stderr, "%5lu %c %-16s", d->d_ino, dirtype (d->d_type), d->d_name); if (lstat (d->d_name, &statbuf) >= 0) { - fprintf (stderr, " %06o %d %d:%d", + fprintf (stderr, " %06o %ld %d:%d", statbuf.st_mode, statbuf.st_size, statbuf.st_uid, statbuf.st_gid); if (S_ISLNK (statbuf.st_mode)) {