Subject: kern/2004: stat of msdosfs time off by up to 29 seconds
To: None <gnats-bugs@NetBSD.ORG>
From: None <johnh@wheaton.edu>
List: netbsd-bugs
Date: 01/31/1996 10:50:06
>Number:         2004
>Category:       kern
>Synopsis:       stat of msdosfs time off by up to 29 seconds
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 31 12:35:11 1996
>Last-Modified:
>Originator:     John Hayward
>Organization:
Wheaton College
	
>Release:        1.1
>Environment:
i386, NetBSD 1-1,
	
System: NetBSD scilab1.wheaton.edu 1.1 NetBSD 1.1 (SCI_LAB) #0: Wed Jan 24 22:38:21 CST 1996 johnh@scilab12.wheaton.edu:/usr/src/sys/arch/i386/compile/SCI_LAB i386


>Description:
	
	The times comming back from stat and friends of a file on a msdosfs
can be low between 0 and 29 seconds.  This was first discovered in attempting
to use rdist to get two msdos partitions in sync.  It was further verified
by writing a short program which first uses stat to find out the times
of the file then uses utimes to set the times to the time reported by
stat and finally to re stat the files which results in small differences
in the times of when the files were orginally stated.

         Apparently in the msdos system times are keept in bit fields and
aparently there was not enough space to store the seconds so they allocated
5 bits for the seconds area and store the number of 2 seconds in that field.
In sys/msdosfs/msdos_conv.c the routine which converts from msdos time
format to seconds has omitted a multipling factor of 2 for the seconds
field which results in the time being between 0 and 29 lower than they
should.
>How-To-Repeat:
	
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
main(){
struct stat sb;
struct timeval times[2];

   stat("/c:/test", &sb);
   printf("atime is %x, mtime is %x\n",sb.st_atime, sb.st_mtime);
   printf("atime is %x nanosec, mtime is %x nanosec\n",
          sb.st_atimespec.ts_nsec, sb.st_mtimespec.ts_nsec);
   times[0].tv_sec = sb.st_atime;
   times[0].tv_usec = 0;
   times[1].tv_sec = sb.st_mtime;
   times[1].tv_usec = 0;
   utimes("/c:/test", &times);
   stat("/c:/test", &sb);
   printf("atime is %x, mtime is %x\n",sb.st_atime, sb.st_mtime);
   printf("atime is %x nanosec, mtime is %x nanosec\n",
          sb.st_atimespec.ts_nsec, sb.st_mtimespec.ts_nsec);
}  

This program assumes the existance of /c:/test and touching that file
between runs will result in differences in the times reported.
Fix:
	<how to correct or work around the problem, if known (multiple lines)>
in: /usr/src/sys/msdosfs/msdosfs_conv.c line 156
modify to read:
================================================================vvvv==========
        seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2
            + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60 
            + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600;
=============================================================================
Note: the * 2 is omitted in the original code.
johnh...
>Fix:
>Audit-Trail:
>Unformatted: