Fixed the init problem where it wouldn't unmount filesystems

on reboot.  Also fixed swapoff -a so it works.
 -Erik
This commit is contained in:
Erik Andersen 2000-02-09 04:16:43 +00:00
parent e49d5ecbbe
commit e132f4b09e
13 changed files with 483 additions and 380 deletions

View File

@ -84,6 +84,8 @@
- `fdflush', `length' and `printf' crashed when run without arguments - `fdflush', `length' and `printf' crashed when run without arguments
- `fdflush' tried to flush itself using *argv - `fdflush' tried to flush itself using *argv
- added "skip" and "seek" to dd. - added "skip" and "seek" to dd.
* swapoff -a was not working. Now it is.
* init did not cleanly unmount filesystems on reboot. Now it does.
-Erik Andersen -Erik Andersen

View File

@ -62,7 +62,7 @@ endif
# -D_GNU_SOURCE is needed because environ is used in init.c # -D_GNU_SOURCE is needed because environ is used in init.c
ifeq ($(DODEBUG),true) ifeq ($(DODEBUG),true)
CFLAGS += -Wall -g -D_GNU_SOURCE -DDEBUG_INIT CFLAGS += -Wall -g -D_GNU_SOURCE
STRIP = STRIP =
LDFLAGS = LDFLAGS =
else else

View File

@ -59,7 +59,6 @@
#define BB_MOUNT #define BB_MOUNT
#define BB_NFSMOUNT #define BB_NFSMOUNT
//#define BB_MT //#define BB_MT
//#define BB_MTAB
#define BB_NSLOOKUP #define BB_NSLOOKUP
#define BB_PING #define BB_PING
#define BB_POWEROFF #define BB_POWEROFF

108
init.c
View File

