Subject: Fix for PR kern/2187 (msdosfs w/Win95 support tries to keep access
To: None <netbsd-bugs@NetBSD.ORG>
From: Dave Huang <khym@bga.com>
List: current-users
Date: 04/27/1997 16:21:52
Okay, after seeing Jason Thorpe's comment about PRs with patches being
fixed faster than those without (and waiting over a year :), here's a
patch for kern/2187...

I couldn't find any detailed "official" docs on the structure of a
VFAT directory entry, so I used the brief description from the Windows
NT resource kit (Figure 17.7, p. 571) and the Linux VFAT
implementation as my documentation. It seems to work fine for me; NT's
chkdsk no longer complains "Unrecognized extended attribute handle",
and creation timestamps now have 100th of a second accuracy.

diff -ur /usr/src/sys/msdosfs/denode.h ./denode.h
--- /usr/src/sys/msdosfs/denode.h	Sat Apr 12 06:42:53 1997
+++ ./denode.h	Sun Apr 27 16:13:05 1997
@@ -151,10 +151,10 @@
 	pid_t de_lockwaiter;	/* lock wanter */
 	u_char de_Name[12];	/* name, from DOS directory entry */
 	u_char de_Attributes;	/* attributes, from directory entry */
+	u_char de_CTimeHundredth; /* creation time, 1/100th of a sec */
 	u_short de_CTime;	/* creation time */
 	u_short de_CDate;	/* creation date */
 	u_short de_ADate;	/* access date */
-	u_short de_ATime;	/* access time */
 	u_short de_MTime;	/* modification time */
 	u_short de_MDate;	/* modification date */
 	u_short de_StartCluster; /* starting cluster of file */
@@ -187,9 +187,9 @@
 #define DE_INTERNALIZE(dep, dp)			\
 	(bcopy((dp)->deName, (dep)->de_Name, 11),	\
 	 (dep)->de_Attributes = (dp)->deAttributes,	\
+	 (dep)->de_CTimeHundredth = (dp)->deCTimeHundredth, \
 	 (dep)->de_CTime = getushort((dp)->deCTime),	\
 	 (dep)->de_CDate = getushort((dp)->deCDate),	\
-	 (dep)->de_ATime = getushort((dp)->deATime),	\
 	 (dep)->de_ADate = getushort((dp)->deADate),	\
 	 (dep)->de_MTime = getushort((dp)->deMTime),	\
 	 (dep)->de_MDate = getushort((dp)->deMDate),	\
@@ -199,10 +199,13 @@
 #define DE_EXTERNALIZE(dp, dep)				\
 	(bcopy((dep)->de_Name, (dp)->deName, 11),	\
 	 (dp)->deAttributes = (dep)->de_Attributes,	\
+	 (dp)->deLowerCase = CASE_LOWER_BASE | CASE_LOWER_EXT,	\
+	 (dp)->deCTimeHundredth = (dep)->de_CTimeHundredth, \
 	 putushort((dp)->deCTime, (dep)->de_CTime),	\
 	 putushort((dp)->deCDate, (dep)->de_CDate),	\
-	 putushort((dp)->deATime, (dep)->de_ATime),	\
 	 putushort((dp)->deADate, (dep)->de_ADate),	\
+	 (dp)->deReserved[0] = 0,			\
+	 (dp)->deReserved[1] = 0,			\
 	 putushort((dp)->deMTime, (dep)->de_MTime),	\
 	 putushort((dp)->deMDate, (dep)->de_MDate),	\
 	 putushort((dp)->deStartCluster, (dep)->de_StartCluster), \
@@ -226,9 +229,11 @@
 		} \
 		if (!((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)) { \
 			if ((dep)->de_flag & DE_ACCESS) \
-				unix2dostime((acc), &(dep)->de_ADate, &(dep)->de_ATime); \
-			if ((dep)->de_flag & DE_CREATE) \
+				unix2dostime((acc), &(dep)->de_ADate, NULL); \
+			if ((dep)->de_flag & DE_CREATE) { \
 				unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime); \
+				(dep)->de_CTimeHundredth = ((cre)->tv_sec & 1 ? 100 : 0) + (cre)->tv_nsec / 10000000; \
+			} \
 		} \
 		(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
 	}
diff -ur /usr/src/sys/msdosfs/direntry.h ./direntry.h
--- /usr/src/sys/msdosfs/direntry.h	Sat Oct 26 06:21:01 1996
+++ ./direntry.h	Sun Apr 27 16:11:26 1997
@@ -64,11 +64,14 @@
 #define	ATTR_VOLUME	0x08		/* entry is a volume label */
 #define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
 #define	ATTR_ARCHIVE	0x20		/* file is new or modified */
-	u_int8_t	deReserved[2];	/* reserved */
+	u_int8_t	deLowerCase;	/* case for base and extension */
+#define	CASE_LOWER_BASE	0x08		/* base is lower case */
+#define	CASE_LOWER_EXT	0x10		/* extension is lower case */
+	u_int8_t	deCTimeHundredth; /* create time, 1/100th of a sec */
 	u_int8_t	deCTime[2];	/* create time */
 	u_int8_t	deCDate[2];	/* create date */
 	u_int8_t	deADate[2];	/* access date */
-	u_int8_t	deATime[2];	/* access time */
+	u_int8_t	deReserved[2];	/* reserved */
 	u_int8_t	deMTime[2];	/* last update time */
 	u_int8_t	deMDate[2];	/* last update date */
 	u_int8_t	deStartCluster[2]; /* starting cluster of file */
diff -ur /usr/src/sys/msdosfs/msdosfs_conv.c ./msdosfs_conv.c
--- /usr/src/sys/msdosfs/msdosfs_conv.c	Wed Jan 15 06:23:19 1997
+++ ./msdosfs_conv.c	Sun Apr 27 12:51:46 1997
@@ -150,7 +150,9 @@
 				lastddate += (year - 1980) << DD_YEAR_SHIFT;
 		}
 	}
