Date: Sat, 08 May 2004 21:55:48 +0900 From: "Akinori MUSHA" <knu@iDaemons.org> To: current@FreeBSD.org, audit@FreeBSD.org Subject: making test(1)'s -nt/-ot ignore nanosecond fractions Message-ID: <86smebgjsb.knu@iDaemons.org>
next in thread | raw e-mail | index | archive | help
Hello, I faced an odd situation regarding file timestamps: knu@archon[2]% sh $ ls a b a b $ touch -r a b $ [ a -nt b ] && echo "D'oh!" D'oh! $ touch -r a a $ [ a -nt b ] || echo "Nah, how did it fix?" Nah, how did it fix? (Note that this is only rarely reproducible) I tracked it down and found out some facts: - File timestamps are recorded in nanoseconds on a UFS, and sometimes a file's timestamp actually has >1000 nanosecond (= >1 microsecond) value. - Stat(2) offers a file's mtime in nanoseconds through st_mtimespec.tv_nsec. - sh(1)'s builtin test command, which entity is test(1), compares times strictly in nanoseconds when seconds match. - On the other hand, there is no API to set a file's mtime in nanoseconds; utimes(2) takes time values in microseconds, and utime(3), which just calls utimes, takes time values in seconds. - Which means touch(1) or any other userland tool can only set a file's mtime in microseconds at most. - So, copying timestamps from a file "a" to a file "b" leaves a under-microsecond fraction only in "a", and after the copy "a" is "newer" than "b" by test(1). In order to fix this, we could consider adding a syscall or extend utimes(2) to take nanoseconds, but I'm afraid it would take a long time before it becomes available on -STABLE and the API spread over third-party applications. So, I'd suggest the following simple fix to make test(1) ignore such nanosecond fractions as a temporary measure: Index: test.c =================================================================== RCS file: /mirror/freebsd/ncvs/root/src/src/bin/test/test.c,v retrieving revision 1.52 diff -u -r1.52 test.c --- test.c 19 Aug 2002 09:19:31 -0000 1.52 +++ test.c 7 May 2004 17:06:54 -0000 @@ -527,7 +527,7 @@ if (b1.st_mtimespec.tv_sec < b2.st_mtimespec.tv_sec) return 0; - return (b1.st_mtimespec.tv_nsec > b2.st_mtimespec.tv_nsec); + return (b1.st_mtimespec.tv_nsec / 1000 > b2.st_mtimespec.tv_nsec / 1000); } static int Fortunately, bash and zsh behave the same way, as nanosecond times support is so heavily system dependent they give up to care about, which means the above change only makes test(1) compatible with other shells and would cause any harm. IMHO, no userland tool should care about nanosecond fractions when there is no API to set times in nanoseconds. Opinions? -- / /__ __ Akinori.org / MUSHA.org / ) ) ) ) / FreeBSD.org / Ruby-lang.org Akinori MUSHA aka / (_ / ( (__( @ iDaemons.org / and.or.jp "It seems to me as we make our own few circles 'round the sun We get it backwards and our seven years go by like one"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86smebgjsb.knu>