summaryrefslogtreecommitdiff
path: root/usr/src/cmd/swap
diff options
context:
space:
mode:
authorpetede <none@none>2006-05-15 10:32:03 -0700
committerpetede <none@none>2006-05-15 10:32:03 -0700
commit56f10d37c1fa50cc562c3a4c2633af1ccef2aaa4 (patch)
tree6598c81637ae615efe9e2ff1bf32e36a9b1c2bdf /usr/src/cmd/swap
parent044802ffd0b6258ef2221463b41121e8df53782f (diff)
downloadillumos-joyent-56f10d37c1fa50cc562c3a4c2633af1ccef2aaa4.tar.gz
PSARC 2006/179 swap(1m) humanisation
5064163 *swap* should have -h option like df, du, and ls Contributed by Yann Poupet <yann.poupet@free.fr>
Diffstat (limited to 'usr/src/cmd/swap')
-rw-r--r--usr/src/cmd/swap/swap.c199
1 files changed, 169 insertions, 30 deletions
diff --git a/usr/src/cmd/swap/swap.c b/usr/src/cmd/swap/swap.c
index 4a53a1a14f..192f25bd15 100644
--- a/usr/src/cmd/swap/swap.c
+++ b/usr/src/cmd/swap/swap.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,15 +70,23 @@
#define SFLAG 0x08 /* swap -s (swap info summary) */
#define P1FLAG 0x10 /* swap -1 (swapadd pass1; do not modify dump device) */
#define P2FLAG 0x20 /* swap -2 (swapadd pass2; do not modify dump device) */
+#define HFLAG 0x40 /* swap -h (size in human readable format) */
+#define KFLAG 0x80 /* swap -k (size in kilobytes) */
+
+#define NUMBER_WIDTH 64
+typedef char numbuf_t[NUMBER_WIDTH];
static char *prognamep;
static int add(char *, off_t, off_t, int);
static int delete(char *, off_t);
static void usage(void);
-static int doswap(void);
+static int doswap(int flag);
static int valid(char *, off_t, off_t);
-static int list(void);
+static int list(int flag);
+static char *number_to_scaled_string(numbuf_t buf, unsigned long long number,
+ unsigned long long unit_from, unsigned long long scale);
+
int
main(int argc, char **argv)
@@ -105,24 +112,14 @@ main(int argc, char **argv)
exit(1);
}
- while ((c = getopt(argc, argv, "lsd:a:12")) != EOF) {
+ while ((c = getopt(argc, argv, "khlsd:a:12")) != EOF) {
char *char_p;
switch (c) {
case 'l': /* list all the swap devices */
- if (argc != 2 || flag) {
- usage();
- exit(1);
- }
flag |= LFLAG;
- ret = list();
break;
case 's':
- if (argc != 2 || flag) {
- usage();
- exit(1);
- }
flag |= SFLAG;
- ret = doswap();
break;
case 'd':
/*
@@ -189,6 +186,13 @@ main(int argc, char **argv)
}
}
break;
+ case 'h':
+ flag |= HFLAG;
+ break;
+
+ case 'k':
+ flag |= KFLAG;
+ break;
case '1':
flag |= P1FLAG;
@@ -203,6 +207,28 @@ main(int argc, char **argv)
exit(1);
}
}
+
+ if (flag & SFLAG) {
+ if (flag & ~SFLAG & ~HFLAG) {
+ /*
+ * The only option that can be used with -s is -h.
+ */
+ usage();
+ exit(1);
+ }
+
+ ret = doswap(flag);
+
+ }
+
+ if (flag & LFLAG) {
+ if (flag & ~KFLAG & ~HFLAG & ~LFLAG) {
+ usage();
+ exit(1);
+ }
+ ret = list(flag);
+ }
+
/*
* do the add here. Check for in use prior to add.
* The values for length and offset are set above.
@@ -229,7 +255,8 @@ main(int argc, char **argv)
ret = add(pathname, s_offset, length, flag);
}
}
- if (!flag) {
+ if (!(flag & ~HFLAG & ~KFLAG)) {
+ /* only -h and/or -k flag, or no flag */
usage();
exit(1);
}
@@ -241,11 +268,18 @@ static void
usage(void)
{
(void) fprintf(stderr, gettext("Usage:\t%s -l\n"), prognamep);
+ (void) fprintf(stderr, gettext("\tsub option :\n"));
+ (void) fprintf(stderr, gettext("\t\t-h : displays size in human "
+ "readable format\n"));
+ (void) fprintf(stderr, gettext("\t\t-k : displays size in KB\n"));
(void) fprintf(stderr, "\t%s -s\n", prognamep);
+ (void) fprintf(stderr, gettext("\tsub option :\n"));
+ (void) fprintf(stderr, gettext("\t\t-h : displays size in human "
+ "readable format rather than KB\n"));
(void) fprintf(stderr, gettext("\t%s -d <file name> [low block]\n"),
- prognamep);
+ prognamep);
(void) fprintf(stderr, gettext("\t%s -a <file name> [low block]"
- " [nbr of blocks]\n"), prognamep);
+ " [nbr of blocks]\n"), prognamep);
}
/*
@@ -265,10 +299,12 @@ ctok(pgcnt_t clicks)
static int
-doswap(void)
+doswap(int flag)
{
struct anoninfo ai;
pgcnt_t allocated, reserved, available;
+ numbuf_t numbuf;
+ unsigned long long scale = 1024L;
/*
* max = total amount of swap space including physical memory
@@ -299,16 +335,34 @@ doswap(void)
* translations (if any) of the swap.1M man page keywords for
* -s option: "allocated", "reserved", "used", "available"
*/
- (void) printf(gettext("total: %luk bytes allocated + %luk reserved = \
-%luk used, %luk available\n"),
- ctok(allocated), ctok(reserved), ctok(reserved) + ctok(allocated),
- ctok(available));
+
+ if (flag & HFLAG) {
+ int factor = (int)(sysconf(_SC_PAGESIZE));
+ (void) printf(gettext("total: %s allocated + "),
+ number_to_scaled_string(numbuf, allocated,
+ factor, scale));
+ (void) printf(gettext("%s reserved = "),
+ number_to_scaled_string(numbuf, allocated,
+ factor, scale));
+ (void) printf(gettext("%s used, "),
+ number_to_scaled_string(numbuf,
+ allocated + reserved, factor, scale));
+ (void) printf(gettext("%s available\n"),
+ number_to_scaled_string(numbuf, available,
+ factor, scale));
+ } else {
+ (void) printf(gettext("total: %luk bytes allocated + %luk"
+ " reserved = %luk used, %luk available\n"),
+ ctok(allocated), ctok(reserved),
+ ctok(reserved) + ctok(allocated),
+ ctok(available));
+ }
return (0);
}
static int
-list(void)
+list(int flag)
{
struct swaptable *st;
struct swapent *swapent;
@@ -317,6 +371,8 @@ list(void)
char *path;
char fullpath[MAXPATHLEN+1];
int num;
+ numbuf_t numbuf;
+ unsigned long long scale = 1024L;
if ((num = swapctl(SC_GETNSWP, NULL)) == -1) {
perror(prognamep);
@@ -368,7 +424,7 @@ list(void)
* -l option: "swapfile", "dev", "swaplo", "blocks", "free"
*/
(void) printf(
- gettext("swapfile dev swaplo blocks free\n"));
+ gettext("swapfile dev swaplo blocks free\n"));
swapent = st->swt_ent;
for (i = 0; i < num; i++, swapent++) {
@@ -399,9 +455,34 @@ list(void)
{
int diskblks_per_page =
(int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT);
- (void) printf(gettext(" %6lu %6lu %6lu"), swapent->ste_start,
- swapent->ste_pages * diskblks_per_page,
- swapent->ste_free * diskblks_per_page);
+ if (flag & HFLAG) {
+ (void) printf(gettext(" %8s"),
+ number_to_scaled_string(numbuf,
+ swapent->ste_start, DEV_BSIZE,
+ scale));
+ (void) printf(gettext(" %8s"),
+ number_to_scaled_string(numbuf,
+ swapent->ste_pages *
+ diskblks_per_page,
+ DEV_BSIZE, scale));
+ (void) printf(gettext(" %8s"),
+ number_to_scaled_string(numbuf,
+ swapent->ste_free *
+ diskblks_per_page,
+ DEV_BSIZE, scale));
+ } else if (flag & KFLAG) {
+ (void) printf(gettext(" %7luK %7luK %7luK"),
+ swapent->ste_start * DEV_BSIZE / 1024,
+ swapent->ste_pages * diskblks_per_page *
+ DEV_BSIZE / 1024,
+ swapent->ste_free * diskblks_per_page *
+ DEV_BSIZE / 1024);
+ } else {
+ (void) printf(gettext(" %8lu %8lu %8lu"),
+ swapent->ste_start,
+ swapent->ste_pages * diskblks_per_page,
+ swapent->ste_free * diskblks_per_page);
+ }
}
if (swapent->ste_flags & ST_INDEL)
(void) printf(" INDEL\n");
@@ -411,6 +492,64 @@ list(void)
return (0);
}
+/* Copied from du.c */
+static char *
+number_to_scaled_string(
+ numbuf_t buf, /* put the result here */
+ unsigned long long number, /* convert this number */
+ unsigned long long unit_from, /* number of byes per input unit */
+ unsigned long long scale) /* 1024 (-h) or 1000 (-H) */
+{
+ unsigned long long save = 0;
+ char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
+ char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
+
+ if ((long long)number == (long long) -1) {
+ (void) strcpy(buf, "-1");
+ return (buf);
+ }
+
+ /*
+ * Convert number from unit_from to given scale (1024 or 1000)
+ * This means multiply number with unit_from and divide by scale.
+ * if number is large enough, we first divide and then multiply
+ * to avoid an overflow (large enough here means 100 (rather arbitrary
+ * value) times scale in order to reduce rounding errors)
+ * otherwise, we first multiply and then divide to avoid an underflow.
+ */
+ if (number >= 100L * scale) {
+ number = number / scale;
+ number = number * unit_from;
+ } else {
+ number = number * unit_from;
+ number = number / scale;
+ }
+
+ /*
+ * Now we have number as a count of scale units.
+ * Stop scaling when we reached exa bytes, then something is
+ * probably wrong with our number.probably wrong with our number.
+ */
+ while ((number >= scale) && (*uom != 'E')) {
+ uom++; /* Next unit of measurement */
+ save = number;
+ number = (number + (scale / 2)) / scale;
+ }
+
+ /* Check if we should output a decimal place after the point */
+ if (save && ((save / scale) < 10)) {
+ /* sprintf() will round for us */
+ float fnum = (float)save / scale;
+ (void) sprintf(buf, "%.1f%c", fnum, *uom);
+ } else {
+ (void) sprintf(buf, "%llu%c", number, *uom);
+ }
+ return (buf);
+}
+
+
+
+
static void
dumpadm_err(const char *warning)
{