Handle access times in sub-seconds.

Use contemporary and resonably portable techniques
for microsecond or better accuracy in `struct stat'.
This commit is contained in:
Mats Erik Andersson
2014-07-17 23:27:08 +02:00
parent 57c3bb4c9b
commit faff170bbc
4 changed files with 145 additions and 41 deletions

View File

@@ -1,3 +1,29 @@
2014-07-16 Mats Erik Andersson <gnu@gisladisker.se>
Handle access timing in fractions of a second.
* configure.ac (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
(HAVE_STRUCT_STAT_ST_ATIM_TV_USEC, HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC)
(HAVE_STRUCT_STAT_ST_CTIM_TV_USEC, HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC): Check for existing time field
for sub-second timing in `struct stat'.
(HAVE_STRUCT_STAT_ST_BLKSTAT): Make the macro functional!
* libls/cmp.c (modcmp) [HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC]
[HAVE_STRUCT_STAT_ST_MTIM_TV_USEC]: Compare in sub-seconds.
(acccmp) [HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC]
[HAVE_STRUCT_STAT_ST_ATIM_TV_USEC]: Likewise.
(statmod) [HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC]
[HAVE_STRUCT_STAT_CT_MTIM_TV_USEC]: Likewise
(revmodcmp, revaccmp, revstatmod, revsizecmp): Replace code
by a simple sign change of modcmp(), acccmp(), etcetera.
* src/rcp.c [HAVE_STAT_ST_MTIMESPEC || HAVE_STAT_ST_MTIME_USEC]
(write_stat_time): Remove unused and obsolete code.
[HAVE_STRUCT_STAT_ST_ATIM_NSEC || HAVE_STRUCT_STAT_ST_ATIM_USEC]
[HAVE_STRUCT_STAT_ST_MTIM_NSEC || HAVE_STRUCT_STAT_ST_MTIM_USEC]
(write_stat_time): Code portably for sub-second accuracy.
2014-07-14 Mats Erik Andersson <gnu@gisladisker.se>
ftp: Hash command semantic.

View File

