summaryrefslogtreecommitdiff
path: root/sbin/swapctl
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/swapctl')
-rw-r--r--sbin/swapctl/Makefile10
-rw-r--r--sbin/swapctl/swapctl.8224
-rw-r--r--sbin/swapctl/swapctl.c451
-rw-r--r--sbin/swapctl/swapctl.h32
-rw-r--r--sbin/swapctl/swaplist.c137
5 files changed, 854 insertions, 0 deletions
diff --git a/sbin/swapctl/Makefile b/sbin/swapctl/Makefile
new file mode 100644
index 00000000000..81fde35ae61
--- /dev/null
+++ b/sbin/swapctl/Makefile
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile,v 1.2 1997/06/12 16:18:50 mrg Exp $
+
+PROG= swapctl
+SRCS= swapctl.c swaplist.c
+MAN= swapctl.8
+
+LINKS= ${BINDIR}/swapctl ${BINDIR}/swapon
+MLINKS= swapctl.8 swapon.8
+
+.include <bsd.prog.mk>
diff --git a/sbin/swapctl/swapctl.8 b/sbin/swapctl/swapctl.8
new file mode 100644
index 00000000000..af8e7561789
--- /dev/null
+++ b/sbin/swapctl/swapctl.8
@@ -0,0 +1,224 @@
+.\" $NetBSD: swapctl.8,v 1.14 1998/05/22 18:27:52 msaitoh Exp $
+.\"
+.\" Copyright (c) 1997 Matthew R. Green
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd June 12, 1997
+.Dt SWAPCTL 8
+.Os NetBSD
+.Sh NAME
+.Nm swapctl ,
+.Nm swapon
+.Nd system swap management tool
+.Sh SYNOPSIS
+.Nm
+.Fl A
+.Op Fl p Ar priority
+.Op Fl t Ar blk|noblk
+.Nm ""
+.Fl a
+.Op Fl p Ar priority
+.Ar path
+.Nm ""
+.Fl c
+.Fl p Ar priority
+.Ar path
+.Nm ""
+.Fl d
+.Ar path
+.Nm ""
+.Fl l | Fl s
+.Op Fl k
+.Nm swapon
+.Fl a | Ar path
+.Nm swapoff
+.Ar path
+.Sh DESCRIPTION
+The
+.Nm
+program adds, removes,
+lists and prioritizes swap devices and files for the system.
+The
+.Nm swapon
+program acts the same as the
+.Nm
+program, as if called with the
+.Fl a
+option, except if
+.Nm swapon
+itself is called with
+.Fl a
+in which case,
+.Nm swapon
+acts as
+.Nm
+with the
+.Fl A
+option.
+.Sh OPTIONS
+The following options are available:
+.Bl -tag -width 123456
+.It Fl A
+This option causes
+.Nm
+to read the
+.Pa /etc/fstab
+file for devices and files with a ``sw'' type, and adds all these entries
+as swap devices. If no swap devices are configured,
+.Nm
+will exit with an error code.
+.It Fl a
+The
+.Fl a
+option requires that a
+.Ar path
+also be in the argument list. The
+.Ar path
+is added to the kernel's list of swap devices using the
+.Xr swapctl 2
+system call. When using the
+.Nm swapon
+form of this command, the
+.Fl a
+option is treated the same as the
+.Fl A
+option, for backwards compatibility.
+.It Fl c
+The
+.Fl c
+option changes the priority of the listed swap device or file.
+.It Fl d
+The
+.Fl d
+option removes the listed
+.Ar path
+from the kernel's list of swap devices or files.
+.It Fl l
+The
+.Fl l
+option lists the current swap devices and files, and their usage statistics.
+.It Fl s
+The
+.Fl s
+option displays a single line summary of current swap statistics.
+.It Fl p
+The
+.Fl p
+option sets the priority of swap devices or files to the
+.Ar priority
+argument. This works with the
+.\" .Fl d ,
+.Fl a ,
+.Fl c
+and
+.Fl l
+options.
+.It Fl k
+The
+.Fl k
+option uses 1024 byte blocks instead of the default 512 byte.
+.It Fl t
+This flag modifies the function of the
+.Fl A
+option.
+The
+.Fl t
+option allows the type of device to add to be specified. An argument of
+.Ar blk
+causes all block devices in
+.Pa /etc/fstab
+to be added. An argument of
+.Ar noblk
+causes all non-block devices in
+.Pa /etc/fstab
+to be added. This option is useful in early system startup, where swapping
+may be needed before all file systems are available, such as during
+disk checks of large file systems.
+.El
+.Sh SWAP OPTIONS
+When parsing the
+.Pa /etc/fstab
+file for swap devices, the following options are recognized:
+.Pp
+.Bl -tag -width nfsmntpt=/path -compact
+.It priority=N
+This option sets the priority of the specified swap device to N. The
+highest priority is 0, second priority is 1, etc.
+.It nfsmntpt=/path
+This option is useful for swapping to NFS files. It specifies
+the local mount point to mount an NFS filesystem. Typically, once
+this mount has succeeded, the file to be used for swapping on will
+be available under this point mount. For example:
+.Bd -literal
+server:/export/swap/client none swap sw,nfsmntpt=/swap
+.Ed
+.El
+.Sh WARNINGS
+If no swap information is specified in
+.Pa /etc/fstab ,
+the system startup scripts (see
+.Xr rc 8 )
+will configure no swap space and your machine will behave very badly
+if (more likely when) it runs out of real memory.
+.Pp
+Local and remote swap files cannot be configured until after the file
+systems they reside on are mounted read/write. The system startup
+scripts need to
+.Xr fsck 8
+all local file systems before this can happen. This process requires
+substantial amounts of memory on some systems. If you configure no
+local block swap devices on a machine that has local file systems to
+check and rely only on swap files, the machine will have no swap space
+at all during system
+.Xr fsck 8
+and may run out of real memory, causing fsck to abnormally exit and
+startup scripts to fail.
+.Sh HISTORY
+The
+.Nm
+program was first made available in
+.Nx 1.3 .
+The original
+.Nm swapon
+program, provided for backwards compatibility, appeared in
+.Bx 4.0 .
+.Sh AUTHOR
+The
+.Nm
+program was written by Matthew R. Green <mrg@eterna.com.au>.
+.Sh BUGS
+The
+.Nm swapoff
+command and the
+.Fl d
+option of
+.Nm
+are not currently supported by
+.Nx .
+.Sh SEE ALSO
+.Xr swapctl 2 ,
+.Xr fstab 5 ,
+.Xr mount_nfs 8
diff --git a/sbin/swapctl/swapctl.c b/sbin/swapctl/swapctl.c
new file mode 100644
index 00000000000..6494137ec7b
--- /dev/null
+++ b/sbin/swapctl/swapctl.c
@@ -0,0 +1,451 @@
+/* $NetBSD: swapctl.c,v 1.9 1998/07/26 20:23:15 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1996, 1997 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * swapctl command:
+ * -A add all devices listed as `sw' in /etc/fstab
+ * -t [blk|noblk] if -A, add either all block device or all non-block
+ * devices
+ * -a <dev> add this device
+ * -d <dev> remove this swap device (not supported yet)
+ * -l list swap devices
+ * -s short listing of swap devices
+ * -k use kilobytes
+ * -p <pri> use this priority
+ * -c change priority
+ *
+ * or, if invoked as "swapon" (compatibility mode):
+ *
+ * -a all devices listed as `sw' in /etc/fstab
+ * -t same as -t above (feature not present in old
+ * swapon(8) command)
+ * <dev> add this device
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <sys/swap.h>
+
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fstab.h>
+
+#include "swapctl.h"
+
+int command;
+
+/*
+ * Commands for swapctl(8). These are mutually exclusive.
+ */
+#define CMD_A 0x01 /* process /etc/fstab */
+#define CMD_a 0x02 /* add a swap file/device */
+#define CMD_c 0x04 /* change priority of a swap file/device */
+#define CMD_d 0x08 /* delete a swap file/device */
+#define CMD_l 0x10 /* list swap files/devices */
+#define CMD_s 0x20 /* summary of swap files/devices */
+
+#define SET_COMMAND(cmd) \
+do { \
+ if (command) \
+ usage(); \
+ command = (cmd); \
+} while (0)
+
+/*
+ * Commands that require a "path" argument at the end of the command
+ * line, and the ones which require that none exist.
+ */
+#define REQUIRE_PATH (CMD_a | CMD_c | CMD_d)
+#define REQUIRE_NOPATH (CMD_A | CMD_l | CMD_s)
+
+/*
+ * Option flags, and the commands with which they are valid.
+ */
+int kflag; /* display in 1K blocks */
+#define KFLAG_CMDS (CMD_l | CMD_s)
+
+int pflag; /* priority was specified */
+#define PFLAG_CMDS (CMD_A | CMD_a | CMD_c)
+
+char *tflag; /* swap device type (blk or noblk) */
+#define TFLAG_CMDS (CMD_A)
+
+int pri; /* uses 0 as default pri */
+
+static void change_priority __P((char *));
+static void add_swap __P((char *));
+static void del_swap __P((char *));
+ int main __P((int, char *[]));
+static void do_fstab __P((void));
+static void usage __P((void));
+static void swapon_command __P((int, char **));
+#if 0
+static void swapoff_command __P((int, char **));
+#endif
+
+extern char *__progname; /* from crt0.o */
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int c;
+
+ if (strcmp(__progname, "swapon") == 0) {
+ swapon_command(argc, argv);
+ /* NOTREACHED */
+ }
+
+#if 0
+ if (strcmp(__progname, "swapoff") == 0) {
+ swapoff_command(argc, argv);
+ /* NOTREACHED */
+ }
+#endif
+
+ while ((c = getopt(argc, argv, "Aacdlkp:st:")) != -1) {
+ switch (c) {
+ case 'A':
+ SET_COMMAND(CMD_A);
+ break;
+
+ case 'a':
+ SET_COMMAND(CMD_a);
+ break;
+
+ case 'c':
+ SET_COMMAND(CMD_c);
+ break;
+
+ case 'd':
+ SET_COMMAND(CMD_d);
+ break;
+
+ case 'l':
+ SET_COMMAND(CMD_l);
+ break;
+
+ case 'k':
+ kflag = 1;
+ break;
+
+ case 'p':
+ pflag = 1;
+ /* XXX strtol() */
+ pri = atoi(optarg);
+ break;
+
+ case 's':
+ SET_COMMAND(CMD_s);
+ break;
+
+ case 't':
+ if (tflag != NULL)
+ usage();
+ tflag = optarg;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ /* Did the user specify a command? */
+ if (command == 0)
+ usage();
+
+ argv += optind;
+ argc -= optind;
+
+ switch (argc) {
+ case 0:
+ if (command & REQUIRE_PATH)
+ usage();
+ break;
+
+ case 1:
+ if (command & REQUIRE_NOPATH)
+ usage();
+ break;
+
+ default:
+ usage();
+ }
+
+ /* To change priority, you have to specify one. */
+ if ((command == CMD_c) && pflag == 0)
+ usage();
+
+ /* Sanity-check -t */
+ if (tflag != NULL) {
+ if (command != CMD_A)
+ usage();
+ if (strcmp(tflag, "blk") != 0 &&
+ strcmp(tflag, "noblk") != 0)
+ usage();
+ }
+
+ /* Dispatch the command. */
+ switch (command) {
+ case CMD_l:
+ list_swap(pri, kflag, pflag, 0, 1);
+ break;
+
+ case CMD_s:
+ list_swap(pri, kflag, pflag, 0, 0);
+ break;
+
+ case CMD_c:
+ change_priority(argv[0]);
+ break;
+
+ case CMD_a:
+ add_swap(argv[0]);
+ break;
+
+ case CMD_d:
+ del_swap(argv[0]);
+ break;
+
+ case CMD_A:
+ do_fstab();
+ break;
+ }
+
+ exit(0);
+}
+
+/*
+ * swapon_command: emulate the old swapon(8) program.
+ */
+void
+swapon_command(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ch, fiztab = 0;
+
+ while ((ch = getopt(argc, argv, "at:")) != -1) {
+ switch (ch) {
+ case 'a':
+ fiztab = 1;
+ break;
+ case 't':
+ if (tflag != NULL)
+ usage();
+ tflag = optarg;
+ break;
+ default:
+ goto swapon_usage;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (fiztab) {
+ if (argc)
+ goto swapon_usage;
+ /* Sanity-check -t */
+ if (tflag != NULL) {
+ if (strcmp(tflag, "blk") != 0 &&
+ strcmp(tflag, "noblk") != 0)
+ usage();
+ }
+ do_fstab();
+ exit(0);
+ } else if (argc == 0 || tflag != NULL)
+ goto swapon_usage;
+
+ while (argc) {
+ add_swap(argv[0]);
+ argc--;
+ argv++;
+ }
+ exit(0);
+ /* NOTREACHED */
+
+ swapon_usage:
+ fprintf(stderr, "usage: %s -a [-t blk|noblk]\n", __progname);
+ fprintf(stderr, " %s <path> ...\n", __progname);
+ exit(1);
+}
+
+/*
+ * change_priority: change the priority of a swap device.
+ */
+void
+change_priority(path)
+ char *path;
+{
+
+ if (swapctl(SWAP_CTL, path, pri) < 0)
+ warn("%s", path);
+}
+
+/*
+ * add_swap: add the pathname to the list of swap devices.
+ */
+void
+add_swap(path)
+ char *path;
+{
+
+ if (swapctl(SWAP_ON, path, pri) < 0)
+ err(1, "%s", path);
+}
+
+/*
+ * del_swap: remove the pathname to the list of swap devices.
+ */
+void
+del_swap(path)
+ char *path;
+{
+
+ if (swapctl(SWAP_OFF, path, pri) < 0)
+ err(1, "%s", path);
+}
+
+void
+do_fstab()
+{
+ struct fstab *fp;
+ char *s;
+ long priority;
+ struct stat st;
+ int isblk;
+ int gotone = 0;
+
+#define PRIORITYEQ "priority="
+#define NFSMNTPT "nfsmntpt="
+#define PATH_MOUNT "/sbin/mount_nfs"
+ while ((fp = getfsent()) != NULL) {
+ const char *spec;
+
+ if (strcmp(fp->fs_type, "sw") != 0)
+ continue;
+
+ spec = fp->fs_spec;
+ isblk = 0;
+
+ if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) {
+ s += sizeof(PRIORITYEQ) - 1;
+ priority = atol(s);
+ } else
+ priority = pri;
+
+ if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) {
+ char *t, cmd[2*PATH_MAX+sizeof(PATH_MOUNT)+2];
+
+ /*
+ * Skip this song and dance if we're only
+ * doing block devices.
+ */
+ if (tflag != NULL &&
+ strcmp(tflag, "blk") == 0)
+ continue;
+
+ t = strpbrk(s, ",");
+ if (t != 0)
+ *t = '\0';
+ spec = strdup(s + strlen(NFSMNTPT));
+ if (t != 0)
+ *t = ',';
+
+ if (spec == NULL)
+ errx(1, "Out of memory");
+
+ if (strlen(spec) == 0) {
+ warnx("empty mountpoint");
+ free((char *)spec);
+ continue;
+ }
+ snprintf(cmd, sizeof(cmd), "%s %s %s",
+ PATH_MOUNT, fp->fs_spec, spec);
+ if (system(cmd) != 0) {
+ warnx("%s: mount failed", fp->fs_spec);
+ continue;
+ }
+ } else {
+ /*
+ * Determine blk-ness.
+ */
+ if (stat(spec, &st) < 0) {
+ warn(spec);
+ continue;
+ }
+ if (S_ISBLK(st.st_mode))
+ isblk = 1;
+ }
+
+ /*
+ * Skip this type if we're told to.
+ */
+ if (tflag != NULL) {
+ if (strcmp(tflag, "blk") == 0 && isblk == 0)
+ continue;
+ if (strcmp(tflag, "noblk") == 0 && isblk == 1)
+ continue;
+ }
+
+ if (swapctl(SWAP_ON, spec, (int)priority) < 0)
+ warn("%s", spec);
+ else {
+ gotone = 1;
+ printf("%s: adding %s as swap device at priority %d\n",
+ __progname, fp->fs_spec, (int)priority);
+ }
+
+ if (spec != fp->fs_spec)
+ free((char *)spec);
+ }
+ if (gotone == 0)
+ exit(1);
+}
+
+void
+usage()
+{
+
+ fprintf(stderr, "usage: %s -A [-p priority] [-t blk|noblk]\n",
+ __progname);
+ fprintf(stderr, " %s -a [-p priority] path\n", __progname);
+ fprintf(stderr, " %s -c -p priority path\n", __progname);
+ fprintf(stderr, " %s -d path\n", __progname);
+ fprintf(stderr, " %s -l | -s [-k]\n", __progname);
+ exit(1);
+}
diff --git a/sbin/swapctl/swapctl.h b/sbin/swapctl/swapctl.h
new file mode 100644
index 00000000000..0e25838234f
--- /dev/null
+++ b/sbin/swapctl/swapctl.h
@@ -0,0 +1,32 @@
+/* $NetBSD: swapctl.h,v 1.2 1997/10/10 05:39:54 mrg Exp $ */
+
+/*
+ * Copyright (c) 1997 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* pri, kflag, pflag, tflag, dolong (1 for long, 0 for short) */
+void list_swap __P((int, int, int, int, int));
diff --git a/sbin/swapctl/swaplist.c b/sbin/swapctl/swaplist.c
new file mode 100644
index 00000000000..29e37c2daee
--- /dev/null
+++ b/sbin/swapctl/swaplist.c
@@ -0,0 +1,137 @@
+/* $NetBSD: swaplist.c,v 1.8 1998/10/08 10:00:31 mrg Exp $ */
+
+/*
+ * Copyright (c) 1997 Matthew R. Green
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/swap.h>
+
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#define dbtoqb(b) dbtob((int64_t)(b))
+
+/*
+ * NOTE: This file is separate from swapctl.c so that pstat can grab it.
+ */
+
+#include "swapctl.h"
+
+void
+list_swap(pri, kflag, pflag, tflag, dolong)
+ int pri;
+ int kflag;
+ int pflag;
+ int tflag;
+ int dolong;
+{
+ struct swapent *sep, *fsep;
+ long blocksize;
+ char *header;
+ size_t l;
+ int hlen, totalsize, size, totalinuse, inuse, ncounted, pathmax;
+ int rnswap, nswap = swapctl(SWAP_NSWAP, 0, 0), i;
+
+ if (nswap < 1) {
+ puts("no swap devices configured");
+ exit(0);
+ }
+
+ fsep = sep = (struct swapent *)malloc(nswap * sizeof(*sep));
+ if (sep == NULL)
+ err(1, "malloc");
+ rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
+ if (rnswap < 0)
+ err(1, "SWAP_STATS");
+ if (nswap != rnswap)
+ warnx("SWAP_STATS different to SWAP_NSWAP (%d != %d)",
+ rnswap, nswap);
+
+ pathmax = 11;
+ if (dolong && tflag == 0) {
+ if (kflag) {
+ header = "1K-blocks";
+ blocksize = 1024;
+ hlen = strlen(header);
+ } else
+ header = getbsize(&hlen, &blocksize);
+ for (i = rnswap; i-- > 0; sep++)
+ if (pathmax < (l = strlen(sep->se_path)))
+ pathmax = l;
+ sep = fsep;
+ (void)printf("%-*s %*s %8s %8s %8s %s\n",
+ pathmax, "Device", hlen, header,
+ "Used", "Avail", "Capacity", "Priority");
+ }
+ totalsize = totalinuse = ncounted = 0;
+ for (; rnswap-- > 0; sep++) {
+ if (pflag && sep->se_priority != pri)
+ continue;
+ ncounted++;
+ size = sep->se_nblks;
+ inuse = sep->se_inuse;
+ totalsize += size;
+ totalinuse += inuse;
+
+ if (dolong && tflag == 0) {
+ (void)printf("%-*s %*ld ", pathmax, sep->se_path, hlen,
+ (long)(dbtoqb(size) / blocksize));
+
+ (void)printf("%8ld %8ld %5.0f%% %d\n",
+ (long)(dbtoqb(inuse) / blocksize),
+ (long)(dbtoqb(size - inuse) / blocksize),
+ (double)inuse / (double)size * 100.0,
+ sep->se_priority);
+ }
+ }
+ if (tflag)
+ (void)printf("%dM/%dM swap space\n",
+ (int)(dbtoqb(totalinuse) / (1024 * 1024)),
+ (int)(dbtoqb(totalsize) / (1024 * 1024)));
+ else if (dolong == 0)
+ printf("total: %ldk bytes allocated = %ldk used,"
+ "%ldk available\n",
+ (long)(dbtoqb(totalsize) / 1024),
+ (long)(dbtoqb(totalinuse) / 1024),
+ (long)(dbtoqb(totalsize - totalinuse) / 1024));
+ else if (ncounted > 1)
+ (void)printf("%-*s %*ld %8ld %8ld %5.0f%%\n", pathmax, "Total",
+ hlen,
+ (long)(dbtoqb(totalsize) / blocksize),
+ (long)(dbtoqb(totalinuse) / blocksize),
+ (long)(dbtoqb(totalsize - totalinuse) / blocksize),
+ (double)(totalinuse) / (double)totalsize * 100.0);
+ if (fsep)
+ (void)free(fsep);
+}