@ -22,6 +22,11 @@
* *
*/ */
/* Turn this on to disable all the dangerous
rebooting stuff when debugging.
#define DEBUG_INIT
*/
#include "internal.h" #include "internal.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -78,7 +83,8 @@ typedef enum {
RESPAWN, RESPAWN,
ASKFIRST, ASKFIRST,
WAIT, WAIT,
ONCE ONCE,
CTRLALTDEL
} initActionEnum; } initActionEnum;
/* And now a list of the actions we support in the version of init */ /* And now a list of the actions we support in the version of init */
@ -93,6 +99,7 @@ static const struct initActionType actions[] = {
{"askfirst", ASKFIRST}, {"askfirst", ASKFIRST},
{"wait", WAIT}, {"wait", WAIT},
{"once", ONCE}, {"once", ONCE},
{"ctrlaltdel", CTRLALTDEL},
{0} {0}
}; };
@ -113,6 +120,7 @@ static char *log = VT_LOG;
static int kernelVersion = 0; static int kernelVersion = 0;
static char termType[32] = "TERM=ansi"; static char termType[32] = "TERM=ansi";
static char console[32] = _PATH_CONSOLE; static char console[32] = _PATH_CONSOLE;
static void delete_initAction(initAction * action);
/* print a message to the specified device: /* print a message to the specified device:
@ -131,8 +139,8 @@ void message(int device, char *fmt, ...)
va_start(arguments, fmt); va_start(arguments, fmt);
vsnprintf(msg, sizeof(msg), fmt, arguments); vsnprintf(msg, sizeof(msg), fmt, arguments);
va_end(arguments); va_end(arguments);
openlog("init", 0, LOG_DAEMON); openlog("init", 0, LOG_USER);
syslog(LOG_DAEMON | LOG_NOTICE, msg); syslog(LOG_USER|LOG_INFO, msg);
closelog(); closelog();
} }
#else #else
@ -147,10 +155,11 @@ void message(int device, char *fmt, ...)
/* log to main console instead */ /* log to main console instead */
device = CONSOLE; device = CONSOLE;
} else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { } else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) {
log_fd = -1; log_fd = -2;
fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
fflush(stderr); fflush(stderr);
return; log = NULL;
device = CONSOLE;
} }
} }
if ((device & LOG) && (log_fd >= 0)) { if ((device & LOG) && (log_fd >= 0)) {
@ -303,10 +312,10 @@ static void console_init()
/* check for serial console and disable logging to tty3 & running a /* check for serial console and disable logging to tty3 & running a
* shell to tty2 */ * shell to tty2 */
if (ioctl(0, TIOCGSERIAL, &sr) == 0) { if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
message(LOG | CONSOLE,
"serial console detected. Disabling virtual terminals.\r\n");
log = NULL; log = NULL;
secondConsole = NULL; secondConsole = NULL;
message(LOG | CONSOLE,
"serial console detected. Disabling virtual terminals.\r\n");
} }
close(fd); close(fd);
} }
@ -319,6 +328,7 @@ static pid_t run(char *command, char *terminal, int get_enter)
pid_t pid; pid_t pid;
char *tmpCmd; char *tmpCmd;
char *cmd[255]; char *cmd[255];
char buf[255];
static const char press_enter[] = static const char press_enter[] =
"\nPlease press Enter to activate this console. "; "\nPlease press Enter to activate this console. ";
@ -333,7 +343,9 @@ static pid_t run(char *command, char *terminal, int get_enter)
if ((pid = fork()) == 0) { if ((pid = fork()) == 0) {
#ifdef DEBUG_INIT
pid_t shell_pgid = getpid(); pid_t shell_pgid = getpid();
#endif
/* Clean up */ /* Clean up */
close(0); close(0);
@ -369,30 +381,40 @@ static pid_t run(char *command, char *terminal, int get_enter)
*/ */
char c; char c;
#ifdef DEBUG_INIT
message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
command, shell_pgid, terminal); command, shell_pgid, terminal);
#endif
write(fileno(stdout), press_enter, sizeof(press_enter) - 1); write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
read(fileno(stdin), &c, 1); read(fileno(stdin), &c, 1);
} }
#ifdef DEBUG_INIT
/* Log the process name and args */ /* Log the process name and args */
message(LOG, "Starting pid %d, console %s: '", message(LOG, "Starting pid %d, console %s: '%s'\r\n",
shell_pgid, terminal, command); shell_pgid, terminal, command);
#endif
/* See if any special /bin/sh requiring characters are present */
if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
cmd[0] = SHELL;
cmd[1] = "-c";
strcpy(buf, "exec ");
strncat(buf, command, sizeof(buf) - strlen(buf) - 1);
cmd[2] = buf;
cmd[3] = NULL;
} else {
/* Convert command (char*) into cmd (char**, one word per string) */ /* Convert command (char*) into cmd (char**, one word per string) */
for (tmpCmd = command, i = 0; for (tmpCmd = command, i = 0;
(tmpCmd = strsep(&command, " \t")) != NULL;) { (tmpCmd = strsep(&command, " \t")) != NULL;) {
if (*tmpCmd != '\0') { if (*tmpCmd != '\0') {
cmd[i] = tmpCmd; cmd[i] = tmpCmd;
#ifdef DEBUG_INIT
message(LOG, "%s ", tmpCmd);
#endif
tmpCmd++; tmpCmd++;
i++; i++;
} }
} }
cmd[i] = NULL; cmd[i] = NULL;
message(LOG, "'\r\n"); }
/* Now run it. The new program will take over this PID, /* Now run it. The new program will take over this PID,
* so nothing further in init.c should be run. */ * so nothing further in init.c should be run. */
@ -413,9 +435,8 @@ static int waitfor(char *command, char *terminal, int get_enter)
while (1) { while (1) {
wpid = wait(&status); wpid = wait(&status);
if (wpid > 0) { if (wpid > 0 && wpid != pid) {
message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid); continue;
break;
} }
if (wpid == pid) if (wpid == pid)
break; break;
@ -424,7 +445,7 @@ static int waitfor(char *command, char *terminal, int get_enter)
} }
/* Make sure there is enough memory to do something useful. * /* Make sure there is enough memory to do something useful. *
* Calls swapon if needed so be sure /proc is mounted. */ * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
static void check_memory() static void check_memory()
{ {
struct stat statBuf; struct stat statBuf;
@ -434,7 +455,7 @@ static void check_memory()
if (stat("/etc/fstab", &statBuf) == 0) { if (stat("/etc/fstab", &statBuf) == 0) {
/* Try to turn on swap */ /* Try to turn on swap */
waitfor("/bin/swapon swapon -a", log, FALSE); system("/sbin/swapon swapon -a");
if (mem_total() < 3500) if (mem_total() < 3500)
goto goodnight; goto goodnight;
} else } else
@ -448,31 +469,45 @@ static void check_memory()
sleep(1); sleep(1);
} }
/* Run all commands to be run right before halt/reboot */
static void run_lastAction(void)
{
initAction *a;
for (a = initActionList; a; a = a->nextPtr) {
if (a->action == CTRLALTDEL) {
waitfor(a->process, a->console, FALSE);
delete_initAction(a);
}
}
}
#ifndef DEBUG_INIT #ifndef DEBUG_INIT
static void shutdown_system(void) static void shutdown_system(void)
{ {
/* first disable our SIGHUP signal */ /* first disable our SIGHUP signal */
signal(SIGHUP, SIG_DFL); signal(SIGHUP, SIG_DFL);
/* Allow Ctrl-Alt-Del to reboot system. */ /* Allow Ctrl-Alt-Del to reboot system. */
reboot(RB_ENABLE_CAD); reboot(RB_ENABLE_CAD);
message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n");
sync(); sync();
/* Send signals to every process _except_ pid 1 */ /* Send signals to every process _except_ pid 1 */
message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n");
kill(-1, SIGTERM); kill(-1, SIGTERM);
sleep(5); sleep(1);
sync(); sync();
message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n");
kill(-1, SIGKILL); kill(-1, SIGKILL);
sleep(5); sleep(1);
/* run everything to be run at "ctrlaltdel" */
run_lastAction();
message(CONSOLE, "Disabling swap.\r\n");
waitfor("swapoff -a", console, FALSE);
message(CONSOLE, "Unmounting filesystems.\r\n");
waitfor("umount -a -r", console, FALSE);
sync(); sync();
if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) { if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
/* bdflush, kupdate not needed for kernels >2.2.11 */ /* bdflush, kupdate not needed for kernels >2.2.11 */
@ -484,14 +519,14 @@ static void shutdown_system(void)
static void halt_signal(int sig) static void halt_signal(int sig)
{ {
shutdown_system(); shutdown_system();
message(CONSOLE, message(CONSOLE|LOG,
"The system is halted. Press %s or turn off power\r\n", "The system is halted. Press %s or turn off power\r\n",
(secondConsole == NULL) /* serial console */ (secondConsole == NULL) /* serial console */
? "Reset" : "CTRL-ALT-DEL"); ? "Reset" : "CTRL-ALT-DEL");
sync(); sync();
/* allow time for last message to reach serial console */ /* allow time for last message to reach serial console */
sleep(5); sleep(2);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if (sig == SIGUSR2) if (sig == SIGUSR2)
@ -505,7 +540,7 @@ static void halt_signal(int sig)
static void reboot_signal(int sig) static void reboot_signal(int sig)
{ {
shutdown_system(); shutdown_system();
message(CONSOLE, "Please stand by while rebooting the system.\r\n"); message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n");
sync(); sync();
/* allow time for last message to reach serial console */ /* allow time for last message to reach serial console */
@ -631,7 +666,7 @@ void new_initAction(initActionEnum action, char *process, char *cons)
// newAction->process, newAction->action, newAction->console); // newAction->process, newAction->action, newAction->console);
} }
void delete_initAction(initAction * action) static void delete_initAction(initAction * action)
{ {
initAction *a, *b = NULL; initAction *a, *b = NULL;
@ -669,6 +704,10 @@ void parse_inittab(void)
if (file == NULL) { if (file == NULL) {
/* No inittab file -- set up some default behavior */ /* No inittab file -- set up some default behavior */
#endif #endif
/* Swapoff on halt/reboot */
new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
/* Umount all filesystems on halt/reboot */
new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
/* Askfirst shell on tty1 */ /* Askfirst shell on tty1 */
new_initAction(ASKFIRST, SHELL, console); new_initAction(ASKFIRST, SHELL, console);
/* Askfirst shell on tty2 */ /* Askfirst shell on tty2 */
@ -756,6 +795,8 @@ void parse_inittab(void)
#endif #endif
} }
extern int init_main(int argc, char **argv) extern int init_main(int argc, char **argv)
{ {
initAction *a; initAction *a;
@ -768,9 +809,6 @@ extern int init_main(int argc, char **argv)
usage("init\n\nInit is the parent of all processes.\n\n" usage("init\n\nInit is the parent of all processes.\n\n"
"This version of init is designed to be run only by the kernel\n"); "This version of init is designed to be run only by the kernel\n");
} }
/* Fix up argv[0] to be certain we claim to be init */
strncpy(argv[0], "init", strlen(argv[0]));
/* Set up sig handlers -- be sure to /* Set up sig handlers -- be sure to
* clear all of these in run() */ * clear all of these in run() */
signal(SIGUSR1, halt_signal); signal(SIGUSR1, halt_signal);
@ -839,6 +877,10 @@ extern int init_main(int argc, char **argv)
parse_inittab(); parse_inittab();
} }
/* Fix up argv[0] to be certain we claim to be init */
strncpy(argv[0], "init", strlen(argv[0])+1);
strncpy(argv[1], "\0", strlen(argv[1])+1);
/* Now run everything that needs to be run */ /* Now run everything that needs to be run */
/* First run the sysinit command */ /* First run the sysinit command */

View File

@ -22,6 +22,11 @@
* *
*/ */
/* Turn this on to disable all the dangerous
rebooting stuff when debugging.
#define DEBUG_INIT
*/
#include "internal.h" #include "internal.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -78,7 +83,8 @@ typedef enum {
RESPAWN, RESPAWN,
ASKFIRST, ASKFIRST,
WAIT, WAIT,
ONCE ONCE,
CTRLALTDEL
} initActionEnum; } initActionEnum;
/* And now a list of the actions we support in the version of init */ /* And now a list of the actions we support in the version of init */
@ -93,6 +99,7 @@ static const struct initActionType actions[] = {
{"askfirst", ASKFIRST}, {"askfirst", ASKFIRST},
{"wait", WAIT}, {"wait", WAIT},
{"once", ONCE}, {"once", ONCE},
{"ctrlaltdel", CTRLALTDEL},
{0} {0}
}; };
@ -113,6 +120,7 @@ static char *log = VT_LOG;
static int kernelVersion = 0; static int kernelVersion = 0;
static char termType[32] = "TERM=ansi"; static char termType[32] = "TERM=ansi";
static char console[32] = _PATH_CONSOLE; static char console[32] = _PATH_CONSOLE;
static void delete_initAction(initAction * action);
/* print a message to the specified device: /* print a message to the specified device:
@ -131,8 +139,8 @@ void message(int device, char *fmt, ...)
va_start(arguments, fmt); va_start(arguments, fmt);
vsnprintf(msg, sizeof(msg), fmt, arguments); vsnprintf(msg, sizeof(msg), fmt, arguments);
va_end(arguments); va_end(arguments);
openlog("init", 0, LOG_DAEMON); openlog("init", 0, LOG_USER);
syslog(LOG_DAEMON | LOG_NOTICE, msg); syslog(LOG_USER|LOG_INFO, msg);
closelog(); closelog();
} }
#else #else
@ -147,10 +155,11 @@ void message(int device, char *fmt, ...)
/* log to main console instead */ /* log to main console instead */
device = CONSOLE; device = CONSOLE;
} else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { } else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) {
log_fd = -1; log_fd = -2;
fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
fflush(stderr); fflush(stderr);
return; log = NULL;
device = CONSOLE;
} }
} }
if ((device & LOG) && (log_fd >= 0)) { if ((device & LOG) && (log_fd >= 0)) {
@ -303,10 +312,10 @@ static void console_init()
/* check for serial console and disable logging to tty3 & running a /* check for serial console and disable logging to tty3 & running a
* shell to tty2 */ * shell to tty2 */
if (ioctl(0, TIOCGSERIAL, &sr) == 0) { if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
message(LOG | CONSOLE,
"serial console detected. Disabling virtual terminals.\r\n");
log = NULL; log = NULL;
secondConsole = NULL; secondConsole = NULL;
message(LOG | CONSOLE,
"serial console detected. Disabling virtual terminals.\r\n");
} }
close(fd); close(fd);
} }
@ -319,6 +328,7 @@ static pid_t run(char *command, char *terminal, int get_enter)
pid_t pid; pid_t pid;
char *tmpCmd; char *tmpCmd;
char *cmd[255]; char *cmd[255];
char buf[255];
static const char press_enter[] = static const char press_enter[] =
"\nPlease press Enter to activate this console. "; "\nPlease press Enter to activate this console. ";
@ -333,7 +343,9 @@ static pid_t run(char *command, char *terminal, int get_enter)
if ((pid = fork()) == 0) { if ((pid = fork()) == 0) {
#ifdef DEBUG_INIT
pid_t shell_pgid = getpid(); pid_t shell_pgid = getpid();
#endif
/* Clean up */ /* Clean up */
close(0); close(0);
@ -369,30 +381,40 @@ static pid_t run(char *command, char *terminal, int get_enter)
*/ */
char c; char c;
#ifdef DEBUG_INIT
message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
command, shell_pgid, terminal); command, shell_pgid, terminal);
#endif
write(fileno(stdout), press_enter, sizeof(press_enter) - 1); write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
read(fileno(stdin), &c, 1); read(fileno(stdin), &c, 1);
} }
#ifdef DEBUG_INIT
/* Log the process name and args */ /* Log the process name and args */
message(LOG, "Starting pid %d, console %s: '", message(LOG, "Starting pid %d, console %s: '%s'\r\n",
shell_pgid, terminal, command); shell_pgid, terminal, command);
#endif
/* See if any special /bin/sh requiring characters are present */
if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
cmd[0] = SHELL;
cmd[1] = "-c";
strcpy(buf, "exec ");
strncat(buf, command, sizeof(buf) - strlen(buf) - 1);
cmd[2] = buf;
cmd[3] = NULL;
} else {
/* Convert command (char*) into cmd (char**, one word per string) */ /* Convert command (char*) into cmd (char**, one word per string) */
for (tmpCmd = command, i = 0; for (tmpCmd = command, i = 0;
(tmpCmd = strsep(&command, " \t")) != NULL;) { (tmpCmd = strsep(&command, " \t")) != NULL;) {
if (*tmpCmd != '\0') { if (*tmpCmd != '\0') {
cmd[i] = tmpCmd; cmd[i] = tmpCmd;
#ifdef DEBUG_INIT
message(LOG, "%s ", tmpCmd);
#endif
tmpCmd++; tmpCmd++;
i++; i++;
} }
} }
cmd[i] = NULL; cmd[i] = NULL;
message(LOG, "'\r\n"); }
/* Now run it. The new program will take over this PID, /* Now run it. The new program will take over this PID,
* so nothing further in init.c should be run. */ * so nothing further in init.c should be run. */
@ -413,9 +435,8 @@ static int waitfor(char *command, char *terminal, int get_enter)
while (1) { while (1) {
wpid = wait(&status); wpid = wait(&status);
if (wpid > 0) { if (wpid > 0 && wpid != pid) {
message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid); continue;
break;
} }
if (wpid == pid) if (wpid == pid)
break; break;
@ -424,7 +445,7 @@ static int waitfor(char *command, char *terminal, int get_enter)
} }
/* Make sure there is enough memory to do something useful. * /* Make sure there is enough memory to do something useful. *
* Calls swapon if needed so be sure /proc is mounted. */ * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
static void check_memory() static void check_memory()
{ {
struct stat statBuf; struct stat statBuf;
@ -434,7 +455,7 @@ static void check_memory()
if (stat("/etc/fstab", &statBuf) == 0) { if (stat("/etc/fstab", &statBuf) == 0) {
/* Try to turn on swap */ /* Try to turn on swap */
waitfor("/bin/swapon swapon -a", log, FALSE); system("/sbin/swapon swapon -a");
if (mem_total() < 3500) if (mem_total() < 3500)
goto goodnight; goto goodnight;
} else } else
@ -448,31 +469,45 @@ static void check_memory()
sleep(1); sleep(1);
} }
/* Run all commands to be run right before halt/reboot */
static void run_lastAction(void)
{
initAction *a;
for (a = initActionList; a; a = a->nextPtr) {
if (a->action == CTRLALTDEL) {
waitfor(a->process, a->console, FALSE);
delete_initAction(a);
}
}
}
#ifndef DEBUG_INIT #ifndef DEBUG_INIT
static void shutdown_system(void) static void shutdown_system(void)
{ {
/* first disable our SIGHUP signal */ /* first disable our SIGHUP signal */
signal(SIGHUP, SIG_DFL); signal(SIGHUP, SIG_DFL);
/* Allow Ctrl-Alt-Del to reboot system. */ /* Allow Ctrl-Alt-Del to reboot system. */
reboot(RB_ENABLE_CAD); reboot(RB_ENABLE_CAD);
message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n");
sync(); sync();
/* Send signals to every process _except_ pid 1 */ /* Send signals to every process _except_ pid 1 */
message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n");
kill(-1, SIGTERM); kill(-1, SIGTERM);
sleep(5); sleep(1);
sync(); sync();
message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n");
kill(-1, SIGKILL); kill(-1, SIGKILL);
sleep(5); sleep(1);
/* run everything to be run at "ctrlaltdel" */
run_lastAction();
message(CONSOLE, "Disabling swap.\r\n");
waitfor("swapoff -a", console, FALSE);
message(CONSOLE, "Unmounting filesystems.\r\n");
waitfor("umount -a -r", console, FALSE);
sync(); sync();
if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) { if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
/* bdflush, kupdate not needed for kernels >2.2.11 */ /* bdflush, kupdate not needed for kernels >2.2.11 */
@ -484,14 +519,14 @@ static void shutdown_system(void)
static void halt_signal(int sig) static void halt_signal(int sig)
{ {
shutdown_system(); shutdown_system();
message(CONSOLE, message(CONSOLE|LOG,
"The system is halted. Press %s or turn off power\r\n", "The system is halted. Press %s or turn off power\r\n",
(secondConsole == NULL) /* serial console */ (secondConsole == NULL) /* serial console */
? "Reset" : "CTRL-ALT-DEL"); ? "Reset" : "CTRL-ALT-DEL");
sync(); sync();
/* allow time for last message to reach serial console */ /* allow time for last message to reach serial console */
sleep(5); sleep(2);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if (sig == SIGUSR2) if (sig == SIGUSR2)
@ -505,7 +540,7 @@ static void halt_signal(int sig)
static void reboot_signal(int sig) static void reboot_signal(int sig)
{ {
shutdown_system(); shutdown_system();
message(CONSOLE, "Please stand by while rebooting the system.\r\n"); message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n");
sync(); sync();
/* allow time for last message to reach serial console */ /* allow time for last message to reach serial console */
@ -631,7 +666,7 @@ void new_initAction(initActionEnum action, char *process, char *cons)
// newAction->process, newAction->action, newAction->console); // newAction->process, newAction->action, newAction->console);
} }
void delete_initAction(initAction * action) static void delete_initAction(initAction * action)
{ {
initAction *a, *b = NULL; initAction *a, *b = NULL;
@ -669,6 +704,10 @@ void parse_inittab(void)
if (file == NULL) { if (file == NULL) {
/* No inittab file -- set up some default behavior */ /* No inittab file -- set up some default behavior */
#endif #endif
/* Swapoff on halt/reboot */
new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
/* Umount all filesystems on halt/reboot */
new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console);
/* Askfirst shell on tty1 */ /* Askfirst shell on tty1 */
new_initAction(ASKFIRST, SHELL, console); new_initAction(ASKFIRST, SHELL, console);
/* Askfirst shell on tty2 */ /* Askfirst shell on tty2 */
@ -756,6 +795,8 @@ void parse_inittab(void)
#endif #endif
} }
extern int init_main(int argc, char **argv) extern int init_main(int argc, char **argv)
{ {
initAction *a; initAction *a;
@ -768,9 +809,6 @@ extern int init_main(int argc, char **argv)
usage("init\n\nInit is the parent of all processes.\n\n" usage("init\n\nInit is the parent of all processes.\n\n"
"This version of init is designed to be run only by the kernel\n"); "This version of init is designed to be run only by the kernel\n");
} }
/* Fix up argv[0] to be certain we claim to be init */
strncpy(argv[0], "init", strlen(argv[0]));
/* Set up sig handlers -- be sure to /* Set up sig handlers -- be sure to
* clear all of these in run() */ * clear all of these in run() */
signal(SIGUSR1, halt_signal); signal(SIGUSR1, halt_signal);
@ -839,6 +877,10 @@ extern int init_main(int argc, char **argv)
parse_inittab(); parse_inittab();
} }
/* Fix up argv[0] to be certain we claim to be init */
strncpy(argv[0], "init", strlen(argv[0])+1);
strncpy(argv[1], "\0", strlen(argv[1])+1);
/* Now run everything that needs to be run */ /* Now run everything that needs to be run */
/* First run the sysinit command */ /* First run the sysinit command */

View File

@ -31,6 +31,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
//#include <sys/param.h>
#include <mntent.h> #include <mntent.h>
@ -186,6 +187,7 @@ extern pid_t findInitPid();
#if defined BB_INIT || defined BB_SYSLOGD #if defined BB_INIT || defined BB_SYSLOGD
extern int device_open(char *device, int mode); extern int device_open(char *device, int mode);
#endif #endif
extern void whine_if_fstab_is_missing();
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
extern int del_loop(const char *device); extern int del_loop(const char *device);

50
mount.c
View File

@ -53,7 +53,7 @@
#include <linux/loop.h> #include <linux/loop.h>
static int use_loop = 0; static int use_loop = FALSE;
#endif #endif
extern const char mtab_file[]; /* Defined in utility.c */ extern const char mtab_file[]; /* Defined in utility.c */
@ -114,13 +114,14 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
char *mtab_opts) char *mtab_opts)
{ {
int status = 0; int status = 0;
char *lofile = NULL;
#if defined BB_MTAB #if defined BB_MTAB
if (fakeIt == FALSE) if (fakeIt == FALSE)
#endif #endif
{ {
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (use_loop) { if (use_loop==TRUE) {
int loro = flags & MS_RDONLY; int loro = flags & MS_RDONLY;
char *lofile = specialfile; char *lofile = specialfile;
@ -137,6 +138,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
fprintf(stderr, "WARNING: loop device is read-only\n"); fprintf(stderr, "WARNING: loop device is read-only\n");
flags &= ~MS_RDONLY; flags &= ~MS_RDONLY;
} }
use_loop = FALSE;
} }
#endif #endif
status = status =
@ -157,7 +159,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
/* Bummer. mount failed. Clean up */ /* Bummer. mount failed. Clean up */
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (specialfile != NULL) { if (lofile != NULL) {
del_loop(specialfile); del_loop(specialfile);
} }
#endif #endif
@ -166,20 +168,6 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
#if defined BB_MTAB
#define whine_if_fstab_is_missing() {}
#else
extern void whine_if_fstab_is_missing()
{
struct stat statBuf;
if (stat("/etc/fstab", &statBuf) < 0)
fprintf(stderr,
"/etc/fstab file missing -- install one to name /dev/root.\n\n");
}
#endif
/* Seperate standard mount options from the nonstandard string options */ /* Seperate standard mount options from the nonstandard string options */
static void static void
parse_mount_options(char *options, unsigned long *flags, char *strflags) parse_mount_options(char *options, unsigned long *flags, char *strflags)
@ -204,7 +192,7 @@ parse_mount_options(char *options, unsigned long *flags, char *strflags)
} }
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */ if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */
use_loop = 1; use_loop = TRUE;
gotone = TRUE; gotone = TRUE;
} }
#endif #endif
@ -229,7 +217,7 @@ parse_mount_options(char *options, unsigned long *flags, char *strflags)
int int
mount_one(char *blockDevice, char *directory, char *filesystemType, mount_one(char *blockDevice, char *directory, char *filesystemType,
unsigned long flags, char *string_flags, int useMtab, int fakeIt, unsigned long flags, char *string_flags, int useMtab, int fakeIt,
char *mtab_opts) char *mtab_opts, int whineOnErrors)
{ {
int status = 0; int status = 0;
@ -270,9 +258,11 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
fakeIt, mtab_opts); fakeIt, mtab_opts);
} }
if (status == FALSE) { if (status == FALSE && whineOnErrors == TRUE) {
if (whineOnErrors == TRUE) {
fprintf(stderr, "Mounting %s on %s failed: %s\n", fprintf(stderr, "Mounting %s on %s failed: %s\n",
blockDevice, directory, strerror(errno)); blockDevice, directory, strerror(errno));
}
return (FALSE); return (FALSE);
} }
return (TRUE); return (TRUE);
@ -387,18 +377,28 @@ extern int mount_main(int argc, char **argv)
exit(FALSE); exit(FALSE);
} }
while ((m = getmntent(f)) != NULL) { while ((m = getmntent(f)) != NULL) {
// If the file system isn't noauto, and isn't mounted on /, // If the file system isn't noauto,
// and isn't swap or nfs, then mount it // and isn't swap or nfs, then mount it
if ((!strstr(m->mnt_opts, "noauto")) && if ((!strstr(m->mnt_opts, "noauto")) &&
(m->mnt_dir[1] != '\0') &&
(!strstr(m->mnt_type, "swap")) && (!strstr(m->mnt_type, "swap")) &&
(!strstr(m->mnt_type, "nfs"))) { (!strstr(m->mnt_type, "nfs"))) {
flags = 0; flags = 0;
*string_flags = '\0'; *string_flags = '\0';
parse_mount_options(m->mnt_opts, &flags, string_flags); parse_mount_options(m->mnt_opts, &flags, string_flags);
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, /* If the directory is /, try to remount
* with the options specified in fstab */
if (m->mnt_dir[0] == '/' && m->mnt_dir[1] == '\0') {
flags |= MS_REMOUNT;
}
if (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
flags, string_flags, useMtab, fakeIt, flags, string_flags, useMtab, fakeIt,
extra_opts); extra_opts, FALSE))
{
/* Try again, but this time try a remount */
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
extra_opts, TRUE);
}
} }
} }
endmntent(f); endmntent(f);
@ -414,7 +414,7 @@ extern int mount_main(int argc, char **argv)
#endif #endif
exit(mount_one(device, directory, filesystemType, exit(mount_one(device, directory, filesystemType,
flags, string_flags, useMtab, fakeIt, flags, string_flags, useMtab, fakeIt,
extra_opts)); extra_opts, TRUE));
} else { } else {
goto goodbye; goto goodbye;
} }