-	*dtp = lastdtime;
+
+	if (dtp != NULL)
+		*dtp = lastdtime;
 	*ddp = lastddate;
 }
 
diff -ur /usr/src/sys/msdosfs/msdosfs_denode.c ./msdosfs_denode.c
--- /usr/src/sys/msdosfs/msdosfs_denode.c	Mon Oct 14 11:42:15 1996
+++ ./msdosfs_denode.c	Sun Apr 27 16:10:07 1997
@@ -240,10 +240,10 @@
 		 * denode
 		 */
 		ldep->de_CTime = 0x0000;	/* 00:00:00	 */
+		ldep->de_CTimeHundredth = 0;
 		ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
 		    | (1 << DD_DAY_SHIFT);
 		/* Jan 1, 1980	 */
-		ldep->de_ATime = ldep->de_CTime;
 		ldep->de_ADate = ldep->de_CDate;
 		ldep->de_MTime = ldep->de_CTime;
 		ldep->de_MDate = ldep->de_CDate;
diff -ur /usr/src/sys/msdosfs/msdosfs_vnops.c ./msdosfs_vnops.c
--- /usr/src/sys/msdosfs/msdosfs_vnops.c	Sat Nov  9 06:20:26 1996
+++ ./msdosfs_vnops.c	Sun Apr 27 16:10:56 1997
@@ -301,8 +301,14 @@
 	vap->va_size = dep->de_FileSize;
 	dos2unixtime(dep->de_MDate, dep->de_MTime, &vap->va_mtime);
 	if (dep->de_pmp->pm_flags & MSDOSFSMNT_LONGNAME) {
-		dos2unixtime(dep->de_ADate, dep->de_ATime, &vap->va_atime);
+		dos2unixtime(dep->de_ADate, 0, &vap->va_atime);
 		dos2unixtime(dep->de_CDate, dep->de_CTime, &vap->va_ctime);
+		if (dep->de_CTimeHundredth >= 100) {
+			vap->va_ctime.tv_sec++;
+			vap->va_ctime.tv_nsec = (dep->de_CTimeHundredth - 100) * 10000000;
+		} else
+			vap->va_ctime.tv_nsec = dep->de_CTimeHundredth * 10000000; 
+
 	} else {
 		vap->va_atime = vap->va_mtime;
 		vap->va_ctime = vap->va_mtime;
@@ -372,7 +378,7 @@
 			return (error);
 		if (!(dep->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)
 		    && vap->va_atime.tv_sec != VNOVAL)
-			unix2dostime(&vap->va_atime, &dep->de_ADate, &dep->de_ATime);
+			unix2dostime(&vap->va_atime, &dep->de_ADate, NULL);
 		if (vap->va_mtime.tv_sec != VNOVAL)
 			unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime);
 		dep->de_Attributes |= ATTR_ARCHIVE;
