summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLaMont Jones <lamont@debian.org>2010-12-29 09:33:45 -0700
committerLaMont Jones <lamont@debian.org>2010-12-29 09:33:45 -0700
commit4f9e177060fb5ad6e574598aefdf2d5f50a8b54f (patch)
tree840ca668a45e389792ccebaa1c414211c59ff620 /lib
parent0d32820f872a43ef8c3021dc9b9741f2b8228b40 (diff)
parent6c6f2af9e3949197cf7a70255895a2f4451f2319 (diff)
downloadutil-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.am3
-rw-r--r--lib/fsprobe.c2
-rw-r--r--lib/ismounted.c4
-rw-r--r--lib/langinfo.c121
-rw-r--r--lib/strtosize.c148
-rw-r--r--lib/strutils.c275
-rw-r--r--lib/tt.c75
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);
+}
diff --git a/lib/tt.c b/lib/tt.c
index 7d87bf54..1043ee32 100644
--- a/lib/tt.c
+++ b/lib/tt.c
@@ -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);