humanize.c (2635B)
- // utils-extra: Collection of extra tools for Unixes
- // SPDX-FileCopyrightText: 2017-2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <errno.h> // EINVAL, ERANGE
- #include <limits.h> // LLONG_MIN, LLONG_MAX
- #include <stdbool.h> // bool
- #include <stdio.h> // fprintf, perror, sscanf
- #include <unistd.h> // opt*, getopt
- static void
- human_num(long double num, bool iec)
- {
- #define PFX 11
- char *si_prefixes[PFX] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"};
- char *iec_prefixes[PFX] = {
- "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"};
- unsigned div = iec ? 1024 : 1000;
- char **prefixes = iec ? iec_prefixes : si_prefixes;
- unsigned quotient = 0;
- while(num > div && quotient < PFX)
- {
- num /= div;
- quotient += 1;
- }
- printf("%Lg %s\n", num, prefixes[quotient]);
- }
- static void
- human_time(long int epoch)
- {
- int year = 0, month = 0, mday = 0, hour = 0, min = 0, sec = 0;
- year = epoch / 31556926; // round(year)
- epoch %= 31556926;
- month = epoch / 2629743; // year/12
- epoch %= 2629743;
- mday = epoch / 86400;
- epoch %= 86400;
- hour = epoch / 3600;
- epoch %= 3600;
- min = epoch / 60;
- epoch %= 60;
- sec = epoch;
- if(year > 0) printf("%dY ", year);
- if(month > 0) printf("%dM ", month);
- if(mday > 0) printf("%dD ", mday);
- if(hour > 0) printf("%dh ", hour);
- if(min > 0) printf("%dm ", min);
- if(sec > 0) printf("%ds", sec);
- printf("\n");
- }
- static void
- usage()
- {
- fprintf(stderr, "Usage: humanize [-bdt] number\n");
- }
- int
- main(int argc, char *argv[])
- {
- // default to -d
- bool iec = false, time = false;
- int c = -1;
- while((c = getopt(argc, argv, ":bdt")) != -1)
- {
- switch(c)
- {
- case 'b':
- iec = true;
- break;
- case 'd':
- iec = false;
- break;
- case 't':
- time = true;
- break;
- case ':':
- fprintf(stderr, "humanize: Error: Missing operand for option: '-%c'\n", optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "humanize: Error: Unrecognised option: '-%c'\n", optopt);
- usage();
- return 1;
- }
- }
- argc -= optind;
- argv += optind;
- if(argc < 1)
- {
- usage();
- return 1;
- }
- for(int argi = 0; argi < argc; argi++)
- {
- // Keep sscanf here for easier error handling, rest being pure math
- if(time)
- {
- long int epoch = 0;
- if(sscanf(argv[argi], "%ld", &epoch) < 1)
- {
- perror("humanize: sscanf");
- return 1;
- }
- human_time(epoch);
- }
- else
- {
- long double num = 0;
- if(sscanf(argv[argi], "%Lg", &num) < 1)
- {
- perror("humanize: sscanf");
- return 1;
- }
- human_num(num, iec);
- }
- }
- return 0;
- }