about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@users.sourceforge.net>2007-11-01 17:57:57 +0000
committerOliver Kiddle <opk@users.sourceforge.net>2007-11-01 17:57:57 +0000
commitfe5390a04ce44daf1604298756d772b2ce12b268 (patch)
tree1c13e446cacb0e9462c07e5de027a181b592ea8f
parent8d956e9bcb8fe5aa3ca92e3c856b26800af11ff5 (diff)
downloadzsh-fe5390a04ce44daf1604298756d772b2ce12b268.tar.gz
zsh-fe5390a04ce44daf1604298756d772b2ce12b268.tar.xz
zsh-fe5390a04ce44daf1604298756d772b2ce12b268.zip
24050: handle nanosecond resolution timestamps on systems that support them
-rw-r--r--ChangeLog3
-rw-r--r--Src/cond.c20
-rw-r--r--Src/glob.c54
-rw-r--r--Src/system.h21
-rw-r--r--configure.ac11
5 files changed, 109 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 5334df940..572b2a745 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-11-01  Oliver Kiddle  <opk@zsh.org>
 
+	* 24050: configure.ac, Src/cond.c, Src/glob.c, Src/system.h:
+	handle nanosecond timestamps on systems that support them
+
 	* 24048: Src/hashtable.c: fix home directory expansion with
 	NIS on Solaris
 
diff --git a/Src/cond.c b/Src/cond.c
index a38df6fb7..cabe64446 100644
--- a/Src/cond.c
+++ b/Src/cond.c
@@ -344,19 +344,39 @@ evalcond(Estate state, char *fromtest)
     case 'G':
 	return !((st = getstat(left)) && st->st_gid == getegid());
     case 'N':
+#if defined(GET_ST_MTIME_NSEC) && defined(GET_ST_ATIME_NSEC)
+	if (!(st = getstat(left)))
+	    return 1;
+        return (st->st_atime == st->st_mtime) ?
+        	GET_ST_ATIME_NSEC(*st) > GET_ST_MTIME_NSEC(*st) :
+        	st->st_atime > st->st_mtime;
+#else
 	return !((st = getstat(left)) && st->st_atime <= st->st_mtime);
+#endif
     case 't':
 	return !isatty(mathevali(left));
     case COND_NT:
     case COND_OT:
 	{
 	    time_t a;
+#ifdef GET_ST_MTIME_NSEC
+	    long nsecs;
+#endif
 
 	    if (!(st = getstat(left)))
 		return 1;
 	    a = st->st_mtime;
+#ifdef GET_ST_MTIME_NSEC
+	    nsecs = GET_ST_MTIME_NSEC(*st);
+#endif
 	    if (!(st = getstat(right)))
 		return 1;
+#ifdef GET_ST_MTIME_NSEC
+	    if (a == st->st_mtime) {
+                return !((ctype == COND_NT) ? nsecs > GET_ST_MTIME_NSEC(*st) :
+                        nsecs < GET_ST_MTIME_NSEC(*st));
+	    }
+#endif
 	    return !((ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime);
 	}
     case COND_EF:
diff --git a/Src/glob.c b/Src/glob.c
index b703926a9..e81fd1e97 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -52,6 +52,18 @@ struct gmatch {
     long _mtime;
     long _ctime;
     long _links;
+#ifdef GET_ST_ATIME_NSEC
+    long ansec;
+    long _ansec;
+#endif
+#ifdef GET_ST_MTIME_NSEC
+    long mnsec;
+    long _mnsec;
+#endif
+#ifdef GET_ST_CTIME_NSEC
+    long cnsec;
+    long _cnsec;
+#endif
 };
 
 #define GS_NAME   1
@@ -373,6 +385,15 @@ insert(char *s, int checked)
 	    matchptr->mtime = buf.st_mtime;
 	    matchptr->ctime = buf.st_ctime;
 	    matchptr->links = buf.st_nlink;
+#ifdef GET_ST_ATIME_NSEC
+	    matchptr->ansec = GET_ST_ATIME_NSEC(buf);
+#endif
+#ifdef GET_ST_MTIME_NSEC
+	    matchptr->mnsec = GET_ST_MTIME_NSEC(buf);
+#endif
+#ifdef GET_ST_CTIME_NSEC
+	    matchptr->cnsec = GET_ST_CTIME_NSEC(buf);
+#endif
 	}
 	if (statted & 2) {
 	    matchptr->_size = buf2.st_size;
@@ -380,6 +401,15 @@ insert(char *s, int checked)
 	    matchptr->_mtime = buf2.st_mtime;
 	    matchptr->_ctime = buf2.st_ctime;
 	    matchptr->_links = buf2.st_nlink;
+#ifdef GET_ST_ATIME_NSEC
+	    matchptr->_ansec = GET_ST_ATIME_NSEC(buf);
+#endif
+#ifdef GET_ST_MTIME_NSEC
+	    matchptr->_mnsec = GET_ST_MTIME_NSEC(buf);
+#endif
+#ifdef GET_ST_CTIME_NSEC
+	    matchptr->_cnsec = GET_ST_CTIME_NSEC(buf);
+#endif
 	}
 	matchptr++;
 
