summaryrefslogtreecommitdiff
path: root/sys/msdosfs/msdosfs_lookup.c
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1998-01-11 20:39:12 +0000
committerNiels Provos <provos@cvs.openbsd.org>1998-01-11 20:39:12 +0000
commit487fe4efe824e828cdefbee41c1d03ef04a885f3 (patch)
tree49663eae55a517c8ad3c2220a6ede523fa5dc975 /sys/msdosfs/msdosfs_lookup.c
parent6607731225347e583be10d914e5758d7a9726fc9 (diff)
FAT32 support from NetBSD by Wolfgang Solfrank.
Diffstat (limited to 'sys/msdosfs/msdosfs_lookup.c')
-rw-r--r--sys/msdosfs/msdosfs_lookup.c80
1 files changed, 67 insertions, 13 deletions
diff --git a/sys/msdosfs/msdosfs_lookup.c b/sys/msdosfs/msdosfs_lookup.c
index eaaef5667b9..f36f051057e 100644
--- a/sys/msdosfs/msdosfs_lookup.c
+++ b/sys/msdosfs/msdosfs_lookup.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: msdosfs_lookup.c,v 1.9 1997/11/11 18:57:16 niklas Exp $ */
-/* $NetBSD: msdosfs_lookup.c,v 1.30 1996/10/25 23:14:08 cgd Exp $ */
+/* $OpenBSD: msdosfs_lookup.c,v 1.10 1998/01/11 20:39:09 provos Exp $ */
+/* $NetBSD: msdosfs_lookup.c,v 1.34 1997/10/18 22:12:27 ws Exp $ */
/*-
- * Copyright (C) 1994, 1995 Wolfgang Solfrank.
- * Copyright (C) 1994, 1995 TooLs GmbH.
+ * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
+ * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
* All rights reserved.
* Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
*
@@ -433,9 +433,17 @@ found:;
*/
isadir = dep->deAttributes & ATTR_DIRECTORY;
scn = getushort(dep->deStartCluster);
+ if (FAT32(pmp)) {
+ scn |= getushort(dep->deHighClust) << 16;
+ if (scn == pmp->pm_rootdirblk) {
+ /*
+ * There should actually be 0 here.
+ * Just ignore the error.
+ */
+ scn = MSDOSFSROOT;
+ }
+ }
- if (cluster == MSDOSFSROOT)
- blkoff = diroff;
if (isadir) {
cluster = scn;
if (cluster == MSDOSFSROOT)
@@ -457,6 +465,8 @@ foundroot:;
* entry of the filesystems root directory. isadir and scn were
* setup before jumping here. And, bp is already null.
*/
+ if (FAT32(pmp) && scn == MSDOSFSROOT)
+ scn = pmp->pm_rootdirblk;
/*
* If deleting, and at end of pathname, return
@@ -467,6 +477,12 @@ foundroot:;
*/
if (nameiop == DELETE && (flags & ISLASTCN)) {
/*
+ * Don't allow deleting the root.
+ */
+ if (blkoff == MSDOSFSROOT_OFS)
+ return EROFS; /* really? XXX */
+
+ /*
* Write access to directory required to delete files.
*/
error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc);
@@ -498,6 +514,9 @@ foundroot:;
*/
if (nameiop == RENAME && wantparent &&
(flags & ISLASTCN)) {
+ if (blkoff == MSDOSFSROOT_OFS)
+ return EROFS; /* really? XXX */
+
error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc);
if (error)
return (error);
@@ -638,7 +657,7 @@ createde(dep, ddep, depp, cnp)
ndep = bptoep(pmp, bp, ddep->de_fndoffset);
DE_EXTERNALIZE(ndep, dep);
-
+
/*
* Now write the Win95 long name
*/
@@ -686,6 +705,8 @@ createde(dep, ddep, depp, cnp)
if (depp) {
if (dep->de_Attributes & ATTR_DIRECTORY) {
dirclust = dep->de_StartCluster;
+ if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)
+ dirclust = MSDOSFSROOT;
if (dirclust == MSDOSFSROOT)
diroffset = MSDOSFSROOT_OFS;
else
@@ -802,12 +823,19 @@ doscheckpath(source, target)
}
if (dep->de_StartCluster == MSDOSFSROOT)
goto out;
+ pmp = dep->de_pmp;
+#ifdef DIAGNOSTIC
+ if (pmp != source->de_pmp)
+ panic("doscheckpath: source and target on different filesystems");
+#endif
+ if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)
+ goto out;
+
for (;;) {
if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) {
error = ENOTDIR;
break;
}
- pmp = dep->de_pmp;
scn = dep->de_StartCluster;
error = bread(pmp->pm_devvp, cntobn(pmp, scn),
pmp->pm_bpcluster, NOCRED, &bp);
@@ -821,12 +849,23 @@ doscheckpath(source, target)
break;
}
scn = getushort(ep->deStartCluster);
+ if (FAT32(pmp))
+ scn |= getushort(ep->deHighClust) << 16;
+
if (scn == source->de_StartCluster) {
error = EINVAL;
break;
}
if (scn == MSDOSFSROOT)
break;
+ if (FAT32(pmp) && scn == pmp->pm_rootdirblk) {
+ /*
+ * scn should be 0 in this case,
+ * but we silently ignore the error.
+ */
+ break;
+ }
+
vput(DETOV(dep));
brelse(bp);
bp = NULL;
@@ -895,7 +934,7 @@ readde(dep, bpp, epp)
/*
* Remove a directory entry. At this point the file represented by the
- * directory entry to be removed is still full length until no one has it
+ * directory entry to be removed is still full length until noone has it
* open. When the file no longer being used msdosfs_inactive() is called
* and will truncate the file to 0 length. When the vnode containing the
* denode is needed for some other purpose by VFS it will call
@@ -920,7 +959,9 @@ removede(pdep, dep)
#endif
dep->de_refcnt--;
+ offset += sizeof(struct direntry);
do {
+ offset -= sizeof(struct direntry);
error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize);
if (error)
return error;
@@ -930,6 +971,17 @@ removede(pdep, dep)
return error;
}
ep = bptoep(pmp, bp, offset);
+ /*
+ * Check whether, if we came here the second time, i.e.
+ * when underflowing into the previous block, the last
+ * entry in this block is a longfilename entry, too.
+ */
+ if (ep->deAttributes != ATTR_WIN95
+ && offset != pdep->de_fndoffset) {
+ brelse(bp);
+ break;
+ }
+ offset += sizeof(struct direntry);
while (1) {
/*
* We are a bit agressive here in that we delete any Win95
@@ -937,18 +989,18 @@ removede(pdep, dep)
* Since these presumably aren't valid anyway,
* there should be no harm.
*/
- ep--->deName[0] = SLOT_DELETED;
offset -= sizeof(struct direntry);
+ ep--->deName[0] = SLOT_DELETED;
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95)
- || !((offset + sizeof(struct direntry)) & pmp->pm_crbomask)
+ || !(offset & pmp->pm_crbomask)
|| ep->deAttributes != ATTR_WIN95)
break;
}
if ((error = bwrite(bp)) != 0)
return error;
} while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95)
- && offset
- && !(offset & pmp->pm_crbomask));
+ && !(offset & pmp->pm_crbomask)
+ && offset);
return 0;
}
@@ -1014,6 +1066,8 @@ uniqdosname(dep, cnp, cp)
brelse(bp);
}
}
+
+ return (EEXIST);
}
/*