Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Jul 2006 21:03:26 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Robert Watson <rwatson@FreeBSD.org>
Cc:        Christoph Hellwig <hch@infradead.org>, Craig Rodrigues <rodrigc@crodrigues.org>, freebsd-current@FreeBSD.org, freebsd-arch@FreeBSD.org
Subject:   Re: [RFC] mount can figure out fstype automatically
Message-ID:  <20060713204716.D23325@delplex.bde.org>
In-Reply-To: <20060711124356.Y78628@fledge.watson.org>
References:  <20060708152801.GA3671@crodrigues.org> <44AFD7DF.8090002@errno.com> <20060708174606.GA29602@infradead.org> <44B2A51A.4040103@samsco.org> <20060710202219.GA29786@infradead.org> <20060711124356.Y78628@fledge.watson.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 11 Jul 2006, Robert Watson wrote:

> In both FreeBSD and Darwin, I've noticed that the kernel msdosfs code is 
> excessively permissive as to what it considers a FAT file system.  This is 
> presumably necessary due to the enourmous diversity of FAT file systems 
> floating around, but it makes it a little too easy to cause msdos to trip 
> over layouts that violate its layout assumptions. :-)  FAT is much more 
> reliably detected by looking at the partition type it lives in than by 
> looking at the bytes that appear inside the partition, I believe.

Um, most msdosfs file systems are on floppies so they don't even have a
partition.

Msdosfs can be very reliably detected from the bpb provided the bpb isn't
uncleared garbage left from a previous file system, but the checks aren't
very cocomplete and people keep relaxing them.  In the old version that
I use, the checks are mainly:

% #ifndef MSDOSFS_NOCHECKSIG
% 	if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
% 	    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
% 		error = EINVAL;
% 		goto error_exit;
% 	}
% #endif

Was relaxed.

% [... a few too many assignments before checking anything]

% 	/* XXX - We should probably check more values here */
% 	if (!pmp->pm_BytesPerSec || !SecPerClust
% 		|| !pmp->pm_Heads
% #ifdef PC98
%     		|| !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 255) {
% #else
% 		|| !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 63) {
% #endif
% 		error = EINVAL;
% 		goto error_exit;
% 	}

Not a very good check.

% 	if (pmp->pm_Sectors == 0) {
% 		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
% 		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
% 	} else {
% 		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
% 		pmp->pm_HugeSectors = pmp->pm_Sectors;
% 	}

Not a consistency check, but how the extension works.

% 	if (pmp->pm_HugeSectors > 0xffffffff / 
% 	    (pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) {
% 		/*
% 		 * We cannot deal currently with this size of disk
% 		 * due to fileid limitations (see msdosfs_getattr and
% 		 * msdosfs_readdir)
% 		 */
% 		error = EINVAL;
% 		printf("mountmsdosfs(): disk too big, sorry\n");
% 		goto error_exit;
% 	}

Consistency check only as a side effect.

% 
% 	if (pmp->pm_RootDirEnts == 0) {
% 		if (bsp->bs710.bsBootSectSig2 != BOOTSIG2
% 		    || bsp->bs710.bsBootSectSig3 != BOOTSIG3
% 		    || pmp->pm_Sectors
% 		    || pmp->pm_FATsecs
% 		    || getushort(b710->bpbFSVers)) {
% 			error = EINVAL;
% 			printf("mountmsdosfs(): bad FAT32 filesystem\n");
% 			goto error_exit;
% 		}

Not a very good consistency check.

% 		pmp->pm_fatmask = FAT32_MASK;
% 		pmp->pm_fatmult = 4;
% 		pmp->pm_fatdiv = 1;
% 		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
% 		if (getushort(b710->bpbExtFlags) & FATMIRROR)
% 			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
% 		else
% 			pmp->pm_flags |= MSDOSFS_FATMIRROR;
% 	} else
% 		pmp->pm_flags |= MSDOSFS_FATMIRROR;
% 
% 	/*
% 	 * Check a few values (could do some more):
% 	 * - logical sector size: power of 2, >= block size
% 	 * - sectors per cluster: power of 2, >= 1
% 	 * - number of sectors:   >= 1, <= size of partition
% 	 * - number of FAT sectors: >= 1
% 	 */
% 	if ( (SecPerClust == 0)
% 	  || (SecPerClust & (SecPerClust - 1))
% 	  || (pmp->pm_BytesPerSec < DEV_BSIZE)
% 	  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
% 	  || (pmp->pm_HugeSectors == 0)
% 	  || (pmp->pm_FATsecs == 0)
% 	) {
% 		error = EINVAL;
% 		goto error_exit;
% 	}

More not very good consistency checks.

Better checks would determine the location of the FAT and root directory
and check that is there.

% 	if (pmp->pm_fatmask == 0) {
% 		if (pmp->pm_maxcluster
% 		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
% 			/*
% 			 * This will usually be a floppy disk. This size makes
% 			 * sure that one fat entry will not be split across
% 			 * multiple blocks.
% 			 */
% 			pmp->pm_fatmask = FAT12_MASK;
% 			pmp->pm_fatmult = 3;
% 			pmp->pm_fatdiv = 2;
% 		} else {
% 			pmp->pm_fatmask = FAT16_MASK;
% 			pmp->pm_fatmult = 2;
% 			pmp->pm_fatdiv = 1;
% 		}
% 	}

We do check the FAT, but default to FAT16 if it doesn't lool like FAT12.

% [... a few more]

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060713204716.D23325>