>From 013ba07f19a209685331cac3f8202591b5b90dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Sun, 20 Jun 2021 15:16:49 +0100 Subject: [PATCH] stat: support more device number representations In preparation for changing the default device number representation (to decomposed decimal), provide more formatting options for device numbers. These new (FreeBSD compat) formatting options are added: %Hd major device number in decimal (st_dev) %Ld minor device number in decimal (st_dev) %Hr major device type in decimal (st_rdev) %Lr minor device type in decimal (st_rdev) %r (composed) device type in decimal (st_rdev) %R (composed) device type in hex (st_rdev) * doc/coreutils.texi (stat invocation): Document new formats. * src/stat.c (print_it): Handle the new %H and %L modifiers. (print_stat): Handle any modifiers and the new 'r' format. (usage): Document the new formats. Addresses https://bugs.gnu.org/48960 --- doc/coreutils.texi | 14 ++++++++---- src/stat.c | 57 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 3e3aedb0f..2b69e1a2a 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -12506,8 +12506,10 @@ The valid @var{format} directives for files with @option{--format} and @item %b - Number of blocks allocated (see @samp{%B}) @item %B - The size in bytes of each block reported by @samp{%b} @item %C - The SELinux security context of a file, if available -@item %d - Device number in decimal -@item %D - Device number in hex +@item %d - Device number in decimal (st_dev) +@item %D - Device number in hex (st_dev) +@item %Hd - Major device number in decimal +@item %Ld - Minor device number in decimal @item %f - Raw mode in hex @item %F - File type @item %g - Group ID of owner @@ -12519,6 +12521,10 @@ The valid @var{format} directives for files with @option{--format} and @item %N - Quoted file name with dereference if symbolic link (see below) @item %o - Optimal I/O transfer size hint @item %s - Total size, in bytes +@item %r - Device type in decimal (st_rdev) +@item %R - Device type in hex (st_rdev) +@item %Hr - Major device type in decimal (see below) +@item %Lr - Minor device type in decimal (see below) @item %t - Major device type in hex (see below) @item %T - Minor device type in hex (see below) @item %u - User ID of owner @@ -12543,8 +12549,8 @@ The @samp{%N} format can be set with the environment variable the default value is @samp{shell-escape-always}. Valid quoting styles are: @quotingStyles -The @samp{%t} and @samp{%T} formats operate on the st_rdev member of -the stat(2) structure, and are only defined for character and block +The @samp{r}, @samp{R}, @samp{%t}, and @samp{%T} formats operate on the st_rdev +member of the stat(2) structure, and are only defined for character and block special files. On some systems or file types, st_rdev may be used to represent other quantities. diff --git a/src/stat.c b/src/stat.c index 56e4867b9..8c9c69e7c 100644 --- a/src/stat.c +++ b/src/stat.c @@ -1144,11 +1144,12 @@ print_it (char const *format, int fd, char const *filename, case '%': { size_t len = format_code_offset (b); - char const *fmt_char = b + len; + char fmt_char = *(b + len); + char mod_char = 0; memcpy (dest, b, len); b += len; - switch (*fmt_char) + switch (fmt_char) { case '\0': --b; @@ -1156,15 +1157,32 @@ print_it (char const *format, int fd, char const *filename, case '%': if (1 < len) { - dest[len] = *fmt_char; + dest[len] = fmt_char; dest[len + 1] = '\0'; die (EXIT_FAILURE, 0, _("%s: invalid directive"), quote (dest)); } putchar ('%'); break; + case 'H': + case 'L': + mod_char = fmt_char; + fmt_char = *(b + 1); + if (print_func == print_stat + && (fmt_char == 'd' || fmt_char == 'r')) + { + b++; + } + else + { + fmt_char = mod_char; + mod_char = 0; + } + FALLTHROUGH; default: - fail |= print_func (dest, len, to_uchar (*fmt_char), + fail |= print_func (dest, len, + (to_uchar (mod_char) << CHAR_BIT) + + to_uchar (fmt_char), fd, filename, data); break; } @@ -1470,6 +1488,9 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m, struct group *gw_ent; bool fail = false; + char mod_char = m >> CHAR_BIT; + m &= UCHAR_MAX; + switch (m) { case 'n': @@ -1492,7 +1513,12 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m, } break; case 'd': - out_uint (pformat, prefix_len, statbuf->st_dev); + if (mod_char == 'H') + out_uint (pformat, prefix_len, major (statbuf->st_dev)); + else if (mod_char == 'L') + out_uint (pformat, prefix_len, minor (statbuf->st_dev)); + else + out_uint (pformat, prefix_len, statbuf->st_dev); break; case 'D': out_uint_x (pformat, prefix_len, statbuf->st_dev); @@ -1537,6 +1563,17 @@ print_stat (char *pformat, size_t prefix_len, unsigned int m, case 's': out_int (pformat, prefix_len, statbuf->st_size); break; + case 'r': + if (mod_char == 'H') + out_uint (pformat, prefix_len, major (statbuf->st_rdev)); + else if (mod_char == 'L') + out_uint (pformat, prefix_len, minor (statbuf->st_rdev)); + else + out_uint (pformat, prefix_len, statbuf->st_rdev); + break; + case 'R': + out_uint_x (pformat, prefix_len, statbuf->st_rdev); + break; case 't': out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); break; @@ -1739,8 +1776,10 @@ The valid format sequences for files (without --file-system):\n\ %C SELinux security context string\n\ "), stdout); fputs (_("\ - %d device number in decimal\n\ - %D device number in hex\n\ + %d device number in decimal (st_dev)\n\ + %D device number in hex (st_dev)\n\ + %Hd major device number in decimal\n\ + %Ld minor device number in decimal\n\ %f raw mode in hex\n\ %F file type\n\ %g group ID of owner\n\ @@ -1754,6 +1793,10 @@ The valid format sequences for files (without --file-system):\n\ %N quoted file name with dereference if symbolic link\n\ %o optimal I/O transfer size hint\n\ %s total size, in bytes\n\ + %r device type in decimal (st_rdev)\n\ + %R device type in hex (st_rdev)\n\ + %Hr major device type in decimal, for character/block device special files\n\ + %Lr minor device type in decimal, for character/block device special files\n\ %t major device type in hex, for character/block device special files\n\ %T minor device type in hex, for character/block device special files\n\ "), stdout); -- 2.26.2