diff options
| author | petede <none@none> | 2006-05-15 10:32:03 -0700 |
|---|---|---|
| committer | petede <none@none> | 2006-05-15 10:32:03 -0700 |
| commit | 56f10d37c1fa50cc562c3a4c2633af1ccef2aaa4 (patch) | |
| tree | 6598c81637ae615efe9e2ff1bf32e36a9b1c2bdf /usr/src/cmd/swap | |
| parent | 044802ffd0b6258ef2221463b41121e8df53782f (diff) | |
| download | illumos-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.c | 199 |
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) { |
