Add support for FAT32
Don't panic if renaming a file to itself Don't try to keep access times, there is no place for them While being here, fix some minor bugs with VFAT handling
This commit is contained in:
parent
d445160e23
commit
9c1b7cfa37
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bootsect.h,v 1.7 1995/07/24 06:36:23 leo Exp $ */
|
||||
/* $NetBSD: bootsect.h,v 1.8 1997/10/17 11:23:29 ws Exp $ */
|
||||
|
||||
/*
|
||||
* Written by Paul Popelka (paulp@uts.amdahl.com)
|
||||
|
@ -27,24 +27,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
|
||||
/*
|
||||
|
@ -66,8 +90,10 @@ struct bootsec_atari {
|
|||
union bootsector {
|
||||
struct bootsector33 bs33;
|
||||
struct bootsector50 bs50;
|
||||
struct bootsector710 bs710;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Shorthand for fields in the bpb.
|
||||
*/
|
||||
|
@ -83,3 +109,4 @@ union bootsector {
|
|||
#define bsHeads bsBPB.bpbHeads
|
||||
#define bsHiddenSecs bsBPB.bpbHiddenSecs
|
||||
#define bsHugeSectors bsBPB.bpbHugeSectors
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bpb.h,v 1.5 1995/07/24 06:37:15 leo Exp $ */
|
||||
/* $NetBSD: bpb.h,v 1.6 1997/10/17 11:23:35 ws Exp $ */
|
||||
|
||||
/*
|
||||
* Written by Paul Popelka (paulp@uts.amdahl.com)
|
||||
|
@ -52,6 +52,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.
|
||||
|
@ -138,3 +166,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];
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: denode.h,v 1.23 1997/04/11 21:52:06 kleink 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).
|
||||
*
|
||||
|
@ -102,8 +102,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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -120,7 +120,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.
|
||||
|
@ -151,13 +151,13 @@ struct denode {
|
|||
pid_t de_lockwaiter; /* lock wanter */
|
||||
u_char de_Name[12]; /* name, from DOS directory entry */
|
||||
u_char de_Attributes; /* attributes, from directory entry */
|
||||
u_char de_CHun; /* Hundredth of second of CTime*/
|
||||
u_short de_CTime; /* creation time */
|
||||
u_short de_CDate; /* creation date */
|
||||
u_short de_ADate; /* access date */
|
||||
u_short de_ATime; /* access time */
|
||||
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 */
|
||||
};
|
||||
|
@ -184,30 +184,36 @@ struct denode {
|
|||
* dep is a struct denode * (internal form),
|
||||
* dp is a struct direntry * (external form).
|
||||
*/
|
||||
#define DE_INTERNALIZE(dep, dp) \
|
||||
#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, \
|
||||
(dep)->de_CHun = (dp)->deCHundredth, \
|
||||
(dep)->de_CTime = getushort((dp)->deCTime), \
|
||||
(dep)->de_CDate = getushort((dp)->deCDate), \
|
||||
(dep)->de_ATime = getushort((dp)->deATime), \
|
||||
(dep)->de_ADate = getushort((dp)->deADate), \
|
||||
(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, \
|
||||
(dp)->deCHundredth = (dep)->de_CHun, \
|
||||
putushort((dp)->deCTime, (dep)->de_CTime), \
|
||||
putushort((dp)->deCDate, (dep)->de_CDate), \
|
||||
putushort((dp)->deATime, (dep)->de_ATime), \
|
||||
putushort((dp)->deADate, (dep)->de_ADate), \
|
||||
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))
|
||||
putulong((dp)->deFileSize, \
|
||||
((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]
|
||||
|
@ -221,14 +227,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, &(dep)->de_ATime); \
|
||||
unix2dostime((acc), &(dep)->de_ADate, NULL, NULL); \
|
||||
if ((dep)->de_flag & DE_CREATE) \
|
||||
unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime); \
|
||||
unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime, &(dep)->de_CHun); \
|
||||
} \
|
||||
(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: direntry.h,v 1.12 1996/10/25 23:14:05 cgd 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).
|
||||
*
|
||||
|
@ -64,11 +64,12 @@ struct direntry {
|
|||
#define ATTR_VOLUME 0x08 /* entry is a volume label */
|
||||
#define ATTR_DIRECTORY 0x10 /* entry is a directory name */
|
||||
#define ATTR_ARCHIVE 0x20 /* file is new or modified */
|
||||
u_int8_t deReserved[2]; /* reserved */
|
||||
u_int8_t deReserved; /* reserved */
|
||||
u_int8_t deCHundredth; /* hundredth of seconds in CTime */
|
||||
u_int8_t deCTime[2]; /* create time */
|
||||
u_int8_t deCDate[2]; /* create date */
|
||||
u_int8_t deADate[2]; /* access date */
|
||||
u_int8_t deATime[2]; /* access time */
|
||||
u_int8_t deHighClust[2]; /* high bytes 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 */
|
||||
|
@ -119,8 +120,8 @@ struct winentry {
|
|||
|
||||
#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));
|
||||
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((const u_char *un, u_char dn[12], int unlen,
|
||||
u_int gen));
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: fat.h,v 1.10 1996/02/11 22:48:14 ws 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).
|
||||
*
|
||||
|
@ -50,18 +50,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:
|
||||
|
@ -76,10 +76,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
|
||||
/*
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_conv.c,v 1.23 1997/01/15 01:37:54 perry 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).
|
||||
*
|
||||
|
@ -93,10 +93,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)
|
|||
/* XXX NOTE: Removed tz, which is obsolete. Must replace!!! */
|
||||
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)
|
||||
|
@ -150,7 +152,11 @@ unix2dostime(tsp, ddp, dtp)
|
|||
lastddate += (year - 1980) << DD_YEAR_SHIFT;
|
||||
}
|
||||
}
|
||||
*dtp = lastdtime;
|
||||
if (dtp)
|
||||
*dtp = lastdtime;
|
||||
if (dhp)
|
||||
*dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
|
||||
|
||||
*ddp = lastddate;
|
||||
}
|
||||
|
||||
|
@ -169,9 +175,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;
|
||||
|
@ -190,7 +197,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.
|
||||
|
@ -220,7 +228,7 @@ dos2unixtime(dd, dt, tsp)
|
|||
/* XXX NOTE: Removed tz, which is obsolete. Must replace!!! */
|
||||
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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_denode.c,v 1.22 1996/10/13 04:16:31 christos 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).
|
||||
*
|
||||
|
@ -171,11 +171,18 @@ deget(pmp, dirclust, diroffset, depp)
|
|||
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.
|
||||
|
@ -220,10 +227,15 @@ deget(pmp, dirclust, diroffset, depp)
|
|||
VOP_LOCK(nvp);
|
||||
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
|
||||
|
@ -231,19 +243,26 @@ 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
|
||||
* denode
|
||||
*/
|
||||
ldep->de_CHun = 0;
|
||||
ldep->de_CTime = 0x0000; /* 00:00:00 */
|
||||
ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
|
||||
| (1 << DD_DAY_SHIFT);
|
||||
/* Jan 1, 1980 */
|
||||
ldep->de_ATime = ldep->de_CTime;
|
||||
ldep->de_ADate = ldep->de_CDate;
|
||||
ldep->de_MTime = ldep->de_CTime;
|
||||
ldep->de_MDate = ldep->de_CDate;
|
||||
|
@ -260,9 +279,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
|
||||
|
@ -273,9 +289,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);
|
||||
|
@ -335,7 +349,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);
|
||||
|
@ -441,7 +455,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);
|
||||
|
@ -463,7 +477,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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_fat.c,v 1.25 1997/05/17 20:33:57 pk 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).
|
||||
*
|
||||
|
@ -82,9 +82,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));
|
||||
|
@ -108,7 +105,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)
|
||||
|
@ -154,7 +152,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++;
|
||||
|
||||
|
@ -216,7 +213,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);
|
||||
|
@ -231,23 +231,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)
|
||||
|
@ -316,7 +318,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
|
||||
|
@ -337,32 +341,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?
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -413,15 +461,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);
|
||||
|
@ -459,7 +509,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
|
||||
|
@ -497,19 +547,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;
|
||||
|
@ -519,8 +571,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;
|
||||
|
@ -570,7 +635,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;
|
||||
|
@ -583,9 +649,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;
|
||||
|
@ -658,7 +733,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
|
||||
|
@ -669,8 +747,6 @@ chainalloc(pmp, start, count, fillwith, retcluster, got)
|
|||
*retcluster = start;
|
||||
if (got)
|
||||
*got = count;
|
||||
while (count-- > 0)
|
||||
usemap_alloc(pmp, start++);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -800,8 +876,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;
|
||||
|
@ -812,13 +889,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);
|
||||
|
@ -836,7 +920,6 @@ fillinusemap(pmp)
|
|||
struct buf *bp = NULL;
|
||||
u_long cn, readcn;
|
||||
int error;
|
||||
int fat12 = FAT12(pmp);
|
||||
u_long bn, bo, bsize, byteoffset;
|
||||
|
||||
/*
|
||||
|
@ -866,12 +949,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);
|
||||
|
@ -912,7 +996,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);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_lookup.c,v 1.32 1997/05/08 16:20:25 mycroft Exp $ */
|
||||
/* $NetBSD: msdosfs_lookup.c,v 1.33 1997/10/17 11:24:08 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).
|
||||
*
|
||||
|
@ -431,9 +431,24 @@ 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)
|
||||
if (cluster == MSDOSFSROOT) {
|
||||
/*
|
||||
* Force root to be a directory.
|
||||
*/
|
||||
isadir = ATTR_DIRECTORY;
|
||||
blkoff = diroff;
|
||||
}
|
||||
if (isadir) {
|
||||
cluster = scn;
|
||||
if (cluster == MSDOSFSROOT)
|
||||
|
@ -455,6 +470,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
|
||||
|
@ -464,6 +481,12 @@ foundroot:;
|
|||
* on and lock the inode, being careful with ".".
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -496,6 +519,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);
|
||||
|
@ -636,7 +662,7 @@ createde(dep, ddep, depp, cnp)
|
|||
ndep = bptoep(pmp, bp, ddep->de_fndoffset);
|
||||
|
||||
DE_EXTERNALIZE(ndep, dep);
|
||||
|
||||
|
||||
/*
|
||||
* Now write the Win95 long name
|
||||
*/
|
||||
|
@ -684,6 +710,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
|
||||
|
@ -800,12 +828,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);
|
||||
|
@ -819,12 +854,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;
|
||||
|
@ -893,7 +939,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
|
||||
|
@ -918,7 +964,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;
|
||||
|
@ -928,6 +976,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
|
||||
|
@ -935,18 +994,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_vfsops.c,v 1.46 1997/07/28 23:41:04 christos Exp $ */
|
||||
/* $NetBSD: msdosfs_vfsops.c,v 1.47 1997/10/17 11:24:13 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).
|
||||
*
|
||||
|
@ -136,12 +136,16 @@ update_mp(mp, argp)
|
|||
/*
|
||||
* Try to divine whether to support Win'95 long filenames
|
||||
*/
|
||||
if ((error = msdosfs_root(mp, &rootvp)) != 0)
|
||||
return error;
|
||||
pmp->pm_flags |= findwin95(VTODE(rootvp))
|
||||
? MSDOSFSMNT_LONGNAME
|
||||
: MSDOSFSMNT_SHORTNAME;
|
||||
vput(rootvp);
|
||||
if (FAT32(pmp))
|
||||
pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
|
||||
else {
|
||||
if ((error = msdosfs_root(mp, &rootvp)) != 0)
|
||||
return error;
|
||||
pmp->pm_flags |= findwin95(VTODE(rootvp))
|
||||
? MSDOSFSMNT_LONGNAME
|
||||
: MSDOSFSMNT_SHORTNAME;
|
||||
vput(rootvp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -360,6 +364,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;
|
||||
|
@ -420,13 +425,15 @@ 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 = EINVAL;
|
||||
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);
|
||||
|
@ -464,8 +471,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
|
||||
|
@ -499,12 +543,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;
|
||||
|
@ -514,21 +566,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;
|
||||
|
@ -561,6 +623,30 @@ msdosfs_mountfs(devvp, mp, p, argp)
|
|||
brelse(bp);
|
||||
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 (!memcmp(fp->fsisig1, "RRaA", 4)
|
||||
&& !memcmp(fp->fsisig2, "rrAa", 4)
|
||||
&& !memcmp(fp->fsisig3, "\0\0\125\252", 4)
|
||||
&& !memcmp(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.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfs_vnops.c,v 1.62 1997/10/16 23:58:05 christos 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,12 +265,13 @@ 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;
|
||||
mode_t mode;
|
||||
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);
|
||||
|
@ -281,15 +282,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;
|
||||
if ((dep->de_Attributes & ATTR_READONLY) == 0)
|
||||
mode = S_IRWXU|S_IRWXG|S_IRWXO;
|
||||
else
|
||||
|
@ -300,10 +302,10 @@ msdosfs_getattr(v)
|
|||
vap->va_nlink = 1;
|
||||
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, dep->de_ATime, &vap->va_atime);
|
||||
dos2unixtime(dep->de_CDate, dep->de_CTime, &vap->va_ctime);
|
||||
dos2unixtime(dep->de_ADate, 0, 0, &vap->va_atime);
|
||||
dos2unixtime(dep->de_CDate, dep->de_CTime, dep->de_CHun, &vap->va_ctime);
|
||||
} else {
|
||||
vap->va_atime = vap->va_mtime;
|
||||
vap->va_ctime = vap->va_mtime;
|
||||
|
@ -374,9 +376,9 @@ msdosfs_setattr(v)
|
|||
return (error);
|
||||
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
|
||||
vap->va_atime.tv_sec != VNOVAL)
|
||||
unix2dostime(&vap->va_atime, &dep->de_ADate, &dep->de_ATime);
|
||||
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;
|
||||
}
|
||||
|
@ -926,6 +928,14 @@ abortit:
|
|||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If source and dest are the same, do nothing.
|
||||
*/
|
||||
if (tvp == fvp) {
|
||||
error = 0;
|
||||
goto abortit;
|
||||
}
|
||||
|
||||
/* */
|
||||
if ((error = VOP_LOCK(fvp)) != 0)
|
||||
goto abortit;
|
||||
|
@ -1176,18 +1186,20 @@ struct {
|
|||
} dosdirtemplate = {
|
||||
{ ". ", " ", /* the . entry */
|
||||
ATTR_DIRECTORY, /* file attribute */
|
||||
{ 0, 0 }, /* reserved */
|
||||
{ 0, 0 }, { 0, 0 }, /* create time & date */
|
||||
{ 0, 0 }, { 0, 0 }, /* access time & date */
|
||||
0, /* reserved */
|
||||
0, { 0, 0 }, { 0, 0 }, /* create time & date */
|
||||
{ 0, 0 }, /* access date */
|
||||
{ 0, 0 }, /* high bits of start cluster */
|
||||
{ 210, 4 }, { 210, 4 }, /* modify time & date */
|
||||
{ 0, 0 }, /* startcluster */
|
||||
{ 0, 0, 0, 0 } /* filesize */
|
||||
},
|
||||
{ ".. ", " ", /* the .. entry */
|
||||
ATTR_DIRECTORY, /* file attribute */
|
||||
{ 0, 0 }, /* reserved */
|
||||
{ 0, 0 }, { 0, 0 }, /* create time & date */
|
||||
{ 0, 0 }, { 0, 0 }, /* access time & date */
|
||||
0, /* reserved */
|
||||
0, { 0, 0 }, { 0, 0 }, /* create time & date */
|
||||
{ 0, 0 }, /* access date */
|
||||
{ 0, 0 }, /* high bits of start cluster */
|
||||
{ 210, 4 }, { 210, 4 }, /* modify time & date */
|
||||
{ 0, 0 }, /* startcluster */
|
||||
{ 0, 0, 0, 0 } /* filesize */
|
||||
|
@ -1210,7 +1222,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;
|
||||
|
@ -1254,17 +1266,25 @@ msdosfs_mkdir(v)
|
|||
putushort(denp[0].deStartCluster, newcluster);
|
||||
putushort(denp[0].deCDate, ndirent.de_CDate);
|
||||
putushort(denp[0].deCTime, ndirent.de_CTime);
|
||||
denp[0].deCHundredth = ndirent.de_CHun;
|
||||
putushort(denp[0].deADate, ndirent.de_ADate);
|
||||
putushort(denp[0].deATime, ndirent.de_ATime);
|
||||
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].deCHundredth = ndirent.de_CHun;
|
||||
putushort(denp[1].deADate, ndirent.de_ADate);
|
||||
putushort(denp[1].deATime, ndirent.de_ATime);
|
||||
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;
|
||||
|
||||
|
@ -1409,6 +1429,7 @@ msdosfs_readdir(v)
|
|||
long count;
|
||||
u_long cn;
|
||||
u_long fileno;
|
||||
u_long dirsperblk;
|
||||
long bias = 0;
|
||||
daddr_t bn, lbn;
|
||||
struct buf *bp;
|
||||
|
@ -1456,7 +1477,9 @@ msdosfs_readdir(v)
|
|||
|
||||
cookies = ap->a_cookies;
|
||||
ncookies = ap->a_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
|
||||
|
@ -1464,7 +1487,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);
|
||||
|
@ -1473,7 +1497,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:
|
||||
|
@ -1569,23 +1598,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,
|
||||
|
@ -1837,7 +1876,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),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $NetBSD: msdosfsmount.h,v 1.15 1996/12/22 10:31:41 cgd 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).
|
||||
*
|
||||
|
@ -58,8 +58,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 */
|
||||
|
@ -73,11 +74,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:
|
||||
|
@ -96,6 +104,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)
|
||||
|
||||
|
@ -111,7 +120,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
|
||||
|
|
Loading…
Reference in New Issue