@@ -1169,18 +1175,22 @@
 } dosdirtemplate = {
 	{	".       ", "   ",			/* the . entry */
 		ATTR_DIRECTORY,				/* file attribute */
-		{ 0, 0 }, 				/* reserved */
+		CASE_LOWER_BASE | CASE_LOWER_EXT,	/* lower case */
+		0,					/* create time 100ths */
 		{ 0, 0 }, { 0, 0 },			/* create time & date */
-		{ 0, 0 }, { 0, 0 },			/* access time & date */
+		{ 0, 0 },	 			/* access date */
+		{ 0, 0 },				/* reserved */
 		{ 210, 4 }, { 210, 4 },			/* modify time & date */
 		{ 0, 0 },				/* startcluster */
 		{ 0, 0, 0, 0 } 				/* filesize */
 	},
 	{	"..      ", "   ",			/* the .. entry */
 		ATTR_DIRECTORY,				/* file attribute */
-		{ 0, 0 }, 				/* reserved */
+		CASE_LOWER_BASE | CASE_LOWER_EXT,	/* lower case */
+		0,					/* create time 100ths */
 		{ 0, 0 }, { 0, 0 },			/* create time & date */
-		{ 0, 0 }, { 0, 0 },			/* access time & date */
+		{ 0, 0 },				/* access date */
+		{ 0, 0 },				/* reserved */
 		{ 210, 4 }, { 210, 4 },			/* modify time & date */
 		{ 0, 0 },				/* startcluster */
 		{ 0, 0, 0, 0 }				/* filesize */
@@ -1247,15 +1257,15 @@
 	putushort(denp[0].deStartCluster, newcluster);
 	putushort(denp[0].deCDate, ndirent.de_CDate);
 	putushort(denp[0].deCTime, ndirent.de_CTime);
+	denp[0].deCTimeHundredth = ndirent.de_CTimeHundredth;
 	putushort(denp[0].deADate, ndirent.de_ADate);
-	putushort(denp[0].deATime, ndirent.de_ATime);
 	putushort(denp[0].deMDate, ndirent.de_MDate);
 	putushort(denp[0].deMTime, ndirent.de_MTime);
 	putushort(denp[1].deStartCluster, pdep->de_StartCluster);
 	putushort(denp[1].deCDate, ndirent.de_CDate);
 	putushort(denp[1].deCTime, ndirent.de_CTime);
+	denp[1].deCTimeHundredth = ndirent.de_CTimeHundredth;
 	putushort(denp[1].deADate, ndirent.de_ADate);
-	putushort(denp[1].deATime, ndirent.de_ATime);
 	putushort(denp[1].deMDate, ndirent.de_MDate);
 	putushort(denp[1].deMTime, ndirent.de_MTime);
 	if ((error = bwrite(bp)) != 0)

Name: Dave Huang     |   Mammal, mammal / their names are called /
INet: khym@bga.com   |   they raise a paw / the bat, the cat /
FurryMUCK: Dahan     |   dolphin and dog / koala bear and hog -- TMBG
Dahan: Hani G Y+C 21 Y++ L+++ W- C++ T++ A+ E+ S++ V++ F- Q+++ P+ B+ PA+ PL++