kern/106018: [PATCH] msdosfs: fix handling of mtime, ctime and birthtime

Oliver Fromme olli at secnetix.de
Wed Nov 29 07:43:54 PST 2006


>Number:         106018
>Category:       kern
>Synopsis:       [PATCH] msdosfs: fix handling of mtime, ctime and birthtime
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 29 15:40:14 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Oliver Fromme
>Release:        RELENG_6 + HEAD
>Organization:
secnetix GmbH & Co. KG
		http://www.secnetix.de/bsd
>Environment:
	This PR provides patches for RELENG_6 and HEAD
	(as of 2006-11-29).  However, the problem seems
	to exist for as long as FreeBSD has msdosfs.

>Description:

	A recent thread in the freebsd-fs mailing list
	reveals that src/sys/fs/msdosfs/msdosfs_vnops.c
	has a bug handling ctime, mtime and birthtime
	time stamps.  The cause of the bug is probably
	the confusing fact that the FAT world calls the
	birthtime "CTime" (creation time), while it does
	not support at all what UNIX calls the ctime.

	As a result from that confusion, the function
	msdosfs_getattr() sets ctime field to the "CTime"
	of the FAT entry (which is really the birthtime),
	and doesn't set the birthtime in the struct vattr
	at all, returning garbage.

	The patch below fixes the problem as follows:
	First, the ctime (which FAT doesn't support) is
	always set equal to the mtime.
	Second, in the MSDOSFSMNT_LONGNAME case, the
	birthtime is taken from the FAT's "CTime", and
	in the other case (unsupported) it is set to -1
	which should be a reasonable value.

	Bruce Evans asked me to record the whole thing
	via send-pr, so here it is.

>How-To-Repeat:

	Mount an msdosfs (you can easily create one with
	mdconfig + newfs_msdos, or use a USB stick with
	a FAT on it if you have one handy), touch a file
	in it, and check the birthtime with "ls -lU".

>Fix:

Patch for RELENG_6:

--- src/sys/fs/msdosfs/msdosfs_vnops.c.orig	Mon Mar 13 04:05:13 2006
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	Wed Nov 29 15:51:20 2006
@@ -341,12 +341,15 @@
 	vap->va_rdev = 0;
 	vap->va_size = dep->de_FileSize;
 	dos2unixtime(dep->de_MDate, dep->de_MTime, 0, &vap->va_mtime);
+	vap->va_ctime = vap->va_mtime;
 	if (pmp->pm_flags & MSDOSFSMNT_LONGNAME) {
 		dos2unixtime(dep->de_ADate, 0, 0, &vap->va_atime);
-		dos2unixtime(dep->de_CDate, dep->de_CTime, dep->de_CHun, &vap->va_ctime);
+		dos2unixtime(dep->de_CDate, dep->de_CTime, dep->de_CHun,
+		    &vap->va_birthtime);
 	} else {
 		vap->va_atime = vap->va_mtime;
-		vap->va_ctime = vap->va_mtime;
+		vap->va_birthtime.tv_sec = -1;
+		vap->va_birthtime.tv_nsec = 0;
 	}
 	vap->va_flags = 0;
 	if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)

Patch for HEAD (untested!):

--- src/sys/fs/msdosfs/msdosfs_vnops.c.orig	Mon Nov  6 14:41:57 2006
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	Wed Nov 29 16:13:19 2006
@@ -343,13 +343,15 @@
 	vap->va_rdev = 0;
 	vap->va_size = dep->de_FileSize;
 	fattime2timespec(dep->de_MDate, dep->de_MTime, 0, 0, &vap->va_mtime);
+	vap->va_ctime = vap->va_mtime;
 	if (pmp->pm_flags & MSDOSFSMNT_LONGNAME) {
 		fattime2timespec(dep->de_ADate, 0, 0, 0, &vap->va_atime);
 		fattime2timespec(dep->de_CDate, dep->de_CTime, dep->de_CHun,
-		    0, &vap->va_ctime);
+		    0, &vap->va_birthtime);
 	} else {
 		vap->va_atime = vap->va_mtime;
-		vap->va_ctime = vap->va_mtime;
+		vap->va_birthtime.tv_sec = -1;
+		vap->va_birthtime.tv_nsec = 0;
 	}
 	vap->va_flags = 0;
 	if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list