svn commit: r246217 - head/sys/fs/msdosfs

Konstantin Belousov kib at FreeBSD.org
Fri Feb 1 18:06:07 UTC 2013


Author: kib
Date: Fri Feb  1 18:06:06 2013
New Revision: 246217
URL: http://svnweb.freebsd.org/changeset/base/246217

Log:
  The directory entry for dotdot was corrupted in the FAT32 case when moving
  a directory to a subdir of the root directory from somewhere else.
  
  For all directory moves that change the parent directory, the dotdot
  entry must be fixed up.  For msdosfs, the root directory is magic for
  non-FAT32.  It is less magic for FAT32, but needs the same magic for
  the dotdot fixup.  It didn't have it.
  
  Both chkdsk and fsck_msdosfs fix the corrupt directory entries with no
  problems.
  
  The fix is to use the same magic for dotdot in msdosfs_rename() as in
  msdosfs_mkdir().
  
  For msdosfs_mkdir(), document the magic. When writing the dotdot entry
  in mkdir, use explicitly set pcl variable instead on relying on the
  start cluster of the root directory typically has a value < 65536.
  
  Submitted by:	bde
  MFC after:	1 week

Modified:
  head/sys/fs/msdosfs/msdosfs_vnops.c

Modified: head/sys/fs/msdosfs/msdosfs_vnops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Feb  1 18:01:03 2013	(r246216)
+++ head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Feb  1 18:06:06 2013	(r246217)
@@ -973,7 +973,7 @@ msdosfs_rename(ap)
 	u_char to_count;
 	int doingdirectory = 0, newparent = 0;
 	int error;
-	u_long cn;
+	u_long cn, pcl;
 	daddr_t bn;
 	struct denode *fddep;	/* from file's parent directory	 */
 	struct msdosfsmount *pmp;
@@ -1246,9 +1246,12 @@ abortit:
 			goto bad;
 		}
 		dotdotp = (struct direntry *)bp->b_data + 1;
-		putushort(dotdotp->deStartCluster, dp->de_StartCluster);
+		pcl = dp->de_StartCluster;
+		if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
+			pcl = MSDOSFSROOT;
+		putushort(dotdotp->deStartCluster, pcl);
 		if (FAT32(pmp))
-			putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
+			putushort(dotdotp->deHighClust, pcl >> 16);
 		if (DOINGASYNC(fvp))
 			bdwrite(bp);
 		else if ((error = bwrite(bp)) != 0) {
@@ -1369,8 +1372,13 @@ msdosfs_mkdir(ap)
 	putushort(denp[0].deMDate, ndirent.de_MDate);
 	putushort(denp[0].deMTime, ndirent.de_MTime);
 	pcl = pdep->de_StartCluster;
+	/*
+	 * Although the root directory has a non-magic starting cluster
+	 * number for FAT32, chkdsk and fsck_msdosfs still require
+	 * references to it in dotdot entries to be magic.
+	 */
 	if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
-		pcl = 0;
+		pcl = MSDOSFSROOT;
 	putushort(denp[1].deStartCluster, pcl);
 	putushort(denp[1].deCDate, ndirent.de_CDate);
 	putushort(denp[1].deCTime, ndirent.de_CTime);
@@ -1380,7 +1388,7 @@ msdosfs_mkdir(ap)
 	putushort(denp[1].deMTime, ndirent.de_MTime);
 	if (FAT32(pmp)) {
 		putushort(denp[0].deHighClust, newcluster >> 16);
-		putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16);
+		putushort(denp[1].deHighClust, pcl >> 16);
 	}
 
 	if (DOINGASYNC(ap->a_dvp))


More information about the svn-src-head mailing list