stat: print nanosecond times, fix printing of empty lines

function                                             old     new   delta
human_time                                            36      73     +37

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2019-08-03 18:08:27 +02:00
parent 2f9c124f7d
commit b81f805658

View File

@ -150,20 +150,16 @@ static const char *file_type(const struct stat *st)
return "weird file"; return "weird file";
} }
static const char *human_time(time_t t) static const char *human_time(struct timespec *ts)
{ {
/* Old char fmt[sizeof("%Y-%m-%d %H:%M:%S.123456789 %z") + /*paranoia*/ 8];
static char *str;
str = ctime(&t);
str[strlen(str)-1] = '\0';
return str;
*/
/* coreutils 6.3 compat: */
/*static char buf[sizeof("YYYY-MM-DD HH:MM:SS.000000000")] ALIGN1;*/ /* coreutils 6.3 compat */
#define buf bb_common_bufsiz1 #define buf bb_common_bufsiz1
setup_common_bufsiz(); setup_common_bufsiz();
strcpy(strftime_YYYYMMDDHHMMSS(buf, COMMON_BUFSIZE, &t), ".000000000");
sprintf(stpcpy(fmt, "%Y-%m-%d %H:%M:%S"), ".%09u %%z", (unsigned)ts->tv_nsec);
strftime(buf, COMMON_BUFSIZE, fmt, localtime(&ts->tv_sec));
return buf; return buf;
#undef buf #undef buf
} }
@ -384,19 +380,19 @@ static void FAST_FUNC print_stat(char *pformat, const char m,
strcat(pformat, "lu"); strcat(pformat, "lu");
printf(pformat, (unsigned long) statbuf->st_blksize); printf(pformat, (unsigned long) statbuf->st_blksize);
} else if (m == 'x') { } else if (m == 'x') {
printfs(pformat, human_time(statbuf->st_atime)); printfs(pformat, human_time(&statbuf->st_atim));
} else if (m == 'X') { } else if (m == 'X') {
strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
/* note: (unsigned long) would be wrong: /* note: (unsigned long) would be wrong:
* imagine (unsigned long64)int32 */ * imagine (unsigned long64)int32 */
printf(pformat, (long) statbuf->st_atime); printf(pformat, (long) statbuf->st_atime);
} else if (m == 'y') { } else if (m == 'y') {
printfs(pformat, human_time(statbuf->st_mtime)); printfs(pformat, human_time(&statbuf->st_mtim));
} else if (m == 'Y') { } else if (m == 'Y') {
strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
printf(pformat, (long) statbuf->st_mtime); printf(pformat, (long) statbuf->st_mtime);
} else if (m == 'z') { } else if (m == 'z') {
printfs(pformat, human_time(statbuf->st_ctime)); printfs(pformat, human_time(&statbuf->st_ctim));
} else if (m == 'Z') { } else if (m == 'Z') {
strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu"); strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
printf(pformat, (long) statbuf->st_ctime); printf(pformat, (long) statbuf->st_ctime);
@ -501,7 +497,7 @@ static bool do_statfs(const char *filename, const char *format)
if (format == NULL) { if (format == NULL) {
# if !ENABLE_SELINUX # if !ENABLE_SELINUX
format = (option_mask32 & OPT_TERSE format = (option_mask32 & OPT_TERSE
? "%n %i %l %t %s %b %f %a %c %d\n" ? "%n %i %l %t %s %b %f %a %c %d"
: " File: \"%n\"\n" : " File: \"%n\"\n"
" ID: %-8i Namelen: %-7l Type: %T\n" " ID: %-8i Namelen: %-7l Type: %T\n"
"Block size: %-10s\n" "Block size: %-10s\n"
@ -509,25 +505,26 @@ static bool do_statfs(const char *filename, const char *format)
"Inodes: Total: %-10c Free: %d"); "Inodes: Total: %-10c Free: %d");
# else # else
format = (option_mask32 & OPT_TERSE format = (option_mask32 & OPT_TERSE
? (option_mask32 & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n": ? (option_mask32 & OPT_SELINUX
"%n %i %l %t %s %b %f %a %c %d\n") ? "%n %i %l %t %s %b %f %a %c %d %C"
: (option_mask32 & OPT_SELINUX ? : "%n %i %l %t %s %b %f %a %c %d")
" File: \"%n\"\n" : (option_mask32 & OPT_SELINUX
" ID: %-8i Namelen: %-7l Type: %T\n" ? " File: \"%n\"\n"
"Block size: %-10s\n" " ID: %-8i Namelen: %-7l Type: %T\n"
"Blocks: Total: %-10b Free: %-10f Available: %a\n" "Block size: %-10s\n"
"Inodes: Total: %-10c Free: %d" "Blocks: Total: %-10b Free: %-10f Available: %a\n"
" S_context: %C\n": "Inodes: Total: %-10c Free: %d"
" File: \"%n\"\n" " S_context: %C"
" ID: %-8i Namelen: %-7l Type: %T\n" : " File: \"%n\"\n"
"Block size: %-10s\n" " ID: %-8i Namelen: %-7l Type: %T\n"
"Blocks: Total: %-10b Free: %-10f Available: %a\n" "Block size: %-10s\n"
"Inodes: Total: %-10c Free: %d\n") "Blocks: Total: %-10b Free: %-10f Available: %a\n"
"Inodes: Total: %-10c Free: %d")
); );
# endif /* SELINUX */ # endif /* SELINUX */
} }
print_it(format, filename, print_statfs, &statfsbuf IF_SELINUX(, scontext)); print_it(format, filename, print_statfs, &statfsbuf IF_SELINUX(, scontext));
#else /* FEATURE_STAT_FORMAT */ #else /* !FEATURE_STAT_FORMAT */
format = (option_mask32 & OPT_TERSE format = (option_mask32 & OPT_TERSE
? "%s %llx %lu " ? "%s %llx %lu "
: " File: \"%s\"\n" : " File: \"%s\"\n"
@ -624,14 +621,14 @@ static bool do_stat(const char *filename, const char *format)
"Device: %Dh/%dd\tInode: %-10i Links: %-5h" "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
" Device type: %t,%T\n" " Device type: %t,%T\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n"; "Access: %x\n" "Modify: %y\n" "Change: %z";
} else { } else {
format = format =
" File: %N\n" " File: %N\n"
" Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
"Device: %Dh/%dd\tInode: %-10i Links: %h\n" "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n"; "Access: %x\n" "Modify: %y\n" "Change: %z";
} }
} }
# else # else
@ -650,14 +647,14 @@ static bool do_stat(const char *filename, const char *format)
" Device type: %t,%T\n" " Device type: %t,%T\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
" S_Context: %C\n" " S_Context: %C\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n" "Access: %x\n" "Modify: %y\n" "Change: %z"
: :
" File: %N\n" " File: %N\n"
" Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
"Device: %Dh/%dd\tInode: %-10i Links: %-5h" "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
" Device type: %t,%T\n" " Device type: %t,%T\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n" "Access: %x\n" "Modify: %y\n" "Change: %z"
); );
} else { } else {
format = (option_mask32 & OPT_SELINUX ? format = (option_mask32 & OPT_SELINUX ?
@ -666,13 +663,13 @@ static bool do_stat(const char *filename, const char *format)
"Device: %Dh/%dd\tInode: %-10i Links: %h\n" "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
"S_Context: %C\n" "S_Context: %C\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n" "Access: %x\n" "Modify: %y\n" "Change: %z"
: :
" File: %N\n" " File: %N\n"
" Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n" " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
"Device: %Dh/%dd\tInode: %-10i Links: %h\n" "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
"Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n" "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
"Access: %x\n" "Modify: %y\n" "Change: %z\n" "Access: %x\n" "Modify: %y\n" "Change: %z"
); );
} }
} }
@ -749,9 +746,9 @@ static bool do_stat(const char *filename, const char *format)
if (option_mask32 & OPT_SELINUX) if (option_mask32 & OPT_SELINUX)
printf(" S_Context: %s\n", scontext); printf(" S_Context: %s\n", scontext);
# endif # endif
printf("Access: %s\n", human_time(statbuf.st_atime)); printf("Access: %s\n", human_time(&statbuf.st_atim));
printf("Modify: %s\n", human_time(statbuf.st_mtime)); printf("Modify: %s\n", human_time(&statbuf.st_mtim));
printf("Change: %s\n", human_time(statbuf.st_ctime)); printf("Change: %s\n", human_time(&statbuf.st_ctim));
} }
#endif /* FEATURE_STAT_FORMAT */ #endif /* FEATURE_STAT_FORMAT */
return 1; return 1;