diff --git a/Makefile.am b/Makefile.am index be039931..f71de8b0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,3 +29,5 @@ release: distcheck printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \ printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \ done + +DISTCHECK_CONFIGURE_FLAGS = --with-fstab=/etc/fstab diff --git a/configure.ac b/configure.ac index abdb1b29..923db532 100644 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,10 @@ AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to- AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown]) # Check for extra arguments or packages +AC_ARG_WITH(fstab, + AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]), + [fstab=$withval], [fstab=yes]) + AC_ARG_WITH(heading, AS_HELP_STRING([--with-heading=GREET], [Heading for boot progress. Default: PRETTY_NAME from /etc/os-release, fallback to "Finit vX.YY"]), [heading=$withval], [heading=yes]) @@ -164,6 +168,12 @@ AS_IF([test "x$enable_logrotate" != "xno"], [ AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"]) ### With features ############################################################################## +AS_IF([test "x$with_fstab" != "xno"], [ + AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab]) + AC_EXPAND_DIR(fstab_path, "$fstab") + AC_DEFINE_UNQUOTED(FINIT_FSTAB, "$fstab_path", [Built-in default: /etc/fstab])],[ + AC_DEFINE_UNQUOTED(FINIT_FSTAB, NULL, [No built-in default fstab])]) + AS_IF([test "x$with_config" != "xno"], [ AS_IF([test "x$conf" = "xyes"], [ conf=$sysconfdir/finit.conf])]) @@ -261,6 +271,7 @@ cat <`: Tell Finit to use an + alternate `fstab` to mount the file system from. Remember, this file + must be on the `root=...` file system provided to Finit from the + kernel. By default the built-in fstab is used, which itself defaults + to `/etc/fstab`, but can be changed at build time with: + + ./configure --with-fstab=/path/to/fstab + + It is even possible to disable a built-in default using: + + ./configure --without-fstab + + Making `finit.fstab=/path/to/fstab` a *mandatory* command line option. + Note, if the command line fstab is missing, Finit falls back to the + built-in fstab, and if both are missing, the system treats this as a + bad `fsck` and thus calls `sulogin`. If, in turn, `sulogin` is not + available on the system, Finit calls reboot, which is also what will + happen when a user exits from `sulogin`. + * `finit.status[=bool]`: Control finit boot progress, including banner. (Used to be `finit.show_status`, which works but is deprecated.) diff --git a/man/finit.8 b/man/finit.8 index f0013ae1..aa3f0c22 100644 --- a/man/finit.8 +++ b/man/finit.8 @@ -13,6 +13,7 @@ .Nm /sbin/finit .Op -- .Op finit.debug +.Op finit.fstab=/etc/fstab.alt .Op finit.status= .Op finit.status_style= .Op rescue | recover @@ -77,6 +78,43 @@ Enable Finit debug messages on system console and log. Sometimes useful when doing board bringup. Before the system log daemon has started, Finit use the kernel ring buffer, .Pa /dev/kmsg . +.It Cm finit.fstab=/path/to/fstab.alt +Tell +.Nm +to use an alternate +.Cm fstab +to mount the file system from. Remember, this file must be on the +.Cm root=... +file system provided to Finit from the kernel. If this file is missing, +.Nm +falls back to its built-in default, which can be changed at build time +using the +.Cm --with-fstab=/path/to/footab +configure option. It is even possible to completely disable the +built-in using +.Cm --without-fstab , +meaning +.Nm +.Sy must +be started with the +.Cm finit.fstab +option. +.Pp +Should +.Nm +discover that there is no fstab file available, including the fallback, +it triggers the same failure mode as when +.Cm fsck +fails, starting +.Xr sulogin 8 , +if that is availble. When +.Cm sulogin +is missing, or when the user exits from +.Cm sulogin , +the system is rebooted. +.Pp +Default fstab, unless changed at build-time: +.Pa /etc/fstab .It Cm finit.status= Control finit boot progress, including banner. This used to be called .Cm finit.show_status , @@ -108,6 +146,10 @@ Before laucnhing services, the system needs to be bootstrapped. This involves mounting all filesystems (not already mounted by an initramfs) in .Pa /etc/fstab , +or any alternate +.Pa fstab +file provided on the Finit command line using +.Cm finit.fstab , ensuring that necessary filesystems like: .Pa /dev , .Pa /proc , diff --git a/src/conf.c b/src/conf.c index 7c19d1c9..eb4740dc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -87,6 +87,7 @@ fallback: /* * finit.debug = [on,off] + * finit.fstab = /path/to/etc/fstab.aternative * finit.status = [on,off] (compat finit.show_status) * finit.status_style = [old,classic,modern] */ @@ -103,6 +104,11 @@ static void parse_finit_opts(char *opt) return; } + if (string_compare(opt, "fstab")) { + fstab = arg; + return; + } + if (string_compare(opt, "status_style")) { if (!arg) { _e("status_style option requires an argument, skipping."); diff --git a/src/finit.c b/src/finit.c index c36cd860..d49a5135 100644 --- a/src/finit.c +++ b/src/finit.c @@ -65,6 +65,7 @@ int rescue = 0; /* rescue mode from kernel cmdline */ int single = 0; /* single user mode from kernel cmdline */ int bootstrap = 1; /* set while bootrapping (for TTYs) */ int kerndebug = 0; /* set if /proc/sys/kernel/printk > 7 */ +char *fstab = FINIT_FSTAB; char *sdown = NULL; char *network = NULL; char *hostname = NULL; @@ -105,6 +106,35 @@ static void banner(void) #endif } +static int sulogin(int do_reboot) +{ + int rc = EX_OSFILE; + char *cmd[] = { + _PATH_SULOGIN, + "sulogin", + }; + size_t i; + + for (i = 0; i < NELEMS(cmd); i++) { + char *path = which(cmd[i]); + + if (access(path, X_OK)) { + free(path); + continue; + } + + rc = systemf("%s", path); + break; + } + + if (do_reboot) { + do_shutdown(SHUT_REBOOT); + exit(rc); + } + + return rc; +} + /* * Check all filesystems in /etc/fstab with a fs_passno > 0 */ @@ -114,10 +144,10 @@ static int fsck(int pass) int rc = 0; FILE *fp; - fp = setmntent("/etc/fstab", "r"); + fp = setmntent(fstab, "r"); if (!fp) { - _pe("Failed opening fstab"); - return 1; + _pe("Failed opening fstab: %s", fstab); + sulogin(1); } while ((mnt = getmntent(fp))) { @@ -153,19 +183,8 @@ static int fsck(int pass) * errors were corrected but that the boot may proceed. */ if (fsck_rc > 1) { - char *sulogin[] = { - _PATH_SULOGIN, - "sulogin", - }; - size_t i; - - for (i = 0; i < NELEMS(sulogin); i++) { - if (systemf("%s", sulogin[i])) - continue; - break; - } - - do_shutdown(SHUT_REBOOT); + logit(LOG_CONSOLE | LOG_ALERT, "Failed fsck of %s, attempting sulogin ...", mnt->mnt_fsname); + sulogin(1); } rc += fsck_rc; } @@ -208,7 +227,7 @@ static void fs_remount_root(int fsckerr) struct mntent *mnt; FILE *fp; - fp = setmntent("/etc/fstab", "r"); + fp = setmntent(fstab, "r"); if (!fp) return; @@ -306,13 +325,29 @@ static void fs_finalize(void) static void fs_mount_all(void) { + char cmd[256] = "mount -na"; + + if (!fstab || !fexist(fstab)) { + logit(LOG_CONSOLE | LOG_NOTICE, "%s system fstab %s, trying fallback ...", + !fstab ? "Missing" : "Cannot find", fstab ?: "\b"); + fstab = FINIT_FSTAB; + } + if (!fstab || !fexist(fstab)) { + logit(LOG_CONSOLE | LOG_EMERG, "%s system fstab %s, attempting sulogin ...", + !fstab ? "Missing" : "Cannot find", fstab ?: "\b"); + sulogin(1); + } + if (!rescue) fs_remount_root(fsck_all()); _d("Root FS up, calling hooks ..."); plugin_run_hooks(HOOK_ROOTFS_UP); - if (run_interactive("mount -na", "Mounting filesystems")) + if (fstab && strcmp(fstab, "/etc/fstab")) + snprintf(cmd, sizeof(cmd), "mount -na -T %s", fstab); + + if (run_interactive(cmd, "Mounting filesystems from %s", fstab)) plugin_run_hooks(HOOK_MOUNT_ERROR); _d("Calling extra mount hook, after mount -a ..."); @@ -595,21 +630,8 @@ int main(int argc, char *argv[]) /* * In case of emergency. */ - if (rescue) { - char *sulogin[] = { - _PATH_SULOGIN, - "sulogin", - }; - size_t i; - - for (i = 0; i < NELEMS(sulogin); i++) { - if (systemf("%s", sulogin[i])) - continue; - - rescue = 0; - break; - } - } + if (rescue) + rescue = sulogin(0); /* * Load plugins early, the first hook is in banner(), so we @@ -638,7 +660,10 @@ int main(int argc, char *argv[]) */ cgroup_init(&loop); - /* Check and mount filesystems. */ + /* + * Check custom fstab from cmdline, including fallback, then run + * fsck before mounting all filesystems, on error call sulogin. + */ fs_mount_all(); /* Bootstrap conditions, needed for hooks */ diff --git a/src/finit.h b/src/finit.h index df165524..4e4c6889 100644 --- a/src/finit.h +++ b/src/finit.h @@ -116,6 +116,7 @@ extern int rescue; extern int single; extern int bootstrap; extern int kerndebug; +extern char *fstab; extern char *sdown; extern char *network; extern char *hostname;