diff options
-rw-r--r-- | sys/msdosfs/bootsect.h | 53 | ||||
-rw-r--r-- | sys/msdosfs/bpb.h | 72 | ||||
-rw-r--r-- | sys/msdosfs/denode.h | 38 | ||||
-rw-r--r-- | sys/msdosfs/direntry.h | 14 | ||||
-rw-r--r-- | sys/msdosfs/fat.h | 35 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_conv.c | 25 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_denode.c | 50 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_fat.c | 241 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_lookup.c | 80 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 149 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vnops.c | 110 | ||||
-rw-r--r-- | sys/msdosfs/msdosfsmount.h | 22 |
12 files changed, 636 insertions, 253 deletions
diff --git a/sys/msdosfs/bootsect.h b/sys/msdosfs/bootsect.h index 16e695fce3b..d806713da44 100644 --- a/sys/msdosfs/bootsect.h +++ b/sys/msdosfs/bootsect.h @@ -1,5 +1,5 @@ -/* $OpenBSD: bootsect.h,v 1.2 1997/02/24 14:32:46 niklas Exp $ */ -/* $NetBSD: bootsect.h,v 1.7 1995/07/24 06:36:23 leo Exp $ */ +/* $OpenBSD: bootsect.h,v 1.3 1998/01/11 20:39:02 provos Exp $ */ +/* $NetBSD: bootsect.h,v 1.8 1997/10/17 11:23:29 ws Exp $ */ /* * Written by Paul Popelka (paulp@uts.amdahl.com) @@ -28,24 +28,48 @@ struct bootsector33 { int8_t bsBPB[19]; /* BIOS parameter block */ int8_t bsDriveNumber; /* drive number (0x80) */ int8_t bsBootCode[479]; /* pad so struct is 512b */ - u_int16_t bsBootSectSig; -#define BOOTSIG 0xaa55 + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct extboot { + int8_t exDriveNumber; /* drive number (0x80) */ + int8_t exReserved1; /* reserved */ + int8_t exBootSignature; /* ext. boot signature (0x29) */ +#define EXBOOTSIG 0x29 + int8_t exVolumeID[4]; /* volume ID number */ + int8_t exVolumeLabel[11]; /* volume label */ + int8_t exFileSysType[8]; /* fs type (FAT12 or FAT16) */ }; struct bootsector50 { u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ int8_t bsOemName[8]; /* OEM name and version */ int8_t bsBPB[25]; /* BIOS parameter block */ - int8_t bsDriveNumber; /* drive number (0x80) */ - int8_t bsReserved1; /* reserved */ - int8_t bsBootSignature; /* ext. boot signature (0x29) */ -#define EXBOOTSIG 0x29 - int8_t bsVolumeID[4]; /* volume ID number */ - int8_t bsVolumeLabel[11]; /* volume label */ - int8_t bsFileSysType[8]; /* fs type (FAT12 or FAT16) */ + int8_t bsExt[26]; /* Bootsector Extension */ int8_t bsBootCode[448]; /* pad so structure is 512b */ - u_int16_t bsBootSectSig; -#define BOOTSIG 0xaa55 + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +}; + +struct bootsector710 { + u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ + int8_t bsOEMName[8]; /* OEM name and version */ + int8_t bsPBP[53]; /* BIOS parameter block */ + int8_t bsExt[26]; /* Bootsector Extension */ + int8_t bsBootCode[418]; /* pad so structure is 512b */ + u_int8_t bsBootSectSig2; /* 2 & 3 are only defined for FAT32? */ + u_int8_t bsBootSectSig3; + u_int8_t bsBootSectSig0; + u_int8_t bsBootSectSig1; +#define BOOTSIG0 0x55 +#define BOOTSIG1 0xaa +#define BOOTSIG2 0 +#define BOOTSIG3 0 }; #ifdef atari /* @@ -67,8 +91,10 @@ struct bootsec_atari { union bootsector { struct bootsector33 bs33; struct bootsector50 bs50; + struct bootsector710 bs710; }; +#if 0 /* * Shorthand for fields in the bpb. */ @@ -84,3 +110,4 @@ union bootsector { #define bsHeads bsBPB.bpbHeads #define bsHiddenSecs bsBPB.bpbHiddenSecs #define bsHugeSectors bsBPB.bpbHugeSectors +#endif diff --git a/sys/msdosfs/bpb.h b/sys/msdosfs/bpb.h index 445940d924a..399e592530b 100644 --- a/sys/msdosfs/bpb.h +++ b/sys/msdosfs/bpb.h @@ -1,5 +1,5 @@ -/* $OpenBSD: bpb.h,v 1.2 1997/02/24 14:32:47 niklas Exp $ */ -/* $NetBSD: bpb.h,v 1.5 1995/07/24 06:37:15 leo Exp $ */ +/* $OpenBSD: bpb.h,v 1.3 1998/01/11 20:39:03 provos Exp $ */ +/* $NetBSD: bpb.h,v 1.6 1997/10/17 11:23:35 ws Exp $ */ /* * Written by Paul Popelka (paulp@uts.amdahl.com) @@ -53,6 +53,34 @@ struct bpb50 { u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ }; +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct bpb710 { + u_int16_t bpbBytesPerSec; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int16_t bpbResSectors; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int16_t bpbRootDirEnts; /* number of root directory entries */ + u_int16_t bpbSectors; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int16_t bpbFATsecs; /* number of sectors per FAT */ + u_int16_t bpbSecPerTrack; /* sectors per track */ + u_int16_t bpbHeads; /* number of heads */ + u_int32_t bpbHiddenSecs; /* # of hidden sectors */ + u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ + u_int16_t bpbExtFlags; /* extended flags: */ +#define FATNUM 0xf /* mask for numbering active FAT */ +#define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */ + u_int16_t bpbFSVers; /* filesystem version */ +#define FSVERS 0 /* currently only 0 is understood */ + u_int32_t bpbRootClust; /* start cluster for root directory */ + u_int16_t bpbFSInfo; /* filesystem info structure sector */ + u_int16_t bpbBackup; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +}; + #ifdef atari /* * BPB for gemdos filesystems. Atari leaves the obsolete stuff undefined. @@ -139,3 +167,43 @@ struct byte_bpb50 { int8_t bpbHiddenSecs[4]; /* number of hidden sectors */ int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ }; + +/* + * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. + */ +struct byte_bpb710 { + u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ + u_int8_t bpbSecPerClust; /* sectors per cluster */ + u_int8_t bpbResSectors[2]; /* number of reserved sectors */ + u_int8_t bpbFATs; /* number of FATs */ + u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ + u_int8_t bpbSectors[2]; /* total number of sectors */ + u_int8_t bpbMedia; /* media descriptor */ + u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ + u_int8_t bpbSecPerTrack[2]; /* sectors per track */ + u_int8_t bpbHeads[2]; /* number of heads */ + u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ + u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ + u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ + u_int8_t bpbExtFlags[2]; /* extended flags: */ + u_int8_t bpbFSVers[2]; /* filesystem version */ + u_int8_t bpbRootClust[4]; /* start cluster for root directory */ + u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ + u_int8_t bpbBackup[2]; /* backup boot sector */ + /* There is a 12 byte filler here, but we ignore it */ +}; + +/* + * FAT32 FSInfo block. + */ +struct fsinfo { + u_int8_t fsisig1[4]; + u_int8_t fsifill1[480]; + u_int8_t fsisig2[4]; + u_int8_t fsinfree[4]; + u_int8_t fsinxtfree[4]; + u_int8_t fsifill2[12]; + u_int8_t fsisig3[4]; + u_int8_t fsifill3[508]; + u_int8_t fsisig4[4]; +}; diff --git a/sys/msdosfs/denode.h b/sys/msdosfs/denode.h index e035b866bb4..1f66bf49847 100644 --- a/sys/msdosfs/denode.h +++ b/sys/msdosfs/denode.h @@ -1,9 +1,9 @@ -/* $OpenBSD: denode.h,v 1.6 1997/11/06 05:58:55 csapuntz Exp $ */ -/* $NetBSD: denode.h,v 1.20 1996/02/09 19:13:39 christos Exp $ */ +/* $OpenBSD: denode.h,v 1.7 1998/01/11 20:39:04 provos Exp $ */ +/* $NetBSD: denode.h,v 1.24 1997/10/17 11:23:39 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -103,8 +103,8 @@ * structure (fc_frcn). */ struct fatcache { - u_short fc_frcn; /* file relative cluster number */ - u_short fc_fsrcn; /* filesystem relative cluster number */ + u_long fc_frcn; /* file relative cluster number */ + u_long fc_fsrcn; /* filesystem relative cluster number */ }; /* @@ -121,7 +121,7 @@ struct fatcache { * to */ #define FC_LASTFC 1 /* entry for the last cluster in the file */ -#define FCE_EMPTY 0xffff /* doesn't represent an actual cluster # */ +#define FCE_EMPTY 0xffffffff /* doesn't represent an actual cluster # */ /* * Set a slot in the fat cache. @@ -157,7 +157,7 @@ struct denode { u_short de_ADate; /* access date */ u_short de_MTime; /* modification time */ u_short de_MDate; /* modification date */ - u_short de_StartCluster; /* starting cluster of file */ + u_long de_StartCluster; /* starting cluster of file */ u_long de_FileSize; /* size of file in bytes */ struct fatcache de_fc[FC_SIZE]; /* fat cache */ }; @@ -182,6 +182,8 @@ struct denode { * dep is a struct denode * (internal form), * dp is a struct direntry * (external form). */ +#define DE_INTERNALIZE32(dep, dp) \ + ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16) #define DE_INTERNALIZE(dep, dp) \ (bcopy((dp)->deName, (dep)->de_Name, 11), \ (dep)->de_Attributes = (dp)->deAttributes, \ @@ -192,8 +194,11 @@ struct denode { (dep)->de_MTime = getushort((dp)->deMTime), \ (dep)->de_MDate = getushort((dp)->deMDate), \ (dep)->de_StartCluster = getushort((dp)->deStartCluster), \ - (dep)->de_FileSize = getulong((dp)->deFileSize)) + (dep)->de_FileSize = getulong((dp)->deFileSize), \ + (FAT32((dep)->de_pmp) ? DE_INTERNALIZE32((dep), (dp)) : 0)) +#define DE_EXTERNALIZE32(dp, dep) \ + putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16) #define DE_EXTERNALIZE(dp, dep) \ (bcopy((dep)->de_Name, (dp)->deName, 11), \ (dp)->deAttributes = (dep)->de_Attributes, \ @@ -202,13 +207,12 @@ struct denode { putushort((dp)->deCTime, (dep)->de_CTime), \ putushort((dp)->deCDate, (dep)->de_CDate), \ 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), \ putulong((dp)->deFileSize, \ - ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize)) + ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize),\ + (FAT32((dep)->de_pmp) ? DE_EXTERNALIZE32((dp), (dep)) : 0)) #define de_forw de_chain[0] #define de_back de_chain[1] @@ -222,16 +226,14 @@ struct denode { if ((dep)->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS)) { \ (dep)->de_flag |= DE_MODIFIED; \ if ((dep)->de_flag & DE_UPDATE) { \ - unix2dostime((mod), &(dep)->de_MDate, &(dep)->de_MTime); \ + unix2dostime((mod), &(dep)->de_MDate, &(dep)->de_MTime, NULL); \ (dep)->de_Attributes |= ATTR_ARCHIVE; \ } \ if (!((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)) { \ if ((dep)->de_flag & DE_ACCESS) \ - 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; \ - } \ + unix2dostime((acc), &(dep)->de_ADate, NULL, NULL); \ + if ((dep)->de_flag & DE_CREATE) \ + unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime, &(dep)->de_CTimeHundredth); \ } \ (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \ } diff --git a/sys/msdosfs/direntry.h b/sys/msdosfs/direntry.h index 6a6a00dc147..6b35caea902 100644 --- a/sys/msdosfs/direntry.h +++ b/sys/msdosfs/direntry.h @@ -1,9 +1,9 @@ -/* $OpenBSD: direntry.h,v 1.4 1997/10/04 19:08:10 deraadt Exp $ */ -/* $NetBSD: direntry.h,v 1.11 1995/11/29 15:08:34 ws Exp $ */ +/* $OpenBSD: direntry.h,v 1.5 1998/01/11 20:39:05 provos Exp $ */ +/* $NetBSD: direntry.h,v 1.13 1997/10/17 11:23:45 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -72,7 +72,7 @@ struct direntry { u_int8_t deCTime[2]; /* create time */ u_int8_t deCDate[2]; /* create date */ u_int8_t deADate[2]; /* access date */ - u_int8_t deReserved[2]; /* reserved */ + u_int8_t deHighClust[2]; /* high byte of cluster number */ 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 */ @@ -122,8 +122,8 @@ struct winentry { #define DD_YEAR_SHIFT 9 #ifdef _KERNEL -void unix2dostime __P((struct timespec *tsp, u_int16_t *ddp, u_int16_t *dtp)); -void dos2unixtime __P((u_int dd, u_int dt, struct timespec *tsp)); +void unix2dostime __P((struct timespec *tsp, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp)); +void dos2unixtime __P((u_int dd, u_int dt, u_int dh, struct timespec *tsp)); int dos2unixfn __P((u_char dn[11], u_char *un, int lower)); int unix2dosfn __P((u_char *un, u_char dn[12], int unlen, u_int gen)); int unix2winfn __P((u_char *un, int unlen, struct winentry *wep, int cnt, int chksum)); diff --git a/sys/msdosfs/fat.h b/sys/msdosfs/fat.h index 48ac2671701..4da7af73386 100644 --- a/sys/msdosfs/fat.h +++ b/sys/msdosfs/fat.h @@ -1,9 +1,9 @@ -/* $OpenBSD: fat.h,v 1.3 1996/02/29 10:46:47 niklas Exp $ */ -/* $NetBSD: fat.h,v 1.10 1996/02/11 22:48:14 ws Exp $ */ +/* $OpenBSD: fat.h,v 1.4 1998/01/11 20:39:05 provos Exp $ */ +/* $NetBSD: fat.h,v 1.11 1997/10/17 11:23:49 ws Exp $ */ /*- - * Copyright (C) 1994 Wolfgang Solfrank. - * Copyright (C) 1994 TooLs GmbH. + * Copyright (C) 1994, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -51,18 +51,18 @@ /* * Some useful cluster numbers. */ -#define MSDOSFSROOT 0 /* cluster 0 means the root dir */ -#define CLUST_FREE 0 /* cluster 0 also means a free cluster */ +#define MSDOSFSROOT 0 /* cluster 0 means the root dir */ +#define CLUST_FREE 0 /* cluster 0 also means a free cluster */ #define MSDOSFSFREE CLUST_FREE -#define CLUST_FIRST 2 /* first legal cluster number */ -#define CLUST_RSRVS 0xfff0 /* start of reserved cluster range */ -#define CLUST_RSRVE 0xfff6 /* end of reserved cluster range */ -#define CLUST_BAD 0xfff7 /* a cluster with a defect */ -#define CLUST_EOFS 0xfff8 /* start of eof cluster range */ -#define CLUST_EOFE 0xffff /* end of eof cluster range */ +#define CLUST_FIRST 2 /* first legal cluster number */ +#define CLUST_RSRVD 0xfffffff6 /* reserved cluster range */ +#define CLUST_BAD 0xfffffff7 /* a cluster with a defect */ +#define CLUST_EOFS 0xfffffff8 /* start of eof cluster range */ +#define CLUST_EOFE 0xffffffff /* end of eof cluster range */ -#define FAT12_MASK 0x0fff /* mask for 12 bit cluster numbers */ -#define FAT16_MASK 0xffff /* mask for 16 bit cluster numbers */ +#define FAT12_MASK 0x00000fff /* mask for 12 bit cluster numbers */ +#define FAT16_MASK 0x0000ffff /* mask for 16 bit cluster numbers */ +#define FAT32_MASK 0x0fffffff /* mask for FAT32 cluster numbers */ /* * MSDOSFS: @@ -77,10 +77,11 @@ * and store the result in the pm_fatentrysize. Note that this kind of * detection gets flakey when mounting a vnd-device. */ -#define FAT12(pmp) (pmp->pm_fatentrysize == 12) -#define FAT16(pmp) (pmp->pm_fatentrysize == 16) +#define FAT12(pmp) (pmp->pm_fatmask == FAT12_MASK) +#define FAT16(pmp) (pmp->pm_fatmask == FAT16_MASK) +#define FAT32(pmp) (pmp->pm_fatmask == FAT32_MASK) -#define MSDOSFSEOF(cn) (((cn) & 0xfff8) == 0xfff8) +#define MSDOSFSEOF(pmp, cn) ((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS) #ifdef _KERNEL /* diff --git a/sys/msdosfs/msdosfs_conv.c b/sys/msdosfs/msdosfs_conv.c index bb439feeeae..c2d0babdfbc 100644 --- a/sys/msdosfs/msdosfs_conv.c +++ b/sys/msdosfs/msdosfs_conv.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_conv.c,v 1.7 1997/10/04 19:08:11 deraadt Exp $ */ -/* $NetBSD: msdosfs_conv.c,v 1.17 1996/02/09 19:13:42 christos Exp $ */ +/* $OpenBSD: msdosfs_conv.c,v 1.8 1998/01/11 20:39:06 provos Exp $ */ +/* $NetBSD: msdosfs_conv.c,v 1.24 1997/10/17 11:23:54 ws Exp $ */ /*- - * Copyright (C) 1995 Wolfgang Solfrank. - * Copyright (C) 1995 TooLs GmbH. + * Copyright (C) 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -94,10 +94,11 @@ u_short lastdtime; * file timestamps. The passed in unix time is assumed to be in GMT. */ void -unix2dostime(tsp, ddp, dtp) +unix2dostime(tsp, ddp, dtp, dhp) struct timespec *tsp; u_int16_t *ddp; u_int16_t *dtp; + u_int8_t *dhp; { u_long t; u_long days; @@ -112,6 +113,7 @@ unix2dostime(tsp, ddp, dtp) */ t = tsp->tv_sec - (tz.tz_minuteswest * 60) /* +- daylight savings time correction */ ; + t &= ~1; if (lasttime != t) { lasttime = t; lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT) @@ -153,6 +155,9 @@ unix2dostime(tsp, ddp, dtp) if (dtp != NULL) *dtp = lastdtime; + if (dhp != NULL) + *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000; + *ddp = lastddate; } @@ -171,9 +176,10 @@ u_long lastseconds; * not be too efficient. */ void -dos2unixtime(dd, dt, tsp) +dos2unixtime(dd, dt, dh, tsp) u_int dd; u_int dt; + u_int dh; struct timespec *tsp; { u_long seconds; @@ -192,7 +198,8 @@ dos2unixtime(dd, dt, tsp) } seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) * 2 + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60 - + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600; + + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600 + + dh / 100; /* * If the year, month, and day from the last conversion are the * same then use the saved value. @@ -221,7 +228,7 @@ dos2unixtime(dd, dt, tsp) } tsp->tv_sec = seconds + lastseconds + (tz.tz_minuteswest * 60) /* -+ daylight savings time correction */ ; - tsp->tv_nsec = 0; + tsp->tv_nsec = (dh % 100) * 10000000; } static u_char @@ -546,7 +553,7 @@ unix2dosfn(un, dn, unlen, gen) i = 8 - (gentext + sizeof(gentext) - cp + 1); dn[i++] = '~'; while (cp < gentext + sizeof(gentext)) - dn[i] = *cp++; + dn[i++] = *cp++; return 3; } diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c index 457ba634089..0604abb8c0e 100644 --- a/sys/msdosfs/msdosfs_denode.c +++ b/sys/msdosfs/msdosfs_denode.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_denode.c,v 1.10 1997/11/11 18:57:16 niklas Exp $ */ -/* $NetBSD: msdosfs_denode.c,v 1.22 1996/10/13 04:16:31 christos Exp $ */ +/* $OpenBSD: msdosfs_denode.c,v 1.11 1998/01/11 20:39:07 provos Exp $ */ +/* $NetBSD: msdosfs_denode.c,v 1.23 1997/10/17 11:23:58 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -177,10 +177,17 @@ deget(pmp, dirclust, diroffset, depp) #endif /* + * On FAT32 filesystems, root is a (more or less) normal + * directory + */ + if (FAT32(pmp) && dirclust == MSDOSFSROOT) + dirclust = pmp->pm_rootdirblk; + + /* * See if the denode is in the denode cache. Use the location of * the directory entry to compute the hash value. For subdir use - * address of "." entry. for root dir use cluster MSDOSFSROOT, - * offset MSDOSFSROOT_OFS + * address of "." entry. For root dir (if not FAT32) use cluster + * MSDOSFSROOT, offset MSDOSFSROOT_OFS * * NOTE: The check for de_refcnt > 0 below insures the denode being * examined does not represent an unlinked but still open file. @@ -227,10 +234,15 @@ deget(pmp, dirclust, diroffset, depp) vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, p); msdosfs_hashins(ldep); + ldep->de_pmp = pmp; + ldep->de_devvp = pmp->pm_devvp; + ldep->de_refcnt = 1; /* * Copy the directory entry into the denode area of the vnode. */ - if (dirclust == MSDOSFSROOT && diroffset == MSDOSFSROOT_OFS) { + if ((dirclust == MSDOSFSROOT + || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)) + && diroffset == MSDOSFSROOT_OFS) { /* * Directory entry for the root directory. There isn't one, * so we manufacture one. We should probably rummage @@ -238,9 +250,16 @@ deget(pmp, dirclust, diroffset, depp) * exists), and then use the time and date from that entry * as the time and date for the root denode. */ + nvp->v_flag |= VROOT; /* should be further down XXX */ + ldep->de_Attributes = ATTR_DIRECTORY; - ldep->de_StartCluster = MSDOSFSROOT; - ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec; + if (FAT32(pmp)) + ldep->de_StartCluster = pmp->pm_rootdirblk; + /* de_FileSize will be filled in further down */ + else { + ldep->de_StartCluster = MSDOSFSROOT; + ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec; + } /* * fill in time and date so that dos2unixtime() doesn't * spit up when called from msdosfs_getattr() with root @@ -267,9 +286,6 @@ deget(pmp, dirclust, diroffset, depp) * Fill in a few fields of the vnode and finish filling in the * denode. Then return the address of the found denode. */ - ldep->de_pmp = pmp; - ldep->de_devvp = pmp->pm_devvp; - ldep->de_refcnt = 1; if (ldep->de_Attributes & ATTR_DIRECTORY) { /* * Since DOS directory entries that describe directories @@ -280,9 +296,7 @@ deget(pmp, dirclust, diroffset, depp) u_long size; nvp->v_type = VDIR; - if (ldep->de_StartCluster == MSDOSFSROOT) - nvp->v_flag |= VROOT; - else { + if (ldep->de_StartCluster != MSDOSFSROOT) { error = pcbmap(ldep, 0xffff, 0, &size, 0); if (error == E2BIG) { ldep->de_FileSize = de_cn2off(pmp, size); @@ -342,7 +356,7 @@ detrunc(dep, length, flags, cred, p) * recognize the root directory at this point in a file or * directory's life. */ - if (DETOV(dep)->v_flag & VROOT) { + if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) { printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n", dep->de_dirclust, dep->de_diroffset); return (EINVAL); @@ -448,7 +462,7 @@ detrunc(dep, length, flags, cred, p) * Now free the clusters removed from the file because of the * truncation. */ - if (chaintofree != 0 && !MSDOSFSEOF(chaintofree)) + if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree)) freeclusterchain(pmp, chaintofree); return (allerror); @@ -470,7 +484,7 @@ deextend(dep, length, cred) /* * The root of a DOS filesystem cannot be extended. */ - if (DETOV(dep)->v_flag & VROOT) + if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) return (EINVAL); /* diff --git a/sys/msdosfs/msdosfs_fat.c b/sys/msdosfs/msdosfs_fat.c index fe044d1a6e3..a215bdc98bc 100644 --- a/sys/msdosfs/msdosfs_fat.c +++ b/sys/msdosfs/msdosfs_fat.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_fat.c,v 1.4 1997/03/02 18:01:56 millert Exp $ */ -/* $NetBSD: msdosfs_fat.c,v 1.24 1996/10/13 04:16:32 christos Exp $ */ +/* $OpenBSD: msdosfs_fat.c,v 1.5 1998/01/11 20:39:08 provos Exp $ */ +/* $NetBSD: msdosfs_fat.c,v 1.26 1997/10/17 11:24:02 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -83,9 +83,6 @@ int fc_lmdistance[LMMAX]; /* counters for how far off the last * cluster mapped entry was. */ int fc_largedistance; /* off by more than LMMAX */ -/* Byte offset in FAT on filesystem pmp, cluster cn */ -#define FATOFS(pmp, cn) (FAT12(pmp) ? (cn) * 3 / 2 : (cn) * 2) - static void fatblock __P((struct msdosfsmount *, u_long, u_long *, u_long *, u_long *)); void updatefats __P((struct msdosfsmount *, struct buf *, u_long)); @@ -109,7 +106,8 @@ fatblock(pmp, ofs, bnp, sizep, bop) bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * pmp->pm_BytesPerSec; - bn += pmp->pm_fatblk; + bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; + if (bnp) *bnp = bn; if (sizep) @@ -155,7 +153,6 @@ pcbmap(dep, findcn, bnp, cnp, sp) u_long bp_bn = -1; struct msdosfsmount *pmp = dep->de_pmp; u_long bsize; - int fat12 = FAT12(pmp); /* 12 bit fat */ fc_bmapcalls++; @@ -217,7 +214,10 @@ pcbmap(dep, findcn, bnp, cnp, sp) * Handle all other files or directories the normal way. */ for (; i < findcn; i++) { - if (MSDOSFSEOF(cn)) + /* + * Stop with all reserved clusters, not just with EOF. + */ + if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) goto hiteof; byteoffset = FATOFS(pmp, cn); fatblock(pmp, byteoffset, &bn, &bsize, &bo); @@ -232,23 +232,25 @@ pcbmap(dep, findcn, bnp, cnp, sp) bp_bn = bn; } prevcn = cn; - cn = getushort(&bp->b_data[bo]); - if (fat12) { - if (prevcn & 1) - cn >>= 4; - cn &= 0x0fff; - /* - * Force the special cluster numbers in the range - * 0x0ff0-0x0fff to be the same as for 16 bit - * cluster numbers to let the rest of msdosfs think - * it is always dealing with 16 bit fats. - */ - if ((cn & 0x0ff0) == 0x0ff0) - cn |= 0xf000; - } + if (FAT32(pmp)) + cn = getulong(&bp->b_data[bo]); + else + cn = getushort(&bp->b_data[bo]); + if (FAT12(pmp) && (prevcn & 1)) + cn >>= 4; + cn &= pmp->pm_fatmask; + + /* + * Force the special cluster numbers + * to be the same for all cluster sizes + * to let the rest of msdosfs handle + * all cases the same. + */ + if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) + cn |= ~pmp->pm_fatmask; } - if (!MSDOSFSEOF(cn)) { + if (!MSDOSFSEOF(pmp, cn)) { if (bp) brelse(bp); if (bnp) @@ -317,7 +319,9 @@ fc_purge(dep, frcn) } /* - * Update all copies of the fat. The first copy is updated last. + * Update the fat. + * If mirroring the fat, update all copies, with the first copy as last. + * Else update only the current fat (ignoring the others). * * pmp - msdosfsmount structure for filesystem to update * bp - addr of modified fat block @@ -338,32 +342,76 @@ updatefats(pmp, bp, fatbn) #endif /* - * Now copy the block(s) of the modified fat to the other copies of - * the fat and write them out. This is faster than reading in the - * other fats and then writing them back out. This could tie up - * the fat for quite a while. Preventing others from accessing it. - * To prevent us from going after the fat quite so much we use - * delayed writes, unless they specfied "synchronous" when the - * filesystem was mounted. If synch is asked for then use - * bwrite()'s and really slow things down. + * If we have an FSInfo block, update it. */ - for (i = 1; i < pmp->pm_FATs; i++) { - fatbn += pmp->pm_FATsecs; - /* getblk() never fails */ - bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0); - bcopy(bp->b_data, bpn->b_data, bp->b_bcount); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else - bdwrite(bpn); + if (pmp->pm_fsinfo) { + u_long cn = pmp->pm_nxtfree; + + if (pmp->pm_freeclustercount + && (pmp->pm_inusemap[cn / N_INUSEBITS] + & (1 << (cn % N_INUSEBITS)))) { + /* + * The cluster indicated in FSInfo isn't free + * any longer. Got get a new free one. + */ + for (cn = 0; cn < pmp->pm_maxcluster;) + if (pmp->pm_inusemap[cn / N_INUSEBITS] != (u_int)-1) + break; + pmp->pm_nxtfree = cn + + ffs(pmp->pm_inusemap[cn / N_INUSEBITS] + ^ (u_int)-1) - 1; + } + if (bread(pmp->pm_devvp, pmp->pm_fsinfo, 1024, NOCRED, &bpn) != 0) { + /* + * Ignore the error, but turn off FSInfo update for the future. + */ + pmp->pm_fsinfo = 0; + brelse(bpn); + } else { + struct fsinfo *fp = (struct fsinfo *)bpn->b_data; + + putulong(fp->fsinfree, pmp->pm_freeclustercount); + putulong(fp->fsinxtfree, pmp->pm_nxtfree); + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) + bwrite(bpn); + else + bdwrite(bpn); + } } + + if (pmp->pm_flags & MSDOSFS_FATMIRROR) { + /* + * Now copy the block(s) of the modified fat to the other copies of + * the fat and write them out. This is faster than reading in the + * other fats and then writing them back out. This could tie up + * the fat for quite a while. Preventing others from accessing it. + * To prevent us from going after the fat quite so much we use + * delayed writes, unless they specfied "synchronous" when the + * filesystem was mounted. If synch is asked for then use + * bwrite()'s and really slow things down. + */ + for (i = 1; i < pmp->pm_FATs; i++) { + fatbn += pmp->pm_FATsecs; + /* getblk() never fails */ + bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0); + bcopy(bp->b_data, bpn->b_data, bp->b_bcount); + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) + bwrite(bpn); + else + bdwrite(bpn); + } + } + /* - * Write out the first fat last. + * Write out the first (or current) fat last. */ if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) bwrite(bp); else bdwrite(bp); + /* + * Maybe update fsinfo sector here? + */ } /* @@ -414,15 +462,17 @@ clusterfree(pmp, cluster, oldcnp) int error; u_long oldcn; + usemap_free(pmp, cluster); error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE); - if (error) + if (error) { + usemap_alloc(pmp, cluster); return (error); + } /* * If the cluster was successfully marked free, then update * the count of free clusters, and turn off the "allocated" * bit in the "in use" cluster bit map. */ - usemap_free(pmp, cluster); if (oldcnp) *oldcnp = oldcn; return (0); @@ -460,7 +510,7 @@ fatentry(function, pmp, cn, oldcontents, newcontents) u_long bn, bo, bsize, byteoffset; struct buf *bp; -#if 0 +#ifdef MSDOSFS_DEBUG printf("fatentry(func %d, pmp %08x, clust %d, oldcon %08x, newcon %d)\n", function, pmp, cluster, oldcontents, newcontents); #endif @@ -498,19 +548,21 @@ fatentry(function, pmp, cn, oldcontents, newcontents) } if (function & FAT_GET) { - readcn = getushort(&bp->b_data[bo]); - if (FAT12(pmp)) { - if (cn & 1) - readcn >>= 4; - readcn &= 0x0fff; - /* map certain 12 bit fat entries to 16 bit */ - if ((readcn & 0x0ff0) == 0x0ff0) - readcn |= 0xf000; - } + if (FAT32(pmp)) + readcn = getulong(&bp->b_data[bo]); + else + readcn = getushort(&bp->b_data[bo]); + if (FAT12(pmp) & (cn & 1)) + readcn >>= 4; + readcn &= pmp->pm_fatmask; + /* map reserved fat entries to same values for all fats */ + if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD) + readcn |= ~pmp->pm_fatmask; *oldcontents = readcn; } if (function & FAT_SET) { - if (FAT12(pmp)) { + switch (pmp->pm_fatmask) { + case FAT12_MASK: readcn = getushort(&bp->b_data[bo]); if (cn & 1) { readcn &= 0x000f; @@ -520,8 +572,21 @@ fatentry(function, pmp, cn, oldcontents, newcontents) readcn |= newcontents & 0xfff; } putushort(&bp->b_data[bo], readcn); - } else + break; + case FAT16_MASK: putushort(&bp->b_data[bo], newcontents); + break; + case FAT32_MASK: + /* + * According to spec we have to retain the + * high order bits of the fat entry. + */ + readcn = getulong(&bp->b_data[bo]); + readcn &= ~FAT32_MASK; + readcn |= newcontents & FAT32_MASK; + putulong(&bp->b_data[bo], readcn); + break; + } updatefats(pmp, bp, bn); bp = NULL; pmp->pm_fmod = 1; @@ -571,7 +636,8 @@ fatchain(pmp, start, count, fillwith) while (count > 0) { start++; newc = --count > 0 ? start : fillwith; - if (FAT12(pmp)) { + switch (pmp->pm_fatmask) { + case FAT12_MASK: readcn = getushort(&bp->b_data[bo]); if (start & 1) { readcn &= 0xf000; @@ -584,9 +650,18 @@ fatchain(pmp, start, count, fillwith) bo++; if (!(start & 1)) bo++; - } else { + break; + case FAT16_MASK: putushort(&bp->b_data[bo], newc); bo += 2; + break; + case FAT32_MASK: + readcn = getulong(&bp->b_data[bo]); + readcn &= ~pmp->pm_fatmask; + readcn |= newc & pmp->pm_fatmask; + putulong(&bp->b_data[bo], readcn); + bo += 4; + break; } if (bo >= bsize) break; @@ -659,7 +734,10 @@ chainalloc(pmp, start, count, fillwith, retcluster, got) u_long *got; { int error; - + u_long cl, n; + + for (cl = start, n = count; n-- > 0;) + usemap_alloc(pmp, cl++); if ((error = fatchain(pmp, start, count, fillwith)) != 0) return (error); #ifdef MSDOSFS_DEBUG @@ -670,8 +748,6 @@ chainalloc(pmp, start, count, fillwith, retcluster, got) *retcluster = start; if (got) *got = count; - while (count-- > 0) - usemap_alloc(pmp, start++); return (0); } @@ -801,8 +877,9 @@ freeclusterchain(pmp, cluster) lbn = bn; } usemap_free(pmp, cluster); - readcn = getushort(&bp->b_data[bo]); - if (FAT12(pmp)) { + switch (pmp->pm_fatmask) { + case FAT12_MASK: + readcn = getushort(&bp->b_data[bo]); if (cluster & 1) { cluster = readcn >> 4; readcn &= 0x000f; @@ -813,13 +890,20 @@ freeclusterchain(pmp, cluster) readcn |= MSDOSFSFREE & 0xfff; } putushort(&bp->b_data[bo], readcn); - cluster &= 0x0fff; - if ((cluster&0x0ff0) == 0x0ff0) - cluster |= 0xf000; - } else { - cluster = readcn; + break; + case FAT16_MASK: + cluster = getushort(&bp->b_data[bo]); putushort(&bp->b_data[bo], MSDOSFSFREE); + break; + case FAT32_MASK: + cluster = getulong(&bp->b_data[bo]); + putulong(&bp->b_data[bo], + (MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK)); + break; } + cluster &= pmp->pm_fatmask; + if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD) + cluster |= pmp->pm_fatmask; } if (bp) updatefats(pmp, bp, bn); @@ -837,7 +921,6 @@ fillinusemap(pmp) struct buf *bp = NULL; u_long cn, readcn; int error; - int fat12 = FAT12(pmp); u_long bn, bo, bsize, byteoffset; /* @@ -867,12 +950,13 @@ fillinusemap(pmp) return (error); } } - readcn = getushort(&bp->b_data[bo]); - if (fat12) { - if (cn & 1) - readcn >>= 4; - readcn &= 0x0fff; - } + if (FAT32(pmp)) + readcn = getulong(&bp->b_data[bo]); + else + readcn = getushort(&bp->b_data[bo]); + if (FAT12(pmp) && (cn & 1)) + readcn >>= 4; + readcn &= pmp->pm_fatmask; if (readcn == 0) usemap_free(pmp, cn); @@ -913,7 +997,8 @@ extendfile(dep, count, bpp, ncp, flags) /* * Don't try to extend the root directory */ - if (DETOV(dep)->v_flag & VROOT) { + if (dep->de_StartCluster == MSDOSFSROOT + && (dep->de_Attributes & ATTR_DIRECTORY)) { printf("extendfile(): attempt to extend root directory\n"); return (ENOSPC); } diff --git a/sys/msdosfs/msdosfs_lookup.c b/sys/msdosfs/msdosfs_lookup.c index eaaef5667b9..f36f051057e 100644 --- a/sys/msdosfs/msdosfs_lookup.c +++ b/sys/msdosfs/msdosfs_lookup.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_lookup.c,v 1.9 1997/11/11 18:57:16 niklas Exp $ */ -/* $NetBSD: msdosfs_lookup.c,v 1.30 1996/10/25 23:14:08 cgd Exp $ */ +/* $OpenBSD: msdosfs_lookup.c,v 1.10 1998/01/11 20:39:09 provos Exp $ */ +/* $NetBSD: msdosfs_lookup.c,v 1.34 1997/10/18 22:12:27 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -433,9 +433,17 @@ found:; */ isadir = dep->deAttributes & ATTR_DIRECTORY; scn = getushort(dep->deStartCluster); + if (FAT32(pmp)) { + scn |= getushort(dep->deHighClust) << 16; + if (scn == pmp->pm_rootdirblk) { + /* + * There should actually be 0 here. + * Just ignore the error. + */ + scn = MSDOSFSROOT; + } + } - if (cluster == MSDOSFSROOT) - blkoff = diroff; if (isadir) { cluster = scn; if (cluster == MSDOSFSROOT) @@ -457,6 +465,8 @@ foundroot:; * entry of the filesystems root directory. isadir and scn were * setup before jumping here. And, bp is already null. */ + if (FAT32(pmp) && scn == MSDOSFSROOT) + scn = pmp->pm_rootdirblk; /* * If deleting, and at end of pathname, return @@ -467,6 +477,12 @@ foundroot:; */ if (nameiop == DELETE && (flags & ISLASTCN)) { /* + * Don't allow deleting the root. + */ + if (blkoff == MSDOSFSROOT_OFS) + return EROFS; /* really? XXX */ + + /* * Write access to directory required to delete files. */ error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc); @@ -498,6 +514,9 @@ foundroot:; */ if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) { + if (blkoff == MSDOSFSROOT_OFS) + return EROFS; /* really? XXX */ + error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc); if (error) return (error); @@ -638,7 +657,7 @@ createde(dep, ddep, depp, cnp) ndep = bptoep(pmp, bp, ddep->de_fndoffset); DE_EXTERNALIZE(ndep, dep); - + /* * Now write the Win95 long name */ @@ -686,6 +705,8 @@ createde(dep, ddep, depp, cnp) if (depp) { if (dep->de_Attributes & ATTR_DIRECTORY) { dirclust = dep->de_StartCluster; + if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk) + dirclust = MSDOSFSROOT; if (dirclust == MSDOSFSROOT) diroffset = MSDOSFSROOT_OFS; else @@ -802,12 +823,19 @@ doscheckpath(source, target) } if (dep->de_StartCluster == MSDOSFSROOT) goto out; + pmp = dep->de_pmp; +#ifdef DIAGNOSTIC + if (pmp != source->de_pmp) + panic("doscheckpath: source and target on different filesystems"); +#endif + if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk) + goto out; + for (;;) { if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { error = ENOTDIR; break; } - pmp = dep->de_pmp; scn = dep->de_StartCluster; error = bread(pmp->pm_devvp, cntobn(pmp, scn), pmp->pm_bpcluster, NOCRED, &bp); @@ -821,12 +849,23 @@ doscheckpath(source, target) break; } scn = getushort(ep->deStartCluster); + if (FAT32(pmp)) + scn |= getushort(ep->deHighClust) << 16; + if (scn == source->de_StartCluster) { error = EINVAL; break; } if (scn == MSDOSFSROOT) break; + if (FAT32(pmp) && scn == pmp->pm_rootdirblk) { + /* + * scn should be 0 in this case, + * but we silently ignore the error. + */ + break; + } + vput(DETOV(dep)); brelse(bp); bp = NULL; @@ -895,7 +934,7 @@ readde(dep, bpp, epp) /* * Remove a directory entry. At this point the file represented by the - * directory entry to be removed is still full length until no one has it + * directory entry to be removed is still full length until noone has it * open. When the file no longer being used msdosfs_inactive() is called * and will truncate the file to 0 length. When the vnode containing the * denode is needed for some other purpose by VFS it will call @@ -920,7 +959,9 @@ removede(pdep, dep) #endif dep->de_refcnt--; + offset += sizeof(struct direntry); do { + offset -= sizeof(struct direntry); error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize); if (error) return error; @@ -930,6 +971,17 @@ removede(pdep, dep) return error; } ep = bptoep(pmp, bp, offset); + /* + * Check whether, if we came here the second time, i.e. + * when underflowing into the previous block, the last + * entry in this block is a longfilename entry, too. + */ + if (ep->deAttributes != ATTR_WIN95 + && offset != pdep->de_fndoffset) { + brelse(bp); + break; + } + offset += sizeof(struct direntry); while (1) { /* * We are a bit agressive here in that we delete any Win95 @@ -937,18 +989,18 @@ removede(pdep, dep) * Since these presumably aren't valid anyway, * there should be no harm. */ - ep--->deName[0] = SLOT_DELETED; offset -= sizeof(struct direntry); + ep--->deName[0] = SLOT_DELETED; if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) - || !((offset + sizeof(struct direntry)) & pmp->pm_crbomask) + || !(offset & pmp->pm_crbomask) || ep->deAttributes != ATTR_WIN95) break; } if ((error = bwrite(bp)) != 0) return error; } while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95) - && offset - && !(offset & pmp->pm_crbomask)); + && !(offset & pmp->pm_crbomask) + && offset); return 0; } @@ -1014,6 +1066,8 @@ uniqdosname(dep, cnp, cp) brelse(bp); } } + + return (EEXIST); } /* diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index 053a646f5e3..d8107dac9be 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_vfsops.c,v 1.12 1997/11/10 21:17:29 provos Exp $ */ -/* $NetBSD: msdosfs_vfsops.c,v 1.44 1996/12/22 10:10:32 cgd Exp $ */ +/* $OpenBSD: msdosfs_vfsops.c,v 1.13 1998/01/11 20:39:10 provos Exp $ */ +/* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -224,14 +224,18 @@ msdosfs_mount(mp, path, data, ndp, p) /* * Try to divine whether to support Win'95 long filenames */ - if ((error = msdosfs_root(mp, &rootvp)) != 0) { - msdosfs_unmount(mp, MNT_FORCE, p); - return (error); + if (FAT32(pmp)) + pmp->pm_flags |= MSDOSFSMNT_LONGNAME; + else { + if ((error = msdosfs_root(mp, &rootvp)) != 0) { + msdosfs_unmount(mp, MNT_FORCE, p); + return (error); + } + pmp->pm_flags |= findwin95(VTODE(rootvp)) + ? MSDOSFSMNT_LONGNAME + : MSDOSFSMNT_SHORTNAME; + vput(rootvp); } - pmp->pm_flags |= findwin95(VTODE(rootvp)) - ? MSDOSFSMNT_LONGNAME - : MSDOSFSMNT_SHORTNAME; - vput(rootvp); } (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); @@ -258,6 +262,7 @@ msdosfs_mountfs(devvp, mp, p, argp) union bootsector *bsp; struct byte_bpb33 *b33; struct byte_bpb50 *b50; + struct byte_bpb710 *b710; extern struct vnode *rootvp; u_int8_t SecPerClust; int ronly, error; @@ -321,13 +326,14 @@ msdosfs_mountfs(devvp, mp, p, argp) bsp = (union bootsector *)bp->b_data; b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; -#ifdef MSDOSFS_CHECKSIG - if (!(argp->flags & MSDOSFSMNT_GEMDOSFS) - && (bsp->bs50.bsBootSectSig != BOOTSIG)) { - error = EFTYPE; - goto error_exit; + b710 = (struct byte_bpb710 *)bsp->bs710.bsPBP; + if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) { + if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 + || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { + error = EINVAL; + goto error_exit; + } } -#endif pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK); bzero((caddr_t)pmp, sizeof *pmp); @@ -365,8 +371,45 @@ msdosfs_mountfs(devvp, mp, p, argp) pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); pmp->pm_HugeSectors = pmp->pm_Sectors; } + if (pmp->pm_HugeSectors > 0xffffffff / pmp->pm_BytesPerSec + 1) { + /* + * We cannot deal currently with this size of disk + * due to fileid limitations (see msdosfs_getattr and + * msdosfs_readdir) + */ + error = EINVAL; + goto error_exit; + } + + 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; + goto error_exit; + } + 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; if (argp->flags & MSDOSFSMNT_GEMDOSFS) { + if (FAT32(pmp)) { + /* + * GEMDOS doesn't know fat32. + */ + error = EINVAL; + goto error_exit; + } + /* * Check a few values (could do some more): * - logical sector size: power of 2, >= block size @@ -400,12 +443,20 @@ msdosfs_mountfs(devvp, mp, p, argp) SecPerClust *= tmp; } pmp->pm_fatblk = pmp->pm_ResSectors; - pmp->pm_rootdirblk = pmp->pm_fatblk + - (pmp->pm_FATs * pmp->pm_FATsecs); - pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) - + pmp->pm_BytesPerSec - 1) - / pmp->pm_BytesPerSec;/* in sectors */ - pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; + if (FAT32(pmp)) { + pmp->pm_rootdirblk = getulong(b710->bpbRootClust); + pmp->pm_firstcluster = pmp->pm_fatblk + + (pmp->pm_FATs * pmp->pm_FATsecs); + pmp->pm_fsinfo = getushort(b710->bpbFSInfo); + } else { + pmp->pm_rootdirblk = pmp->pm_fatblk + + (pmp->pm_FATs * pmp->pm_FATsecs); + pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) + + pmp->pm_BytesPerSec - 1) + / pmp->pm_BytesPerSec;/* in sectors */ + pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; + } + pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / SecPerClust; pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; @@ -415,21 +466,31 @@ msdosfs_mountfs(devvp, mp, p, argp) if ((pmp->pm_nmbrofclusters <= (0xff0 - 2)) && ((dtype == DTYPE_FLOPPY) || ((dtype == DTYPE_VNODE) && ((pmp->pm_Heads == 1) || (pmp->pm_Heads == 2)))) - ) - pmp->pm_fatentrysize = 12; - else - pmp->pm_fatentrysize = 16; - } else { + ) { + 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; + } + } else if (pmp->pm_fatmask == 0) { if (pmp->pm_maxcluster - <= ((CLUST_RSRVS - CLUST_FIRST) & FAT12_MASK)) + <= ((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_fatentrysize = 12; - else - pmp->pm_fatentrysize = 16; + 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; + } } if (FAT12(pmp)) pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; @@ -463,6 +524,30 @@ msdosfs_mountfs(devvp, mp, p, argp) bp = NULL; /* + * Check FSInfo + */ + if (pmp->pm_fsinfo) { + struct fsinfo *fp; + + if ((error = bread(devvp, pmp->pm_fsinfo, 1024, NOCRED, &bp)) != 0) + goto error_exit; + fp = (struct fsinfo *)bp->b_data; + if (!bcmp(fp->fsisig1, "RRaA", 4) + && !bcmp(fp->fsisig2, "rrAa", 4) + && !bcmp(fp->fsisig3, "\0\0\125\252", 4) + && !bcmp(fp->fsisig4, "\0\0\125\252", 4)) + pmp->pm_nxtfree = getulong(fp->fsinxtfree); + else + pmp->pm_fsinfo = 0; + brelse(bp); + bp = NULL; + } + + /* + * Check and validate (or perhaps invalidate?) the fsinfo structure? XXX + */ + + /* * Allocate memory for the bitmap of allocated clusters, and then * fill it in. */ diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 69b924aa763..33e123e2fca 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfs_vnops.c,v 1.14 1997/11/11 18:57:17 niklas Exp $ */ -/* $NetBSD: msdosfs_vnops.c,v 1.48 1996/03/20 00:45:43 thorpej Exp $ */ +/* $OpenBSD: msdosfs_vnops.c,v 1.15 1998/01/11 20:39:10 provos Exp $ */ +/* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -265,10 +265,12 @@ msdosfs_getattr(v) struct ucred *a_cred; struct proc *a_p; } */ *ap = v; - u_int cn; struct denode *dep = VTODE(ap->a_vp); + struct msdosfsmount *pmp = dep->de_pmp; struct vattr *vap = ap->a_vap; struct timespec ts; + u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); + u_long fileid; TIMEVAL_TO_TIMESPEC(&time, &ts); DETIMES(dep, &ts, &ts, &ts); @@ -279,15 +281,16 @@ msdosfs_getattr(v) * doesn't work. */ if (dep->de_Attributes & ATTR_DIRECTORY) { - if ((cn = dep->de_StartCluster) == MSDOSFSROOT) - cn = 1; + fileid = cntobn(pmp, dep->de_StartCluster) * dirsperblk; + if (dep->de_StartCluster == MSDOSFSROOT) + fileid = 1; } else { - if ((cn = dep->de_dirclust) == MSDOSFSROOT) - cn = 1; - cn = (cn << 16) - | ((dep->de_diroffset / sizeof(struct direntry)) & 0xffff); + fileid = cntobn(pmp, dep->de_dirclust) * dirsperblk; + if (dep->de_dirclust == MSDOSFSROOT) + fileid = roottobn(pmp, 0) * dirsperblk; + fileid += dep->de_diroffset / sizeof(struct direntry); } - vap->va_fileid = cn; + vap->va_fileid = fileid; vap->va_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); vap->va_mode &= dep->de_pmp->pm_mask; @@ -298,16 +301,10 @@ msdosfs_getattr(v) vap->va_uid = dep->de_pmp->pm_uid; vap->va_rdev = 0; vap->va_size = dep->de_FileSize; - dos2unixtime(dep->de_MDate, dep->de_MTime, &vap->va_mtime); + dos2unixtime(dep->de_MDate, dep->de_MTime, 0, &vap->va_mtime); if (dep->de_pmp->pm_flags & MSDOSFSMNT_LONGNAME) { - 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; - + dos2unixtime(dep->de_ADate, 0, 0, &vap->va_atime); + dos2unixtime(dep->de_CDate, dep->de_CTime, dep->de_CTimeHundredth, &vap->va_ctime); } else { vap->va_atime = vap->va_mtime; vap->va_ctime = vap->va_mtime; @@ -377,9 +374,9 @@ msdosfs_setattr(v) return (error); if (!(dep->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) && vap->va_atime.tv_sec != VNOVAL) - unix2dostime(&vap->va_atime, &dep->de_ADate, NULL); + unix2dostime(&vap->va_atime, &dep->de_ADate, NULL, NULL); if (vap->va_mtime.tv_sec != VNOVAL) - unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime); + unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime, NULL); dep->de_Attributes |= ATTR_ARCHIVE; dep->de_flag |= DE_MODIFIED; } @@ -988,6 +985,14 @@ abortit: vrele(fvp); return (error); } + + /* + * If source and dest are the same, do nothing. + */ + if (tvp == fvp) { + error = 0; + goto abortit; + } /* */ if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p)) != 0) @@ -1243,7 +1248,7 @@ struct { 0, /* create time 100ths */ { 0, 0 }, { 0, 0 }, /* create time & date */ { 0, 0 }, /* access date */ - { 0, 0 }, /* reserved */ + { 0, 0 }, /* high bits of start cluster */ { 210, 4 }, { 210, 4 }, /* modify time & date */ { 0, 0 }, /* startcluster */ { 0, 0, 0, 0 } /* filesize */ @@ -1254,7 +1259,7 @@ struct { 0, /* create time 100ths */ { 0, 0 }, { 0, 0 }, /* create time & date */ { 0, 0 }, /* access date */ - { 0, 0 }, /* reserved */ + { 0, 0 }, /* high bits of start cluster */ { 210, 4 }, { 210, 4 }, /* modify time & date */ { 0, 0 }, /* startcluster */ { 0, 0, 0, 0 } /* filesize */ @@ -1277,7 +1282,7 @@ msdosfs_mkdir(v) struct denode *pdep = VTODE(ap->a_dvp); int error; int bn; - u_long newcluster; + u_long newcluster, pcl; struct direntry *denp; struct msdosfsmount *pmp = pdep->de_pmp; struct buf *bp; @@ -1325,13 +1330,21 @@ msdosfs_mkdir(v) putushort(denp[0].deADate, ndirent.de_ADate); putushort(denp[0].deMDate, ndirent.de_MDate); putushort(denp[0].deMTime, ndirent.de_MTime); - putushort(denp[1].deStartCluster, pdep->de_StartCluster); + pcl = pdep->de_StartCluster; + if (FAT32(pmp) && pcl == pmp->pm_rootdirblk) + pcl = 0; + putushort(denp[1].deStartCluster, pcl); 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].deMDate, ndirent.de_MDate); putushort(denp[1].deMTime, ndirent.de_MTime); + if (FAT32(pmp)) { + putushort(denp[0].deHighClust, newcluster >> 16); + putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16); + } + if ((error = bwrite(bp)) != 0) goto bad; @@ -1474,6 +1487,7 @@ msdosfs_readdir(v) long on; long lost; long count; + u_long dirsperblk; u_long cn; u_long fileno; long bias = 0; @@ -1529,6 +1543,8 @@ msdosfs_readdir(v) *ap->a_ncookies = ncookies; } + dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); + /* * If they are reading from the root directory then, we simulate * the . and .. entries since these don't exist in the root @@ -1536,7 +1552,8 @@ msdosfs_readdir(v) * simulate these entries. By this I mean that at file offset 64 we * read the first entry in the root directory that lives on disk. */ - if (dep->de_StartCluster == MSDOSFSROOT) { + if (dep->de_StartCluster == MSDOSFSROOT + || (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)) { #if 0 printf("msdosfs_readdir(): going after . or .. in root dir, offset %d\n", offset); @@ -1545,7 +1562,12 @@ msdosfs_readdir(v) if (offset < bias) { for (n = (int)offset / sizeof(struct direntry); n < 2; n++) { - dirbuf.d_fileno = 1; + if (FAT32(pmp)) + dirbuf.d_fileno = cntobn(pmp, + pmp->pm_rootdirblk) + * dirsperblk; + else + dirbuf.d_fileno = 1; dirbuf.d_type = DT_DIR; switch (n) { case 0: @@ -1640,23 +1662,33 @@ msdosfs_readdir(v) * msdosfs_getattr. */ if (dentp->deAttributes & ATTR_DIRECTORY) { - /* if this is the root directory */ fileno = getushort(dentp->deStartCluster); + if (FAT32(pmp)) + fileno |= getushort(dentp->deHighClust) << 16; + /* if this is the root directory */ if (fileno == MSDOSFSROOT) - fileno = 1; + if (FAT32(pmp)) + fileno = cntobn(pmp, + pmp->pm_rootdirblk) + * dirsperblk; + else + fileno = 1; + else + fileno = cntobn(pmp, fileno) * dirsperblk; + dirbuf.d_fileno = fileno; + dirbuf.d_type = DT_DIR; } else { /* * If the file's dirent lives in * root dir. */ - if ((fileno = cn) == MSDOSFSROOT) - fileno = 1; - fileno = (fileno << 16) | - ((dentp - (struct direntry *)bp->b_data) & 0xffff); + fileno = cntobn(pmp, cn) * dirsperblk; + if (cn == MSDOSFSROOT) + fileno = roottobn(pmp, 0) * dirsperblk; + fileno += dentp - (struct direntry *)bp->b_data; + dirbuf.d_fileno = fileno; + dirbuf.d_type = DT_REG; } - dirbuf.d_fileno = fileno; - dirbuf.d_type = - (dentp->deAttributes & ATTR_DIRECTORY) ? DT_DIR : DT_REG; if (chksum != winChksum(dentp->deName)) dirbuf.d_namlen = dos2unixfn(dentp->deName, (u_char *)dirbuf.d_name, @@ -1874,7 +1906,7 @@ msdosfs_print(v) struct denode *dep = VTODE(ap->a_vp); printf( - "tag VT_MSDOSFS, startcluster %d, dircluster %ld, diroffset %ld ", + "tag VT_MSDOSFS, startcluster %ld, dircluster %ld, diroffset %ld ", dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset); printf(" dev %d, %d, %s\n", major(dep->de_dev), minor(dep->de_dev), diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h index b0f6a33aa6b..069b5a13c3b 100644 --- a/sys/msdosfs/msdosfsmount.h +++ b/sys/msdosfs/msdosfsmount.h @@ -1,9 +1,9 @@ -/* $OpenBSD: msdosfsmount.h,v 1.8 1997/11/06 05:58:59 csapuntz Exp $ */ -/* $NetBSD: msdosfsmount.h,v 1.15 1996/12/22 10:31:41 cgd Exp $ */ +/* $OpenBSD: msdosfsmount.h,v 1.9 1998/01/11 20:39:11 provos Exp $ */ +/* $NetBSD: msdosfsmount.h,v 1.16 1997/10/17 11:24:24 ws Exp $ */ /*- - * Copyright (C) 1994, 1995 Wolfgang Solfrank. - * Copyright (C) 1994, 1995 TooLs GmbH. + * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. + * Copyright (C) 1994, 1995, 1997 TooLs GmbH. * All rights reserved. * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). * @@ -59,8 +59,9 @@ struct msdosfsmount { mode_t pm_mask; /* mask to and with file protection bits */ struct vnode *pm_devvp; /* vnode for block device mntd */ struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */ + u_long pm_FATsecs; /* actual number of fat sectors */ u_long pm_fatblk; /* block # of first FAT */ - u_long pm_rootdirblk; /* block # of root directory */ + u_long pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */ u_long pm_rootdirsize; /* size in blocks (not clusters) */ u_long pm_firstcluster; /* block number of first cluster */ u_long pm_nmbrofclusters; /* # of clusters in filesystem */ @@ -74,11 +75,18 @@ struct msdosfsmount { u_long pm_fatblocksize; /* size of fat blocks in bytes */ u_long pm_fatblocksec; /* size of fat blocks in sectors */ u_long pm_fatsize; /* size of fat in bytes */ + u_long pm_fatmask; /* mask to use for fat numbers */ + u_long pm_fsinfo; /* fsinfo block number */ + u_long pm_nxtfree; /* next free cluster in fsinfo block */ + u_int pm_fatmult; /* these 2 values are used in fat */ + u_int pm_fatdiv; /* offset computation */ + u_int pm_curfat; /* current fat for FAT32 (0 otherwise) */ u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */ u_int pm_flags; /* see below */ struct netexport pm_export; /* export information */ - u_int pm_fatentrysize; /* size of fat entry (12/16) */ }; +/* Byte offset in FAT on filesystem pmp, cluster cn */ +#define FATOFS(pmp, cn) ((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv) /* * Mount point flags: @@ -97,6 +105,7 @@ struct msdosfsmount { |MSDOSFSMNT_GEMDOSFS) #define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ +#define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ #define VFSTOMSDOSFS(mp) ((struct msdosfsmount *)mp->mnt_data) @@ -112,7 +121,6 @@ struct msdosfsmount { #define pm_RootDirEnts pm_bpb.bpbRootDirEnts #define pm_Sectors pm_bpb.bpbSectors #define pm_Media pm_bpb.bpbMedia -#define pm_FATsecs pm_bpb.bpbFATsecs #define pm_SecPerTrack pm_bpb.bpbSecPerTrack #define pm_Heads pm_bpb.bpbHeads #define pm_HiddenSects pm_bpb.bpbHiddenSecs |