Get a Nanosecond-Precise Atime, Mtime, Ctime Fields for File (Stat)

Get a nanosecond-precise atime, mtime, ctime fields for file (stat?)

The second-resolution times are in the fields:

           time_t    st_atime;   /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */

But "NOTES" section of the man http://www.kernel.org/doc/man-pages/online/pages/man2/stat.2.html says:

Since kernel 2.5.48, the stat structure supports nanosecond resolution for the three file timestamp fields. Glibc exposes the nanosecond component of each
field using names of the form st_atim.tv_nsec if the _BSD_SOURCE or
_SVID_SOURCE feature test macro is defined. These fields are specified in
POSIX.1-2008, and, starting with version 2.12, glibc also exposes these field
names if _POSIX_C_SOURCE is defined with the value 200809L or greater, or
_XOPEN_SOURCE is defined with the value 700 or greater. If none of the
aforementioned macros are defined, then the nanosecond values are exposed with
names of the form st_atimensec.

So, nsec parts of times are in the same "struct stat": ( /usr/include/asm/stat.h )

 unsigned long st_atime_nsec;

unsigned int st_mtime_nsec;

unsigned long st_ctime_nsec;

#define STAT_HAVE_NSEC 1

How to retrieve file times with nanosecond precision?

The stat structure returned by stat() itself has been upgraded for POSIX.1-2008.

The struct stat structure contains the three modification times as:

struct timespec st_atim - Last data access timestamp. 
struct timespec st_mtim - Last data modification timestamp.
struct timespec st_ctim - Last file status change timestamp.

(from this OpenGroup link here under Headers, <sys/stat.h>) and that struct timespec is defined there (in <time.h>) as containing at least:

time_t  tv_sec          - Seconds. 
long tv_nsec - Nanoseconds.

Previously, these three times were time_t values with their one-second resolution.

Nanosecond-resolution mtime/ctime/atime with Node's fs.stat

As of Node v8.10 millisecond and nanosecond resolution time is available as separate properties:

 stats.mtimeMs
stats.ctimeMs
stats.atimeMs

i.e.

stats.mtime.getMillieseconds() //546
stats.mtimeMs // 1391354639546.3066

Get file modification time to nanosecond precision

Alternatively you coudl use the cffi library which works with Python 2 with the follwoing code (tested on LInux):

from __future__ import print_function

from cffi import FFI

ffi = FFI()
ffi.cdef("""
typedef long long time_t;

typedef struct timespec {
time_t tv_sec;
long tv_nsec;
...;
};

typedef struct stat {
struct timespec st_mtim;
...;
};

int lstat(const char *path, struct stat *buf);
""")

C = ffi.verify()

result = ffi.new("struct stat *")
p = C.lstat("foo.txt", result)
print("mtime = {0:d}.{1:09d}".format(result.st_mtim.tv_sec, result.st_mtim.tv_nsec))

This is identical in behavior to your C program in your question.
This produces the output:

$ ./test.py
mtime = 1381711568.315075616

Which has the same precision as your C program:

$ gcc test.c -o test
$ ./test
mtime = 1381711568.315075616

C Linux stat() getting atime/mtime with nsec precision


  1. st_mtime should be a time_t.
  2. According to POSIX <time.h>, the type of tv_nsec is just long.
  3. The fields like st_mtim.tv_nsec will return the number of nanoseconds.
  4. For the long, you need l; for time_t, it is not clearly defined, AFAIK.

ctime, atime, and mtime - How to interpret them?

You can get something useful from this by using the stat module to interpret the stat() results and converting from the epoch to a datetime:

import os
import datetime

print datetime.datetime.fromtimestamp(os.stat(".").st_atime)

This prints out a datetime object showing the last time the current directory was accessed:

datetime.datetime(2014, 12, 17, 7, 19, 14, 947384)

Why does stat mtime only update twice each second?

If you are getting updates twice per second you are actually doing pretty good. An excerpt from page 227 of the R-project reference regarding file.info:

What is meant by the three file times depends on the OS and file system. On Windows native file systems ctime is the file creation time (something which is not recorded on most Unix-alike file
systems). What is meant by ‘file access’ and hence the ‘last access time’ is system-dependent.

The times are reported to an accuracy of seconds, and perhaps more on some systems. However,
many file systems only record times in seconds, and some (e.g. modification time on FAT systems)
are recorded in increments of 2 or more seconds

why stat() does not show correct value of mtime?

Quote from here: https://www.php.net/manual/en/function.stat.php

    Note: The results of this function are cached. See clearstatcache() for more details.

Just add clearstatcache(); before calling stat for the second time

debugfs set_inode_field ctime with nanoseconds

After a little digging I managed to solve this problem. Solution: read the manual.

  • https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Table

  • https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps

debugfs supports setting of ctime/atime/mtime/crtime time_extra bytes with

set_inode_field foo/bar ctime_extra 0

The ctime_extra field is a unsigned integer, so the value of 0 gives the expected setting.

dtime was not widend and therefor does not support dtime_extra



Related Topics



Leave a reply



Submit