$ stat foo
[..]
Access: 2012-12-27 15:07:08.020388663 +0300
Modify: 2012-12-27 15:07:08.020388663 +0300
Change: 2012-12-27 15:07:08.020388663 +0300
where does nanosecond precision come from?
man 2 stat
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
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 */
};
as we can see, stat struct contains ctime/mtime/atime, which are time_t, so it's quiet
unlikely to store nanosecond resolution.
The note part 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. On file systems that do not support
subsecond timestamps, the nanosecond fields are returned with the value 0.
GLIBC defines struct stat as
struct stat
[..]
#if defined __USE_MISC || defined __USE_XOPEN2K8
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
whenever possible but the Unix namespace rules do not allow the
identifier 'timespec' to appear in the
Therefore we have to handle the use of this header in strictly
standard-compliant sources special. */
struct timespec st_atim; /* Time of last access. */
struct timespec st_mtim; /* Time of last modification. */
struct timespec st_ctim; /* Time of last status change. */
# define st_atime st_atim.tv_sec /* Backward compatibility. */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
#else
__time_t st_atime; /* Time of last access. */
unsigned long int st_atimensec; /* Nscecs of last access. */
__time_t st_mtime; /* Time of last modification. */
unsigned long int st_mtimensec; /* Nsecs of last modification. */
__time_t st_ctime; /* Time of last status change. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
#endif
[..]
where MISC or XOPEN2K8 defs are coming from
glibc/include/features.h
#if (_POSIX_C_SOURCE - 0) >= 200809L
# define __USE_XOPEN2K8 1
# undef _ATFILE_SOURCE
# define _ATFILE_SOURCE 1
#endif
or
# if (_XOPEN_SOURCE - 0) >= 600
# if (_XOPEN_SOURCE - 0) >= 700
# define __USE_XOPEN2K8 1
# define __USE_XOPEN2K8XSI 1
# endif
#if defined _BSD_SOURCE || defined _SVID_SOURCE
# define __USE_MISC 1
#endif
So it seems, that 'if defined __USE_MISC || defined __USE_XOPEN2K8' or
'if defined _BSD_SOURCE' is sufficient. However, the real world code(tm) is a bit more
complicated. Here is a small part of core-utils' stat:
[..]
/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST,
ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
for access, status change, data modification, or birth (creation)
time respectively.
These macros are private to stat-time.h. */
#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
# ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
# else
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
# endif
#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
#endif
/* Return the nanosecond component of *ST's status change time. */
static inline long int
get_stat_ctime_ns (struct stat const *st)
{
# if defined STAT_TIMESPEC
return STAT_TIMESPEC (st, st_ctim).tv_nsec;
# elif defined STAT_TIMESPEC_NS
return STAT_TIMESPEC_NS (st, st_ctim);
# else
return 0;
# endif
}
[..]