summaryrefslogtreecommitdiffstats
path: root/bin/ls/print.c
diff options
context:
space:
mode:
authorjoe <joe@FreeBSD.org>2001-12-28 20:50:12 +0000
committerjoe <joe@FreeBSD.org>2001-12-28 20:50:12 +0000
commitdfee532b860ae8392d001e56b14faf954a365fb8 (patch)
tree95cb44773e27fe8bfcef9a8f79767b90422dc3d9 /bin/ls/print.c
parentdde2b7683ece45d306f0d20e281e8ee844196689 (diff)
downloadFreeBSD-src-dfee532b860ae8392d001e56b14faf954a365fb8.zip
FreeBSD-src-dfee532b860ae8392d001e56b14faf954a365fb8.tar.gz
Add a new flag, -h which when combined with the -l option causes
file sizes to be displayed with unit suffixes; Byte, Kilobyte, Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the number of digits to three or less. Submitted by: nik
Diffstat (limited to 'bin/ls/print.c')
-rw-r--r--bin/ls/print.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/bin/ls/print.c b/bin/ls/print.c
index 209f620..74d30c5 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -50,6 +50,7 @@ static const char rcsid[] =
#include <errno.h>
#include <fts.h>
#include <grp.h>
+#include <math.h>
#include <langinfo.h>
#include <pwd.h>
#include <stdio.h>
@@ -70,12 +71,33 @@ static int printaname __P((FTSENT *, u_long, u_long));
static void printlink __P((FTSENT *));
static void printtime __P((time_t));
static int printtype __P((u_int));
+static void printsize __P((size_t, off_t));
#ifdef COLORLS
static void endcolor __P((int));
static int colortype __P((mode_t));
#endif
#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
+#define UNITS_2 2
+
+#define KILO_SZ(n) (n)
+#define MEGA_SZ(n) ((n) * (n))
+#define GIGA_SZ(n) ((n) * (n) * (n))
+#define TERA_SZ(n) ((n) * (n) * (n) * (n))
+#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
+
+#define KILO_2_SZ (KILO_SZ(1024ULL))
+#define MEGA_2_SZ (MEGA_SZ(1024ULL))
+#define GIGA_2_SZ (GIGA_SZ(1024ULL))
+#define TERA_2_SZ (TERA_SZ(1024ULL))
+#define PETA_2_SZ (PETA_SZ(1024ULL))
+
+unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
+
+typedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t;
+static unit_t unit_adjust __P((off_t *));
+
+int unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
#ifdef COLORLS
/* Most of these are taken from <sys/stat.h> */
@@ -178,7 +200,7 @@ printlong(dp)
(void)printf("%*s%*qd ",
8 - dp->s_size, "", dp->s_size, sp->st_size);
else
- (void)printf("%*qd ", dp->s_size, sp->st_size);
+ printsize(dp->s_size, sp->st_size);
if (f_accesstime)
printtime(sp->st_atime);
else if (f_statustime)
@@ -550,3 +572,51 @@ printlink(p)
(void)printf(" -> ");
printname(path);
}
+
+static void
+printsize(width, bytes)
+ size_t width;
+ off_t bytes;
+{
+ unit_t unit;
+
+ if (f_humanval) {
+ unit = unit_adjust(&bytes);
+
+ if (bytes == 0)
+ (void)printf("%*s ", width, "0B");
+ else
+ (void)printf("%*qd%c ", width - 1, bytes,
+ "BKMGTPE"[unit]);
+ }
+ else
+ (void)printf("%*qd ", width, bytes);
+}
+
+/*
+ * Output in "human-readable" format. Uses 3 digits max and puts
+ * unit suffixes at the end. Makes output compact and easy to read,
+ * especially on huge disks.
+ *
+ */
+unit_t
+unit_adjust(val)
+ off_t *val;
+{
+ double abval;
+ unit_t unit;
+ unsigned int unit_sz;
+
+ abval = fabs(*val);
+
+ unit_sz = abval ? ilogb(abval) / 10 : 0;
+
+ if (unit_sz >= UNIT_MAX) {
+ unit = NONE;
+ } else {
+ unit = unitp[unit_sz];
+ *val /= (double)vals_base2[unit_sz];
+ }
+
+ return (unit);
+}
OpenPOWER on IntegriCloud