Date: Wed, 29 Nov 2006 16:30:53 +0100 (CET) From: Oliver Fromme <olli@secnetix.de> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Oliver Fromme <olli@secnetix.de> Subject: kern/106018: [PATCH] msdosfs: fix handling of mtime, ctime and birthtime Message-ID: <200611291530.kATFUrhW077559@lurza.secnetix.de> Resent-Message-ID: <200611291540.kATFeFqR040590@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611291530.kATFUrhW077559>