diff options
author | Niels Provos <provos@cvs.openbsd.org> | 1998-01-11 20:39:12 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 1998-01-11 20:39:12 +0000 |
commit | 487fe4efe824e828cdefbee41c1d03ef04a885f3 (patch) | |
tree | 49663eae55a517c8ad3c2220a6ede523fa5dc975 /sys/msdosfs/msdosfs_lookup.c | |
parent | 6607731225347e583be10d914e5758d7a9726fc9 (diff) |
FAT32 support from NetBSD by Wolfgang Solfrank.
Diffstat (limited to 'sys/msdosfs/msdosfs_lookup.c')
-rw-r--r-- | sys/msdosfs/msdosfs_lookup.c | 80 |
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); } /* |