diff options
author | LaMont Jones <lamont@debian.org> | 2010-12-29 09:33:45 -0700 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2010-12-29 09:33:45 -0700 |
commit | 4f9e177060fb5ad6e574598aefdf2d5f50a8b54f (patch) | |
tree | 840ca668a45e389792ccebaa1c414211c59ff620 /lib | |
parent | 0d32820f872a43ef8c3021dc9b9741f2b8228b40 (diff) | |
parent | 6c6f2af9e3949197cf7a70255895a2f4451f2319 (diff) | |
download | util-linux-old-4f9e177060fb5ad6e574598aefdf2d5f50a8b54f.tar.gz |
Merge remote branch 'origin/master'
Conflicts:
login-utils/Makefile.am
mount/lomount.c
text-utils/od.1
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 3 | ||||
-rw-r--r-- | lib/fsprobe.c | 2 | ||||
-rw-r--r-- | lib/ismounted.c | 4 | ||||
-rw-r--r-- | lib/langinfo.c | 121 | ||||
-rw-r--r-- | lib/strtosize.c | 148 | ||||
-rw-r--r-- | lib/strutils.c | 275 | ||||
-rw-r--r-- | lib/tt.c | 75 |
7 files changed, 463 insertions, 165 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 45d319d3..9a3bf35b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am AM_CPPFLAGS += -DTEST_PROGRAM noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle \ - test_strtosize test_tt test_canonicalize + test_tt test_canonicalize if LINUX if HAVE_CPU_SET_T noinst_PROGRAMS += test_cpuset @@ -14,7 +14,6 @@ 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_cpuset_SOURCES = cpuset.c endif diff --git a/lib/fsprobe.c b/lib/fsprobe.c index e92e03fc..e298639a 100644 --- a/lib/fsprobe.c +++ b/lib/fsprobe.c @@ -76,7 +76,7 @@ fsprobe_known_fstype(const char *fstype) #ifdef HAVE_LIBBLKID_INTERNAL /* - * libblkid from util-linux-ng + * libblkid from util-linux * -- recommended */ static blkid_probe blprobe; diff --git a/lib/ismounted.c b/lib/ismounted.c index 592df308..f19d67b1 100644 --- a/lib/ismounted.c +++ b/lib/ismounted.c @@ -171,6 +171,10 @@ static int check_mntent(const char *file, int *mount_flags, mtpt, mtlen); if (retval == 0 && (*mount_flags != 0)) return 0; + if (access("/proc/mounts", R_OK) == 0) { + *mount_flags = 0; + return retval; + } #endif /* __linux__ */ #if defined(MOUNTED) || defined(_PATH_MOUNTED) #ifndef MOUNTED diff --git a/lib/langinfo.c b/lib/langinfo.c new file mode 100644 index 00000000..deeab9b1 --- /dev/null +++ b/lib/langinfo.c @@ -0,0 +1,121 @@ +/* + * This is callback solution for systems without nl_langinfo(), this function + * returns hardcoded and on locale setting independed value. + * + * See langinfo.h man page for more details. + * + * Copyright (C) 2010 Karel Zak <kzak@redhat.com> + */ +#include "nls.h" + +char *langinfo_fallback(nl_item item) +{ + switch (item) { + case CODESET: + return "ISO-8859-1"; + case THOUSEP: + return ","; + case D_T_FMT: + case ERA_D_T_FMT: + return "%a %b %e %H:%M:%S %Y"; + case D_FMT: + case ERA_D_FMT: + return "%m/%d/%y"; + case T_FMT: + case ERA_T_FMT: + return "%H:%M:%S"; + case T_FMT_AMPM: + return "%I:%M:%S %p"; + case AM_STR: + return "AM"; + case PM_STR: + return "PM"; + case DAY_1: + return "Sunday"; + case DAY_2: + return "Monday"; + case DAY_3: + return "Tuesday"; + case DAY_4: + return "Wednesday"; + case DAY_5: + return "Thursday"; + case DAY_6: + return "Friday"; + case DAY_7: + return "Saturday"; + case ABDAY_1: + return "Sun"; + case ABDAY_2: + return "Mon"; + case ABDAY_3: + return "Tue"; + case ABDAY_4: + return "Wed"; + case ABDAY_5: + return "Thu"; + case ABDAY_6: + return "Fri"; + case ABDAY_7: + return "Sat"; + case MON_1: + return "January"; + case MON_2: + return "February"; + case MON_3: + return "March"; + case MON_4: + return "April"; + case MON_5: + return "May"; + case MON_6: + return "June"; + case MON_7: + return "July"; + case MON_8: + return "August"; + case MON_9: + return "September"; + case MON_10: + return "October"; + case MON_11: + return "November"; + case MON_12: + return "December"; + case ABMON_1: + return "Jan"; + case ABMON_2: + return "Feb"; + case ABMON_3: + return "Mar"; + case ABMON_4: + return "Apr"; + case ABMON_5: + return "May"; + case ABMON_6: + return "Jun"; + case ABMON_7: + return "Jul"; + case ABMON_8: + return "Aug"; + case ABMON_9: + return "Sep"; + case ABMON_10: + return "Oct"; + case ABMON_11: + return "Nov"; + case ABMON_12: + return "Dec"; + case ALT_DIGITS: + return "\0\0\0\0\0\0\0\0\0\0"; + case CRNCYSTR: + return "-"; + case YESEXPR: + return "^[yY]"; + case NOEXPR: + return "^[nN]"; + default: + return ""; + } +} + diff --git a/lib/strtosize.c b/lib/strtosize.c deleted file mode 100644 index 068c5429..00000000 --- a/lib/strtosize.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 */ - diff --git a/lib/strutils.c b/lib/strutils.c new file mode 100644 index 00000000..e8e86865 --- /dev/null +++ b/lib/strutils.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010 Karel Zak <kzak@redhat.com> + * Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <ctype.h> +#include <errno.h> +#include <err.h> +#include <sys/stat.h> +#include <locale.h> +#include <string.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; +} + +/* + * 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. + */ +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; +} + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t maxlen) +{ + int i; + + for (i = 0; i < maxlen; i++) { + if (s[i] == '\0') + return i + 1; + } + return maxlen; +} +#endif + +#ifndef HAVE_STRNCHR +char *strnchr(const char *s, size_t maxlen, int c) +{ + for (; maxlen-- && *s != '\0'; ++s) + if (*s == (char)c) + return (char *)s; + return NULL; +} +#endif + +#ifndef HAVE_STRNDUP +char *strndup(const char *s, size_t n) +{ + size_t len = strnlen(s, n); + char *new = (char *) malloc((len + 1) * sizeof(char)); + if (!new) + return NULL; + new[len] = '\0'; + return (char *) memcpy(new, s, len); +} +#endif + +/* + * same as strtol(3) but exit on failure instead of returning crap + */ +long strtol_or_err(const char *str, const char *errmesg) +{ + long num; + char *end = NULL; + + if (str == NULL || *str == '\0') + goto err; + errno = 0; + num = strtol(str, &end, 10); + + if (errno || (end && *end)) + goto err; + + return num; +err: + if (errno) + err(EXIT_FAILURE, "%s: '%s'", errmesg, str); + else + errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); + return 0; +} + +/* + * Converts stat->st_mode to ls(1)-like mode string. The size of "str" must + * be 10 bytes. + */ +void strmode(mode_t mode, char *str) +{ + if (S_ISDIR(mode)) + str[0] = 'd'; + else if (S_ISLNK(mode)) + str[0] = 'l'; + else if (S_ISCHR(mode)) + str[0] = 'c'; + else if (S_ISBLK(mode)) + str[0] = 'b'; + else if (S_ISSOCK(mode)) + str[0] = 's'; + else if (S_ISFIFO(mode)) + str[0] = 'p'; + else if (S_ISREG(mode)) + str[0] = '-'; + + str[1] = mode & S_IRUSR ? 'r' : '-'; + str[2] = mode & S_IWUSR ? 'w' : '-'; + str[3] = (mode & S_ISUID + ? (mode & S_IXUSR ? 's' : 'S') + : (mode & S_IXUSR ? 'x' : '-')); + str[4] = mode & S_IRGRP ? 'r' : '-'; + str[5] = mode & S_IWGRP ? 'w' : '-'; + str[6] = (mode & S_ISGID + ? (mode & S_IXGRP ? 's' : 'S') + : (mode & S_IXGRP ? 'x' : '-')); + str[7] = mode & S_IROTH ? 'r' : '-'; + str[8] = mode & S_IWOTH ? 'w' : '-'; + str[9] = (mode & S_ISVTX + ? (mode & S_IXOTH ? 't' : 'T') + : (mode & S_IXOTH ? 'x' : '-')); + str[10] = '\0'; +} + +/* + * returns exponent (2^x=n) in range KiB..PiB + */ +static int get_exp(uint64_t n) +{ + int shft; + + for (shft = 10; shft <= 60; shft += 10) { + if (n < (1ULL << shft)) + break; + } + return shft - 10; +} + +char *size_to_human_string(uint64_t bytes) +{ + char buf[32]; + int dec, frac, exp; + const char *letters = "BKMGTP"; + char c; + + exp = get_exp(bytes); + c = *(letters + (exp ? exp / 10 : 0)); + dec = exp ? bytes / (1ULL << exp) : bytes; + frac = exp ? bytes % (1ULL << exp) : 0; + + if (frac) { + /* round */ + frac = (frac / (1ULL << (exp - 10)) + 50) / 100; + if (frac == 10) + dec++, frac = 0; + } + + if (frac) { + struct lconv const *l = localeconv(); + char *dp = l ? l->decimal_point : NULL; + + if (!dp || !*dp) + dp = "."; + snprintf(buf, sizeof(buf), "%d%s%d%c", dec, dp, frac, c); + } else + snprintf(buf, sizeof(buf), "%d%c", dec, c); + + return strdup(buf); +} @@ -15,9 +15,6 @@ #include <unistd.h> #include <string.h> #include <termios.h> -#ifdef HAVE_LANGINFO_H -#include <langinfo.h> -#endif #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif @@ -138,7 +135,7 @@ struct tt *tt_new_table(int flags) INIT_LIST_HEAD(&tb->tb_lines); INIT_LIST_HEAD(&tb->tb_columns); -#ifdef HAVE_WIDECHAR +#if defined(HAVE_WIDECHAR) if (!(flags & TT_FL_ASCII) && !strcmp(nl_langinfo(CODESET), "UTF-8")) tb->symbols = &utf8_tt_symbols; else @@ -320,7 +317,7 @@ static char *line_get_ascii_art(struct tt_line *ln, char *buf, size_t *bufsz) return NULL; if (list_last_entry(&ln->ln_children, &ln->parent->ln_branch)) - art = " "; + art = " "; else art = ln->table->symbols->vert; @@ -397,12 +394,16 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) struct tt_column *cl = list_entry(p, struct tt_column, cl_columns); - cl->width_min = mbs_width(cl->name); + if (cl->name) + cl->width_min = mbs_width(cl->name); if (cl->width < cl->width_min) cl->width = cl->width_min; + else if (cl->width_hint >= 1 && + cl->width < (int) cl->width_hint && cl->width_min < (int) cl->width_hint) + cl->width = (int) cl->width_hint; width += cl->width + (is_last_column(tb, cl) ? 0 : 1); @@ -415,7 +416,8 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) struct tt_column *cl = list_entry( tb->tb_columns.prev, struct tt_column, cl_columns); - cl->width += tb->termwidth - width; + if (!(cl->flags & TT_FL_RIGHT)) + cl->width += tb->termwidth - width; goto leave; } @@ -437,7 +439,7 @@ static void recount_widths(struct tt *tb, char *buf, size_t bufsz) continue; /* never truncate columns with absolute sizes */ if (cl->flags & TT_FL_TREE) continue; /* never truncate the tree */ - if (trunc_only && !(cl->flags & TT_FL_TRUNCATE)) + if (trunc_only && !(cl->flags & TT_FL_TRUNC)) continue; if (cl->width == cl->width_min) continue; @@ -461,7 +463,7 @@ leave: struct tt_column *cl = list_entry(p, struct tt_column, cl_columns); - fprintf(stderr, "width: %s=%d [%d]\n", + fprintf(stderr, "width: %s=%d [hint=%d]\n", cl->name, cl->width, cl->width_hint > 1 ? (int) cl->width_hint : (int) (cl->width_hint * tb->termwidth)); @@ -501,20 +503,28 @@ static void print_data(struct tt *tb, struct tt_column *cl, char *data) width = len; /* truncate data */ - if (len > width && (cl->flags & TT_FL_TRUNCATE)) { + if (len > width && (cl->flags & TT_FL_TRUNC)) { len = mbs_truncate(data, width); if (!data || len == (size_t) -1) { len = 0; data = NULL; } } - if (data) - fputs(data, stdout); + if (data) { + if (!(tb->flags & TT_FL_RAW) && (cl->flags & TT_FL_RIGHT)) { + int xw = cl->width; + fprintf(stdout, "%*s", xw, data); + if (len < xw) + len = xw; + } + else + fputs(data, stdout); + } for (i = len; i < width; i++) fputc(' ', stdout); /* padding */ if (!is_last_column(tb, cl)) { - if (len > width && !(cl->flags & TT_FL_TRUNCATE)) { + if (len > width && !(cl->flags & TT_FL_TRUNC)) { fputc('\n', stdout); for (i = 0; i <= cl->seqnum; i++) { struct tt_column *x = tt_get_column(tb, i); @@ -636,6 +646,43 @@ int tt_print_table(struct tt *tb) return 0; } +int tt_parse_columns_list(const char *list, int cols[], int *ncols, + int (name2id)(const char *, size_t)) +{ + const char *begin = NULL, *p; + + if (!list || !*list || !cols || !ncols || !name2id) + return -1; + + *ncols = 0; + + for (p = list; p && *p; p++) { + const char *end = NULL; + int id; + + if (!begin) + begin = p; /* begin of the column name */ + if (*p == ',') + end = p; /* terminate the name */ + if (*(p + 1) == '\0') + end = p + 1; /* end of string */ + if (!begin || !end) + continue; + if (end <= begin) + return -1; + + id = name2id(begin, end - begin); + if (id == -1) + return -1; + cols[ *ncols ] = id; + (*ncols)++; + begin = NULL; + if (end && !*end) + break; + } + return 0; +} + #ifdef TEST_PROGRAM #include <err.h> #include <errno.h> @@ -669,7 +716,7 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, "table initialization failed"); tt_define_column(tb, "NAME", 0.3, notree ? 0 : TT_FL_TREE); - tt_define_column(tb, "FOO", 0.3, TT_FL_TRUNCATE); + tt_define_column(tb, "FOO", 0.3, TT_FL_TRUNC); tt_define_column(tb, "BAR", 0.3, 0); tt_define_column(tb, "PATH", 0.3, 0); |