View File

@ -36,13 +36,16 @@ static int whichApp;
static const char *appName; static const char *appName;
static const char swapoff_usage[] = static const char swapoff_usage[] =
"swapoff [OPTION] [device]\n\n"
"Stop swapping virtual memory pages on the given device.\n\n"
"Options:\n"
"\t-a\tStop swapping on all swap devices\n";
"swapoff device\n"
"\nStop swapping virtual memory pages on the given device.\n";
static const char swapon_usage[] = static const char swapon_usage[] =
"swapon [OPTION] [device]\n\n"
"swapon device\n" "Start swapping virtual memory pages on the given device.\n\n"
"\nStart swapping virtual memory pages on the given device.\n"; "Options:\n"
"\t-a\tStart swapping on all swap devices\n";
#define SWAPON_APP 1 #define SWAPON_APP 1
@ -85,12 +88,6 @@ static void do_em_all()
extern int swap_on_off_main(int argc, char **argv) extern int swap_on_off_main(int argc, char **argv)
{ {
struct stat statBuf;
if (stat("/etc/fstab", &statBuf) < 0)
fprintf(stderr,
"/etc/fstab file missing -- Please install one.\n\n");
if (strcmp(*argv, "swapon") == 0) { if (strcmp(*argv, "swapon") == 0) {
appName = *argv; appName = *argv;
whichApp = SWAPON_APP; whichApp = SWAPON_APP;
@ -100,8 +97,9 @@ extern int swap_on_off_main(int argc, char **argv)
whichApp = SWAPOFF_APP; whichApp = SWAPOFF_APP;
} }
if (argc < 2) if (argc != 2) {
goto usage_and_exit; goto usage_and_exit;
}
argc--; argc--;
argv++; argv++;
@ -110,6 +108,7 @@ extern int swap_on_off_main(int argc, char **argv)
while (*++(*argv)) while (*++(*argv))
switch (**argv) { switch (**argv) {
case 'a': case 'a':
whine_if_fstab_is_missing();
do_em_all(); do_em_all();
break; break;
default: default:

216
umount.c
View File

@ -29,6 +29,7 @@
#include <fstab.h> #include <fstab.h>
#include <errno.h> #include <errno.h>
static const char umount_usage[] = static const char umount_usage[] =
"umount [flags] filesystem|directory\n\n" "umount [flags] filesystem|directory\n\n"
"Flags:\n" "\t-a:\tUnmount all file systems" "Flags:\n" "\t-a:\tUnmount all file systems"
@ -57,113 +58,6 @@ static int umountAll = FALSE;
static int doRemount = FALSE; static int doRemount = FALSE;
extern const char mtab_file[]; /* Defined in utility.c */ extern const char mtab_file[]; /* Defined in utility.c */
#define MIN(x,y) (x > y ? x : y)
static int do_umount(const char *name, int useMtab)
{
int status;
char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
if (blockDevice && strcmp(blockDevice, name) == 0)
name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
status = umount(name);
#if defined BB_FEATURE_MOUNT_LOOP
if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
/* this was a loop device, delete it */
del_loop(blockDevice);
#endif
#if defined BB_FEATURE_REMOUNT
if (status != 0 && doRemount == TRUE && errno == EBUSY) {
status = mount(blockDevice, name, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (status == 0) {
fprintf(stderr, "umount: %s busy - remounted read-only\n",
blockDevice);
/* TODO: update mtab if BB_MTAB is defined */
} else {
fprintf(stderr, "umount: Cannot remount %s read-only\n",
blockDevice);
}
}
#endif
if (status == 0) {
#if defined BB_MTAB
if (useMtab == TRUE)
erase_mtab(name);
#endif
return (TRUE);
}
return (FALSE);
}
static int umount_all(int useMtab)
{
int status = TRUE;
char *mountpt;
void *iter;
for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
status = do_umount(mountpt, useMtab);
if (status != 0) {
/* Don't bother retrying the umount on busy devices */
if (errno == EBUSY) {
perror(mountpt);
continue;
}
status = do_umount(mountpt, useMtab);
if (status != 0) {
printf("Couldn't umount %s on %s: %s\n",
mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
strerror(errno));
}
}
}
return (status);
}
extern int umount_main(int argc, char **argv)
{
if (argc < 2) {
usage(umount_usage);
}
/* Parse any options */
while (--argc > 0 && **(++argv) == '-') {
while (*++(*argv))
switch (**argv) {
case 'a':
umountAll = TRUE;
break;
#ifdef BB_MTAB
case 'n':
useMtab = FALSE;
break;
#endif
#ifdef BB_FEATURE_REMOUNT
case 'r':
doRemount = TRUE;
break;
#endif
default:
usage(umount_usage);
}
}
mtab_read();
if (umountAll == TRUE) {
exit(umount_all(useMtab));
}
if (do_umount(*argv, useMtab) == 0)
exit(TRUE);
else {
perror("umount");
exit(FALSE);
}
}
/* These functions are here because the getmntent functions do not appear /* These functions are here because the getmntent functions do not appear
* to be re-entrant, which leads to all sorts of problems when we try to * to be re-entrant, which leads to all sorts of problems when we try to
@ -257,3 +151,111 @@ void mtab_free(void)
this = next; this = next;
} }
} }
static int do_umount(const char *name, int useMtab)
{
int status;
char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
if (blockDevice && strcmp(blockDevice, name) == 0)
name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
status = umount(name);
#if defined BB_FEATURE_MOUNT_LOOP
if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
/* this was a loop device, delete it */
del_loop(blockDevice);
#endif
#if defined BB_FEATURE_REMOUNT
if (status != 0 && doRemount == TRUE && errno == EBUSY) {
status = mount(blockDevice, name, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (status == 0) {
fprintf(stderr, "umount: %s busy - remounted read-only\n",
blockDevice);
/* TODO: update mtab if BB_MTAB is defined */
} else {
fprintf(stderr, "umount: Cannot remount %s read-only\n",
blockDevice);
}
}
#endif
if (status == 0) {
#if defined BB_MTAB
if (useMtab == TRUE)
erase_mtab(name);
#endif
return (TRUE);
}
return (FALSE);
}
static int umount_all(int useMtab)
{
int status = TRUE;
char *mountpt;
void *iter;
for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
/* Never umount /proc on a umount -a */
if (strstr(mountpt, "proc")!= NULL)
continue;
status = do_umount(mountpt, useMtab);
if (status != 0) {
/* Don't bother retrying the umount on busy devices */
if (errno == EBUSY) {
perror(mountpt);
continue;
}
status = do_umount(mountpt, useMtab);
if (status != 0) {
printf("Couldn't umount %s on %s: %s\n",
mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
strerror(errno));
}
}
}
return (status);
}
extern int umount_main(int argc, char **argv)
{
if (argc < 2) {
usage(umount_usage);
}
/* Parse any options */
while (--argc > 0 && **(++argv) == '-') {
while (*++(*argv))
switch (**argv) {
case 'a':
umountAll = TRUE;
break;
#ifdef BB_MTAB
case 'n':
useMtab = FALSE;
break;
#endif
#ifdef BB_FEATURE_REMOUNT
case 'r':
doRemount = TRUE;
break;
#endif
default:
usage(umount_usage);
}
}
mtab_read();
if (umountAll == TRUE) {
exit(umount_all(useMtab));
}
if (do_umount(*argv, useMtab) == 0)
exit(TRUE);
else {
perror("umount");
exit(FALSE);
}
}

View File

@ -53,7 +53,7 @@
#include <linux/loop.h> #include <linux/loop.h>
static int use_loop = 0; static int use_loop = FALSE;
#endif #endif
extern const char mtab_file[]; /* Defined in utility.c */ extern const char mtab_file[]; /* Defined in utility.c */
@ -114,13 +114,14 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
char *mtab_opts) char *mtab_opts)
{ {
int status = 0; int status = 0;
char *lofile = NULL;
#if defined BB_MTAB #if defined BB_MTAB
if (fakeIt == FALSE) if (fakeIt == FALSE)
#endif #endif
{ {
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (use_loop) { if (use_loop==TRUE) {
int loro = flags & MS_RDONLY; int loro = flags & MS_RDONLY;
char *lofile = specialfile; char *lofile = specialfile;
@ -137,6 +138,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
fprintf(stderr, "WARNING: loop device is read-only\n"); fprintf(stderr, "WARNING: loop device is read-only\n");
flags &= ~MS_RDONLY; flags &= ~MS_RDONLY;
} }
use_loop = FALSE;
} }
#endif #endif
status = status =
@ -157,7 +159,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
/* Bummer. mount failed. Clean up */ /* Bummer. mount failed. Clean up */
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (specialfile != NULL) { if (lofile != NULL) {
del_loop(specialfile); del_loop(specialfile);
} }
#endif #endif
@ -166,20 +168,6 @@ do_mount(char *specialfile, char *dir, char *filesystemtype,
#if defined BB_MTAB
#define whine_if_fstab_is_missing() {}
#else
extern void whine_if_fstab_is_missing()
{
struct stat statBuf;
if (stat("/etc/fstab", &statBuf) < 0)
fprintf(stderr,
"/etc/fstab file missing -- install one to name /dev/root.\n\n");
}
#endif
/* Seperate standard mount options from the nonstandard string options */ /* Seperate standard mount options from the nonstandard string options */
static void static void
parse_mount_options(char *options, unsigned long *flags, char *strflags) parse_mount_options(char *options, unsigned long *flags, char *strflags)
@ -204,7 +192,7 @@ parse_mount_options(char *options, unsigned long *flags, char *strflags)
} }
#if defined BB_FEATURE_MOUNT_LOOP #if defined BB_FEATURE_MOUNT_LOOP
if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */ if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */
use_loop = 1; use_loop = TRUE;
gotone = TRUE; gotone = TRUE;
} }
#endif #endif
@ -229,7 +217,7 @@ parse_mount_options(char *options, unsigned long *flags, char *strflags)
int int
mount_one(char *blockDevice, char *directory, char *filesystemType, mount_one(char *blockDevice, char *directory, char *filesystemType,
unsigned long flags, char *string_flags, int useMtab, int fakeIt, unsigned long flags, char *string_flags, int useMtab, int fakeIt,
char *mtab_opts) char *mtab_opts, int whineOnErrors)
{ {
int status = 0; int status = 0;
@ -270,9 +258,11 @@ mount_one(char *blockDevice, char *directory, char *filesystemType,
fakeIt, mtab_opts); fakeIt, mtab_opts);
} }
if (status == FALSE) { if (status == FALSE && whineOnErrors == TRUE) {
if (whineOnErrors == TRUE) {
fprintf(stderr, "Mounting %s on %s failed: %s\n", fprintf(stderr, "Mounting %s on %s failed: %s\n",
blockDevice, directory, strerror(errno)); blockDevice, directory, strerror(errno));
}
return (FALSE); return (FALSE);
} }
return (TRUE); return (TRUE);
@ -387,18 +377,28 @@ extern int mount_main(int argc, char **argv)
exit(FALSE); exit(FALSE);
} }
while ((m = getmntent(f)) != NULL) { while ((m = getmntent(f)) != NULL) {
// If the file system isn't noauto, and isn't mounted on /, // If the file system isn't noauto,
// and isn't swap or nfs, then mount it // and isn't swap or nfs, then mount it
if ((!strstr(m->mnt_opts, "noauto")) && if ((!strstr(m->mnt_opts, "noauto")) &&
(m->mnt_dir[1] != '\0') &&
(!strstr(m->mnt_type, "swap")) && (!strstr(m->mnt_type, "swap")) &&
(!strstr(m->mnt_type, "nfs"))) { (!strstr(m->mnt_type, "nfs"))) {
flags = 0; flags = 0;
*string_flags = '\0'; *string_flags = '\0';
parse_mount_options(m->mnt_opts, &flags, string_flags); parse_mount_options(m->mnt_opts, &flags, string_flags);
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type, /* If the directory is /, try to remount
* with the options specified in fstab */
if (m->mnt_dir[0] == '/' && m->mnt_dir[1] == '\0') {
flags |= MS_REMOUNT;
}
if (mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
flags, string_flags, useMtab, fakeIt, flags, string_flags, useMtab, fakeIt,
extra_opts); extra_opts, FALSE))
{
/* Try again, but this time try a remount */
mount_one(m->mnt_fsname, m->mnt_dir, m->mnt_type,
flags|MS_REMOUNT, string_flags, useMtab, fakeIt,
extra_opts, TRUE);
}
} }
} }
endmntent(f); endmntent(f);
@ -414,7 +414,7 @@ extern int mount_main(int argc, char **argv)
#endif #endif
exit(mount_one(device, directory, filesystemType, exit(mount_one(device, directory, filesystemType,
flags, string_flags, useMtab, fakeIt, flags, string_flags, useMtab, fakeIt,
extra_opts)); extra_opts, TRUE));
} else { } else {
goto goodbye; goto goodbye;
} }

