- Add support for Win'95 separate creation/modification/access timestamps

- Re-introduce lowercase filenames for non-Win'95-filesystems
This commit is contained in:
ws 1995-11-29 15:08:32 +00:00
parent 87093145ce
commit debbf2f60e
7 changed files with 130 additions and 71 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: mount_msdos.8,v 1.8 1995/10/15 15:35:47 ws Exp $
.\" $NetBSD: mount_msdos.8,v 1.9 1995/11/29 15:11:37 ws Exp $
.\"
.\" Copyright (c) 1993,1994 Christopher G. Demetriou
.\" All rights reserved.
@ -99,7 +99,8 @@ Force behaviour to
ignore and not generate Win'95 long filenames.
.It Fl l
Force listing and generation of
Win'95 long filenames.
Win'95 long filenames
and separate creation/modification/access dates.
.Pp
If neither
.Fl s
@ -139,6 +140,9 @@ will result in empty filesystems to be populated
with short filenames only. To generate long filenames
on empty DOS filesystems use
.Fl l .
.Pp
Note that Win'95 handles only access dates,
but not access times.
.Sh HISTORY
The
.Nm mount_msdos

View File

@ -1,4 +1,4 @@
/* $NetBSD: denode.h,v 1.18 1995/11/05 18:47:48 ws Exp $ */
/* $NetBSD: denode.h,v 1.19 1995/11/29 15:08:32 ws Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -151,8 +151,12 @@ 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_short de_Time; /* creation time */
u_short de_Date; /* creation date */
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_FileSize; /* size of file in bytes */
struct fatcache de_fc[FC_SIZE]; /* fat cache */
@ -164,8 +168,10 @@ struct denode {
#define DE_LOCKED 0x0001 /* Denode lock. */
#define DE_WANTED 0x0002 /* Denode is wanted by a process. */
#define DE_UPDATE 0x0004 /* Modification time update request. */
#define DE_MODIFIED 0x0008 /* Denode has been modified. */
#define DE_RENAME 0x0010 /* Denode is in the process of being renamed */
#define DE_CREATE 0x0008 /* Creation time update */
#define DE_ACCESS 0x0010 /* Access time update */
#define DE_MODIFIED 0x0020 /* Denode has been modified. */
#define DE_RENAME 0x0040 /* Denode is in the process of being renamed */
/*
* Maximum filename length in Win95
@ -181,16 +187,24 @@ struct denode {
#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_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))
#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)->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))
@ -204,13 +218,22 @@ struct denode {
#define DETOV(de) ((de)->de_vnode)
#define DE_TIMES(dep) \
if ((dep)->de_flag & DE_UPDATE) { \
(dep)->de_flag &= ~DE_UPDATE; \
if ((dep)->de_flag & (DE_UPDATE | DE_CREATE | DE_ACCESS)) { \
if (((dep)->de_Attributes & ATTR_DIRECTORY) == 0) { \
unix2dostime(NULL, &(dep)->de_Date, &(dep)->de_Time); \
(dep)->de_Attributes |= ATTR_ARCHIVE; \
if ((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95 \
|| (dep)->de_flag & DE_UPDATE) { \
unix2dostime(NULL, &(dep)->de_MDate, &(dep)->de_MTime); \
(dep)->de_Attributes |= ATTR_ARCHIVE; \
} \
if (!((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)) { \
if ((dep)->de_flag & DE_ACCESS) \
unix2dostime(NULL, &(dep)->de_ADate, &(dep)->de_ATime); \
if ((dep)->de_flag & DE_CREATE) \
unix2dostime(NULL, &(dep)->de_CDate, &(dep)->de_CTime); \
} \
(dep)->de_flag |= DE_MODIFIED; \
} \
(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: direntry.h,v 1.10 1995/10/15 15:34:20 ws Exp $ */
/* $NetBSD: direntry.h,v 1.11 1995/11/29 15:08:34 ws Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -64,9 +64,13 @@ 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[10]; /* reserved */
u_int8_t deTime[2]; /* create/last update time */
u_int8_t deDate[2]; /* create/last update date */
u_int8_t deReserved[2]; /* reserved */
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 deMTime[2]; /* last update time */
u_int8_t deMDate[2]; /* last update date */
u_int8_t deStartCluster[2]; /* starting cluster of file */
u_int8_t deFileSize[4]; /* size of file in bytes */
};
@ -116,7 +120,7 @@ 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));
int dos2unixfn __P((u_char dn[11], u_char *un));
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));
int winChkName __P((u_char *un, int unlen, struct winentry *wep, int chksum));

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_conv.c,v 1.12 1995/10/30 19:06:15 ws Exp $ */
/* $NetBSD: msdosfs_conv.c,v 1.13 1995/11/29 15:08:36 ws Exp $ */
/*-
* Copyright (C) 1995 Wolfgang Solfrank.
@ -342,12 +342,14 @@ u2l[256] = {
* null.
*/
int
dos2unixfn(dn, un)
dos2unixfn(dn, un, lower)
u_char dn[11];
u_char *un;
int lower;
{
int i;
int thislong = 1;
u_char c;
/*
* If first char of the filename is SLOT_E5 (0x05), then the real
@ -356,16 +358,18 @@ dos2unixfn(dn, un)
* directory slot. Another dos quirk.
*/
if (*dn == SLOT_E5)
*un++ = dos2unix[0xe5];
c = dos2unix[0xe5];
else
*un++ = dos2unix[*dn];
c = dos2unix[*dn];
*un++ = lower ? u2l[c] : c;
dn++;
/*
* Copy the name portion into the unix filename string.
*/
for (i = 1; i < 8 && *dn != ' '; i++) {
*un++ = dos2unix[*dn++];
c = dos2unix[*dn++];
*un++ = lower ? u2l[c] : c;
thislong++;
}
dn += 8 - i;
@ -378,7 +382,8 @@ dos2unixfn(dn, un)
*un++ = '.';
thislong++;
for (i = 0; i < 3 && *dn != ' '; i++) {
*un++ = dos2unix[*dn++];
c = dos2unix[*dn++];
*un++ = lower ? u2l[c] : c;
thislong++;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_denode.c,v 1.17 1995/11/05 18:47:51 ws Exp $ */
/* $NetBSD: msdosfs_denode.c,v 1.18 1995/11/29 15:08:38 ws Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -230,10 +230,14 @@ deget(pmp, dirclust, diroffset, depp)
* spit up when called from msdosfs_getattr() with root
* denode
*/
ldep->de_Time = 0x0000; /* 00:00:00 */
ldep->de_Date = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
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;
/* leave the other fields as garbage */
} else {
if (error = readep(pmp, dirclust, diroffset, &bp, &direntptr))
@ -501,13 +505,10 @@ deextend(dep, length, cred)
return (EINVAL);
/*
* Directories can only be extended by the superuser.
* Is this really important?
* Directories cannot be extended.
*/
if (dep->de_Attributes & ATTR_DIRECTORY) {
if (error = suser(cred, (u_short *)0))
return (error);
}
if (dep->de_Attributes & ATTR_DIRECTORY)
return (EISDIR);
if (length <= dep->de_FileSize)
panic("deextend: file too large");

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vfsops.c,v 1.35 1995/11/05 18:47:59 ws Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.36 1995/11/29 15:08:40 ws Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -664,8 +664,9 @@ loop:
if (VOP_ISLOCKED(vp))
continue;
dep = VTODE(vp);
if ((dep->de_flag & DE_UPDATE) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
if (dep->de_flag
& (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED) == 0
&& vp->v_dirtyblkhd.lh_first == NULL)
continue;
if (vget(vp, 1))
goto loop;

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vnops.c,v 1.40 1995/11/05 18:48:02 ws Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.41 1995/11/29 15:08:42 ws Exp $ */
/*-
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
@ -133,7 +133,6 @@ msdosfs_create(ap)
panic("msdosfs_create: no name");
#endif
bzero(&ndirent, sizeof(ndirent));
unix2dostime(NULL, &ndirent.de_Date, &ndirent.de_Time);
if (error = uniqdosname(pdep, cnp, ndirent.de_Name))
goto bad;
@ -143,6 +142,8 @@ msdosfs_create(ap)
ndirent.de_FileSize = 0;
ndirent.de_dev = pdep->de_dev;
ndirent.de_devvp = pdep->de_devvp;
ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
DE_TIMES(&ndirent);
if (error = createde(&ndirent, pdep, &dep, cnp))
goto bad;
if ((cnp->cn_flags & SAVESTART) == 0)
@ -277,13 +278,14 @@ msdosfs_getattr(ap)
vap->va_uid = dep->de_pmp->pm_uid;
vap->va_rdev = 0;
vap->va_size = dep->de_FileSize;
dos2unixtime(dep->de_Date, dep->de_Time, &vap->va_atime);
vap->va_mtime = vap->va_atime;
#ifndef MSDOSFS_NODIRMOD
if (vap->va_mode & S_IFDIR)
TIMEVAL_TO_TIMESPEC(&time, &vap->va_mtime);
#endif
vap->va_ctime = vap->va_atime;
dos2unixtime(dep->de_MDate, dep->de_MTime, &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);
} else {
vap->va_atime = vap->va_mtime;
vap->va_ctime = vap->va_mtime;
}
vap->va_flags = 0;
if ((dep->de_Attributes & ATTR_ARCHIVE) == 0)
vap->va_flags |= SF_ARCHIVED;
@ -329,6 +331,9 @@ msdosfs_setattr(ap)
#endif
return (EINVAL);
}
/*
* Directories must not ever get their attributes modified
*/
if (ap->a_vp->v_type == VDIR)
return EISDIR;
@ -336,13 +341,17 @@ msdosfs_setattr(ap)
if (error = detrunc(dep, (u_long)vap->va_size, 0, cred, ap->a_p))
return (error);
}
if (vap->va_mtime.ts_sec != VNOVAL) {
if (vap->va_atime.ts_sec != VNOVAL || vap->va_mtime.ts_sec != VNOVAL) {
if (cred->cr_uid != dep->de_pmp->pm_uid &&
(error = suser(cred, &ap->a_p->p_acflag)) &&
((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
(error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p))))
return (error);
unix2dostime(&vap->va_mtime, &dep->de_Date, &dep->de_Time);
if (!(dep->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95)
&& vap->va_atime.ts_sec != VNOVAL)
unix2dostime(&vap->va_atime, &dep->de_ADate, &dep->de_ATime);
if (vap->va_mtime.ts_sec != VNOVAL)
unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime);
dep->de_Attributes |= ATTR_ARCHIVE;
dep->de_flag |= DE_MODIFIED;
}
@ -375,7 +384,7 @@ msdosfs_setattr(ap)
dep->de_Attributes |= ATTR_ARCHIVE;
dep->de_flag |= DE_MODIFIED;
}
return (0);
return (deupdat(dep, 1));
}
int
@ -450,6 +459,8 @@ msdosfs_read(ap)
return (error);
}
error = uiomove(bp->b_data + on, (int) n, uio);
if (!isadir)
dep->de_flag |= DE_ACCESS;
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
@ -491,12 +502,17 @@ msdosfs_write(ap)
dep->de_diroffset, dep->de_dirclust, dep->de_StartCluster);
#endif
if (vp->v_type == VREG) {
switch (vp->v_type) {
case VREG:
if (ioflag & IO_APPEND)
uio->uio_offset = dep->de_FileSize;
thisvp = vp;
} else
break;
case VDIR:
return EISDIR;
default:
panic("msdosfs_write(): bad file type");
}
if (uio->uio_offset < 0)
return (EINVAL);
@ -507,22 +523,13 @@ msdosfs_write(ap)
/*
* If they've exceeded their filesize limit, tell them about it.
*/
if (vp->v_type == VREG && p &&
if (p &&
((uio->uio_offset + uio->uio_resid) >
p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) {
p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) {
psignal(p, SIGXFSZ);
return (EFBIG);
}
/*
* If attempting to write beyond the end of the root directory we
* stop that here because the root directory can not grow.
*/
if ((dep->de_Attributes & ATTR_DIRECTORY) &&
dep->de_StartCluster == MSDOSFSROOT &&
(uio->uio_offset + uio->uio_resid) > dep->de_FileSize)
return (ENOSPC);
/*
* If the offset we are starting the write at is beyond the end of
* the file, then they've done a seek. Unix filesystems allow
@ -645,7 +652,7 @@ errexit:
if (uio->uio_resid != resid)
error = 0;
}
} else
} else if (ioflag & IO_SYNC)
error = deupdat(dep, 1);
return (error);
}
@ -1179,7 +1186,11 @@ msdosfs_mkdir(ap)
goto bad2;
bzero(&ndirent, sizeof(ndirent));
unix2dostime(NULL, &ndirent.de_Date, &ndirent.de_Time);
if (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95)) {
unix2dostime(NULL, &ndirent.de_CDate, &ndirent.de_CTime);
unix2dostime(NULL, &ndirent.de_ADate, &ndirent.de_ATime);
}
unix2dostime(NULL, &ndirent.de_MDate, &ndirent.de_MTime);
/*
* Now fill the cluster with the "." and ".." entries. And write
@ -1193,11 +1204,19 @@ msdosfs_mkdir(ap)
bcopy(&dosdirtemplate, bp->b_data, sizeof dosdirtemplate);
denp = (struct direntry *)bp->b_data;
putushort(denp[0].deStartCluster, newcluster);
putushort(denp[0].deDate, ndirent.de_Date);
putushort(denp[0].deTime, ndirent.de_Time);
putushort(denp[0].deCDate, ndirent.de_CDate);
putushort(denp[0].deCTime, ndirent.de_CTime);
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);
putushort(denp[1].deDate, ndirent.de_Date);
putushort(denp[1].deTime, ndirent.de_Time);
putushort(denp[1].deCDate, ndirent.de_CDate);
putushort(denp[1].deCTime, ndirent.de_CTime);
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 (error = bwrite(bp))
goto bad;
@ -1517,7 +1536,8 @@ msdosfs_readdir(ap)
(dentp->deAttributes & ATTR_DIRECTORY) ? DT_DIR : DT_REG;
if (chksum != winChksum(dentp->deName))
dirbuf.d_namlen = dos2unixfn(dentp->deName,
(u_char *)dirbuf.d_name);
(u_char *)dirbuf.d_name,
pmp->pm_flags & MSDOSFSMNT_SHORTNAME);
else
dirbuf.d_name[dirbuf.d_namlen] = 0;
chksum = -1;
@ -1797,13 +1817,14 @@ msdosfs_pathconf(ap)
register_t *a_retval;
} */ *ap;
{
struct msdosfsmount *pmp = VTODE(ap->a_vp)->de_pmp;
switch (ap->a_name) {
case _PC_LINK_MAX:
*ap->a_retval = 1;
return (0);
case _PC_NAME_MAX:
*ap->a_retval = 12;
*ap->a_retval = pmp->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12;
return (0);
case _PC_PATH_MAX:
*ap->a_retval = PATH_MAX;