stat: print nanosecond times, fix printing of empty lines
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 3 Aug 2019 16:08:27 +0000 (18:08 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 3 Aug 2019 16:08:27 +0000 (18:08 +0200)
function                                             old     new   delta
human_time                                            36      73     +37

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
coreutils/stat.c

index b6ab5205b1a03a4291178b09b3afa0806effe362..fa9ac7b10c87e664b74377437b8d5bf778aa5fdb 100644 (file)
@@ -150,20 +150,16 @@ static const char *file_type(const struct stat *st)
        return "weird file";
 }
 
-static const char *human_time(time_t t)
+static const char *human_time(struct timespec *ts)
 {
-       /* Old
-       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;*/
+       char fmt[sizeof("%Y-%m-%d %H:%M:%S.123456789 %z") + /*paranoia*/ 8];
+
+       /* coreutils 6.3 compat */
 #define buf bb_common_bufsiz1
        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;
 #undef buf
 }
@@ -384,19 +380,19 @@ static void FAST_FUNC print_stat(char *pformat, const char m,
                strcat(pformat, "lu");
                printf(pformat, (unsigned long) statbuf->st_blksize);
        } else if (m == 'x') {
-               printfs(pformat, human_time(statbuf->st_atime));
+               printfs(pformat, human_time(&statbuf->st_atim));
        } else if (m == 'X') {
                strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
                /* note: (unsigned long) would be wrong:
                 * imagine (unsigned long64)int32 */
                printf(pformat, (long) statbuf->st_atime);
        } else if (m == 'y') {
-               printfs(pformat, human_time(statbuf->st_mtime));
+               printfs(pformat, human_time(&statbuf->st_mtim));
        } else if (m == 'Y') {
                strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
                printf(pformat, (long) statbuf->st_mtime);
        } else if (m == 'z') {
-               printfs(pformat, human_time(statbuf->st_ctime));
+               printfs(pformat, human_time(&statbuf->st_ctim));
        } else if (m == 'Z') {
                strcat(pformat, TYPE_SIGNED(time_t) ? "ld" : "lu");
                printf(pformat, (long) statbuf->st_ctime);
@@ -501,7 +497,7 @@ static bool do_statfs(const char *filename, const char *format)
        if (format == NULL) {
 # if !ENABLE_SELINUX
                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"
                          "    ID: %-8i Namelen: %-7l Type: %T\n"
                          "Block size: %-10s\n"
@@ -509,25 +505,26 @@ static bool do_statfs(const char *filename, const char *format)
                          "Inodes: Total: %-10c Free: %d");
 # else
                format = (option_mask32 & OPT_TERSE
-                       ? (option_mask32 & OPT_SELINUX ? "%n %i %l %t %s %b %f %a %c %d %C\n":
-                       "%n %i %l %t %s %b %f %a %c %d\n")
-                       : (option_mask32 & OPT_SELINUX ?
-                       "  File: \"%n\"\n"
-                       "    ID: %-8i Namelen: %-7l Type: %T\n"
-                       "Block size: %-10s\n"
-                       "Blocks: Total: %-10b Free: %-10f Available: %a\n"
-                       "Inodes: Total: %-10c Free: %d"
-                       "  S_context: %C\n":
-                       "  File: \"%n\"\n"
-                       "    ID: %-8i Namelen: %-7l Type: %T\n"
-                       "Block size: %-10s\n"
-                       "Blocks: Total: %-10b Free: %-10f Available: %a\n"
-                       "Inodes: Total: %-10c Free: %d\n")
+                       ? (option_mask32 & OPT_SELINUX
+                               ? "%n %i %l %t %s %b %f %a %c %d %C"
+                               : "%n %i %l %t %s %b %f %a %c %d")
+                       : (option_mask32 & OPT_SELINUX
+                               ? "  File: \"%n\"\n"
+                               "    ID: %-8i Namelen: %-7l Type: %T\n"
+                               "Block size: %-10s\n"
+                               "Blocks: Total: %-10b Free: %-10f Available: %a\n"
+                               "Inodes: Total: %-10c Free: %d"
+                               "  S_context: %C"
+                               : "  File: \"%n\"\n"
+                               "    ID: %-8i Namelen: %-7l Type: %T\n"
+                               "Block size: %-10s\n"
+                               "Blocks: Total: %-10b Free: %-10f Available: %a\n"
+                               "Inodes: Total: %-10c Free: %d")
                        );
 # endif /* SELINUX */
        }
        print_it(format, filename, print_statfs, &statfsbuf IF_SELINUX(, scontext));
-#else /* FEATURE_STAT_FORMAT */
+#else /* !FEATURE_STAT_FORMAT */
        format = (option_mask32 & OPT_TERSE
                ? "%s %llx %lu "
                : "  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 type: %t,%T\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 {
                                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";
+                                       "Access: %x\n" "Modify: %y\n" "Change: %z";
                        }
                }
 # else
@@ -650,14 +647,14 @@ static bool do_stat(const char *filename, const char *format)
                                        " Device type: %t,%T\n"
                                        "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\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"
                                        "  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"
+                                       "Access: %x\n" "Modify: %y\n" "Change: %z"
                                        );
                        } else {
                                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"
                                        "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\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"
                                        "  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"
+                                       "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)
                        printf("   S_Context: %s\n", scontext);
 # endif
-               printf("Access: %s\n", human_time(statbuf.st_atime));
-               printf("Modify: %s\n", human_time(statbuf.st_mtime));
-               printf("Change: %s\n", human_time(statbuf.st_ctime));
+               printf("Access: %s\n", human_time(&statbuf.st_atim));
+               printf("Modify: %s\n", human_time(&statbuf.st_mtim));
+               printf("Change: %s\n", human_time(&statbuf.st_ctim));
        }
 #endif  /* FEATURE_STAT_FORMAT */
        return 1;