diff options
| author | LaMont Jones <lamont@debian.org> | 2010-05-14 05:07:14 -0600 |
|---|---|---|
| committer | LaMont Jones <lamont@debian.org> | 2010-05-14 05:07:14 -0600 |
| commit | 3cbdfd84fde6159d7778e70618fbbc8df219cafe (patch) | |
| tree | e545f7d9e6b73426f590f3195f1d458f5c52d518 /lib | |
| parent | 321ab951929f2ed871751ba8979d1136d036485a (diff) | |
| parent | ab978962b15489b62f41a2ec0de4c44c9e25df6e (diff) | |
| download | util-linux-old-3cbdfd84fde6159d7778e70618fbbc8df219cafe.tar.gz | |
Merge remote branch 'origin/master' into HEAD
Conflicts:
lib/fsprobe.c
mount/lomount.c
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.am | 5 | ||||
| -rw-r--r-- | lib/blkdev.c | 117 | ||||
| -rw-r--r-- | lib/canonicalize.c | 1 | ||||
| -rw-r--r-- | lib/fsprobe.c | 63 | ||||
| -rw-r--r-- | lib/mangle.c | 116 | ||||
| -rw-r--r-- | lib/mbsalign.c | 288 | ||||
| -rw-r--r-- | lib/strtosize.c | 148 |
7 files changed, 686 insertions, 52 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 5600d18c..0f008b30 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,11 +2,14 @@ include $(top_srcdir)/config/include-Makefile.am AM_CPPFLAGS += -DTEST_PROGRAM -noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk +noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle \ + test_strtosize test_blkdev_SOURCES = blkdev.c test_ismounted_SOURCES = ismounted.c test_wholedisk_SOURCES = wholedisk.c +test_mangle_SOURCES = mangle.c +test_strtosize_SOURCES = strtosize.c if LINUX test_blkdev_SOURCES += linux_version.c diff --git a/lib/blkdev.c b/lib/blkdev.c index 1ca4548b..7d00324d 100644 --- a/lib/blkdev.c +++ b/lib/blkdev.c @@ -1,7 +1,24 @@ #include <sys/types.h> +#include <sys/stat.h> #include <sys/ioctl.h> #include <unistd.h> +#include <stdint.h> + +#ifdef HAVE_LINUX_FD_H +#include <linux/fd.h> +#endif + +#ifdef HAVE_SYS_DISKLABEL_H +#include <sys/disklabel.h> +#endif + +#ifdef HAVE_SYS_DISK_H +#ifdef HAVE_SYS_QUEUE_H +#include <sys/queue.h> /* for LIST_HEAD */ +#endif +#include <sys/disk.h> +#endif #include "blkdev.h" #include "linux_version.h" @@ -19,14 +36,23 @@ blkdev_valid_offset (int fd, off_t offset) { off_t blkdev_find_size (int fd) { - off_t high, low; + uintmax_t high, low = 0; + + for (high = 1024; blkdev_valid_offset (fd, high); ) { + if (high == UINTMAX_MAX) + return -1; - low = 0; - for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2) low = high; + + if (high >= UINTMAX_MAX/2) + high = UINTMAX_MAX; + else + high *= 2; + } + while (low < high - 1) { - const off_t mid = (low + high) / 2; + uintmax_t mid = (low + high) / 2; if (blkdev_valid_offset (fd, mid)) low = mid; @@ -41,17 +67,26 @@ blkdev_find_size (int fd) { int blkdev_get_size(int fd, unsigned long long *bytes) { - /* TODO: use stat as well */ +#ifdef DKIOCGETBLOCKCOUNT + /* Apple Darwin */ + if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) { + *bytes <<= 9; + return 0; + } +#endif #ifdef BLKGETSIZE64 + { #ifdef __linux__ - int ver = get_linux_version(); - /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */ - if (ver >= KERNEL_VERSION (2,6,0) || - (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0))) + int ver = get_linux_version(); + + /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */ + if (ver >= KERNEL_VERSION (2,6,0) || + (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0))) #endif - if (ioctl(fd, BLKGETSIZE64, bytes) >= 0) - return 0; + if (ioctl(fd, BLKGETSIZE64, bytes) >= 0) + return 0; + } #endif /* BLKGETSIZE64 */ #ifdef BLKGETSIZE @@ -64,9 +99,67 @@ blkdev_get_size(int fd, unsigned long long *bytes) } } - return -1; #endif /* BLKGETSIZE */ +#ifdef DIOCGMEDIASIZE + /* FreeBSD */ + if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0) + return 0 +#endif + +#ifdef FDGETPRM + { + struct floppy_struct this_floppy; + + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { + *bytes = this_floppy.size << 9; + return 0; + } + } +#endif /* FDGETPRM */ + +#ifdef HAVE_SYS_DISKLABEL_H + { + /* + * This code works for FreeBSD 4.11 i386, except for the full device + * (such as /dev/ad0). It doesn't work properly for newer FreeBSD + * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE + * above however. + * + * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw, + * character) devices, so we need to check for S_ISCHR, too. + */ + int part = -1; + struct disklabel lab; + struct partition *pp; + char ch; + struct stat st; + + if ((fstat(fd, &st) >= 0) && + (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) + part = st.st_rdev & 7; + + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { + pp = &lab.d_partitions[part]; + if (pp->p_size) { + *bytes = pp->p_size << 9; + return 0; + } + } + } +#endif /* HAVE_SYS_DISKLABEL_H */ + + { + struct stat st; + + if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { + *bytes = st.st_size; + return 0; + } + if (!S_ISBLK(st.st_mode)) + return -1; + } + *bytes = blkdev_find_size(fd); return 0; } diff --git a/lib/canonicalize.c b/lib/canonicalize.c index e54cf0c0..29b3f259 100644 --- a/lib/canonicalize.c +++ b/lib/canonicalize.c @@ -24,7 +24,6 @@ #include <string.h> #include <ctype.h> #include <unistd.h> -#include <string.h> #include <errno.h> #include <stdlib.h> diff --git a/lib/fsprobe.c b/lib/fsprobe.c index bc3c13c6..e92e03fc 100644 --- a/lib/fsprobe.c +++ b/lib/fsprobe.c @@ -20,34 +20,6 @@ static blkid_cache blcache; -#ifdef HAVE_LIBBLKID_INTERNAL -/* ask kernel developers why we need such ugly open() method... */ -static int -open_device(const char *devname) -{ - int retries = 0; - - do { - int fd = open(devname, O_RDONLY); - if (fd >= 0) - return fd; -#ifdef ENOMEDIUM - /* ENOMEDIUM is Linux-only */ - if (errno != ENOMEDIUM) - break; -#else - break; -#endif - if (retries >= CRDOM_NOMEDIUM_RETRIES) - break; - ++retries; - sleep(3); - } while(1); - - return -1; -} -#endif - /* * Parses NAME=value, returns -1 on parse error, 0 success. The success is also * when the 'spec' doesn't contain name=value pair (because the spec could be @@ -122,14 +94,14 @@ fsprobe_exit(void) * probing interface */ static char * -fsprobe_get_value(const char *name, const char *devname) +fsprobe_get_value(const char *name, const char *devname, int *ambi) { - int fd; + int fd, rc; const char *data = NULL; if (!devname || !name) return NULL; - fd = open_device(devname); + fd = open(devname, O_RDONLY); if (fd < 0) return NULL; if (!blprobe) @@ -144,10 +116,11 @@ fsprobe_get_value(const char *name, const char *devname) blkid_probe_set_superblocks_flags(blprobe, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE); - if (blkid_do_safeprobe(blprobe)) - goto done; - if (blkid_probe_lookup_value(blprobe, name, &data, NULL)) - goto done; + rc = blkid_do_safeprobe(blprobe); + if (ambi) + *ambi = rc == -2 ? 1 : 0; /* ambivalent probing result */ + if (!rc) + blkid_probe_lookup_value(blprobe, name, &data, NULL); done: close(fd); return data ? strdup((char *) data) : NULL; @@ -156,19 +129,25 @@ done: char * fsprobe_get_label_by_devname(const char *devname) { - return fsprobe_get_value("LABEL", devname); + return fsprobe_get_value("LABEL", devname, NULL); } char * fsprobe_get_uuid_by_devname(const char *devname) { - return fsprobe_get_value("UUID", devname); + return fsprobe_get_value("UUID", devname, NULL); } char * fsprobe_get_fstype_by_devname(const char *devname) { - return fsprobe_get_value("TYPE", devname); + return fsprobe_get_value("TYPE", devname, NULL); +} + +char * +fsprobe_get_fstype_by_devname_ambi(const char *devname, int *ambi) +{ + return fsprobe_get_value("TYPE", devname, ambi); } char * @@ -237,6 +216,14 @@ fsprobe_get_fstype_by_devname(const char *devname) } char * +fsprobe_get_fstype_by_devname_ambi(const char *devname, int *ambi) +{ + if (ambi) + *ambi = 0; + return fsprobe_get_fstype_by_devname(devname); +} + +char * fsprobe_get_label_by_devname(const char *devname) { if (!blcache) diff --git a/lib/mangle.c b/lib/mangle.c new file mode 100644 index 00000000..766d479d --- /dev/null +++ b/lib/mangle.c @@ -0,0 +1,116 @@ +/* + * Functions for \oct encoding used in mtab/fstab/swaps/etc. + * + * Based on code from mount(8). + * + * Copyright (C) 2010 Karel Zak <kzak@redhat.com> + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "mangle.h" + +#define isoctal(a) (((a) & ~7) == '0') + +static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; + +char *mangle(const char *s) +{ + char *ss, *sp; + int n; + + n = strlen(s); + ss = sp = malloc(4*n+1); + if (!sp) + return NULL; + while(1) { + for (n = 0; n < sizeof(need_escaping); n++) { + if (*s == need_escaping[n]) { + *sp++ = '\\'; + *sp++ = '0' + ((*s & 0300) >> 6); + *sp++ = '0' + ((*s & 070) >> 3); + *sp++ = '0' + (*s & 07); + goto next; + } + } + *sp++ = *s; + if (*s == 0) + break; + next: + s++; + } + return ss; +} + +void unmangle_to_buffer(char *s, char *buf, size_t len) +{ + size_t sz = 0; + + while(*s && sz < len - 1) { + if (*s == '\\' && sz + 4 < len - 1 && isoctal(s[1]) && + isoctal(s[2]) && isoctal(s[3])) { + + *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7); + s += 4; + sz += 4; + } else { + *buf++ = *s++; + sz++; + } + } + *buf = '\0'; +} + +static inline char *skip_nonspaces(char *s) +{ + while (*s && !(*s == ' ' || *s == '\t')) + s++; + return s; +} + +/* + * Returns mallocated buffer or NULL in case of error. + */ +char *unmangle(char *s) +{ + char *buf, *end; + size_t sz; + + end = skip_nonspaces(s); + sz = end - s + 1; + + buf = malloc(sz); + if (!buf) + return NULL; + + unmangle_to_buffer(s, buf, sz); + return buf; +} + +#ifdef TEST_PROGRAM +#include <err.h> +#include <errno.h> +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n", + program_invocation_short_name); + return EXIT_FAILURE; + } + + if (!strcmp(argv[1], "--mangle")) + printf("mangled: '%s'\n", mangle(argv[2])); + + else if (!strcmp(argv[1], "--unmangle")) { + char *x = unmangle(argv[2]); + if (x) + printf("unmangled: '%s'\n", x); + else + err(EXIT_FAILURE, "unmangle failed"); + } + + return EXIT_SUCCESS; +} +#endif /* TEST_PROGRAM */ diff --git a/lib/mbsalign.c b/lib/mbsalign.c new file mode 100644 index 00000000..82ffc09c --- /dev/null +++ b/lib/mbsalign.c @@ -0,0 +1,288 @@ +/* Align/Truncate a string in a given screen width + Copyright (C) 2009-2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Pádraig Brady. */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdbool.h> +#include <limits.h> + +#include "c.h" +#include "mbsalign.h" +#include "widechar.h" + + +#ifdef HAVE_WIDECHAR +/* Replace non printable chars. + Note \t and \n etc. are non printable. + Return 1 if replacement made, 0 otherwise. */ + +static bool +wc_ensure_printable (wchar_t *wchars) +{ + bool replaced = false; + wchar_t *wc = wchars; + while (*wc) + { + if (!iswprint ((wint_t) *wc)) + { + *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */ + replaced = true; + } + wc++; + } + return replaced; +} + +/* Truncate wchar string to width cells. + * Returns number of cells used. */ + +static size_t +wc_truncate (wchar_t *wc, size_t width) +{ + size_t cells = 0; + int next_cells = 0; + + while (*wc) + { + next_cells = wcwidth (*wc); + if (next_cells == -1) /* non printable */ + { + *wc = 0xFFFD; /* L'\uFFFD' (replacement char) */ + next_cells = 1; + } + if (cells + next_cells > width) + break; + cells += next_cells; + wc++; + } + *wc = L'\0'; + return cells; +} + +/* FIXME: move this function to gnulib as it's missing on: + OpenBSD 3.8, IRIX 5.3, Solaris 2.5.1, mingw, BeOS */ + +static int +rpl_wcswidth (const wchar_t *s, size_t n) +{ + int ret = 0; + + while (n-- > 0 && *s != L'\0') + { + int nwidth = wcwidth (*s++); + if (nwidth == -1) /* non printable */ + return -1; + if (ret > (INT_MAX - nwidth)) /* overflow */ + return -1; + ret += nwidth; + } + + return ret; +} +#endif + +/* Truncate multi-byte string to @width and returns number of + * bytes of the new string @str, and in @width returns number + * of cells. + */ +size_t +mbs_truncate(char *str, size_t *width) +{ + size_t bytes = strlen(str); +#ifdef HAVE_WIDECHAR + size_t sz = mbstowcs(NULL, str, 0); + wchar_t *wcs = NULL; + + if (sz == (size_t) -1) + goto done; + + wcs = malloc((sz + 1) * sizeof(wchar_t)); + if (!wcs) + goto done; + + if (!mbstowcs(wcs, str, sz)) + goto done; + *width = wc_truncate(wcs, *width); + bytes = wcstombs(str, wcs, bytes); +done: + free(wcs); +#else + if (*width < bytes) + bytes = *width; +#endif + if (bytes >= 0) + str[bytes] = '\0'; + return bytes; +} + +/* Write N_SPACES space characters to DEST while ensuring + nothing is written beyond DEST_END. A terminating NUL + is always added to DEST. + A pointer to the terminating NUL is returned. */ + +static char* +mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces) +{ + /* FIXME: Should we pad with "figure space" (\u2007) + if non ascii data present? */ + while (n_spaces-- && (dest < dest_end)) + *dest++ = ' '; + *dest = '\0'; + return dest; +} + +/* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte + characters; write the result into the DEST_SIZE-byte buffer, DEST. + ALIGNMENT specifies whether to left- or right-justify or to center. + If SRC requires more than *WIDTH columns, truncate it to fit. + When centering, the number of trailing spaces may be one less than the + number of leading spaces. The FLAGS parameter is unused at present. + Return the length in bytes required for the final result, not counting + the trailing NUL. A return value of DEST_SIZE or larger means there + wasn't enough space. DEST will be NUL terminated in any case. + Return (size_t) -1 upon error (invalid multi-byte sequence in SRC, + or malloc failure), unless MBA_UNIBYTE_FALLBACK is specified. + Update *WIDTH to indicate how many columns were used before padding. */ + +size_t +mbsalign (const char *src, char *dest, size_t dest_size, + size_t *width, mbs_align_t align, int flags) +{ + size_t ret = -1; + size_t src_size = strlen (src) + 1; + char *newstr = NULL; + wchar_t *str_wc = NULL; + const char *str_to_print = src; + size_t n_cols = src_size - 1; + size_t n_used_bytes = n_cols; /* Not including NUL */ + size_t n_spaces = 0; + bool conversion = false; + bool wc_enabled = false; + +#ifdef HAVE_WIDECHAR + /* In multi-byte locales convert to wide characters + to allow easy truncation. Also determine number + of screen columns used. */ + if (MB_CUR_MAX > 1) + { + size_t src_chars = mbstowcs (NULL, src, 0); + if (src_chars == (size_t) -1) + { + if (flags & MBA_UNIBYTE_FALLBACK) + goto mbsalign_unibyte; + else + goto mbsalign_cleanup; + } + src_chars += 1; /* make space for NUL */ + str_wc = malloc (src_chars * sizeof (wchar_t)); + if (str_wc == NULL) + { + if (flags & MBA_UNIBYTE_FALLBACK) + goto mbsalign_unibyte; + else + goto mbsalign_cleanup; + } + if (mbstowcs (str_wc, src, src_chars) != 0) + { + str_wc[src_chars - 1] = L'\0'; + wc_enabled = true; + conversion = wc_ensure_printable (str_wc); + n_cols = rpl_wcswidth (str_wc, src_chars); + } + } + + /* If we transformed or need to truncate the source string + then create a modified copy of it. */ + if (wc_enabled && (conversion || (n_cols > *width))) + { + if (conversion) + { + /* May have increased the size by converting + \t to \uFFFD for example. */ + src_size = wcstombs(NULL, str_wc, 0) + 1; + } + newstr = malloc (src_size); + if (newstr == NULL) + { + if (flags & MBA_UNIBYTE_FALLBACK) + goto mbsalign_unibyte; + else + goto mbsalign_cleanup; + } + str_to_print = newstr; + n_cols = wc_truncate (str_wc, *width); + n_used_bytes = wcstombs (newstr, str_wc, src_size); + } +#endif + +mbsalign_unibyte: + + if (n_cols > *width) /* Unibyte truncation required. */ + { + n_cols = *width; + n_used_bytes = n_cols; + } + + if (*width > n_cols) /* Padding required. */ + n_spaces = *width - n_cols; + + /* indicate to caller how many cells needed (not including padding). */ + *width = n_cols; + + /* indicate to caller how many bytes needed (not including NUL). */ + ret = n_used_bytes + (n_spaces * 1); + + /* Write as much NUL terminated output to DEST as possible. */ + if (dest_size != 0) + { + char *dest_end = dest + dest_size - 1; + size_t start_spaces = n_spaces / 2 + n_spaces % 2; + size_t end_spaces = n_spaces / 2; + + switch (align) + { + case MBS_ALIGN_CENTER: + start_spaces = n_spaces / 2 + n_spaces % 2; + end_spaces = n_spaces / 2; + break; + case MBS_ALIGN_LEFT: + start_spaces = 0; + end_spaces = n_spaces; + break; + case MBS_ALIGN_RIGHT: + start_spaces = n_spaces; + end_spaces = 0; + break; + } + + dest = mbs_align_pad (dest, dest_end, start_spaces); + size_t space_left = dest_end - dest; + dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left)); + mbs_align_pad (dest, dest_end, end_spaces); + } + +mbsalign_cleanup: + + free (str_wc); + free (newstr); + + return ret; +} diff --git a/lib/strtosize.c b/lib/strtosize.c new file mode 100644 index 00000000..068c5429 --- /dev/null +++ b/lib/strtosize.c @@ -0,0 +1,148 @@ +/* + * strtosize() - convert string to size (uintmax_t). + * + * Supported suffixes: + * + * XiB or X for 2^N + * where X = {K,M,G,T,P,E,Y,Z} + * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only) + * for example: + * 10KiB = 10240 + * 10K = 10240 + * + * XB for 10^N + * where X = {K,M,G,T,P,E,Y,Z} + * for example: + * 10KB = 10000 + * + * Note that the function does not accept numbers with '-' (negative sign) + * prefix. + * + * Returns 0 on success, -1 in case of error, -2 in case of overflow. + * + * Copyright (C) 2010 Karel Zak <kzak@redhat.com> + */ +#include <stdio.h> +#include <inttypes.h> +#include <ctype.h> +#include <errno.h> + +static int do_scale_by_power (uintmax_t *x, int base, int power) +{ + while (power--) { + if (UINTMAX_MAX / base < *x) + return -2; + *x *= base; + } + return 0; +} + +int strtosize(const char *str, uintmax_t *res) +{ + char *p; + uintmax_t x; + int base = 1024, rc = 0; + + *res = 0; + + if (!str || !*str) + goto err; + + /* Only positive numbers are acceptable + * + * Note that this check is not perfect, it would be better to + * use lconv->negative_sign. But coreutils use the same solution, + * so it's probably good enough... + */ + p = (char *) str; + while (isspace((unsigned char) *p)) + p++; + if (*p == '-') + goto err; + p = NULL; + + errno = 0; + x = strtoumax(str, &p, 0); + + if (p == str || + (errno != 0 && (x == UINTMAX_MAX || x == 0))) + goto err; + + if (!p || !*p) + goto done; /* without suffix */ + + /* + * Check size suffixes + */ + if (*(p + 1) == 'i' && *(p + 2) == 'B' && !*(p + 3)) + base = 1024; /* XiB, 2^N */ + else if (*(p + 1) == 'B' && !*(p + 2)) + base = 1000; /* XB, 10^N */ + else if (*(p + 1)) + goto err; /* unexpected suffix */ + + switch(*p) { + case 'K': + case 'k': + rc = do_scale_by_power(&x, base, 1); + break; + case 'M': + case 'm': + rc = do_scale_by_power(&x, base, 2); + break; + case 'G': + case 'g': + rc = do_scale_by_power(&x, base, 3); + break; + case 'T': + case 't': + rc = do_scale_by_power(&x, base, 4); + break; + case 'P': + case 'p': + rc = do_scale_by_power(&x, base, 5); + break; + case 'E': + case 'e': + rc = do_scale_by_power(&x, base, 6); + break; + case 'Z': + rc = do_scale_by_power(&x, base, 7); + break; + case 'Y': + rc = do_scale_by_power(&x, base, 8); + break; + default: + goto err; + } + +done: + *res = x; + return rc; +err: + return -1; +} + +#ifdef TEST_PROGRAM + +#include <stdio.h> +#include <stdlib.h> +#include <err.h> + +int main(int argc, char *argv[]) +{ + uintmax_t size = 0; + + if (argc < 2) { + fprintf(stderr, "usage: %s <number>[suffix]\n", argv[0]); + exit(EXIT_FAILURE); + } + + if (strtosize(argv[1], &size)) + errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]); + + printf("%25s : %20ju\n", argv[1], size); + return EXIT_FAILURE; +} +#endif /* TEST_PROGRAM */ + |
