aboutsummaryrefslogtreecommitdiff
path: root/sutils
diff options
context:
space:
mode:
Diffstat (limited to 'sutils')
-rw-r--r--sutils/ChangeLog60
-rw-r--r--sutils/MAKEDEV.sh204
-rw-r--r--sutils/Makefile30
-rw-r--r--sutils/clookup.c24
-rwxr-xr-xsutils/e2os.sh153
-rw-r--r--sutils/fsck.c174
-rw-r--r--sutils/fstab.c479
-rw-r--r--sutils/fstab.h64
-rw-r--r--sutils/halt.c14
-rw-r--r--sutils/losetup.sh66
-rw-r--r--sutils/reboot.c18
-rw-r--r--sutils/swapoff.c2
-rw-r--r--sutils/swapon.c536
-rw-r--r--sutils/update.c7
14 files changed, 1577 insertions, 254 deletions
diff --git a/sutils/ChangeLog b/sutils/ChangeLog
deleted file mode 100644
index 7d8ca832..00000000
--- a/sutils/ChangeLog
+++ /dev/null
@@ -1,60 +0,0 @@
-Thu Aug 1 16:29:31 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
-
- * clookup.c (file_name_lookup_carefully/lookup): When appending
- TAIL to RETRY_NAME, use strcpy instead of strcat.
-
-Sat Jul 6 19:55:22 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsck.c: (argp_program_version): New variable.
-
-Wed Jul 3 14:22:03 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fstab.c (fstab_add_fs): Don't SEGV if COPY is 0.
-
-Thu Jun 27 00:01:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsck.c (fsck): Fsck pass 0 if not in automatic mode. Respect
- `noauto' option in automatic mode.
- (main): Set FSCK_F_AUTO flag if in automatic mode.
- (FSCK_F_AUTO): New macro.
- (fs_start_fsck): When deciding to use a flags arg, mask flags
- against an explicit list of valid ones.
-
-Tue Jun 25 18:39:44 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsck.c (main, options): Add --writable/-w option.
- (FSCK_F_WRITABLE): New macro.
- (struct fsck): Rename WAS_READONLY field to MAKE_WRITABLE.
- (fscks_start_fsck): Change to set make_writable field instead of
- was_readonly.
- (fsck_cleanup): Change RESTORE_WRITABLE to MAKE_WRITABLE.
- (fscks_wait): Likewise.
-
-Thu Jun 20 14:08:12 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsck.c (fsck): Wait for fscks to finish.
- * fstab.c (fstypes_create): Copy SEARCH_FMTS contents into NEW.
- (fs_set_mntent): Don't keep old fsys fields if the mnt_dir is changed.
- (fstab_add_mntent): Initialize fields in FS with non-zero values.
- (_fs_check_mounted): The root is always mounted.
-
-Wed Jun 19 10:44:16 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fstab.c (fs_set_readonly, fs_remount): If fsys_set_options
- returns EINVAL, return EOPNOTSUPP instead.
- (fs_set_readonly): Use fsys_set_readonly.
- (fs_remount): Use fsys_remount.
- (fs_readonly): Use fsys_get_readonly.
- (_fs_check_mounted): Use file_name_lookup_carefully.
- * clookup.c: New file.
- * fsck.c (_debug): New variable.
- (debug, fs_debug): New macros.
- (fs_start_fsck, fscks_start_fsck, fsck_cleanup, fscks_wait, fsck, main):
- Add debugging noise.
- (main): Use FSTAB_PATH instead of _PATH_MNTTAB.
- (args_doc): Fix.
-
-Tue Jun 18 22:56:11 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * fsck.c (options): Rename `--max-parallel' to `--parallel'.
-
diff --git a/sutils/MAKEDEV.sh b/sutils/MAKEDEV.sh
new file mode 100644
index 00000000..4277b052
--- /dev/null
+++ b/sutils/MAKEDEV.sh
@@ -0,0 +1,204 @@
+#!/bin/sh
+#
+# Make standard devices
+#
+
+PATH=/bin:/usr/bin
+
+ECHO=: # Change to "echo" to echo commands.
+EXEC="" # Change to ":" to suppress command execution.
+DEVDIR=`pwd` # Reset below by -D/--devdir command line option.
+
+while :; do
+ case "$1" in
+ --help|"-?")
+ echo "\
+Usage: $0 [OPTION...] DEVNAME...
+Make filesystem nodes for accessing standard system devices
+
+ -D, --devdir=DIR Use DIR when a device node name must be
+ embedded in a translator; default is the cwd
+ -n, --dry-run Don't actually execute any commands
+ -v, --verbose Show what commands are executed to make the devices
+ -?, --help Give this help list
+ --usage Give a short usage message
+ -V, --version Print program version"
+ exit 0;;
+ --devdir) DEVDIR="$2"; shift 2;;
+ --devdir=*) DEVDIR="`echo "$1" | sed 's/^--devdir=//'`"; shift 1;;
+ -D) DEVDIR="$2"; shift 2;;
+ -D*) DEVDIR="`echo "$1" | sed 's/^-D//'`"; shift 1;;
+ --verbose|-v) ECHO=echo; shift;;
+ --dry-run|-n) EXEC=:; shift;;
+ -nv|-vn) ECHO=echo; EXEC=:; shift;;
+ --usage)
+ echo "Usage: $0 [-V?] [-D DIR] [--help] [--usage] [--version] [--devdir=DIR] DEVNAME..."
+ exit 0;;
+ --version|-V)
+ echo "STANDARD_HURD_VERSION_MAKEDEV_"; exit 0;;
+ -*)
+ echo 1>&2 "$0: unrecognized option \`$1'"
+ echo 1>&2 "Try \`$0 --help' or \`$0 --usage' for more information";
+ exit 1;;
+ *)
+ break;;
+ esac
+done
+
+case "$#" in 0)
+ echo 1>&2 "Usage: $0 [OPTION...] DEVNAME..."
+ echo 1>&2 "Try \`$0 --help' or \`$0 --usage' for more information"
+ exit 1;;
+esac
+
+cmd() {
+ eval $ECHO "$@"
+ eval $EXEC "$@"
+}
+
+st() {
+ local NODE="$1"
+ local OWNER="$2"
+ local PERM="$3"
+ shift 3
+ if cmd settrans -cg "$NODE"; then
+ cmd chown "$OWNER" "$NODE"
+ cmd chmod "$PERM" "$NODE"
+ cmd settrans "$NODE" "$@"
+ fi
+}
+
+lose() {
+ local line
+ for line; do
+ echo 1>&2 "$0: $line"
+ done
+ exit 1
+}
+
+mkdev() {
+ local I
+ for I; do
+ case $I in
+ /* | */*)
+ lose "Device names cannot contain directories" \
+ "Change to target directory and run $0 from there."
+ ;;
+
+ std)
+ mkdev console tty null zero full fd time mem klog shm
+ ;;
+ console|com[0-9])
+ st $I root 600 /hurd/term ${DEVDIR}/$I device $I;;
+ vcs)
+ st $I root 600 /hurd/console;;
+ tty[1-9][0-9]|tty[1-9])
+ st $I root 600 /hurd/term ${DEVDIR}/$I hurdio \
+ ${DEVDIR}/vcs/`echo $I | sed -e s/tty//`/console;;
+ lpr[0-9])
+ st $I root 660 /hurd/streamio "$I";;
+ null)
+ st $I root 666 /hurd/null;;
+ full)
+ st $I root 666 /hurd/null --full;;
+ zero)
+ st $I root 666 /hurd/storeio -Tzero;;
+ tty)
+ st $I root 666 /hurd/magic tty;;
+ fd)
+ st $I root 666 /hurd/magic --directory fd
+ cmd ln -f -s fd/0 stdin
+ cmd ln -f -s fd/1 stdout
+ cmd ln -f -s fd/2 stderr
+ ;;
+ 'time')
+ st $I root 644 /hurd/storeio --no-cache time ;;
+ mem)
+ st $I root 660 /hurd/storeio --no-cache mem ;;
+ klog)
+ st $I root 660 /hurd/streamio kmsg;;
+ # ptys
+ [pt]ty[pqrstuvwxyzPQRS]?)
+ # Make one pty, both the master and slave halves.
+ local id="${I#???}"
+ st pty$id root 666 /hurd/term ${DEVDIR}/pty$id \
+ pty-master ${DEVDIR}/tty$id
+ st tty$id root 666 /hurd/term ${DEVDIR}/tty$id \
+ pty-slave ${DEVDIR}/pty$id
+ ;;
+ [pt]ty[pqrstuvwxyzPQRS])
+ # Make a bunch of ptys.
+ local n
+ for n in 0 1 2 3 4 5 6 7 8 9 \
+ a b c d e f g h i j k l m n o p q r s t u v; do
+ mkdev ${I}${n}
+ done
+ ;;
+
+ fd*|mt*)
+ st $I root 640 /hurd/storeio $I
+ ;;
+
+ [hrsc]d*)
+ local n="${I#?d}"
+ local major="${n%%[!0-9]*}"
+ if [ -z "$major" ]; then
+ lose "$I: Invalid device name: must supply a device number"
+ fi
+ local minor="${n##$major}"
+ case "$minor" in
+ '') ;; # Whole disk
+ [a-z]) ;; # BSD partition syntax, no slice syntax
+ s[1-9]*) # Slice syntax.
+ local slicestuff="${minor#s}"
+ local slice="${slicestuff%%[!0-9]*}"
+ local rest="${slicestuff##$slice}"
+ case "$slice" in
+ [1-9] | [1-9][0-9]) ;;
+ *)
+ lose "$I: Invalid slice number \`$slice'"
+ ;;
+ esac
+ case "$rest" in
+ '') ;; # Whole slice
+ [a-z]) ;; # BSD partition after slice
+ *)
+ lose "$I: Invalid partition \`$rest'"
+ ;;
+ esac
+ ;;
+ *)
+ lose "$I: Invalid slice or partition syntax"
+ ;;
+ esac
+
+ # The device name passed all syntax checks, so finally use it!
+ st $I root 640 /hurd/storeio $I
+ ;;
+
+ # /dev/shm is used by the POSIX.1 shm_open call in libc.
+ # We don't want the underlying node to be written by randoms,
+ # but the filesystem presented should be writable by anyone
+ # and have the sticky bit set so others' files can't be removed.
+ # tmpfs requires an arbitrary size limitation here. To be like
+ # Linux, we tell tmpfs to set the size to half the physical RAM
+ # in the machine.
+ shm)
+ st $I root 644 /hurd/tmpfs --mode=1777 50%
+ ;;
+
+ # Linux compatibility
+ loop*)
+ # In Linux an inactive "/dev/loopN" device acts like /dev/null.
+ # The `losetup' script changes the translator to "activate" the device.
+ st $I root 640 /hurd/null
+ ;;
+
+ *)
+ lose "$I: Unknown device name"
+ ;;
+ esac
+ done
+}
+
+mkdev "$@"
diff --git a/sutils/Makefile b/sutils/Makefile
index 388bea29..b2383579 100644
--- a/sutils/Makefile
+++ b/sutils/Makefile
@@ -1,6 +1,6 @@
-# Makefile for sutils
-#
-# Copyright (C) 1996 Free Software Foundation
+# Makefile for sutils
+#
+# Copyright (C) 1996,97,99,2000,2010 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
@@ -20,17 +20,25 @@
dir := sutils
makemode := utilities
-targets = reboot halt fsck
-SRCS = reboot.c halt.c fsck.c fstab.c clookup.c
+progs = reboot halt fsck swapon swapoff
+scripts = e2os MAKEDEV losetup
+targets = $(special-targets) $(progs)
+special-targets = $(scripts)
installationdir = $(sbindir)
+SRCS = $(progs:=.c) clookup.c fstab.c update.c $(scripts:=.sh)
+LCLHDRS = fstab.h
-OBJS = $(SRCS:.c=.o)
+OBJS = $(progs:=.c)
+HURDLIBS = store shouldbeinlibc
include ../Makeconf
-fsck: fstab.o clookup.o ../libshouldbeinlibc/libshouldbeinlibc.a
-
-%: %.sh
- cp $< $@
+fsck: fstab.o clookup.o
+swapon swapoff: ../libstore/libstore.a default_pagerUser.o
+$(progs): %: %.o ../libshouldbeinlibc/libshouldbeinlibc.a
-$(filter-out $(special-targets), $(targets)): %: %.o
+install: $(prefix)/dev $(prefix)/dev/MAKEDEV
+$(prefix)/dev/MAKEDEV:
+ ln -s ../sbin/MAKEDEV $@
+$(prefix)/dev:
+ @$(MKINSTALLDIRS) $@
diff --git a/sutils/clookup.c b/sutils/clookup.c
index e39ddd64..0107799c 100644
--- a/sutils/clookup.c
+++ b/sutils/clookup.c
@@ -1,6 +1,6 @@
/* Careful filename lookup
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -25,18 +25,18 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <sys/mman.h>
#include <hurd.h>
#include <hurd/lookup.h>
#include <hurd/id.h>
#include <hurd/fsys.h>
-extern int __getuids (int num, gid_t *buf); /* XXX */
/* This function is like file_name_lookup, but tries hard to avoid starting
any passive translators. If a node with an unstarted passive translator
is encountered, ENXIO is returned in ERRNO; other errors are as for
file_name_lookup. Note that checking for an active translator currently
- requires fetching the control port, which is a priveleged operation. */
+ requires fetching the control port, which is a privileged operation. */
file_t
file_name_lookup_carefully (const char *name, int flags, mode_t mode)
{
@@ -94,8 +94,7 @@ file_name_lookup_carefully (const char *name, int flags, mode_t mode)
if (ptrans != _ptrans)
/* Deallocate out-of-line memory from file_get_translator. */
- vm_deallocate (mach_task_self (),
- (vm_address_t)ptrans, ptrans_len);
+ munmap (ptrans, ptrans_len);
err = file_get_translator_cntl (*node, &fsys);
if (! err)
@@ -107,10 +106,11 @@ file_name_lookup_carefully (const char *name, int flags, mode_t mode)
{
file_t old_node = *node;
err = fsys_getroot (fsys,
- unauth_dir, MACH_MSG_TYPE_MOVE_SEND,
+ unauth_dir, MACH_MSG_TYPE_COPY_SEND,
uids, num_uids, gids, num_gids,
flags & ~O_NOTRANS, retry,
retry_name, node);
+ mach_port_deallocate (mach_task_self (), unauth_dir);
if (! err)
mach_port_deallocate (mach_task_self (), old_node);
}
@@ -143,11 +143,11 @@ file_name_lookup_carefully (const char *name, int flags, mode_t mode)
}
/* Fetch uids for use with fsys_getroot. */
- num_uids = __getuids (0, 0);
+ num_uids = geteuids (0, 0);
if (num_uids < 0)
return errno;
uids = alloca (num_uids * sizeof (uid_t));
- num_uids = __getuids (num_uids, uids);
+ num_uids = geteuids (num_uids, uids);
if (num_uids < 0)
return errno;
@@ -159,11 +159,11 @@ file_name_lookup_carefully (const char *name, int flags, mode_t mode)
num_gids = getgroups (num_gids, gids);
if (num_gids < 0)
return errno;
-
+
/* Look things up ... */
- err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, lookup,
- name, flags, mode & ~_hurd_umask,
- &node);
+ err = hurd_file_name_lookup (&_hurd_ports_use, &getdport, lookup,
+ name, flags, mode & ~getumask (),
+ &node);
return err ? (__hurd_fail (err), MACH_PORT_NULL) : node;
}
diff --git a/sutils/e2os.sh b/sutils/e2os.sh
new file mode 100755
index 00000000..60c9e017
--- /dev/null
+++ b/sutils/e2os.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+# Set/get the `creator_os' field of an ext2fs partition
+#
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+#
+# Written by Miles Bader <miles@gnu.ai.mit.edu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+USAGE="Usage: $0 DEVICE [OS]"
+
+DD=${DD-/bin/dd}
+OD=${OD-/bin/od}
+SED=${SED-/bin/sed}
+AWK=${AWK-/bin/gawk}
+
+# Hack to allow this script to work well under linux too.
+test ! -x "$OD" -a -x /usr/bin/od && OD=/usr/bin/od
+test ! -x "$AWK" -a -x /usr/bin/gawk && AWK=/usr/bin/gawk
+
+while :; do
+ case "$1" in
+ --help|"-?")
+ echo "$USAGE"
+ echo "Get or set the creator_os parameter of an ext2fs partition."
+ echo ""
+ echo " -?, --help Give this help list"
+ echo " --usage Give a short usage message"
+ echo " -V, --version Print program version"
+ exit 0;;
+ --usage)
+ echo "Usage: $0 [-V?] [--help] [--usage] [--version] DEVICE [OS]"
+ exit 0;;
+ --version|-V)
+ echo "STANDARD_HURD_VERSION_e2os_"; exit 0;;
+ -*)
+ echo 1>&2 "$0: unrecognized option \`$1'"
+ echo 1>&2 "Try \`$0 --help' for more information";
+ exit 1;;
+ *)
+ break;;
+ esac
+done
+
+case "$#" in 1 | 2) ;; # ok
+ *) echo 1>&2 "$USAGE"
+ echo 1>&2 "Try \`--help' for more information";
+ exit 1;;
+esac
+
+DEVICE="$1"; shift
+OS="$1"
+
+# Superblock fields (format is "BYTE_OFFS SIZE")
+SB_MAGIC="56 2"
+SB_OS="72 4"
+# Ext2fs magic numbers
+MAGIC_EXT2=ef53
+MAGIC_EXT2_OLD=ef53
+# Symbolic names for os types we know about
+OS_LINUX=0
+OS_HURD=1
+OS_MASIX=2
+OS_FREEBSD=3
+OS_LITES=4
+
+# Superblock
+SB=/tmp/,e2os-sb.$$
+
+# We have to store error output in a file so that we can filter it (for all
+# unix's stressing of pipelines, /bin/sh sure works hard to prevent you using
+# them).
+ERRS=/tmp/,e2os-errs.$$
+
+trap "/bin/rm -f $SB $ERRS" 0
+
+# Read the superblock
+$DD 2>"$ERRS" if="$DEVICE" of="$SB" bs=1k skip=1 count=1 \
+|| { $SED 1>&2 "s;^$DD:;$0:;" "$ERRS"; exit 2; }
+
+# Extract a word of SZ bytes from byte offset POS in the superblock
+# Optional arg FMT is what format to use (x = hex, d = decimal)
+sbget ()
+{
+ local pos="$1" sz="$2" fmt="${3-d}"
+ pos=$(($pos / $sz))
+ $DD 2>/dev/null if="$SB" bs="$sz" skip="$pos" count=1 \
+ | $OD -An -t"$fmt$sz" \
+ | $SED 's;^[ 0]*\(.\);\1;'
+}
+
+# Set a word of SZ bytes at byte offset POS in the superblock to VAL
+sbset ()
+{
+ local pos="$1" sz="$2" val="$3"
+ pos=$(($pos / $sz))
+ echo "$val" \
+ | $AWK '{ n=$1+0; printf ("%c%c%c%c", n, n/256, n/(2^16), n/(2^24)); }' \
+ | $DD 2>/dev/null of="$SB" bs="$sz" seek="$pos" count=1 conv=notrunc
+}
+
+# Check the magic number
+magic="`sbget $SB_MAGIC x`"
+case "$magic" in
+ $MAGIC_EXT2) ;; # ok
+ $MAGIC_EXT2_OLD) echo "$0: $DEVICE: Old-format ext2 filesystem"; exit 3;;
+ *) echo "$0: $DEVICE: Not an ext2 filesystem (magic = 0x$magic)"; exit 4;;
+esac
+
+if test "$OS"; then
+ # Set the os field
+ case "$OS" in
+ linux) OS=$OS_LINUX;;
+ hurd) OS=$OS_HURD;;
+ masix) OS=$OS_MASIX;;
+ freebsd) OS=$OS_FREEBSD;;
+ lites) OS=$OS_LITES;;
+ "*[!0-9]*")
+ echo 1>&2 "$0: $OS: Unknown ext2 creator_os value"; exit 5;;
+ esac
+
+ # Frob the superlock
+ sbset $SB_OS "$OS"
+
+ # Write the superblock
+ $DD 2>"$ERRS" if="$SB" of="$DEVICE" bs=1k seek=1 count=1 conv=notrunc \
+ || { $SED 1>&2 "s;^$DD:;$0:;" "$ERRS"; exit 6; }
+else
+ # Print the os field.
+ OS="`sbget $SB_OS`"
+ case "$OS" in
+ "") exit 2;;
+ $OS_LINUX) OS=linux;;
+ $OS_HURD) OS=hurd;;
+ $OS_MASIX) OS=masix;;
+ $OS_FREEBSD) OS=freebsd;;
+ $OS_LITES) OS=lites;;
+ esac
+ echo "$OS"
+fi
diff --git a/sutils/fsck.c b/sutils/fsck.c
index ec2628ba..1ab9caa5 100644
--- a/sutils/fsck.c
+++ b/sutils/fsck.c
@@ -1,8 +1,8 @@
/* Hurd-aware fsck wrapper
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 97, 98, 99 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This file is part of the GNU Hurd.
@@ -28,7 +28,7 @@
-n Automatically answer no to all questions
-f Check even if clean
-s Only print diagostic messages
-
+
They should also return exit-status codes as following:
0 Filesystem was clean
@@ -41,7 +41,7 @@
Although it knows something about the hurd, this fsck still uses
/etc/fstab, and is generally not very integrated. That will have to wait
- until the appropiate mechanisms for doing so are decided. */
+ until the appropriate mechanisms for doing so are decided. */
#include <stdlib.h>
#include <string.h>
@@ -51,10 +51,12 @@
#include <argp.h>
#include <argz.h>
#include <assert.h>
+#include <version.h>
#include "fstab.h"
-char *argp_program_version = "fsck 1.0 (GNU " HURD_RELEASE ")";
+const char *argp_program_version = STANDARD_HURD_VERSION (fsck);
+
/* for debugging */
static int _debug = 0;
@@ -93,6 +95,7 @@ static int _debug = 0;
#define FSCK_F_VERBOSE 0x100
#define FSCK_F_WRITABLE 0x200 /* Make writable after fscking. */
#define FSCK_F_AUTO 0x400 /* Do all filesystems in fstab. */
+#define FSCK_F_DRYRUN 0x800 /* Don't actually do anything. */
static int got_sigquit = 0, got_sigint = 0;
@@ -110,7 +113,7 @@ struct fsck
{
struct fs *fs; /* Filesystem being fscked. */
int pid; /* Pid for process. */
- int make_writable :1; /* Make writable after fscking if possible. */
+ int make_writable; /* Make writable after fscking if possible. */
struct fsck *next, **self;
};
@@ -155,6 +158,17 @@ fs_start_fsck (struct fs *fs, int flags)
*argp++ = fs->mntent.mnt_fsname;
*argp = 0;
+ if (flags & FSCK_F_DRYRUN)
+ {
+ char *argz;
+ size_t argz_len;
+ argz_create (argv, &argz, &argz_len);
+ argz_stringify (argz, argz_len, ' ');
+ puts (argz);
+ free (argz);
+ return 0;
+ }
+
pid = fork ();
if (pid < 0)
{
@@ -209,7 +223,7 @@ fscks_start_fsck (struct fscks *fscks, struct fs *fs)
fs_debug (fs, "Checking mounted state");
err = fs_mounted (fs, &mounted);
CK (err, "%s: Cannot check mounted state", fs->mntent.mnt_dir);
-
+
if (mounted)
{
int readonly;
@@ -218,6 +232,16 @@ fscks_start_fsck (struct fscks *fscks, struct fs *fs)
err = fs_readonly (fs, &readonly);
CK (err, "%s: Cannot check readonly state", fs->mntent.mnt_dir);
+ if (fscks->flags & FSCK_F_DRYRUN)
+ {
+ if (! readonly)
+ {
+ printf ("%s: writable filesystem %s would be made read-only\n",
+ program_invocation_name, fs->mntent.mnt_dir);
+ readonly = 1;
+ }
+ }
+
if (! readonly)
{
fs_debug (fs, "Making readonly");
@@ -272,7 +296,10 @@ fsck_cleanup (struct fsck *fsck, int remount, int make_writable)
error_t err = 0;
struct fs *fs = fsck->fs;
- *fsck->self = fsck->next; /* Remove from chain. */
+ /* Remove from chain. */
+ *fsck->self = fsck->next;
+ if (fsck->next)
+ fsck->next->self = fsck->self;
fs_debug (fs, "Cleaning up after fsck (remount = %d, make_writable = %d)",
remount, make_writable);
@@ -322,7 +349,7 @@ fscks_wait (struct fscks *fscks)
debug ("Waiting...");
- do
+ do
pid = wait (&wstatus);
while (pid < 0 && errno == EINTR);
@@ -387,20 +414,18 @@ fsck (struct fstab *fstab, int flags, int max_parallel)
summary_status = status;
}
- /* Do in pass order; if in automatic mode, we skip pass 0. */
- for (pass = autom ? 1 : 0; pass >= 0; pass = fstab_next_pass (fstab, pass))
+ /* Do in pass order; pass 0 is never run, it is reserved for "off". */
+ for (pass = 1; pass > 0; pass = fstab_next_pass (fstab, pass))
/* Submit all filesystems in the given pass, up to MAX_PARALLEL at a
time. There should currently be no fscks running. */
{
debug ("Pass %d", pass);
- /* Do pass 0 filesystems one at a time. */
- fscks.free_slots = (pass == 0 ? 1 : max_parallel);
+ fscks.free_slots = max_parallel;
/* Try and fsck every filesystem in this pass. */
for (fs = fstab->entries; fs; fs = fs->next)
- if (fs->mntent.mnt_passno == pass
- && !(autom && hasmntopt (&fs->mntent, "noauto")))
+ if (fs->mntent.mnt_passno == pass)
/* FS is applicable for this pass. */
{
struct fstype *type;
@@ -421,8 +446,11 @@ fsck (struct fstab *fstab, int flags, int max_parallel)
merge_status (fscks_wait (&fscks));
merge_status (fscks_start_fsck (&fscks, fs));
}
- else
+ else if (autom)
fs_debug (fs, "Not fsckable");
+ else
+ error (0, 0, "%s: %s: Not a fsckable filesystem type",
+ fs->mntent.mnt_dir, fs->mntent.mnt_type);
}
/* Now wait for them all to finish. */
@@ -433,48 +461,44 @@ fsck (struct fstab *fstab, int flags, int max_parallel)
return summary_status;
}
-static const struct argp_option
-options[] =
+static const struct argp_option options[] =
{
{"preen", 'p', 0, 0, "Terse automatic mode", 1},
{"yes", 'y', 0, 0, "Automatically answer yes to all questions"},
{"no", 'n', 0, 0, "Automatically answer no to all questions"},
- {"fstab", 't', "FILE", 0, "File to use instead of " _PATH_MNTTAB},
{"parallel", 'l', "NUM", 0, "Limit the number of parallel checks to NUM"},
{"verbose", 'v', 0, 0, "Print informational messages"},
{"writable", 'w', 0, 0,
"Make RW filesystems writable after fscking, if possible"},
{"debug", 'D', 0, OPTION_HIDDEN },
- {"search-fmts",'S', "FMTS", 0,
- "`:' separated list of formats to use for finding fsck programs"},
- {0, 0, 0, 0, "In --preen mode, the following also apply:", 2},
{"force", 'f', 0, 0, "Check even if clean"},
- {"silent", 's', 0, 0, "Only print diagostic messages"},
+
+ {"dry-run", 'N', 0, 0, "Don't check, just show what would be done"},
+ {0, 0, 0, 0, "In --preen mode, the following also apply:", 2},
+ {"silent", 's', 0, 0, "Print only diagnostic messages"},
{"quiet", 'q', 0, OPTION_ALIAS | OPTION_HIDDEN },
{0, 0}
};
-static const char *args_doc = "[ DEVICE|FSYS... ]";
-static const char *doc = 0;
+static const char doc[] = "Filesystem consistency check and repair";
+static const char args_doc[] = "[ DEVICE|FSYS... ]";
+
int
main (int argc, char **argv)
{
- error_t err;
- struct fstab *fstab, *check;
- struct fstypes *types;
+ struct fstab *check;
int status; /* exit status */
int flags = 0;
- char *names = 0;
- size_t names_len = 0;
- char *search_fmts = FSCK_SEARCH_FMTS;
- size_t search_fmts_len = sizeof FSCK_SEARCH_FMTS;
- char *fstab_path = _PATH_MNTTAB;
int max_parallel = -1; /* -1 => use default */
error_t parse_opt (int key, char *arg, struct argp_state *state)
{
+ struct fstab_argp_params *params = state->input;
switch (key)
{
+ case ARGP_KEY_INIT:
+ state->child_inputs[0] = params; /* pass down to fstab_argp parser */
+ break;
case 'p': flags |= FSCK_F_PREEN; break;
case 'y': flags |= FSCK_F_YES; break;
case 'n': flags |= FSCK_F_NO; break;
@@ -482,79 +506,49 @@ main (int argc, char **argv)
case 's': flags |= FSCK_F_SILENT; break;
case 'v': flags |= FSCK_F_VERBOSE; break;
case 'w': flags |= FSCK_F_WRITABLE; break;
- case 't': fstab_path = arg; break;
+ case 'N': flags |= FSCK_F_DRYRUN; break;
case 'D': _debug = 1; break;
case 'l':
max_parallel = atoi (arg);
- if (! max_parallel)
- argp_error (state, "%s: Invalid value for --max-parellel", arg);
- break;
- case 'S':
- argz_create_sep (arg, ':', &search_fmts, &search_fmts_len);
+ if (max_parallel < 1)
+ argp_error (state, "%s: Invalid value for --max-parallel", arg);
break;
- case ARGP_KEY_ARG:
- err = argz_add (&names, &names_len, arg);
- if (err)
- argp_failure (state, 100, ENOMEM, "%s", arg);
+ case ARGP_KEY_NO_ARGS:
+ if (flags & FSCK_F_PREEN)
+ params->do_all = 1;
+ else if (!params->do_all)
+ {
+ argp_usage (state);
+ return EINVAL;
+ }
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
- struct argp argp = {options, parse_opt, args_doc, doc};
-
- argp_parse (&argp, argc, argv, 0, 0, 0);
-
- err = fstypes_create (search_fmts, search_fmts_len, &types);
- if (err)
- error (102, err, "fstypes_create");
-
- err = fstab_create (types, &fstab);
- if (err)
- error (101, err, "fstab_create");
-
- debug ("Reading %s...", fstab_path);
- err = fstab_read (fstab, fstab_path);
- if (err)
- error (103, err, "%s", fstab_path);
+ static const struct argp_child kids[] =
+ { { &fstab_argp, 0,
+ "Filesystem selection (default is all in " _PATH_MNTTAB "):", 2 },
+ { 0 } };
+ struct argp argp = { options, parse_opt, args_doc, doc, kids };
+ struct fstab_argp_params fstab_params;
- if (names)
- /* Fsck specified filesystems; also look at /var/run/mtab. */
- {
- char *name;
-
- debug ("Reading %s...", _PATH_MOUNTED);
- err = fstab_read (fstab, _PATH_MOUNTED);
- if (err && err != ENOENT)
- error (104, err, "%s", _PATH_MOUNTED);
+ argp_parse (&argp, argc, argv, 0, 0, &fstab_params);
- err = fstab_create (types, &check);
- if (err)
- error (105, err, "fstab_create");
+ check = fstab_argp_create (&fstab_params,
+ FSCK_SEARCH_FMTS, sizeof FSCK_SEARCH_FMTS);
+ if (fstab_params.do_all)
+ flags |= FSCK_F_AUTO;
- for (name = names; name; name = argz_next (names, names_len, name))
- {
- struct fs *fs = fstab_find (fstab, name);
- if (! fs)
- error (106, 0, "%s: Unknown device or filesystem", name);
- fs_debug (fs, "Adding to checked filesystems");
- fstab_add_fs (check, fs, 0);
- }
- }
- else
- /* Fsck everything in /etc/fstab. */
+ if (max_parallel <= 0)
{
- check = fstab;
- flags |= FSCK_F_AUTO;
+ if (flags & FSCK_F_PREEN)
+ max_parallel = 100; /* In preen mode, do lots in parallel. */
+ else
+ max_parallel = 1; /* Do one at a time to keep output rational. */
}
- if (max_parallel <= 0)
- if (flags & FSCK_F_PREEN)
- max_parallel = 100; /* In preen mode, do lots in parallel. */
- else
- max_parallel = 1; /* Do one at a time to keep output rational. */
-
/* If the user send a SIGQUIT (usually ^\), then do all checks, but
regardless of their outcome, return a status that will cause the
automatic reboot to stop after fscking is complete. */
diff --git a/sutils/fstab.c b/sutils/fstab.c
index 6c8e0f81..b66e5195 100644
--- a/sutils/fstab.c
+++ b/sutils/fstab.c
@@ -1,6 +1,6 @@
/* Fstab filesystem frobbing
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -27,6 +27,8 @@
#include <fcntl.h>
#include <error.h>
#include <argz.h>
+#include <argp.h>
+#include <fnmatch.h>
#include <hurd/fsys.h>
@@ -34,7 +36,7 @@
extern error_t fsys_set_readonly (fsys_t fsys, int readonly);
extern error_t fsys_get_readonly (fsys_t fsys, int *readonly);
-extern error_t fsys_remount (fsys_t fsys);
+extern error_t fsys_update (fsys_t fsys);
extern file_t file_name_lookup_carefully (const char *file,
int flags, mode_t mode);
@@ -66,7 +68,7 @@ fstab_free (struct fstab *fstab)
/* Return a new fstypes structure in TYPES. SEARCH_FMTS is copied. */
error_t
-fstypes_create (char *search_fmts, size_t search_fmts_len,
+fstypes_create (const char *search_fmts, size_t search_fmts_len,
struct fstypes **types)
{
struct fstypes *new = malloc (sizeof (struct fstypes));
@@ -94,11 +96,12 @@ fstypes_create (char *search_fmts, size_t search_fmts_len,
one is found, it is added to TYPES, otherwise an new entry is created
with a NULL PROGRAM field. */
error_t
-fstypes_get (struct fstypes *types, char *name, struct fstype **fstype)
+fstypes_get (struct fstypes *types, const char *name, struct fstype **fstype)
{
char *fmts, *fmt;
size_t fmts_len;
struct fstype *type;
+ char *program = 0;
for (type = types->entries; type; type = type->next)
if (strcasecmp (type->name, name) == 0)
@@ -108,14 +111,6 @@ fstypes_get (struct fstypes *types, char *name, struct fstype **fstype)
}
/* No existing entry, make a new one. */
- type = malloc (sizeof (struct fstype));
- if (! type)
- return ENOMEM;
-
- type->name = strdup (name);
- type->program = 0;
- type->next = types->entries;
- types->entries = type;
fmts = types->program_search_fmts;
fmts_len = types->program_search_fmts_len;
@@ -123,7 +118,6 @@ fstypes_get (struct fstypes *types, char *name, struct fstype **fstype)
for (fmt = fmts; fmt; fmt = argz_next (fmts, fmts_len, fmt))
{
int fd;
- char *program;
asprintf (&program, fmt, name);
fd = open (program, O_EXEC);
@@ -144,23 +138,109 @@ fstypes_get (struct fstypes *types, char *name, struct fstype **fstype)
close (fd);
if (rv < 0)
- return errno;
-
- if (stat.st_mode & S_IXUSR)
- /* Yup execute bit is set. This must a program... */
{
- type->program = program;
- break;
+ free (program);
+ return errno;
}
+
+ if (stat.st_mode & S_IXUSR)
+ /* Yup execute bit is set. This must be a program... */
+ break;
+
+ free (program);
}
+
+ program = 0;
+ }
+
+ type = malloc (sizeof (struct fstype));
+ if (! type)
+ {
+ free (program);
+ return ENOMEM;
}
+ type->name = strdup (name);
+ if (type->name == 0)
+ {
+ free (type);
+ return ENOMEM;
+ }
+ type->program = program;
+ type->next = types->entries;
+ types->entries = type;
+
+ *fstype = type;
+
return 0;
}
+
+#if 0
+/* XXX nice idea, but not that useful since scanf's %s always eats all
+ non-ws, and it seems a bit overkill to convert it to a .+ regexp match */
+error_t
+fstypes_find_program (struct fstypes *types, const char *program,
+ struct fstype **fstype)
+{
+ char *fmts, *fmt;
+ size_t fmts_len;
+ struct fstype *type;
+ char *typename;
+
+ /* First see if a known type matches this program. */
+ for (type = types->entries; type; type = type->next)
+ if (type->program && !strcmp (type->program, program))
+ {
+ *fstype = type;
+ return 0;
+ }
+
+ /* No existing entry, see if we can make a new one. */
+
+ typename = alloca (strlen (program) + 1);
+
+ fmts = types->program_search_fmts;
+ fmts_len = types->program_search_fmts_len;
+ for (fmt = fmts; fmt; fmt = argz_next (fmts, fmts_len, fmt))
+ /* XXX this only works for trailing %s */
+ if (sscanf (program, fmt, typename) == 1)
+ {
+ /* This format matches the program and yields the type name.
+ Create a new entry for this type. */
+
+ type = malloc (sizeof (struct fstype));
+ if (! type)
+ return ENOMEM;
+ type->name = strdup (typename);
+ if (type->name == 0)
+ {
+ free (type);
+ return ENOMEM;
+ }
+ type->program = strdup (program);
+ if (type->program == 0)
+ {
+ free (type->name);
+ free (type);
+ return ENOMEM;
+ }
+ type->next = types->entries;
+ types->entries = type;
+
+ *fstype = type;
+ return 0;
+ }
+
+ /* We could find no program search format that could have yielded this
+ program name. */
+ *fstype = 0;
+ return 0;
+}
+#endif
/* Copy MNTENT into FS, copying component strings as well. */
error_t
-fs_set_mntent (struct fs *fs, struct mntent *mntent)
+fs_set_mntent (struct fs *fs, const struct mntent *mntent)
{
char *end;
size_t needed = 0;
@@ -180,7 +260,8 @@ fs_set_mntent (struct fs *fs, struct mntent *mntent)
if (! fs->storage)
return ENOMEM;
- if (strcmp (fs->mntent.mnt_dir, mntent->mnt_dir) != 0)
+ if (!fs->mntent.mnt_dir || !mntent->mnt_dir
+ || strcmp (fs->mntent.mnt_dir, mntent->mnt_dir) != 0)
{
fs->mounted = fs->readonly = -1;
if (fs->fsys != MACH_PORT_NULL)
@@ -194,20 +275,28 @@ fs_set_mntent (struct fs *fs, struct mntent *mntent)
/* Copy each mntent field from MNTENT into FS's version. */
end = fs->storage;
#define STORE(field) \
- fs->mntent.field = end; end = stpcpy (end, mntent->field) + 1
+ if (mntent->field) \
+ { \
+ fs->mntent.field = end; \
+ end = stpcpy (end, mntent->field) + 1; \
+ } \
+ else \
+ fs->mntent.field = 0;
STORE (mnt_fsname);
STORE (mnt_dir);
STORE (mnt_type);
STORE (mnt_opts);
#undef STORE
- if (fs->type && strcasecmp (fs->type->name, mntent->mnt_type) != 0)
+ if (fs->type
+ && (!mntent->mnt_type
+ || strcasecmp (fs->type->name, mntent->mnt_type) != 0))
fs->type = 0; /* Type is different. */
return 0;
}
-/* Returns an fstype for FS in TYPE, trying to fillin FS's type field if
+/* Returns an fstype for FS in TYPE, trying to fill in FS's type field if
necessary. */
error_t
fs_type (struct fs *fs, struct fstype **type)
@@ -257,7 +346,7 @@ _fs_check_mounted (struct fs *fs)
the mntent, but oh well, nothing we can do about that.] */
{
err = file_get_translator_cntl (mount_point, &fs->fsys);
- if (err == EINVAL || err == EOPNOTSUPP)
+ if (err == EINVAL || err == EOPNOTSUPP || err == ENXIO)
/* Either the mount point doesn't exist, or wasn't mounted. */
{
fs->fsys = MACH_PORT_NULL;
@@ -318,10 +407,12 @@ fs_readonly (struct fs *fs, int *readonly)
err = fs_fsys (fs, &fsys);
if (! err)
- if (fsys == MACH_PORT_NULL)
- fs->readonly = 1;
- else
- err = fsys_get_readonly (fsys, &fs->readonly);
+ {
+ if (fsys == MACH_PORT_NULL)
+ fs->readonly = 1;
+ else
+ err = fsys_get_readonly (fsys, &fs->readonly);
+ }
}
if (!err && readonly)
@@ -354,7 +445,7 @@ fs_set_readonly (struct fs *fs, int readonly)
return err;
}
-/* If FS is currently mounted tell lit to remount the device. XXX If FS is
+/* If FS is currently mounted tell it to remount the device. XXX If FS is
not mounted at all, then nothing is done. */
error_t
fs_remount (struct fs *fs)
@@ -362,14 +453,14 @@ fs_remount (struct fs *fs)
fsys_t fsys;
error_t err = fs_fsys (fs, &fsys);
if (!err && fsys != MACH_PORT_NULL) /* XXX What to do if not mounted? */
- err = fsys_remount (fsys);
+ err = fsys_update (fsys);
return err;
}
/* Returns the FS entry in FSTAB with the device field NAME (there can only
be one such entry). */
inline struct fs *
-fstab_find_device (struct fstab *fstab, char *name)
+fstab_find_device (const struct fstab *fstab, const char *name)
{
struct fs *fs;
for (fs = fstab->entries; fs; fs = fs->next)
@@ -381,9 +472,20 @@ fstab_find_device (struct fstab *fstab, char *name)
/* Returns the FS entry in FSTAB with the mount point NAME (there can only
be one such entry). */
inline struct fs *
-fstab_find_mount (struct fstab *fstab, char *name)
+fstab_find_mount (const struct fstab *fstab, const char *name)
{
struct fs *fs;
+
+ /* Don't count "none" or "-" as matching any other mount point.
+ It is canonical to use "none" for swap partitions, and multiple
+ such do not in fact conflict with each other. Likewise, the
+ special device name "ignore" is used for things that should not
+ be processed automatically. */
+ if (!strcmp (name, "-")
+ || !strcmp (name, "none")
+ || !strcmp (name, "ignore"))
+ return 0;
+
for (fs = fstab->entries; fs; fs = fs->next)
if (strcmp (fs->mntent.mnt_dir, name) == 0)
return fs;
@@ -393,9 +495,31 @@ fstab_find_mount (struct fstab *fstab, char *name)
/* Returns the FS entry in FSTAB with the device or mount point NAME (there
can only be one such entry). */
inline struct fs *
-fstab_find (struct fstab *fstab, char *name)
+fstab_find (const struct fstab *fstab, const char *name)
{
- return fstab_find_device (fstab, name) ?: fstab_find_mount (fstab, name);
+ struct fs *ret;
+ const char *real_name;
+
+ ret = fstab_find_device (fstab, name);
+ if (ret)
+ return ret;
+
+ ret = fstab_find_mount (fstab, name);
+ if (ret)
+ return ret;
+
+ real_name = realpath (name, NULL);
+
+ ret = fstab_find_device (fstab, real_name);
+ if (ret) {
+ free (real_name);
+ return ret;
+ }
+
+ ret = fstab_find_mount (fstab, real_name);
+ free (real_name);
+
+ return ret;
}
/* Cons FS onto the beginning of FSTAB's entry list. */
@@ -426,7 +550,7 @@ fs_free (struct fs *fs)
conflict (in either the device or mount point). If RESULT is non-zero, the
new entry is returne in it. */
error_t
-fstab_add_mntent (struct fstab *fstab, struct mntent *mntent,
+fstab_add_mntent (struct fstab *const fstab, const struct mntent *mntent,
struct fs **result)
{
int new = 0; /* True if we didn't overwrite an old entry. */
@@ -441,7 +565,7 @@ fstab_add_mntent (struct fstab *fstab, struct mntent *mntent,
fs = mounted_fs;
mounted_fs = 0;
}
-
+
if (! fs)
/* No old entry, make a new one. */
{
@@ -462,15 +586,17 @@ fstab_add_mntent (struct fstab *fstab, struct mntent *mntent,
err = fs_set_mntent (fs, mntent);
if (new)
- if (! err)
- _fstab_add (fstab, fs);
- else if (fs)
- free (fs);
+ {
+ if (! err)
+ _fstab_add (fstab, fs);
+ else if (fs)
+ free (fs);
+ }
- if (!err && mounted_fs)
+ if (!err && mounted_fs && mounted_fs != fs)
/* Get rid of the conflicting entry MOUNTED_FS. */
fs_free (mounted_fs);
-
+
if (!err && result)
*result = fs;
@@ -481,7 +607,7 @@ fstab_add_mntent (struct fstab *fstab, struct mntent *mntent,
DST. If DST & SRC have different TYPES fields, EINVAL is returned. If
COPY is non-zero, the copy is returned in it. */
error_t
-fstab_add_fs (struct fstab *dst, struct fs *fs, struct fs **copy)
+fstab_add_fs (struct fstab *dst, const struct fs *fs, struct fs **copy)
{
error_t err;
struct fs *new;
@@ -525,7 +651,7 @@ fstab_merge (struct fstab *dst, struct fstab *src)
if (old_fs)
fs_free (old_fs);
}
-
+
/* Now that we know there are no conflicts, steal all SRC's entries and
cons them onto DST. */
for (fs = src->entries; fs; fs = fs->next)
@@ -540,7 +666,7 @@ fstab_merge (struct fstab *dst, struct fstab *src)
/* Reads fstab-format entries into FSTAB from the file NAME. Any entries
duplicating one already in FS_LIST supersede the existing entry. */
error_t
-fstab_read (struct fstab *fstab, char *name)
+fstab_read (struct fstab *fstab, const char *name)
{
error_t err;
/* Used to hold entries from the file, before merging with FSTAB at the
@@ -583,7 +709,7 @@ fstab_read (struct fstab *fstab, char *name)
/* Return the next pass number that applies to any filesystem in FSTAB that
is greater than PASS, or -1 if there isn't any. */
-int fstab_next_pass (struct fstab *fstab, int pass)
+int fstab_next_pass (const struct fstab *fstab, int pass)
{
int next_pass = -1;
struct fs *fs;
@@ -597,3 +723,262 @@ int fstab_next_pass (struct fstab *fstab, int pass)
}
return next_pass;
}
+
+
+static const struct argp_option options[] =
+{
+ {"all", 'a', 0, 0, "Do all filesystems in " _PATH_MNTTAB},
+ {0, 'A', 0, OPTION_ALIAS },
+ {"fstab", 'F', "FILE", 0, "File to use instead of " _PATH_MNTTAB},
+ {"fstype", 't', "TYPE", 0, "Do only filesystems of given type(s)"},
+ {"exclude-root",'R',0, 0,
+ "Exclude root (/) filesystem from " _PATH_MNTTAB " list"},
+ {"exclude", 'X', "PATTERN", 0, "Exclude directories matching PATTERN"},
+
+ {"search-fmts",'S', "FMTS", 0,
+ "`:' separated list of formats to use for finding"
+ " filesystem-specific programs"},
+
+ {0, 0}
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ error_t err;
+ struct fstab_argp_params *params = state->input;
+
+ switch (key)
+ {
+ case ARGP_KEY_INIT:
+ /* Initialize our parsing state. */
+ if (! params)
+ return EINVAL; /* Need at least a way to return a result. */
+ bzero (params, sizeof *params);
+ break;
+
+ case 'A':
+ case 'a':
+ params->do_all = 1;
+ break;
+
+ case 'F':
+ params->fstab_path = arg;
+ break;
+
+ case 'S':
+ argz_create_sep (arg, ':',
+ &params->program_search_fmts,
+ &params->program_search_fmts_len);
+ break;
+
+ case 'R':
+ arg = "/";
+ /* FALLTHROUGH */
+ case 'X':
+ err = argz_add (&params->exclude, &params->exclude_len, arg);
+ if (err)
+ argp_failure (state, 100, ENOMEM, "%s", arg);
+ break;
+ case 't':
+ err = argz_add_sep (&params->types, &params->types_len, arg, ',');
+ if (err)
+ argp_failure (state, 100, ENOMEM, "%s", arg);
+ break;
+
+ case ARGP_KEY_ARG:
+ err = argz_add (&params->names, &params->names_len, arg);
+ if (err)
+ argp_failure (state, 100, ENOMEM, "%s", arg);
+ break;
+
+ case ARGP_KEY_END:
+ /* Check for bogus combinations of arguments. */
+ if (params->names)
+ {
+ if (params->do_all)
+ argp_error (state, "filesystem arguments not allowed with --all");
+ if (params->exclude)
+ argp_error (state,
+ "--exclude not allowed with filesystem arguments");
+ if (params->types)
+ argp_error (state,
+ "--fstype not allowed with filesystem arguments");
+ }
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+const struct argp fstab_argp = {options, parse_opt, 0, 0};
+
+struct fstab *
+fstab_argp_create (struct fstab_argp_params *params,
+ const char *default_search_fmts,
+ size_t default_search_fmts_len)
+{
+ error_t err;
+ struct fstab *fstab, *check;
+ struct fstypes *types;
+
+ if (params->fstab_path == 0)
+ params->fstab_path = _PATH_MNTTAB;
+ if (params->program_search_fmts == 0)
+ {
+ params->program_search_fmts = (char *) default_search_fmts;
+ params->program_search_fmts_len = default_search_fmts_len;
+ }
+
+ err = fstypes_create (params->program_search_fmts,
+ params->program_search_fmts_len,
+ &types);
+ if (err)
+ error (102, err, "fstypes_create");
+
+ err = fstab_create (types, &fstab);
+ if (err)
+ error (101, err, "fstab_create");
+
+ err = fstab_read (fstab, params->fstab_path);
+ if (err)
+ error (103, err, "%s", params->fstab_path);
+
+ if (params->names)
+ {
+ /* Process specified filesystems; also look at /var/run/mtab. */
+ const char *name;
+
+ err = fstab_read (fstab, _PATH_MOUNTED);
+ if (err && err != ENOENT)
+ error (104, err, "%s", _PATH_MOUNTED);
+
+ err = fstab_create (types, &check);
+ if (err)
+ error (105, err, "fstab_create");
+
+ for (name = params->names; name; name = argz_next (params->names,
+ params->names_len,
+ name))
+ {
+ struct fs *fs = fstab_find (fstab, name);
+ if (! fs)
+ error (106, 0, "%s: Unknown device or filesystem", name);
+ fstab_add_fs (check, fs, 0);
+ }
+
+ /* fstab_free (fstab); XXX */
+ }
+ else
+ {
+ /* Process everything in /etc/fstab. */
+
+ if (params->exclude == 0 && params->types == 0)
+ check = fstab;
+ else
+ {
+ struct fs *fs;
+ const char *tn;
+ unsigned int nonexclude_types;
+
+ err = fstab_create (types, &check);
+ if (err)
+ error (105, err, "fstab_create");
+
+ /* For each excluded type (i.e. `-t notype'), clobber the
+ fstype entry's program with an empty string to mark it. */
+ nonexclude_types = 0;
+ for (tn = params->types; tn;
+ tn = argz_next (params->types, params->types_len, tn))
+ {
+ if (!strncasecmp (tn, "no", 2))
+ {
+ struct fstype *type;
+ err = fstypes_get (types, &tn[2], &type);
+ if (err)
+ error (106, err, "fstypes_get");
+ free (type->program);
+ type->program = strdup ("");
+ }
+ else
+ ++nonexclude_types;
+ }
+
+ if (nonexclude_types != 0)
+ {
+ const char *tn;
+ struct fstypes *wanttypes;
+
+ /* We will copy the types we want to include into a fresh
+ list in WANTTYPES. Since we specify no search formats,
+ `fstypes_get' applied to WANTTYPES can only create
+ elements with a null `program' field. */
+ err = fstypes_create (0, 0, &wanttypes);
+ if (err)
+ error (102, err, "fstypes_create");
+
+ for (tn = params->types; tn;
+ tn = argz_next (params->types, params->types_len, tn))
+ if (strncasecmp (tn, "no", 2))
+ {
+ struct fstype *type;
+ err = fstypes_get (types, tn, &type);
+ if (err)
+ error (106, err, "fstypes_get");
+ if (type->program == 0)
+ error (0, 0,
+ "requested filesystem type `%s' unknown", tn);
+ else
+ {
+ struct fstype *newtype = malloc (sizeof *newtype);
+ newtype->name = strdup (type->name);
+ newtype->program = strdup (type->program);
+ newtype->next = wanttypes->entries;
+ wanttypes->entries = newtype;
+ }
+ }
+
+ /* fstypes_free (types); */
+ types = wanttypes;
+ }
+
+ for (fs = fstab->entries; fs; fs = fs->next)
+ {
+ const char *ptn;
+ struct fstype *type;
+
+ err = fs_type (fs, &type);
+ if (err || nonexclude_types)
+ {
+ err = fstypes_get (types, fs->mntent.mnt_type, &type);
+ if (err)
+ error (106, err, "fstypes_get");
+ if (params->types != 0)
+ continue;
+ }
+ if (nonexclude_types && type->program == 0)
+ continue; /* Freshly created, was not in WANTTYPES. */
+ if (type->program != 0 && type->program[0] == '\0')
+ continue; /* This type is marked as excluded. */
+
+ for (ptn = params->exclude; ptn;
+ ptn = argz_next (params->exclude, params->exclude_len, ptn))
+ if (fnmatch (ptn, fs->mntent.mnt_dir, 0) == 0)
+ break;
+ if (ptn) /* An exclude pattern matched. */
+ continue;
+
+ err = fstab_add_fs (check, fs, 0);
+ if (err)
+ error (107, err, "fstab_add_fs");
+ }
+
+ /* fstab_free (fstab); XXX */
+ }
+ }
+
+ return check;
+}
diff --git a/sutils/fstab.h b/sutils/fstab.h
index b8616185..ddd1656c 100644
--- a/sutils/fstab.h
+++ b/sutils/fstab.h
@@ -1,6 +1,6 @@
/* Fstab filesystem frobbing
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
@@ -28,7 +28,7 @@
struct fs
{
- struct fstab *fstab; /* Containg fstab. */
+ struct fstab *fstab; /* Containing fstab. */
struct mntent mntent; /* Mount entry from fstab file. */
char *storage; /* Storage for strings in MNTENT. */
struct fstype *type; /* Only set if fs_type called. */
@@ -70,20 +70,21 @@ error_t fstab_create (struct fstypes *types, struct fstab **fstab);
void fstab_free (struct fstab *fstab);
/* Return a new fstypes structure in TYPES. SEARCH_FMTS is copied. */
-error_t fstypes_create (char *search_fmts, size_t search_fmts_len,
+error_t fstypes_create (const char *search_fmts, size_t search_fmts_len,
struct fstypes **types);
/* Return an fstype entry in TYPES called NAME, in FSTYPE. If there is no
- existing entry, an attempt to find a fsck program with the given type,
- using the alternatives in the FSCK_SEARCH_FMTS field in TYPES. If
- one is found, it is added to TYPES, otherwise an new entry is created
- with a NULL PROGRAM field. */
-error_t fstypes_get (struct fstypes *types, char *name, struct fstype **fstype);
+ existing entry, an attempt to find a program with the given type,
+ using the alternatives in the PROGRAM_SEARCH_FMTS field in TYPES. If
+ one is found, it is added to TYPES, otherwise a new entry is created
+ with a null PROGRAM field. */
+error_t fstypes_get (struct fstypes *types,
+ const char *name, struct fstype **fstype);
/* Copy MNTENT into FS, copying component strings as well. */
-error_t fs_set_mntent (struct fs *fs, struct mntent *mntent);
+error_t fs_set_mntent (struct fs *fs, const struct mntent *mntent);
-/* Returns an fstype for FS in TYPE, trying to fillin FS's type field if
+/* Returns an fstype for FS in TYPE, trying to fill in FS's type field if
necessary. */
error_t fs_type (struct fs *fs, struct fstype **type);
@@ -106,7 +107,7 @@ error_t fs_readonly (struct fs *fs, int *readonly);
is not mounted at all, then nothing is done. */
error_t fs_set_readonly (struct fs *fs, int readonly);
-/* If FS is currently mounted tell lit to remount the device. XXX If FS is
+/* If FS is currently mounted tell it to remount the device. XXX If FS is
not mounted at all, then nothing is done. */
error_t fs_remount (struct fs *fs);
@@ -115,26 +116,27 @@ void fs_free (struct fs *fs);
/* Returns the FS entry in FSTAB with the device field NAME (there can only
be one such entry). */
-struct fs *fstab_find_device (struct fstab *fstab, char *name);
+struct fs *fstab_find_device (const struct fstab *fstab, const char *name);
/* Returns the FS entry in FSTAB with the mount point NAME (there can only
be one such entry). */
-struct fs *fstab_find_mount (struct fstab *fstab, char *name);
+struct fs *fstab_find_mount (const struct fstab *fstab, const char *name);
/* Returns the FS entry in FSTAB with the device or mount point NAME (there
can only be one such entry). */
-struct fs *fstab_find (struct fstab *fstab, char *name);
+struct fs *fstab_find (const struct fstab *fstab, const char *name);
/* Add an entry for MNTENT to FSTAB, removing any existing entries that
conflict (in either the device or mount point). If RESULT is non-zero, the
- new entry is returne in it. */
-error_t fstab_add_mntent (struct fstab *fstab, struct mntent *mntent,
+ new entry is returned in it. */
+error_t fstab_add_mntent (struct fstab *fstab, const struct mntent *mntent,
struct fs **result);
/* Copy the entry FS (which should belong to another fstab than DST) into
DST. If DST & SRC have different TYPES fields, EINVAL is returned. If
COPY is non-zero, the copy is returned in it. */
-error_t fstab_add_fs (struct fstab *dst, struct fs *fs, struct fs **copy);
+error_t fstab_add_fs (struct fstab *dst, const struct fs *fs,
+ struct fs **copy);
/* Merge SRC into DST, as if by calling fstab_add_fs on DST with every
entry in SRC, and then deallocating SRC. If DST & SRC have different
@@ -143,10 +145,34 @@ error_t fstab_merge (struct fstab *dst, struct fstab *src);
/* Reads fstab-format entries into FSTAB from the file NAME. Any entries
duplicating one already in FS_LIST supersede the existing entry. */
-error_t fstab_read (struct fstab *fstab, char *name);
+error_t fstab_read (struct fstab *fstab, const char *name);
/* Return the next pass number that applies to any filesystem in FSTAB that
is greater than PASS, or -1 if there isn't any. */
-int fstab_next_pass (struct fstab *fstab, int pass);
+int fstab_next_pass (const struct fstab *fstab, int pass);
+
+
+struct argp;
+extern const struct argp fstab_argp;
+struct fstab_argp_params
+{
+ char *fstab_path;
+ char *program_search_fmts;
+ size_t program_search_fmts_len;
+
+ int do_all;
+ char *types;
+ size_t types_len;
+ char *exclude;
+ size_t exclude_len;
+
+ char *names;
+ size_t names_len;
+};
+
+struct fstab *fstab_argp_create (struct fstab_argp_params *params,
+ const char *default_search_fmts,
+ size_t default_search_fmts_len);
+
#endif /* __FSTAB_H__ */
diff --git a/sutils/halt.c b/sutils/halt.c
index 2d9c1a18..08f754c4 100644
--- a/sutils/halt.c
+++ b/sutils/halt.c
@@ -1,5 +1,5 @@
/* Halt the system
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 1997, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell.
This file is part of the GNU Hurd.
@@ -22,11 +22,19 @@
#include <sys/reboot.h>
#include <unistd.h>
#include <stdio.h>
+#include <argp.h>
+#include <error.h>
+#include <hurd.h>
+#include <version.h>
+
+const char *argp_program_version = STANDARD_HURD_VERSION (halt);
int
-main (void)
+main (int argc, char *argv[])
{
+ struct argp argp = {0, 0, 0, "Halt the system"};
+ argp_parse (&argp, argc, argv, 0, 0, 0);
reboot (RB_HALT);
- perror ("reboot");
+ error (1, errno, "reboot");
return 1;
}
diff --git a/sutils/losetup.sh b/sutils/losetup.sh
new file mode 100644
index 00000000..85734571
--- /dev/null
+++ b/sutils/losetup.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# This script is roughly compatible with the Linux `losetup' utility.
+# The Hurd's `storeio' translator provides the equivalent functionality
+# (and a whole lot more), and of course works on any old file you want
+# to translate, not just magical "/dev/loopN" device files.
+#
+
+PATH=/bin
+
+usage() {
+ echo >&2 ...
+ exit 1
+}
+
+offset=0
+while [ $# -gt 0 ]; do
+ case "$arg" in
+ -d)
+ [ $# -eq 2 ] || usage
+ exec settrans -g -- "$2" /hurd/null
+ ;;
+ -e)
+ echo >&2 "$0: encryption not supported"
+ exit 3
+ ;;
+ -o)
+ [ $# -gt 1 ] || usage
+ offset="$1"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+[ $# -eq 2 ] || usage
+device="$1"
+file="$2"
+
+# If the device name is "/dev/loopN", then create it if necessary. (?)
+create=
+case "$device" in
+'/dev/loop[0-9]*') ;; # smarty pants
+/dev/loop[0-9]*) create=--create ;;
+esac
+
+type='-Tfile '
+if [ "$offset" != 0 ]; then
+ blksz=`storeinfo -B -- "$file"`
+ if [ $[ $offset % $blksz ] -ne 0 ]; then
+ echo >&2 "$0: offset $offset is not a multiple of device block size $blksz"
+ exit 1
+ fi
+ type="-Tremap $[ $offset / $blksz ]+:file:"
+fi
+
+exec settrans $create -gap -- "${device}" /hurd/storeio ${type}"${file}"
diff --git a/sutils/reboot.c b/sutils/reboot.c
index 7844ba06..54b9b99c 100644
--- a/sutils/reboot.c
+++ b/sutils/reboot.c
@@ -1,5 +1,5 @@
/* Reboot the system
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 1997, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell.
This file is part of the GNU Hurd.
@@ -22,15 +22,19 @@
#include <sys/reboot.h>
#include <unistd.h>
#include <stdio.h>
+#include <argp.h>
+#include <error.h>
+#include <hurd.h>
+#include <version.h>
+
+const char *argp_program_version = STANDARD_HURD_VERSION (reboot);
int
-main (void)
+main (int argc, char *argv[])
{
+ struct argp argp = {0, 0, 0, "Reboot the system"};
+ argp_parse (&argp, argc, argv, 0, 0, 0);
reboot (0);
- perror ("reboot");
+ error (1, errno, "reboot");
return 1;
}
-
-
-
-
diff --git a/sutils/swapoff.c b/sutils/swapoff.c
new file mode 100644
index 00000000..42521257
--- /dev/null
+++ b/sutils/swapoff.c
@@ -0,0 +1,2 @@
+#define SWAPOFF
+#include "swapon.c"
diff --git a/sutils/swapon.c b/sutils/swapon.c
new file mode 100644
index 00000000..c0c773bd
--- /dev/null
+++ b/sutils/swapon.c
@@ -0,0 +1,536 @@
+/* Add/remove paging devices
+
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2007
+ Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.org>
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <hurd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <argp.h>
+#include <error.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <hurd/store.h>
+#include <hurd/paths.h>
+#include <version.h>
+#include <mntent.h>
+#include "default_pager_U.h"
+
+#ifdef SWAPOFF
+const char *argp_program_version = STANDARD_HURD_VERSION (swapoff);
+#else
+const char *argp_program_version = STANDARD_HURD_VERSION (swapon);
+#endif
+
+static int ignore_signature, require_signature, quiet;
+
+static struct argp_option options[] =
+{
+ {"standard", 'a', 0, 0,
+ "Use all devices marked as `swap' in " _PATH_MNTTAB},
+ {"no-signature",'n', 0, 0,
+ "Do not check for a Linux swap signature page"},
+ {"require-signature", 's', 0, 0,
+ "Require a Linux swap signature page"},
+ {"silent", 'q', 0, 0, "Print only diagnostic messages"},
+ {"quiet", 'q', 0, OPTION_ALIAS | OPTION_HIDDEN },
+ {0, 0}
+};
+static char *args_doc = "DEVICE...";
+
+static char *doc =
+#ifdef SWAPOFF
+ "Stop paging on DEVICE..."
+ "\vUnless overridden, a swap space signature is not considered when deciding"
+ " whether to remove a paging device or not."
+#else
+ "Start paging onto DEVICE..."
+ "\vUnless overridden, only devices with a valid (Linux) swap space signature"
+ " are considered when deciding whether to add a paging device or not."
+#endif
+;
+
+#define verbose(fmt, arg...) \
+ if (quiet_now) ((void)0); else error (0, 0, fmt ,##arg)
+#define inform_2_0(fmt, arg...) \
+ verbose ("%s: Linux 2.0 swap signature, " fmt, name ,##arg)
+#define inform_2_2(fmt, arg...) \
+ verbose ("%s: Linux 2.2 swap signature v1, %zuk swap-space" fmt, \
+ name, freepages * (LINUX_PAGE_SIZE / 1024) ,##arg)
+
+
+/* Examine the store in *STOREP to see if it has a Linux-compatible
+ swap signature page as created by the Linux `mkswap' utility. If
+ we find such a signature, it indicates some subset of the store
+ that should actually be used for paging; return zero after
+ consuming *STOREP and replacing it by using store_remap to get just
+ the indicated subset (unless NO_REMAP is nonzero). If we get an
+ error reading the store, or find a signature but have some problem
+ with it, return some error code. If the store has no signature at
+ all, and if --require-signature was given, then that is an error.
+ This function prints diagnostics for all those errors. Otherwise
+ (the store has no signature) we return EFTYPE and print nothing. */
+
+static error_t
+check_signature (const char *name, struct store **storep, int no_remap,
+ int quiet_now)
+{
+ struct store *const store = *storep;
+
+#define LINUX_PAGE_SIZE 4096 /* size of pages in Linux swap partitions */
+#define LINUX_PAGE_SHIFT 12
+
+ /* RUNS points to latest run (highest value of start). Each time we
+ remove a bad page from the set, we either adjust the latest run or add
+ a new one and point RUNS at it. */
+
+ struct run
+ {
+ struct run *next;
+ size_t start, limit; /* in units of LINUX_PAGE_SIZE */
+ };
+
+ size_t freepages = store->size / LINUX_PAGE_SIZE;
+ struct run first_run = { NULL, 0, freepages }, *runs = &first_run;
+ size_t nruns = 1;
+ /* This is always called with increasing page numbers. */
+#define BAD_PAGE(pageno) \
+ ({ \
+ size_t page = (pageno); \
+ if (page == runs->start) \
+ runs->start = page + 1; \
+ else \
+ { \
+ runs->next = alloca (sizeof *runs); \
+ runs->next->start = page + 1; \
+ runs->next->limit = runs->limit; \
+ runs->limit = page; \
+ ++nruns; \
+ } \
+ })
+
+ /* Read the first page, which contains the signature. */
+ void *buf = 0;
+ size_t len = 0;
+ error_t err = store_read (store, 0, LINUX_PAGE_SIZE, &buf, &len);
+ if (err)
+ {
+ error (0, err, "%s: cannot read Linux swap signature page", name);
+ return err;
+ }
+ if (len < LINUX_PAGE_SIZE)
+ {
+ error (0, 0, "%s: short read %zu reading Linux swap signature page",
+ name, len);
+ return EINVAL;
+ }
+
+ quiet_now |= quiet;
+
+ /* Check for Linux 2.0 format. */
+ if (!memcmp ("SWAP-SPACE", buf + LINUX_PAGE_SIZE-10, 10))
+ {
+ /* The partition's first page has a Linux swap signature.
+ This means the beginning of the page contains a bitmap
+ of good pages, and all others are bad. */
+ size_t i, bad, max;
+ int waste;
+
+ /* The first page, and the pages corresponding to the bits
+ occupied by the signature in the final 10 bytes of the page,
+ are always unavailable ("bad"). */
+ *(uint32_t *) buf &= ~(u_int32_t) 1;
+ memset (buf + LINUX_PAGE_SIZE-10, 0, 10);
+
+ max = LINUX_PAGE_SIZE / sizeof (uint32_t);
+ if (max > (store->size + 31) / 32)
+ max = (store->size + 31) / 32;
+
+ /* Search the page for zero bits, which indicate unusable pages. */
+ bad = 0;
+ for (i = 0; i < max; ++i)
+ {
+ size_t p = i*32;
+ uint32_t bm = ~((uint32_t *) buf)[i];
+ while (bm != 0) /* inverted so unusable pages are one bits */
+ {
+ /* Find the first bit set in this word. */
+ int bit = ffs (bm);
+ bm >>= bit; /* Next time look at the rest of the word. */
+ p += bit - 1; /* Corresponding page. */
+ if (p >= runs->limit)
+ break;
+ ++bad;
+ BAD_PAGE (p);
+ }
+ }
+ freepages -= bad;
+
+ --bad; /* Don't complain about first page. */
+ waste = (store->size >> LINUX_PAGE_SHIFT) - (8 * (LINUX_PAGE_SIZE-10));
+
+ if (waste > 0)
+ {
+ /* The wasted pages were already marked "bad". */
+ bad -= waste;
+ if (bad > 0)
+ inform_2_0 ("%zdk swap-space (%zdk bad, %dk wasted at end)",
+ freepages * (LINUX_PAGE_SIZE / 1024),
+ bad * (LINUX_PAGE_SIZE / 1024),
+ waste * (LINUX_PAGE_SIZE / 1024));
+ else
+ inform_2_0 ("%zdk swap-space (%dk wasted at end)",
+ freepages * (LINUX_PAGE_SIZE / 1024),
+ waste * (LINUX_PAGE_SIZE / 1024));
+ }
+ else if (bad > 0)
+ inform_2_0 ("%zdk swap-space (excludes %zdk marked bad)",
+ freepages * (LINUX_PAGE_SIZE / 1024),
+ bad * (LINUX_PAGE_SIZE / 1024));
+ else
+ inform_2_0 ("%zdk swap-space", freepages * (LINUX_PAGE_SIZE / 1024));
+ }
+ /* Check for Linux 2.2 format. */
+ else if (!memcmp ("SWAPSPACE2", buf + LINUX_PAGE_SIZE-10, 10))
+ {
+ struct
+ {
+ u_int8_t bootbits[1024];
+ u_int32_t version;
+ u_int32_t last_page;
+ u_int32_t nr_badpages;
+ u_int32_t padding[125];
+ u_int32_t badpages[1];
+ } *hdr = buf;
+
+ ++first_run.start; /* first page unusable */
+ --freepages;
+
+ switch (hdr->version)
+ {
+ default:
+ error (0, 0,
+ "%s: Linux 2.2 swap signature with unknown version %u",
+ name, hdr->version);
+ munmap (buf, len);
+ if (require_signature)
+ {
+ error (0, 0, "%s: will not use without valid signature page",
+ name);
+ return EINVAL;
+ }
+ error (0, 0, "WARNING: ignoring unrecognized signature page");
+ return EFTYPE;
+
+ case 1:
+ {
+ unsigned int waste, i;
+ if (hdr->last_page >= first_run.limit)
+ {
+ error (0, 0,
+ "%s: signature says %uk, partition has only %uk!",
+ name,
+ hdr->last_page * (LINUX_PAGE_SIZE / 1024),
+ (unsigned int) (store->size / 1024));
+ waste = 0;
+ }
+ else
+ {
+ waste = first_run.limit + 1 - hdr->last_page;
+ freepages = first_run.limit - first_run.start;
+ first_run.limit = hdr->last_page + 1;
+ }
+ for (i = 0; i < hdr->nr_badpages; ++i)
+ {
+ BAD_PAGE (hdr->badpages[i]);
+ --freepages;
+ }
+
+ {
+ size_t badk = hdr->nr_badpages * (LINUX_PAGE_SIZE / 1024);
+ size_t wastek = waste * (LINUX_PAGE_SIZE / 1024);
+ if (badk && wastek)
+ inform_2_2 ("\
+ (excludes %zuk marked bad and %zuk at end of partition)",
+ badk, wastek);
+ else if (badk)
+ inform_2_2 (" (excludes %zuk marked bad)", badk);
+ else if (wastek)
+ inform_2_2 (" (excludes %zuk at end of partition)", wastek);
+ else
+ inform_2_2 ("");
+ }
+ }
+ }
+ }
+ /* There does not appear to be any signature page here. */
+ else if (require_signature)
+ {
+ error (0, 0, "%s: will not use without Linux swap signature", name);
+ return EINVAL;
+ }
+ else
+ /* We use this error code to tell our caller that we found nothing. */
+ return EFTYPE;
+
+ /* Now that we have collected the runs of LINUX_PAGE_SIZE we will use,
+ convert those into store_run's in the store's block size. */
+ {
+ const int scale = LINUX_PAGE_SHIFT - store->log2_block_size;
+ struct store_run store_runs[nruns];
+ size_t i = 0;
+ struct run *r = &first_run;
+ do
+ {
+ struct store_run *sr = &store_runs[i++];
+ sr->start = (store_offset_t) r->start << scale;
+ sr->length = (r->limit - r->start) << scale;
+ do
+ r = r->next;
+ while (r != 0 && r->start == r->limit); /* skip empty runs */
+ } while (r != 0);
+
+ /* Give us a new store that uses only the good pages. */
+ return store_remap (store, store_runs, i, storep);
+ }
+}
+
+
+/* Process a single argument file. */
+
+static int
+swaponoff (const char *file, int add)
+{
+ error_t err;
+ struct store *store;
+ static mach_port_t def_pager = MACH_PORT_NULL;
+ static mach_port_t dev_master = MACH_PORT_NULL;
+ static int old_protocol;
+ int quiet_now = 0;
+
+ try_again:
+ err = store_open (file, 0, 0, &store);
+ if (err)
+ {
+ error (0, err, "%s", file);
+ return err;
+ }
+
+ /* Let's see what we've got. */
+ if (old_protocol)
+ {
+ /* The default pager only lets us give a whole partition, and
+ it will read the signature page (but not insist on it). */
+ if (! (store->flags & STORE_ENFORCED))
+ {
+ error (0, 0, "%s: Can only page to the entire device", file);
+ return EINVAL;
+ }
+ /* If we want to require the signature, we can check that it is
+ actually there even though we won't be the one interpreting it. */
+ if (require_signature
+ && check_signature (file, &store, 1, quiet_now) != 0)
+ return EINVAL;
+ }
+ else if (ignore_signature)
+ verbose ("%s: %uk swap space",
+ file, (unsigned int) (store->size / 1024));
+ else
+ {
+ /* Adjust the store according to the Linux signature. */
+ err = check_signature (file, &store, 0, 0);
+ if (err == EFTYPE)
+ verbose ("%s: %uk swap space (no Linux signature page)",
+ file, (unsigned int) (store->size / 1024));
+ else if (err)
+ {
+ store_free (store);
+ return err;
+ }
+ /* Otherwise check_signature printed something out. */
+ }
+
+ if (store->class != &store_device_class)
+ {
+ error (0, 0, "%s: Can't get underlying device", file);
+ store_free (store);
+ return EINVAL;
+ }
+
+ if (def_pager == MACH_PORT_NULL)
+ {
+ mach_port_t host;
+
+ err = get_privileged_ports (&host, &dev_master);
+ if (err == EPERM)
+ {
+ /* We are not root, so try opening the /servers node. */
+ def_pager = file_name_lookup (_SERVERS_DEFPAGER, O_WRITE, 0);
+ if (def_pager == MACH_PORT_NULL)
+ {
+ error (11, errno, _SERVERS_DEFPAGER);
+ return 0;
+ }
+ }
+ else
+ {
+ if (err)
+ error (12, err, "Cannot get privileged ports");
+
+ err = vm_set_default_memory_manager (host, &def_pager);
+ mach_port_deallocate (mach_task_self (), host);
+ if (err)
+ error (13, err, "Cannot get default pager port");
+ if (def_pager == MACH_PORT_NULL)
+ error (14, 0, "No default pager (memory manager) is running!");
+ }
+ }
+
+ if (old_protocol)
+ {
+ /* The default pager does not support the new protocol.
+ We tried it in a previous call (below) and got MIG_BAD_ID. */
+ char pname[sizeof "/dev/" + strlen (store->name) + 1];
+ strcpy (stpcpy (pname, "/dev/"), store->name);
+ err = default_pager_paging_file (def_pager, dev_master, pname, add);
+ }
+ else
+ {
+ /* Try the new protocol, which will take our list of runs. */
+ recnum_t runs[store->num_runs * 2];
+ size_t i, j;
+ for (i = j = 0; i < store->num_runs; ++i)
+ {
+ runs[j++] = store->runs[i].start;
+ runs[j++] = store->runs[i].length;
+ }
+ err = default_pager_paging_storage (def_pager, store->port,
+ runs, j, store->name, add);
+ if (err == MIG_BAD_ID)
+ {
+ /* The default pager does not support the new protocol.
+ We'll do the whole thing over again, since we have
+ different requirements now. */
+ old_protocol = 1;
+ store_free (store);
+ if (! ignore_signature)
+ error (0, 0, "\
+default pager uses old protocol, does its own signature checking");
+ quiet_now = 1;
+ goto try_again;
+ }
+ }
+
+ store_free (store);
+
+ if (err)
+ error (0, err, "%s", file);
+
+ return err;
+}
+
+#undef inform_2_0
+#undef inform_2_2
+#undef verbose
+
+static int do_all;
+
+int
+main (int argc, char *argv[])
+{
+ /* Parse our options... */
+ error_t parse_opt (int key, char *arg, struct argp_state *state)
+ {
+ switch (key)
+ {
+ case 'a':
+ do_all = 1;
+ break;
+
+ case 'n':
+ ignore_signature = 1;
+ break;
+
+ case 's':
+ require_signature = 1;
+ ignore_signature = 0;
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ case ARGP_KEY_ARG:
+#ifdef SWAPOFF
+#define ONOFF 0
+#else
+#define ONOFF 1
+#endif
+ swaponoff (arg, ONOFF);
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+ }
+ struct argp argp = {options, parse_opt, args_doc, doc};
+
+ /* See the documentation string DOC. */
+#ifdef SWAPOFF
+ ignore_signature = 1;
+ require_signature = 0;
+#else
+ ignore_signature = 0;
+ require_signature = 1;
+#endif
+
+ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
+
+ if (do_all)
+ {
+ struct mntent *me;
+ FILE *f;
+
+ f = setmntent (_PATH_MNTTAB, "r");
+ if (f == NULL)
+ error (1, errno, "Cannot read %s", _PATH_MNTTAB);
+ else
+ {
+ int done = 0, err = 0;
+ while ((me = getmntent (f)) != NULL)
+ if (!strcmp (me->mnt_type, MNTTYPE_SWAP))
+ {
+ done = 1;
+
+ err |= swaponoff (me->mnt_fsname, ONOFF);
+ }
+ if (done == 0)
+ error (2, 0, "No swap partitions found in %s", _PATH_MNTTAB);
+ else if (err)
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/sutils/update.c b/sutils/update.c
index 0342824f..c1f4e982 100644
--- a/sutils/update.c
+++ b/sutils/update.c
@@ -1,5 +1,5 @@
/* Periodically call sync.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2002 Free Software Foundation, Inc.
Written by Michael I. Bushnell.
This file is part of the GNU Hurd.
@@ -41,10 +41,7 @@ main (int argc, char **argv)
}
if (daemon (0, 0))
- {
- perror ("daemon");
- exit (1);
- }
+ error (1, errno, "daemon");
for (;;)
{