diff options
author | Eric Blake <eblake@redhat.com> | 2010-10-01 11:44:05 -0600 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2010-10-01 15:24:39 -0600 |
commit | 2c14ec962a46ae53d39149112ae6902ed771d497 (patch) | |
tree | 12e5f290f2d543e6155894bf6339a398768030ee | |
parent | 9069af45e691d1252c727da66aa4f3f3c7f1ea29 (diff) | |
download | coreutils-2c14ec962a46ae53d39149112ae6902ed771d497.tar.xz |
stat: optimize and translate default format strings
Yes, this patch intentionally leaks the results of default_format(),
since it is called only twice, and since the results are in scope
until main() exits. Not worth the extra code to pacify valgrind.
* src/stat.c (main): Hoist default format computation out of loop.
(do_statfs, do_stat): Move default format generation...
(default_format): ...into new function. Allocate the result in
pieces, rather than repeating mostly-similar chunks. Allow
translation of verbose format. Pass a second format to do_stat,
for the one aspect of the default format that is conditional on
file type.
* NEWS: Document the translation aspect.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/stat.c | 110 |
2 files changed, 79 insertions, 33 deletions
@@ -71,6 +71,8 @@ GNU coreutils NEWS -*- outline -*- limited with the --parallel option or with external process control like taskset for example. + stat now provides translated output when no format is specified. + stat no longer accepts the --context (-Z) option. Initially it was merely accepted and ignored, for compatibility. Starting two years ago, with coreutils-7.0, its use evoked a warning. diff --git a/src/stat.c b/src/stat.c index 6b2e99b77..4e3ec1200 100644 --- a/src/stat.c +++ b/src/stat.c @@ -70,6 +70,7 @@ #include "stat-time.h" #include "strftime.h" #include "find-mount-point.h" +#include "xvasprintf.h" #if USE_STATVFS # define STRUCT_STATVFS struct statvfs @@ -1027,24 +1028,14 @@ do_statfs (char const *filename, bool terse, char const *format) return false; } - if (format == NULL) - { - format = (terse - ? "%n %i %l %t %s %S %b %f %a %c %d\n" - : " File: \"%n\"\n" - " ID: %-8i Namelen: %-7l Type: %T\n" - "Block size: %-10s Fundamental block size: %S\n" - "Blocks: Total: %-10b Free: %-10f Available: %a\n" - "Inodes: Total: %-10c Free: %d\n"); - } - bool fail = print_it (format, filename, print_statfs, &statfsbuf); return ! fail; } /* stat the file and print what we find */ static bool ATTRIBUTE_WARN_UNUSED_RESULT -do_stat (char const *filename, bool terse, char const *format) +do_stat (char const *filename, bool terse, char const *format, + char const *format2) { struct stat statbuf; @@ -1067,39 +1058,83 @@ do_stat (char const *filename, bool terse, char const *format) return false; } - if (format == NULL) + if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode)) + format = format2; + + bool fail = print_it (format, filename, print_stat, &statbuf); + return ! fail; +} + +/* Return an allocated format string in static storage that + corresponds to whether FS and TERSE options were declared. */ +static char * +default_format (bool fs, bool terse, bool device) +{ + char *format; + if (fs) { if (terse) + format = xstrdup ("%n %i %l %t %s %S %b %f %a %c %d\n"); + else { - format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o\n"; + /* TRANSLATORS: This string uses format specifiers from + 'stat --help' with --file-system, and NOT from printf. */ + format = xstrdup (_("\ + File: \"%n\"\n\ + ID: %-8i Namelen: %-7l Type: %T\n\ +Block size: %-10s Fundamental block size: %S\n\ +Blocks: Total: %-10b Free: %-10f Available: %a\n\ +Inodes: Total: %-10c Free: %d\n\ +")); } + } + else /* ! fs */ + { + if (terse) + format = xstrdup ("%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o\n"); else { - /* Temporary hack to match original output until conditional - implemented. */ - if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode)) + char *temp; + /* TRANSLATORS: This string uses format specifiers from + 'stat --help' without --file-system, and NOT from printf. */ + format = xstrdup (_("\ + File: %N\n\ + Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n\ +")); + + temp = format; + if (device) { - format = - " File: %N\n" - " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" - "Device: %Dh/%dd\tInode: %-10i Links: %-5h" - " Device type: %t,%T\n" - "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" - "Access: %x\n" "Modify: %y\n" "Change: %z\n" " Birth: %w\n"; + /* TRANSLATORS: This string uses format specifiers from + 'stat --help' without --file-system, and NOT from printf. */ + format = xasprintf ("%s%s", format, _("\ +Device: %Dh/%dd\tInode: %-10i Links: %-5h Device type: %t,%T\n\ +")); } else { - format = - " File: %N\n" - " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" - "Device: %Dh/%dd\tInode: %-10i Links: %h\n" - "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" - "Access: %x\n" "Modify: %y\n" "Change: %z\n" " Birth: %w\n"; + /* TRANSLATORS: This string uses format specifiers from + 'stat --help' without --file-system, and NOT from printf. */ + format = xasprintf ("%s%s", format, _("\ +Device: %Dh/%dd\tInode: %-10i Links: %h\n\ +")); } + free (temp); + + temp = format; + /* TRANSLATORS: This string uses format specifiers from + 'stat --help' without --file-system, and NOT from printf. */ + format = xasprintf ("%s%s", format, _("\ +Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n\ +Access: %x\n\ +Modify: %y\n\ +Change: %z\n\ + Birth: %w\n\ +")); + free (temp); } } - bool fail = print_it (format, filename, print_stat, &statbuf); - return ! fail; + return format; } void @@ -1203,6 +1238,7 @@ main (int argc, char *argv[]) bool fs = false; bool terse = false; char *format = NULL; + char *format2; bool ok = true; initialize_main (&argc, &argv); @@ -1256,10 +1292,18 @@ main (int argc, char *argv[]) usage (EXIT_FAILURE); } + if (format) + format2 = format; + else + { + format = default_format (fs, terse, false); + format2 = default_format (fs, terse, true); + } + for (i = optind; i < argc; i++) ok &= (fs ? do_statfs (argv[i], terse, format) - : do_stat (argv[i], terse, format)); + : do_stat (argv[i], terse, format, format2)); exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); } |