View File

@ -36,13 +36,16 @@ static int whichApp;
static const char *appName; static const char *appName;
static const char swapoff_usage[] = static const char swapoff_usage[] =
"swapoff [OPTION] [device]\n\n"
"Stop swapping virtual memory pages on the given device.\n\n"
"Options:\n"
"\t-a\tStop swapping on all swap devices\n";
"swapoff device\n"
"\nStop swapping virtual memory pages on the given device.\n";
static const char swapon_usage[] = static const char swapon_usage[] =
"swapon [OPTION] [device]\n\n"
"swapon device\n" "Start swapping virtual memory pages on the given device.\n\n"
"\nStart swapping virtual memory pages on the given device.\n"; "Options:\n"
"\t-a\tStart swapping on all swap devices\n";
#define SWAPON_APP 1 #define SWAPON_APP 1
@ -85,12 +88,6 @@ static void do_em_all()
extern int swap_on_off_main(int argc, char **argv) extern int swap_on_off_main(int argc, char **argv)
{ {
struct stat statBuf;
if (stat("/etc/fstab", &statBuf) < 0)
fprintf(stderr,
"/etc/fstab file missing -- Please install one.\n\n");
if (strcmp(*argv, "swapon") == 0) { if (strcmp(*argv, "swapon") == 0) {
appName = *argv; appName = *argv;
whichApp = SWAPON_APP; whichApp = SWAPON_APP;
@ -100,8 +97,9 @@ extern int swap_on_off_main(int argc, char **argv)
whichApp = SWAPOFF_APP; whichApp = SWAPOFF_APP;
} }
if (argc < 2) if (argc != 2) {
goto usage_and_exit; goto usage_and_exit;
}
argc--; argc--;
argv++; argv++;
@ -110,6 +108,7 @@ extern int swap_on_off_main(int argc, char **argv)
while (*++(*argv)) while (*++(*argv))
switch (**argv) { switch (**argv) {
case 'a': case 'a':
whine_if_fstab_is_missing();
do_em_all(); do_em_all();
break; break;
default: default:

View File

@ -29,6 +29,7 @@
#include <fstab.h> #include <fstab.h>
#include <errno.h> #include <errno.h>
static const char umount_usage[] = static const char umount_usage[] =
"umount [flags] filesystem|directory\n\n" "umount [flags] filesystem|directory\n\n"
"Flags:\n" "\t-a:\tUnmount all file systems" "Flags:\n" "\t-a:\tUnmount all file systems"
@ -57,113 +58,6 @@ static int umountAll = FALSE;
static int doRemount = FALSE; static int doRemount = FALSE;
extern const char mtab_file[]; /* Defined in utility.c */ extern const char mtab_file[]; /* Defined in utility.c */
#define MIN(x,y) (x > y ? x : y)
static int do_umount(const char *name, int useMtab)
{
int status;
char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
if (blockDevice && strcmp(blockDevice, name) == 0)
name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
status = umount(name);
#if defined BB_FEATURE_MOUNT_LOOP
if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
/* this was a loop device, delete it */
del_loop(blockDevice);
#endif
#if defined BB_FEATURE_REMOUNT
if (status != 0 && doRemount == TRUE && errno == EBUSY) {
status = mount(blockDevice, name, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (status == 0) {
fprintf(stderr, "umount: %s busy - remounted read-only\n",
blockDevice);
/* TODO: update mtab if BB_MTAB is defined */
} else {
fprintf(stderr, "umount: Cannot remount %s read-only\n",
blockDevice);
}
}
#endif
if (status == 0) {
#if defined BB_MTAB
if (useMtab == TRUE)
erase_mtab(name);
#endif
return (TRUE);
}
return (FALSE);
}
static int umount_all(int useMtab)
{
int status = TRUE;
char *mountpt;
void *iter;
for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
status = do_umount(mountpt, useMtab);
if (status != 0) {
/* Don't bother retrying the umount on busy devices */
if (errno == EBUSY) {
perror(mountpt);
continue;
}
status = do_umount(mountpt, useMtab);
if (status != 0) {
printf("Couldn't umount %s on %s: %s\n",
mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
strerror(errno));
}
}
}
return (status);
}
extern int umount_main(int argc, char **argv)
{
if (argc < 2) {
usage(umount_usage);
}
/* Parse any options */
while (--argc > 0 && **(++argv) == '-') {
while (*++(*argv))
switch (**argv) {
case 'a':
umountAll = TRUE;
break;
#ifdef BB_MTAB
case 'n':
useMtab = FALSE;
break;
#endif
#ifdef BB_FEATURE_REMOUNT
case 'r':
doRemount = TRUE;
break;
#endif
default:
usage(umount_usage);
}
}
mtab_read();
if (umountAll == TRUE) {
exit(umount_all(useMtab));
}
if (do_umount(*argv, useMtab) == 0)
exit(TRUE);
else {
perror("umount");
exit(FALSE);
}
}
/* These functions are here because the getmntent functions do not appear /* These functions are here because the getmntent functions do not appear
* to be re-entrant, which leads to all sorts of problems when we try to * to be re-entrant, which leads to all sorts of problems when we try to
@ -257,3 +151,111 @@ void mtab_free(void)
this = next; this = next;
} }
} }
static int do_umount(const char *name, int useMtab)
{
int status;
char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
if (blockDevice && strcmp(blockDevice, name) == 0)
name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
status = umount(name);
#if defined BB_FEATURE_MOUNT_LOOP
if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9))
/* this was a loop device, delete it */
del_loop(blockDevice);
#endif
#if defined BB_FEATURE_REMOUNT
if (status != 0 && doRemount == TRUE && errno == EBUSY) {
status = mount(blockDevice, name, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (status == 0) {
fprintf(stderr, "umount: %s busy - remounted read-only\n",
blockDevice);
/* TODO: update mtab if BB_MTAB is defined */
} else {
fprintf(stderr, "umount: Cannot remount %s read-only\n",
blockDevice);
}
}
#endif
if (status == 0) {
#if defined BB_MTAB
if (useMtab == TRUE)
erase_mtab(name);
#endif
return (TRUE);
}
return (FALSE);
}
static int umount_all(int useMtab)
{
int status = TRUE;
char *mountpt;
void *iter;
for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
/* Never umount /proc on a umount -a */
if (strstr(mountpt, "proc")!= NULL)
continue;
status = do_umount(mountpt, useMtab);
if (status != 0) {
/* Don't bother retrying the umount on busy devices */
if (errno == EBUSY) {
perror(mountpt);
continue;
}
status = do_umount(mountpt, useMtab);
if (status != 0) {
printf("Couldn't umount %s on %s: %s\n",
mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE),
strerror(errno));
}
}
}
return (status);
}
extern int umount_main(int argc, char **argv)
{
if (argc < 2) {
usage(umount_usage);
}
/* Parse any options */
while (--argc > 0 && **(++argv) == '-') {
while (*++(*argv))
switch (**argv) {
case 'a':
umountAll = TRUE;
break;
#ifdef BB_MTAB
case 'n':
useMtab = FALSE;
break;
#endif
#ifdef BB_FEATURE_REMOUNT
case 'r':
doRemount = TRUE;
break;
#endif
default:
usage(umount_usage);
}
}
mtab_read();
if (umountAll == TRUE) {
exit(umount_all(useMtab));
}
if (do_umount(*argv, useMtab) == 0)
exit(TRUE);
else {
perror("umount");
exit(FALSE);
}
}

View File

@ -1298,5 +1298,19 @@ extern char *find_unused_loop_device(void)
} }
#endif /* BB_FEATURE_MOUNT_LOOP */ #endif /* BB_FEATURE_MOUNT_LOOP */
#if defined BB_MTAB
#define whine_if_fstab_is_missing() {}
#else
extern void whine_if_fstab_is_missing()
{
struct stat statBuf;
if (stat("/etc/fstab", &statBuf) < 0)
fprintf(stderr,
"/etc/fstab file missing -- install one to name /dev/root.\n\n");
}
#endif
/* END CODE */ /* END CODE */