diff options
Diffstat (limited to 'sutils')
-rw-r--r-- | sutils/ChangeLog | 60 | ||||
-rw-r--r-- | sutils/MAKEDEV.sh | 204 | ||||
-rw-r--r-- | sutils/Makefile | 30 | ||||
-rw-r--r-- | sutils/clookup.c | 24 | ||||
-rwxr-xr-x | sutils/e2os.sh | 153 | ||||
-rw-r--r-- | sutils/fsck.c | 174 | ||||
-rw-r--r-- | sutils/fstab.c | 479 | ||||
-rw-r--r-- | sutils/fstab.h | 64 | ||||
-rw-r--r-- | sutils/halt.c | 14 | ||||
-rw-r--r-- | sutils/losetup.sh | 66 | ||||
-rw-r--r-- | sutils/reboot.c | 18 | ||||
-rw-r--r-- | sutils/swapoff.c | 2 | ||||
-rw-r--r-- | sutils/swapon.c | 536 | ||||
-rw-r--r-- | sutils/update.c | 7 |
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, ':', + ¶ms->program_search_fmts, + ¶ms->program_search_fmts_len); + break; + + case 'R': + arg = "/"; + /* FALLTHROUGH */ + case 'X': + err = argz_add (¶ms->exclude, ¶ms->exclude_len, arg); + if (err) + argp_failure (state, 100, ENOMEM, "%s", arg); + break; + case 't': + err = argz_add_sep (¶ms->types, ¶ms->types_len, arg, ','); + if (err) + argp_failure (state, 100, ENOMEM, "%s", arg); + break; + + case ARGP_KEY_ARG: + err = argz_add (¶ms->names, ¶ms->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 (;;) { |