[PATCH] stat: print nanoseconds immediately after seconds

Dmitry V. Levin ldv at altlinux.org
Mon Apr 10 00:07:33 UTC 2017


On Mon, Apr 03, 2017 at 07:46:11PM +0300, Dmitry Savelyev wrote:
> * util.c: Implement a new sprinttime_nsec function for printing time_t
> and nanoseconds at once.

* util.c (sprinttime_nsec): New function ...

> * defs.h: Prototype for the above.

* defs.h (sprinttime_nsec): New prototype.

> * statx.c: Use it.

* statx.c (SYS_FUNC(statx)): Use it.

> * print_struct_stat.c: Likewise.

* print_struct_stat.c (print_struct_stat): Likewise.

And so on.

> * tests/print_time.c: Separate time_t printing functions with and
> without nanoseconds.
> * tests/tests.h: Prototype for the non-nanosecond function.
> * tests/utime.c: Use the non-nanosecond function.
> ---
>  defs.h              |  1 +
>  print_struct_stat.c |  4 +---
>  statx.c             |  4 +---
>  tests/print_time.c  | 23 +++++++++++++++++++++--
>  tests/tests.h       |  3 +++
>  tests/utime.c       |  4 ++--
>  util.c              | 24 ++++++++++++++++++++++++
>  7 files changed, 53 insertions(+), 10 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index b2be75b9..28a82020 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -546,6 +546,7 @@ extern void addflags(const struct xlat *, uint64_t);
>  extern int printflags64(const struct xlat *, uint64_t, const char *);
>  extern const char *sprintflags(const char *, const struct xlat *, uint64_t);
>  extern const char *sprinttime(time_t);
> +extern const char *sprinttime_nsec(time_t, unsigned long long);

Given that we have a tradition of avoiding zero nsec in the output,
I think a single function that check nsec for zero would be enough.

>  extern void print_symbolic_mode_t(unsigned int);
>  extern void print_numeric_umode_t(unsigned short);
>  extern void print_numeric_long_umask(unsigned long);
> diff --git a/print_struct_stat.c b/print_struct_stat.c
> index b5e0167e..7317328c 100644
> --- a/print_struct_stat.c
> +++ b/print_struct_stat.c
> @@ -67,9 +67,7 @@ print_struct_stat(struct tcb *tcp, const struct strace_stat *const st)
>  	if (!abbrev(tcp)) {
>  #define PRINT_ST_TIME(field)				\
>  	tprints(", st_" #field "=");			\
> -	tprints(sprinttime(st->field));			\
> -	if (st->field ## _nsec)				\
> -		tprintf(".%09llu", st->field ## _nsec)
> +	tprints(sprinttime_nsec(st->field, st->field ## _nsec));

You see, we don't print zero st->field ## _nsec.

>  		PRINT_ST_TIME(atime);
>  		PRINT_ST_TIME(mtime);
> diff --git a/statx.c b/statx.c
> index 7c647fa3..9a9751f0 100644
> --- a/statx.c
> +++ b/statx.c
> @@ -60,9 +60,7 @@ SYS_FUNC(statx)
>  #define PRINT_FIELD_TIME(field)						\
>  	do {								\
>  		tprints(", " #field "=");				\
> -		tprints(sprinttime(stx.field.sec));			\
> -		if (stx.field.nsec)					\
> -			tprintf(".%09" PRId32, stx.field.nsec);		\
> +		tprints(sprinttime_nsec(stx.field.sec, stx.field.nsec)); \

struct_statx_timestamp.nsec has a signed type.  Either the type has to be
changed to unsigned, or it has to be cast explicitly to avoid sign
extension.

>  	} while (0)
>  
>  		struct_statx stx;
> diff --git a/util.c b/util.c
> index 9144efb6..bb7c7883 100644
> --- a/util.c
> +++ b/util.c
> @@ -563,6 +563,30 @@ sprinttime(time_t t)
>  	return buf;
>  }
>  
> +const char *
> +sprinttime_nsec(time_t t, unsigned long long nsec)
> +{
> +	struct tm *tmp;
> +	static char buf[sizeof(int) * 3 * 6 + sizeof(unsigned long long) * 3 +
> +	                sizeof("+0000")];
> +
> +	if(t == 0 && nsec == 0) {
> +		strcpy(buf, "0");
> +		return buf;
> +	}
> +	tmp = localtime(&t);
> +	if(tmp) {
> +		size_t len = strftime(buf, sizeof(buf), "%FT%T", tmp);

In theory, strftime returns 0 in case of an error.

> +		len += snprintf(buf + len, sizeof(buf) - len, ".%09llu",
> +		                nsec);

In theory, snprintf may return a value larger than sizeof(buf) - len, or a
negative value in case of an error.

> +		strftime(buf + len, sizeof(buf) - len, "%z", tmp);
> +	} else
> +		snprintf(buf, sizeof(buf), "%lu.%09llu", (unsigned long) t,
> +		         nsec);
> +
> +	return buf;
> +}
> +
>  enum sock_proto
>  getfdproto(struct tcb *tcp, int fd)
>  {
> diff --git a/tests/tests.h b/tests/tests.h
> index d077c5c8..6f94b692 100644
> --- a/tests/tests.h
> +++ b/tests/tests.h
> @@ -119,6 +119,9 @@ void print_quoted_string(const char *);
>  /* Print memory in a quoted form. */
>  void print_quoted_memory(const char *, size_t);
>  
> +/* Print time_t in symbolic format. */
> +void print_time_t(time_t);
> +
>  /* Print time_t and nanoseconds in symbolic format. */
>  void print_time_t_nsec(time_t, unsigned long long);

Likewise, I think a single function that check nsec for zero would be enough.


-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170410/bf503fae/attachment.bin>


More information about the Strace-devel mailing list