msdos filesystem now works on big-endian machines.

This commit is contained in:
paulus 1994-03-03 00:51:30 +00:00
parent 7b734f94ec
commit 7c687a255f
7 changed files with 156 additions and 128 deletions

View File

@ -13,7 +13,7 @@
*
* October 1992
*
* $Id: bpb.h,v 1.1 1993/08/13 11:35:30 cgd Exp $
* $Id: bpb.h,v 1.2 1994/03/03 00:51:30 paulus Exp $
*/
/*
@ -57,15 +57,29 @@ struct bpb50 {
* and longs are just character arrays of the appropriate length. This is
* because the compiler forces shorts and longs to align on word or
* halfword boundaries.
*
* XXX The little-endian code here assumes that the processor can access
* 16-bit and 32-bit quantities on byte boundaries. If this is not true,
* use the macros for the big-endian case.
*/
#include <machine/endian.h>
#if BYTE_ORDER == LITTLE_ENDIAN
#if BYTE_ORDER == LITTLE_ENDIAN /* && can do unaligned accesses */
#define getushort(x) *((u_short *)(x))
#define getulong(x) *((u_long *)(x))
#define putushort(p, v) (*((u_short *)(p)) = (v))
#define putulong(p, v) (*((u_long *)(p)) = (v))
#else
#else
#define getushort(x) (((u_char *)(x))[0] + (((u_char *)(x))[1] << 8))
#define getulong(x) (((u_char *)(x))[0] + (((u_char *)(x))[1] << 8) \
+ (((u_char *)(x))[2] << 16) \
+ (((u_char *)(x))[3] << 24))
#define putushort(p, v) (((u_char *)(p))[0] = (v), \
((u_char *)(p))[1] = (v) >> 8)
#define putulong(p, v) (((u_char *)(p))[0] = (v), \
((u_char *)(p))[1] = (v) >> 8, \
((u_char *)(p))[2] = (v) >> 16,\
((u_char *)(p))[3] = (v) >> 24)
#endif
/*

View File

@ -13,16 +13,16 @@
*
* October 1992
*
* $Id: denode.h,v 1.2 1993/09/07 15:41:31 ws Exp $
* $Id: denode.h,v 1.3 1994/03/03 00:51:31 paulus Exp $
*/
/*
* This is the pc filesystem specific portion of the vnode structure. To
* describe a file uniquely the de_dirclust, de_diroffset, and
* de_de.deStartCluster fields are used. de_dirclust contains the cluster
* de_StartCluster fields are used. de_dirclust contains the cluster
* number of the directory cluster containing the entry for a file or
* directory. de_diroffset is the index into the cluster for the entry
* describing a file or directory. de_de.deStartCluster is the number of
* describing a file or directory. de_StartCluster is the number of
* the first cluster of the file or directory. Now to describe the quirks
* of the pc filesystem. - Clusters 0 and 1 are reserved. - The first
* allocatable cluster is 2. - The root directory is of fixed size and all
@ -105,7 +105,14 @@ struct denode {
struct lockf *de_lockf; /* byte level lock list */
long de_spare0; /* current lock holder */
long de_spare1; /* lock wanter */
struct direntry de_de; /* the actual directory entry */
/* the next two fields must be contiguous in memory... */
u_char de_Name[8]; /* name, from directory entry */
u_char de_Extension[3]; /* extension, from directory entry */
u_char de_Attributes; /* attributes, from directory entry */
u_short de_Time; /* creation time */
u_short de_Date; /* creation date */
u_short de_StartCluster; /* starting cluster of file */
u_long de_FileSize; /* size of file in bytes */
struct fatcache de_fc[FC_SIZE]; /* fat cache */
};
@ -122,17 +129,26 @@ struct denode {
#define DEMOD 0x0080 /* denode wants to be written back to disk */
/*
* Shorthand macros used to reference fields in the direntry contained in
* the denode structure.
* Transfer directory entries between internal and external form.
* dep is a struct denode * (internal form),
* dp is a struct direntry * (external form).
*/
#define de_Name de_de.deName
#define de_Extension de_de.deExtension
#define de_Attributes de_de.deAttributes
#define de_Reserved de_de.deReserved
#define de_Time de_de.deTime
#define de_Date de_de.deDate
#define de_StartCluster de_de.deStartCluster
#define de_FileSize de_de.deFileSize
#define DE_INTERNALIZE(dep, dp) \
(bcopy((dp)->deName, (dep)->de_Name, 11), \
(dep)->de_Attributes = (dp)->deAttributes, \
(dep)->de_Time = getushort((dp)->deTime), \
(dep)->de_Date = getushort((dp)->deDate), \
(dep)->de_StartCluster = getushort((dp)->deStartCluster), \
(dep)->de_FileSize = getulong((dp)->deFileSize))
#define DE_EXTERNALIZE(dp, dep) \
(bcopy((dep)->de_Name, (dp)->deName, 11), \
(dp)->deAttributes = (dep)->de_Attributes, \
putushort((dp)->deTime, (dep)->de_Time), \
putushort((dp)->deDate, (dep)->de_Date), \
putushort((dp)->deStartCluster, (dep)->de_StartCluster), \
putulong((dp)->deFileSize, (dep)->de_FileSize))
#define de_forw de_chain[0]
#define de_back de_chain[1]
@ -151,8 +167,7 @@ struct denode {
#define DETIMES(dep, t) \
if (dep->de_flag & DEUPD) { \
(dep)->de_flag |= DEMOD; \
unix2dostime(t, (union dosdate *)&dep->de_Date, \
(union dostime *)&dep->de_Time); \
unix2dostime(t, &dep->de_Date, &dep->de_Time); \
(dep)->de_flag &= ~DEUPD; \
}

View File

@ -13,7 +13,7 @@
*
* October 1992
*
* $Id: direntry.h,v 1.1 1993/08/13 11:35:32 cgd Exp $
* $Id: direntry.h,v 1.2 1994/03/03 00:51:32 paulus Exp $
*/
/*
@ -33,44 +33,36 @@ 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 */
char deReserved[10]; /* reserved */
u_short deTime; /* create/last update time */
u_short deDate; /* create/last update date */
u_short deStartCluster; /* starting cluster of file */
u_long deFileSize; /* size of file in bytes */
u_char deReserved[10]; /* reserved */
u_char deTime[2]; /* create/last update time */
u_char deDate[2]; /* create/last update date */
u_char deStartCluster[2]; /* starting cluster of file */
u_char deFileSize[4]; /* size of file in bytes */
};
/*
* This is the format of the contents of the deTime field in the direntry
* structure.
* We don't use bitfields because we don't know how compilers for
* arbitrary machines will lay them out.
*/
struct DOStime {
u_short
dt_2seconds:5, /* seconds divided by 2 */
dt_minutes:6, /* minutes */
dt_hours:5; /* hours */
};
#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
#define DT_2SECONDS_SHIFT 0
#define DT_MINUTES_MASK 0x7E0 /* minutes */
#define DT_MINUTES_SHIFT 5
#define DT_HOURS_MASK 0xF800 /* hours */
#define DT_HOURS_SHIFT 11
/*
* This is the format of the contents of the deDate field in the direntry
* structure.
*/
struct DOSdate {
u_short
dd_day:5, /* day of month */
dd_month:4, /* month */
dd_year:7; /* years since 1980 */
};
union dostime {
struct DOStime dts;
u_short dti;
};
union dosdate {
struct DOSdate dds;
u_short ddi;
};
#define DD_DAY_MASK 0x1F /* day of month */
#define DD_DAY_SHIFT 0
#define DD_MONTH_MASK 0x1E0 /* month */
#define DD_MONTH_SHIFT 5
#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
#define DD_YEAR_SHIFT 9
/*
* The following defines are used to rename fields in the ufs_specific
@ -82,8 +74,8 @@ union dosdate {
#define msdosfs_cluster ufs_ino
#if defined(KERNEL)
void unix2dostime __P((struct timeval * tvp, union dosdate * ddp, union dostime * dtp));
void dos2unixtime __P((union dosdate * ddp, union dostime * dtp, struct timeval * tvp));
void unix2dostime __P((struct timeval * tvp, u_short * ddp, u_short * dtp));
void dos2unixtime __P((u_short dd, u_short dt, struct timeval * tvp));
int dos2unixfn __P((u_char dn[11], u_char * un));
void unix2dosfn __P((u_char * un, u_char dn[11], int unlen));
#endif /* defined(KERNEL) */

View File

@ -13,7 +13,7 @@
*
* October 1992
*
* $Id: msdosfs_conv.c,v 1.2 1993/12/18 00:50:38 mycroft Exp $
* $Id: msdosfs_conv.c,v 1.3 1994/03/03 00:51:33 paulus Exp $
*/
/*
@ -50,8 +50,8 @@ u_short leapyear[] = {
*/
u_long lasttime;
u_long lastday;
union dosdate lastddate;
union dostime lastdtime;
u_short lastddate;
u_short lastdtime;
/*
* Convert the unix version of time to dos's idea of time to be used in
@ -60,9 +60,10 @@ union dostime lastdtime;
void
unix2dostime(tvp, ddp, dtp)
struct timeval *tvp;
union dosdate *ddp;
union dostime *dtp;
u_short *ddp;
u_short *dtp;
{
u_long t;
u_long days;
u_long inc;
u_long year;
@ -73,19 +74,20 @@ unix2dostime(tvp, ddp, dtp)
* If the time from the last conversion is the same as now, then
* skip the computations and use the saved result.
*/
if (lasttime != tvp->tv_sec) {
lasttime = tvp->tv_sec - (tz.tz_minuteswest * 60)
/* +- daylight savings time correction */ ;
lastdtime.dts.dt_2seconds = (lasttime % 60) >> 1;
lastdtime.dts.dt_minutes = (lasttime / 60) % 60;
lastdtime.dts.dt_hours = (lasttime / (60 * 60)) % 24;
t = tvp->tv_sec - (tz.tz_minuteswest * 60)
/* +- daylight savings time correction */ ;
if (lasttime != t) {
lasttime = t;
lastdtime = (((t % 60) >> 1) << DT_2SECONDS_SHIFT)
+ (((t / 60) % 60) << DT_MINUTES_SHIFT)
+ (((t / 3600) % 24) << DT_HOURS_SHIFT);
/*
* If the number of days since 1970 is the same as the last
* time we did the computation then skip all this leap year
* and month stuff.
*/
days = lasttime / (24 * 60 * 60);
days = t / (24 * 60 * 60);
if (days != lastday) {
lastday = days;
for (year = 1970;; year++) {
@ -100,19 +102,20 @@ unix2dostime(tvp, ddp, dtp)
break;
days -= months[month];
}
lastddate.dds.dd_day = days + 1;
lastddate.dds.dd_month = month + 1;
lastddate = ((days + 1) << DD_DAY_SHIFT)
+ ((month + 1) << DD_MONTH_SHIFT);
/*
* Remember dos's idea of time is relative to 1980.
* unix's is relative to 1970. If somehow we get a
* time before 1980 then don't give totally crazy
* results.
*/
lastddate.dds.dd_year = year < 1980 ? 0 : year - 1980;
if (year > 1980)
lastddate += (year - 1980) << DD_YEAR_SHIFT;
}
}
dtp->dti = lastdtime.dti;
ddp->ddi = lastddate.ddi;
*dtp = lastdtime;
*ddp = lastddate;
}
/*
@ -121,7 +124,7 @@ unix2dostime(tvp, ddp, dtp)
*/
#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
union dosdate lastdosdate;
u_short lastdosdate;
u_long lastseconds;
/*
@ -130,44 +133,46 @@ u_long lastseconds;
* not be too efficient.
*/
void
dos2unixtime(ddp, dtp, tvp)
union dosdate *ddp;
union dostime *dtp;
dos2unixtime(dd, dt, tvp)
u_short dd;
u_short dt;
struct timeval *tvp;
{
u_long seconds;
u_long month;
u_long yr;
u_long m, month;
u_long y, year;
u_long days;
u_short *months;
seconds = (dtp->dts.dt_2seconds << 1) +
(dtp->dts.dt_minutes * 60) +
(dtp->dts.dt_hours * 60 * 60);
seconds = ((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT)
+ ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
+ ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600;
/*
* If the year, month, and day from the last conversion are the
* same then use the saved value.
*/
if (lastdosdate.ddi != ddp->ddi) {
lastdosdate.ddi = ddp->ddi;
if (lastdosdate != dd) {
lastdosdate = dd;
days = 0;
for (yr = 0; yr < ddp->dds.dd_year; yr++) {
days += yr & 0x03 ? 365 : 366;
year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
for (y = 0; y < year; y++) {
days += y & 0x03 ? 365 : 366;
}
months = yr & 0x03 ? regyear : leapyear;
months = year & 0x03 ? regyear : leapyear;
/*
* Prevent going from 0 to 0xffffffff in the following
* loop.
*/
if (ddp->dds.dd_month == 0) {
month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
if (month == 0) {
printf("dos2unixtime(): month value out of range (%d)\n",
ddp->dds.dd_month);
ddp->dds.dd_month = 1;
month);
month = 1;
}
for (month = 0; month < ddp->dds.dd_month - 1; month++) {
days += months[month];
for (m = 0; m < month - 1; m++) {
days += months[m];
}
days += ddp->dds.dd_day - 1;
days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
}
tvp->tv_sec = seconds + lastseconds + (tz.tz_minuteswest * 60)

View File

@ -13,7 +13,7 @@
*
* October 1992
*
* $Id: msdosfs_denode.c,v 1.2 1993/12/18 00:50:51 mycroft Exp $
* $Id: msdosfs_denode.c,v 1.3 1994/03/03 00:51:34 paulus Exp $
*/
#include <sys/param.h>
@ -96,7 +96,7 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
* canonical form
*/
if (direntptr && (direntptr->deAttributes & ATTR_DIRECTORY)) {
dirclust = direntptr->deStartCluster;
dirclust = getushort(direntptr->deStartCluster);
if (dirclust == MSDOSFSROOT)
diroffset = MSDOSFSROOT_OFS;
else
@ -185,7 +185,8 @@ loop:
* denode
*/
ldep->de_Time = 0x0000; /* 00:00:00 */
ldep->de_Date = (0 << 9) | (1 << 5) | (1 << 0);
ldep->de_Date = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
| (1 << DD_DAY_SHIFT);
/* Jan 1, 1980 */
/* leave the other fields as garbage */
}
@ -193,11 +194,11 @@ loop:
bp = NULL;
if (!direntptr) {
error = readep(pmp, dirclust, diroffset, &bp,
&direntptr);
&direntptr);
if (error)
return error;
}
ldep->de_de = *direntptr;
DE_INTERNALIZE(ldep, direntptr);
if (bp)
brelse(bp);
}
@ -291,15 +292,14 @@ deupdat(dep, tp, waitfor)
/*
* Put the passed in time into the directory entry.
*/
unix2dostime(&time, (union dosdate *) & dep->de_Date,
(union dostime *) & dep->de_Time);
unix2dostime(&time, &dep->de_Date, &dep->de_Time);
dep->de_flag &= ~DEUPD;
/*
* Copy the directory entry out of the denode into the cluster it
* came from.
*/
*dirp = dep->de_de; /* structure copy */
DE_EXTERNALIZE(dirp, dep);
/*
* Write the cluster back to disk. If they asked for us to wait

View File

@ -13,7 +13,7 @@
*
* October 1992
*
* $Id: msdosfs_lookup.c,v 1.7 1994/02/14 21:47:57 mycroft Exp $
* $Id: msdosfs_lookup.c,v 1.8 1994/03/03 00:51:35 paulus Exp $
*/
#include <sys/param.h>
@ -106,10 +106,10 @@ msdosfs_lookup(vdp, ndp, p)
if (error == ENOENT)
return error;
#ifdef DIAGNOSTIC
#ifdef PARANOID
if (vdp == ndp->ni_rootdir && ndp->ni_isdotdot)
panic("msdosfs_lookup: .. thru root");
#endif
#endif /* PARANOID */
pdp = dp;
vdp = ndp->ni_vp;
dp = VTODE(vdp);
@ -160,7 +160,7 @@ msdosfs_lookup(vdp, ndp, p)
#if defined(MSDOSFSDEBUG)
printf("msdosfs_lookup(): looking for . or .. in root directory\n");
#endif /* defined(MSDOSFSDEBUG) */
cluster == MSDOSFSROOT;
cluster = MSDOSFSROOT;
diroff = MSDOSFSROOT_OFS;
goto foundroot;
}
@ -314,7 +314,7 @@ found: ;
* this point.
*/
isadir = dep->deAttributes & ATTR_DIRECTORY;
scn = dep->deStartCluster;
scn = getushort(dep->deStartCluster);
foundroot:;
/*
@ -482,7 +482,8 @@ createde(dep, ndp, depp)
if (error)
return error;
}
*ndep = dep->de_de;
DE_EXTERNALIZE(ndep, dep);
/*
* If they want us to return with the denode gotten.
*/
@ -672,15 +673,16 @@ doscheckpath(source, target)
error = ENOTDIR;
break;
}
if (ep->deStartCluster == source->de_StartCluster) {
scn = getushort(ep->deStartCluster);
if (scn == source->de_StartCluster) {
error = EINVAL;
break;
}
if (ep->deStartCluster == MSDOSFSROOT)
if (scn == MSDOSFSROOT)
break;
deput(dep);
/* NOTE: deget() clears dep on error */
error = deget(pmp, ep->deStartCluster, 0, ep, &dep);
error = deget(pmp, scn, 0, ep, &dep);
brelse(bp);
bp = NULL;
if (error)

View File

@ -67,7 +67,6 @@ msdosfs_create(ndp, vap, p)
struct proc *p;
{
struct denode ndirent;
struct direntry *ndirp = &ndirent.de_de;
struct denode *dep;
struct denode *pdep = VTODE(ndp->ni_dvp);
int error;
@ -83,12 +82,11 @@ msdosfs_create(ndp, vap, p)
* readonly.
*/
bzero(&ndirent, sizeof(ndirent));
unix2dostime(&time, (union dosdate *) & ndirp->deDate,
(union dostime *) & ndirp->deTime);
unix2dosfn((u_char *) ndp->ni_ptr, ndirp->deName, ndp->ni_namelen);
ndirp->deAttributes = (vap->va_mode & VWRITE) ? 0 : ATTR_READONLY;
ndirp->deStartCluster = 0;
ndirp->deFileSize = 0;
unix2dostime(&time, &ndirent.de_Date, &ndirent.de_Time);
unix2dosfn((u_char *) ndp->ni_ptr, ndirent.de_Name, ndp->ni_namelen);
ndirent.de_Attributes = (vap->va_mode & VWRITE) ? 0 : ATTR_READONLY;
ndirent.de_StartCluster = 0;
ndirent.de_FileSize = 0;
ndirent.de_pmp = pdep->de_pmp;
ndirent.de_dev = pdep->de_dev;
ndirent.de_devvp = pdep->de_devvp;
@ -226,8 +224,7 @@ msdosfs_getattr(vp, vap, cred, p)
vap->va_rdev = 0;
vap->va_size = dep->de_FileSize;
vap->va_size_rsv = 0;
dos2unixtime((union dosdate *) & dep->de_Date,
(union dostime *) & dep->de_Time, &vap->va_atime);
dos2unixtime(dep->de_Date, dep->de_Time, &vap->va_atime);
vap->va_atime.tv_usec = 0;
vap->va_mtime.tv_sec = vap->va_atime.tv_sec;
vap->va_mtime.tv_usec = 0;
@ -590,6 +587,7 @@ msdosfs_ioctl(vp, com, data, fflag, cred, p)
struct vnode *vp;
int com;
caddr_t data;
int fflag;
struct ucred *cred;
struct proc *p;
{
@ -1031,7 +1029,7 @@ msdosfs_rename(fndp, tndp, p)
goto bad;
}
dotdotp = (struct direntry *) bp->b_un.b_addr + 1;
dotdotp->deStartCluster = tddep->de_StartCluster;
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
error = bwrite(bp);
DEUNLOCK(fdep);
if (error) {
@ -1060,15 +1058,15 @@ struct {
". ", " ", /* the . entry */
ATTR_DIRECTORY, /* file attribute */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* resevered */
1234, 1234, /* time and date */
0, /* startcluster */
0, /* filesize */
210, 4, 210, 4, /* time and date */
0, 0, /* startcluster */
0, 0, 0, 0, /* filesize */
".. ", " ", /* the .. entry */
ATTR_DIRECTORY, /* file attribute */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* resevered */
1234, 1234, /* time and date */
0, /* startcluster */
0, /* filesize */
4, 210, 4, 210, /* time and date */
0, 0, /* startcluster */
0, 0, 0, 0, /* filesize */
};
int
@ -1087,6 +1085,7 @@ msdosfs_mkdir(ndp, vap, p)
struct denode ndirent;
struct msdosfsmount *pmp;
struct buf *bp;
u_short dDate, dTime;
pvp = ndp->ni_dvp;
pdep = VTODE(pvp);
@ -1123,13 +1122,14 @@ msdosfs_mkdir(ndp, vap, p)
bzero(bp->b_un.b_addr, pmp->pm_bpcluster);
bcopy(&dosdirtemplate, bp->b_un.b_addr, sizeof dosdirtemplate);
denp = (struct direntry *) bp->b_un.b_addr;
denp->deStartCluster = newcluster;
unix2dostime(&time, (union dosdate *) & denp->deDate,
(union dostime *) & denp->deTime);
putushort(denp->deStartCluster, newcluster);
unix2dostime(&time, &dDate, &dTime);
putushort(denp->deDate, dDate);
putushort(denp->deTime, dTime);
denp++;
denp->deStartCluster = pdep->de_StartCluster;
unix2dostime(&time, (union dosdate *) & denp->deDate,
(union dostime *) & denp->deTime);
putushort(denp->deStartCluster, pdep->de_StartCluster);
putushort(denp->deDate, dDate);
putushort(denp->deTime, dTime);
if (error = bwrite(bp)) {
clusterfree(pmp, newcluster, NULL);
free(ndp->ni_pnbuf, M_NAMEI);
@ -1145,8 +1145,7 @@ msdosfs_mkdir(ndp, vap, p)
ndep = &ndirent;
bzero(ndep, sizeof(*ndep));
unix2dosfn((u_char *) ndp->ni_ptr, ndep->de_Name, ndp->ni_namelen);
unix2dostime(&time, (union dosdate *) & ndep->de_Date,
(union dostime *) & ndep->de_Time);
unix2dostime(&time, &ndep->de_Date, &ndep->de_Time);
ndep->de_StartCluster = newcluster;
ndep->de_Attributes = ATTR_DIRECTORY;
ndep->de_pmp = pmp; /* createde() needs this */
@ -1435,7 +1434,8 @@ msdosfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
*/
if (dentp->deAttributes & ATTR_DIRECTORY) {
/* if this is the root directory */
if ((fileno = dentp->deStartCluster) == MSDOSFSROOT)
fileno = getushort(dentp->deStartCluster);
if (fileno == MSDOSFSROOT)
fileno = 1;
}
else {