summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1998-01-11 20:39:12 +0000
committerNiels Provos <provos@cvs.openbsd.org>1998-01-11 20:39:12 +0000
commit487fe4efe824e828cdefbee41c1d03ef04a885f3 (patch)
tree49663eae55a517c8ad3c2220a6ede523fa5dc975 /sys
parent6607731225347e583be10d914e5758d7a9726fc9 (diff)
FAT32 support from NetBSD by Wolfgang Solfrank.
Diffstat (limited to 'sys')
-rw-r--r--sys/msdosfs/bootsect.h53
-rw-r--r--sys/msdosfs/bpb.h72
-rw-r--r--sys/msdosfs/denode.h38
-rw-r--r--sys/msdosfs/direntry.h14
-rw-r--r--sys/msdosfs/fat.h35
-rw-r--r--sys/msdosfs/msdosfs_conv.c25
-rw-r--r--sys/msdosfs/msdosfs_denode.c50
-rw-r--r--sys/msdosfs/msdosfs_fat.c241
-rw-r--r--sys/msdosfs/msdosfs_lookup.c80
-rw-r--r--sys/msdosfs/msdosfs_vfsops.c149
-rw-r--r--sys/msdosfs/msdosfs_vnops.c110
-rw-r--r--sys/msdosfs/msdosfsmount.h22
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