@@ -703,7 +703,15 @@ IU_CHECK_MEMBERS([struct sockaddr.sa_len], , ,
#include <sys/socket.h>])
IU_CHECK_MEMBERS([struct hostent.h_addr_list], , , [#include <netdb.h>])
IU_CHECK_MEMBERS([struct stat.st_blksize])
IU_CHECK_MEMBERS([struct stat.st_atim.tv_nsec,
struct stat.st_atim.tv_usec,
struct stat.st_blksize,
struct stat.st_ctim.tv_nsec,
struct stat.st_ctim.tv_usec,
struct stat.st_mtim.tv_nsec,
struct stat.st_mtim.tv_usec], , ,
[#include <sys/types.h>
#include <sys/stat.h>])
# OpenSolaris does not use a union for `struct tftphdr.th_u'. As a
# consequence `struct tftphdr.th_stuff' is a macro resolving to a

View File

@@ -74,9 +74,39 @@ revnamecmp (const FTSENT *a, const FTSENT *b)
int
modcmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime
||
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
( b->fts_statp->st_mtime == a->fts_statp->st_mtime
&&
b->fts_statp->st_mtim.tv_nsec > a->fts_statp->st_mtim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_USEC
( b->fts_statp->st_mtime == a->fts_statp->st_mtime
&&
b->fts_statp->st_mtim.tv_usec > a->fts_statp->st_mtim.tv_usec
)
#else
0
#endif
)
return (1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime
||
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
( b->fts_statp->st_mtime == a->fts_statp->st_mtime
&&
b->fts_statp->st_mtim.tv_nsec < a->fts_statp->st_mtim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_USEC
( b->fts_statp->st_mtime == a->fts_statp->st_mtime
&&
b->fts_statp->st_mtim.tv_usec < a->fts_statp->st_mtim.tv_usec
)
#else
0
#endif
)
return (-1);
else
return (namecmp (a, b));
@@ -85,20 +115,45 @@ modcmp (const FTSENT *a, const FTSENT *b)
int
revmodcmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
return (-1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
return (1);
else
return (revnamecmp (a, b));
return (- modcmp (a, b));
}
int
acccmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
if (b->fts_statp->st_atime > a->fts_statp->st_atime
||
#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
( b->fts_statp->st_atime == a->fts_statp->st_atime
&&
b->fts_statp->st_atim.tv_nsec > a->fts_statp->st_atim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_ATIM_TV_USEC
( b->fts_statp->st_atime == a->fts_statp->st_atime
&&
b->fts_statp->st_atim.tv_usec > a->fts_statp->st_atim.tv_usec
)
#else
0
#endif
)
return (1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
else if (b->fts_statp->st_atime < a->fts_statp->st_atime
||
#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
( b->fts_statp->st_atime == a->fts_statp->st_atime
&&
b->fts_statp->st_atim.tv_nsec < a->fts_statp->st_atim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_ATIM_TV_USEC
( b->fts_statp->st_atime == a->fts_statp->st_atime
&&
b->fts_statp->st_atim.tv_usec < a->fts_statp->st_atim.tv_usec
)
#else
0
#endif
)
return (-1);
else
return (namecmp (a, b));
@@ -107,20 +162,45 @@ acccmp (const FTSENT *a, const FTSENT *b)
int
revacccmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
return (-1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
return (1);
else
return (revnamecmp (a, b));
return (- acccmp (a, b));
}
int
statcmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime
||
#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
( b->fts_statp->st_ctime == a->fts_statp->st_ctime
&&
b->fts_statp->st_ctim.tv_nsec > a->fts_statp->st_ctim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_CTIM_TV_USEC
( b->fts_statp->st_ctime == a->fts_statp->st_ctime
&&
b->fts_statp->st_ctim.tv_usec > a->fts_statp->st_ctim.tv_usec
)
#else
0
#endif
)
return (1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime
||
#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
( b->fts_statp->st_ctime == a->fts_statp->st_ctime
&&
b->fts_statp->st_ctim.tv_nsec < a->fts_statp->st_ctim.tv_nsec
)
#elif defined HAVE_STRUCT_STAT_ST_CTIM_TV_USEC
( b->fts_statp->st_ctime == a->fts_statp->st_ctime
&&
b->fts_statp->st_ctim.tv_usec < a->fts_statp->st_ctim.tv_usec
)
#else
0
#endif
)
return (-1);
else
return (namecmp (a, b));
@@ -129,12 +209,7 @@ statcmp (const FTSENT *a, const FTSENT *b)
int
revstatcmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
return (-1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
return (1);
else
return (revnamecmp (a, b));
return (- statcmp (a, b));
}
int
@@ -151,10 +226,5 @@ sizecmp (const FTSENT *a, const FTSENT *b)
int
revsizecmp (const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_size > a->fts_statp->st_size)
return (-1);
if (b->fts_statp->st_size < a->fts_statp->st_size)
return (1);
else
return (revnamecmp (a, b));
return (- sizecmp (a, b));
}

View File

@@ -677,18 +677,18 @@ write_stat_time (int fd, struct stat *stat)
time_t a_sec, m_sec;
long a_usec = 0, m_usec = 0;
#ifdef HAVE_STAT_ST_MTIMESPEC
a_sec = stat->st_atimespec.ts_sec;
a_usec = stat->st_atimespec.ts_nsec / 1000;
m_sec = stat->st_mtimespec.ts_sec;
m_usec = stat->st_mtimespec.ts_nsec / 1000;
#else
a_sec = stat->st_atime;
#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
a_usec = stat->st_atim.tv_nsec / 1000;
#elif defined HAVE_STRUCT_STAT_ST_ATIM_TV_USEC
a_usec = stat->st_atim.tv_usec;
#endif
m_sec = stat->st_mtime;
# ifdef HAVE_STAT_ST_MTIME_USEC
a_usec = stat->st_atime_usec;
m_usec = stat->st_mtime_usec;
# endif
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
m_usec = stat->st_mtim.tv_nsec / 1000;
#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_USEC
m_usec = stat->st_mtim.tv_usec;
#endif
snprintf (buf, sizeof (buf), "T%ld %ld %ld %ld\n",