@@ -885,12 +915,24 @@ gmatchcmp(Gmatch a, Gmatch b)
 	    break;
 	case GS_ATIME:
 	    r = a->atime - b->atime;
+#ifdef GET_ST_ATIME_NSEC
+            if (!r)
+              r = a->ansec - b->ansec;
+#endif
 	    break;
 	case GS_MTIME:
 	    r = a->mtime - b->mtime;
+#ifdef GET_ST_MTIME_NSEC
+            if (!r)
+              r = a->mnsec - b->mnsec;
+#endif
 	    break;
 	case GS_CTIME:
 	    r = a->ctime - b->ctime;
+#ifdef GET_ST_CTIME_NSEC
+            if (!r)
+              r = a->cnsec - b->cnsec;
+#endif
 	    break;
 	case GS_LINKS:
 	    r = b->links - a->links;
@@ -900,12 +942,24 @@ gmatchcmp(Gmatch a, Gmatch b)
 	    break;
 	case GS__ATIME:
 	    r = a->_atime - b->_atime;
+#ifdef GET_ST_ATIME_NSEC
+            if (!r)
+              r = a->_ansec - b->_ansec;
+#endif
 	    break;
 	case GS__MTIME:
 	    r = a->_mtime - b->_mtime;
+#ifdef GET_ST_MTIME_NSEC
+            if (!r)
+              r = a->_mnsec - b->_mnsec;
+#endif
 	    break;
 	case GS__CTIME:
 	    r = a->_ctime - b->_ctime;
+#ifdef GET_ST_CTIME_NSEC
+            if (!r)
+              r = a->_cnsec - b->_cnsec;
+#endif
 	    break;
 	case GS__LINKS:
 	    r = b->_links - a->_links;
diff --git a/Src/system.h b/Src/system.h
index 022ace250..2d89ac80e 100644
--- a/Src/system.h
+++ b/Src/system.h
@@ -805,3 +805,24 @@ extern short ospeed;
 # define USE_GETPWUID
 #endif
 
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_ATIMENSEC
+# define GET_ST_ATIME_NSEC(st) (st).st_atimensec
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+# define GET_ST_MTIME_NSEC(st) (st).st_mtimensec
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctim.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_CTIMESPEC_TV_NSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctimespec.tv_nsec
+#elif HAVE_STRUCT_STAT_ST_CTIMENSEC
+# define GET_ST_CTIME_NSEC(st) (st).st_ctimensec
+#endif
diff --git a/configure.ac b/configure.ac
index 83fda70b8..f42b90994 100644
--- a/configure.ac
+++ b/configure.ac
@@ -977,6 +977,17 @@ if test x$zsh_cv_type_sigset_t = xno; then
   AC_DEFINE(sigset_t, unsigned int)
 fi
 
+dnl check structures for high resolution timestamps
+AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec,
+                  struct stat.st_atimespec.tv_nsec,
+                  struct stat.st_atimensec,
+                  struct stat.st_mtim.tv_nsec,
+                  struct stat.st_mtimespec.tv_nsec,
+                  struct stat.st_mtimensec,
+                  struct stat.st_ctim.tv_nsec,
+                  struct stat.st_ctimespec.tv_nsec,
+                  struct stat.st_ctimensec])
+
 dnl Check for struct timezone since some old SCO versions do not define it
 zsh_TYPE_EXISTS([
 #ifdef HAVE_SYS_TIME_H