diff options
author | dfr <dfr@FreeBSD.org> | 1994-09-19 15:41:57 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1994-09-19 15:41:57 +0000 |
commit | 7efbb964fdff1348e01bdcd7d4bb59551c389bef (patch) | |
tree | 4ee90f451b7756bcd74bbc0c7e0ef0219507ff02 /sys/msdosfs/msdosfs_vfsops.c | |
parent | 7a224749be53b3a6bdb826ffbd93208f0b757586 (diff) | |
download | FreeBSD-src-7efbb964fdff1348e01bdcd7d4bb59551c389bef.zip FreeBSD-src-7efbb964fdff1348e01bdcd7d4bb59551c389bef.tar.gz |
Added msdosfs.
Obtained from: NetBSD
Diffstat (limited to 'sys/msdosfs/msdosfs_vfsops.c')
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 733 |
1 files changed, 733 insertions, 0 deletions
diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c new file mode 100644 index 0000000..ac9c284 --- /dev/null +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -0,0 +1,733 @@ +/* $Id$ */ +/* $NetBSD: msdosfs_vfsops.c,v 1.19 1994/08/21 18:44:10 ws Exp $ */ + +/*- + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 1994 TooLs GmbH. + * All rights reserved. + * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Written by Paul Popelka (paulp@uts.amdahl.com) + * + * You can do anything you want with this software, just don't say you wrote + * it, and don't remove this notice. + * + * This software is provided "as is". + * + * The author supplies this software to be publicly redistributed on the + * understanding that the author is not responsible for the correct + * functioning of this software in any circumstances and is not liable for + * any damages caused by this software. + * + * October 1992 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/kernel.h> +#include <sys/vnode.h> +#include <miscfs/specfs/specdev.h> /* XXX */ /* defines v_rdev */ +#include <sys/mount.h> +#include <sys/buf.h> +#include <sys/file.h> +#include <sys/malloc.h> + +#include <msdosfs/bpb.h> +#include <msdosfs/bootsect.h> +#include <msdosfs/direntry.h> +#include <msdosfs/denode.h> +#include <msdosfs/msdosfsmount.h> +#include <msdosfs/fat.h> + +int msdosfsdoforce = 1; /* 1 = force unmount */ + +/* + * mp - path - addr in user space of mount point (ie /usr or whatever) + * data - addr in user space of mount params including the name of the block + * special file to treat as a filesystem. + */ +int +msdosfs_mount(mp, path, data, ndp, p) + struct mount *mp; + char *path; + caddr_t data; + struct nameidata *ndp; + struct proc *p; +{ + struct vnode *devvp; /* vnode for blk device to mount */ + struct msdosfs_args args; /* will hold data from mount request */ + struct msdosfsmount *pmp; /* msdosfs specific mount control block */ + int error, flags; + u_int size; + struct ucred *cred, *scred; + struct vattr va; + + /* + * Copy in the args for the mount request. + */ + if (error = copyin(data, (caddr_t) & args, sizeof(struct msdosfs_args))) + return error; + + /* + * If they just want to update then be sure we can do what is + * asked. Can't change a filesystem from read/write to read only. + * Why? And if they've supplied a new device file name then we + * continue, otherwise return. + */ + if (mp->mnt_flag & MNT_UPDATE) { + pmp = (struct msdosfsmount *) mp->mnt_data; + error = 0; + if (pmp->pm_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { + flags = WRITECLOSE; + if (mp->mnt_flag & MNT_FORCE) + flags |= FORCECLOSE; + if (vfs_busy(mp)) + return EBUSY; + error = vflush(mp, NULLVP, flags); + vfs_unbusy(mp); + } + if (!error && (mp->mnt_flag & MNT_RELOAD)) + /* not yet implemented */ + error = EINVAL; + if (error) + return error; + if (pmp->pm_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) + pmp->pm_ronly = 0; + if (args.fspec == 0) { + /* + * Process export requests. + */ + return vfs_export(mp, &pmp->pm_export, &args.export); + } + } else + pmp = NULL; + + /* + * check to see that the user in owns the target directory. + * Note the very XXX trick to make sure we're checking as the + * real user -- were mount() executable by anyone, this wouldn't + * be a problem. + * + * XXX there should be one consistent error out. + */ + cred = crdup(p->p_ucred); /* XXX */ + cred->cr_uid = p->p_cred->p_ruid; /* XXX */ + error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p); + if (error) { + crfree(cred); /* XXX */ + return error; + } + if (cred->cr_uid != 0) { + if (va.va_uid != cred->cr_uid) { + error = EACCES; + crfree(cred); /* XXX */ + return error; + } + + /* a user mounted it; we'll verify permissions when unmounting */ + mp->mnt_flag |= MNT_USER; + } + + /* + * Now, lookup the name of the block device this mount or name + * update request is to apply to. + */ + NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); + scred = p->p_ucred; /* XXX */ + p->p_ucred = cred; /* XXX */ + error = namei(ndp); + p->p_ucred = scred; /* XXX */ + crfree(cred); /* XXX */ + if (error != 0) + return error; + + /* + * Be sure they've given us a block device to treat as a + * filesystem. And, that its major number is within the bdevsw + * table. + */ + devvp = ndp->ni_vp; + if (devvp->v_type != VBLK) { + vrele(devvp); + return ENOTBLK; + } + if (major(devvp->v_rdev) >= nblkdev) { + vrele(devvp); + return ENXIO; + } + + /* + * If this is an update, then make sure the vnode for the block + * special device is the same as the one our filesystem is in. + */ + if (mp->mnt_flag & MNT_UPDATE) { + if (devvp != pmp->pm_devvp) + error = EINVAL; + else + vrele(devvp); + } else { + + /* + * Well, it's not an update, it's a real mount request. + * Time to get dirty. + */ + error = mountmsdosfs(devvp, mp, p); + } + if (error) { + vrele(devvp); + return error; + } + + /* + * Copy in the name of the directory the filesystem is to be + * mounted on. Then copy in the name of the block special file + * representing the filesystem being mounted. And we clear the + * remainder of the character strings to be tidy. Set up the + * user id/group id/mask as specified by the user. Then, we try to + * fill in the filesystem stats structure as best we can with + * whatever applies from a dos file system. + */ + pmp = (struct msdosfsmount *) mp->mnt_data; + copyinstr(path, (caddr_t) mp->mnt_stat.f_mntonname, + sizeof(mp->mnt_stat.f_mntonname) - 1, &size); + bzero(mp->mnt_stat.f_mntonname + size, + sizeof(mp->mnt_stat.f_mntonname) - size); + copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); + bzero(mp->mnt_stat.f_mntfromname + size, + MNAMELEN - size); + pmp->pm_mounter = p->p_cred->p_ruid; + pmp->pm_gid = args.gid; + pmp->pm_uid = args.uid; + pmp->pm_mask = args.mask; + (void) msdosfs_statfs(mp, &mp->mnt_stat, p); +#ifdef MSDOSFS_DEBUG + printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap); +#endif + return 0; +} + +int +mountmsdosfs(devvp, mp, p) + struct vnode *devvp; + struct mount *mp; + struct proc *p; +{ + int i; + int bpc; + int bit; + int error; + int needclose; + int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; + dev_t dev = devvp->v_rdev; + union bootsector *bsp; + struct msdosfsmount *pmp = NULL; + struct buf *bp0 = NULL; + struct byte_bpb33 *b33; + struct byte_bpb50 *b50; + + /* + * Multiple mounts of the same block special file aren't allowed. + * Make sure no one else has the special file open. And flush any + * old buffers from this filesystem. Presumably this prevents us + * from running into buffers that are the wrong blocksize. + */ + if (error = vfs_mountedon(devvp)) + return error; + if (vcount(devvp) > 1) + return EBUSY; + if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) + return error; + + /* + * Now open the block special file. + */ + if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE, FSCRED, p)) + return error; + needclose = 1; +#ifdef HDSUPPORT + /* + * Put this in when we support reading dos filesystems from + * partitioned harddisks. + */ + if (VOP_IOCTL(devvp, DIOCGPART, &msdosfspart, FREAD, NOCRED, p) == 0) { + } +#endif + + /* + * Read the boot sector of the filesystem, and then check the boot + * signature. If not a dos boot sector then error out. We could + * also add some checking on the bsOemName field. So far I've seen + * the following values: "IBM 3.3" "MSDOS3.3" "MSDOS5.0" + */ + if (error = bread(devvp, 0, 512, NOCRED, &bp0)) + goto error_exit; + bp0->b_flags |= B_AGE; + bsp = (union bootsector *) bp0->b_data; + b33 = (struct byte_bpb33 *) bsp->bs33.bsBPB; + b50 = (struct byte_bpb50 *) bsp->bs50.bsBPB; +#ifdef MSDOSFS_CHECKSIG + if (bsp->bs50.bsBootSectSig != BOOTSIG) { + error = EINVAL; + goto error_exit; + } +#endif + if ( bsp->bs50.bsJump[0] != 0xe9 && + (bsp->bs50.bsJump[0] != 0xeb || bsp->bs50.bsJump[2] != 0x90)) { + error = EINVAL; + goto error_exit; + } + + pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK); + bzero((caddr_t)pmp, sizeof *pmp); + pmp->pm_mountp = mp; + + /* + * Compute several useful quantities from the bpb in the + * bootsector. Copy in the dos 5 variant of the bpb then fix up + * the fields that are different between dos 5 and dos 3.3. + */ + pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); + pmp->pm_SectPerClust = b50->bpbSecPerClust; + pmp->pm_ResSectors = getushort(b50->bpbResSectors); + pmp->pm_FATs = b50->bpbFATs; + pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); + pmp->pm_Sectors = getushort(b50->bpbSectors); + pmp->pm_Media = b50->bpbMedia; + pmp->pm_FATsecs = getushort(b50->bpbFATsecs); + pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); + pmp->pm_Heads = getushort(b50->bpbHeads); + + /* XXX - We should probably check more values here */ + if (!pmp->pm_BytesPerSec || !pmp->pm_SectPerClust || + !pmp->pm_Heads || pmp->pm_Heads > 255 || + !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 63) { + error = EINVAL; + goto error_exit; + } + + if (pmp->pm_Sectors == 0) { + pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); + pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); + } else { + pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); + pmp->pm_HugeSectors = pmp->pm_Sectors; + } + 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;/* in sectors */ + pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; + pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / + pmp->pm_SectPerClust; + pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; + pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; + if (FAT12(pmp)) + /* + * This will usually be a floppy disk. This size makes sure + * that one fat entry will not be split across multiple + * blocks. + */ + pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; + else + /* + * This will usually be a hard disk. Reading or writing one + * block should be quite fast. + */ + pmp->pm_fatblocksize = MAXBSIZE; + pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; + + + if ((pmp->pm_rootdirsize % pmp->pm_SectPerClust) != 0) + printf("mountmsdosfs(): root directory is not a multiple of the clustersize in length\n"); + + /* + * Compute mask and shift value for isolating cluster relative byte + * offsets and cluster numbers from a file offset. + */ + bpc = pmp->pm_SectPerClust * pmp->pm_BytesPerSec; + pmp->pm_bpcluster = bpc; + pmp->pm_depclust = bpc / sizeof(struct direntry); + pmp->pm_crbomask = bpc - 1; + if (bpc == 0) { + error = EINVAL; + goto error_exit; + } + bit = 1; + for (i = 0; i < 32; i++) { + if (bit & bpc) { + if (bit ^ bpc) { + error = EINVAL; + goto error_exit; + } + pmp->pm_cnshift = i; + break; + } + bit <<= 1; + } + + pmp->pm_brbomask = 0x01ff; /* 512 byte blocks only (so far) */ + pmp->pm_bnshift = 9; /* shift right 9 bits to get bn */ + + /* + * Release the bootsector buffer. + */ + brelse(bp0); + bp0 = NULL; + + /* + * Allocate memory for the bitmap of allocated clusters, and then + * fill it in. + */ + pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1) + / N_INUSEBITS) + * sizeof(*pmp->pm_inusemap), + M_MSDOSFSFAT, M_WAITOK); + + /* + * fillinusemap() needs pm_devvp. + */ + pmp->pm_dev = dev; + pmp->pm_devvp = devvp; + + /* + * Have the inuse map filled in. + */ + error = fillinusemap(pmp); + if (error) + goto error_exit; + + /* + * If they want fat updates to be synchronous then let them suffer + * the performance degradation in exchange for the on disk copy of + * the fat being correct just about all the time. I suppose this + * would be a good thing to turn on if the kernel is still flakey. + */ + pmp->pm_waitonfat = mp->mnt_flag & MNT_SYNCHRONOUS; + + /* + * Finish up. + */ + pmp->pm_ronly = ronly; + if (ronly == 0) + pmp->pm_fmod = 1; + mp->mnt_data = (qaddr_t) pmp; + mp->mnt_stat.f_fsid.val[0] = (long)dev; + mp->mnt_stat.f_fsid.val[1] = MOUNT_MSDOS; + mp->mnt_flag |= MNT_LOCAL; +#ifdef QUOTA + /* + * If we ever do quotas for DOS filesystems this would be a place + * to fill in the info in the msdosfsmount structure. You dolt, + * quotas on dos filesystems make no sense because files have no + * owners on dos filesystems. of course there is some empty space + * in the directory entry where we could put uid's and gid's. + */ +#endif + devvp->v_specflags |= SI_MOUNTEDON; + + return 0; + +error_exit:; + if (bp0) + brelse(bp0); + if (needclose) + (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD | FWRITE, + NOCRED, p); + if (pmp) { + if (pmp->pm_inusemap) + free((caddr_t) pmp->pm_inusemap, M_MSDOSFSFAT); + free((caddr_t) pmp, M_MSDOSFSMNT); + mp->mnt_data = (qaddr_t) 0; + } + return error; +} + +int +msdosfs_start(mp, flags, p) + struct mount *mp; + int flags; + struct proc *p; +{ + return 0; +} + +/* + * Unmount the filesystem described by mp. + */ +int +msdosfs_unmount(mp, mntflags, p) + struct mount *mp; + int mntflags; + struct proc *p; +{ + int flags = 0; + int error; + struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; + struct vnode *vp = pmp->pm_devvp; + + /* only the mounter, or superuser can unmount */ + if ((p->p_cred->p_ruid != pmp->pm_mounter) && + (error = suser(p->p_ucred, &p->p_acflag))) + return error; + + if (mntflags & MNT_FORCE) { + if (!msdosfsdoforce) + return EINVAL; + flags |= FORCECLOSE; + } +#ifdef QUOTA +#endif + if (error = vflush(mp, NULLVP, flags)) + return error; + pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON; +#ifdef MSDOSFS_DEBUG + printf("msdosfs_umount(): just before calling VOP_CLOSE()\n"); + printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n", + vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt); + printf("lastr %d, id %d, mount %08x, op %08x\n", + vp->v_lastr, vp->v_id, vp->v_mount, vp->v_op); + printf("freef %08x, freeb %08x, mountf %08x, mountb %08x\n", + vp->v_freef, vp->v_freeb, vp->v_mountf, vp->v_mountb); + printf("cleanblkhd %08x, dirtyblkhd %08x, numoutput %d, type %d\n", + vp->v_cleanblkhd, vp->v_dirtyblkhd, vp->v_numoutput, vp->v_type); + printf("union %08x, tag %d, data[0] %08x, data[1] %08x\n", + vp->v_socket, vp->v_tag, vp->v_data[0], vp->v_data[1]); +#endif + error = VOP_CLOSE(pmp->pm_devvp, pmp->pm_ronly ? FREAD : FREAD | FWRITE, + NOCRED, p); + vrele(pmp->pm_devvp); + free((caddr_t) pmp->pm_inusemap, M_MSDOSFSFAT); + free((caddr_t) pmp, M_MSDOSFSMNT); + mp->mnt_data = (qaddr_t) 0; + mp->mnt_flag &= ~MNT_LOCAL; + return error; +} + +int +msdosfs_root(mp, vpp) + struct mount *mp; + struct vnode **vpp; +{ + struct denode *ndep; + struct msdosfsmount *pmp = (struct msdosfsmount *) (mp->mnt_data); + int error; + + error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, NULL, &ndep); +#ifdef MSDOSFS_DEBUG + printf("msdosfs_root(); mp %08x, pmp %08x, ndep %08x, vp %08x\n", + mp, pmp, ndep, DETOV(ndep)); +#endif + if (error == 0) + *vpp = DETOV(ndep); + return error; +} + +int +msdosfs_quotactl(mp, cmds, uid, arg, p) + struct mount *mp; + int cmds; + uid_t uid; + caddr_t arg; + struct proc *p; +{ +#ifdef QUOTA +#else + return EOPNOTSUPP; +#endif +} + +int +msdosfs_statfs(mp, sbp, p) + struct mount *mp; + struct statfs *sbp; + struct proc *p; +{ + struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; + + /* + * Fill in the stat block. + */ +#ifdef COMPAT_09 + sbp->f_type = 4; +#else + sbp->f_type = 0; +#endif + sbp->f_bsize = pmp->pm_bpcluster; + sbp->f_iosize = pmp->pm_bpcluster; + sbp->f_blocks = pmp->pm_nmbrofclusters; + sbp->f_bfree = pmp->pm_freeclustercount; + sbp->f_bavail = pmp->pm_freeclustercount; + sbp->f_files = pmp->pm_RootDirEnts; /* XXX */ + sbp->f_ffree = 0; /* what to put in here? */ + + /* + * Copy the mounted on and mounted from names into the passed in + * stat block, if it is not the one in the mount structure. + */ + if (sbp != &mp->mnt_stat) { + bcopy((caddr_t) mp->mnt_stat.f_mntonname, + (caddr_t) & sbp->f_mntonname[0], MNAMELEN); + bcopy((caddr_t) mp->mnt_stat.f_mntfromname, + (caddr_t) & sbp->f_mntfromname[0], MNAMELEN); + } +#if 0 + strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN); + sbp->f_fstypename[MFSNAMELEN] = '\0'; +#endif + return 0; +} + +int +msdosfs_sync(mp, waitfor, cred, p) + struct mount *mp; + int waitfor; + struct ucred *cred; + struct proc *p; +{ + struct vnode *vp; + struct denode *dep; + struct msdosfsmount *pmp; + int error; + int allerror = 0; + + pmp = (struct msdosfsmount *) mp->mnt_data; + + /* + * If we ever switch to not updating all of the fats all the time, + * this would be the place to update them from the first one. + */ + if (pmp->pm_fmod) + if (pmp->pm_ronly) + panic("msdosfs_sync: rofs mod"); + else { + /* update fats here */ + } + + /* + * Go thru in memory denodes and write them out along with + * unwritten file blocks. + */ +loop: + for (vp = mp->mnt_vnodelist.lh_first; vp; + vp = vp->v_mntvnodes.le_next) { + if (vp->v_mount != mp) /* not ours anymore */ + goto loop; + if (VOP_ISLOCKED(vp)) /* file is busy */ + continue; + dep = VTODE(vp); + if ((dep->de_flag & DE_UPDATE) == 0 && + vp->v_dirtyblkhd.lh_first == NULL) + continue; + if (vget(vp, 1)) /* not there anymore? */ + goto loop; + if (error = VOP_FSYNC(vp, cred, waitfor, p)) + allerror = error; + vput(vp); /* done with this one */ + } + + /* + * Flush filesystem control info. + */ + if (error = VOP_FSYNC(pmp->pm_devvp, cred, waitfor, p)) + allerror = error; + return allerror; +} + +int +msdosfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) + struct mount *mp; + struct fid *fhp; + struct mbuf *nam; + struct vnode **vpp; + int *exflagsp; + struct ucred **credanonp; +{ + struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; + struct defid *defhp = (struct defid *) fhp; + struct denode *dep; + struct netcred *np; + int error; + + np = vfs_export_lookup(mp, &pmp->pm_export, nam); + if (np == NULL) + return EACCES; + error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, + NULL, &dep); + if (error) { + *vpp = NULLVP; + return error; + } + *vpp = DETOV(dep); + *exflagsp = np->netc_exflags; + *credanonp = &np->netc_anon; + return 0; +} + + +int +msdosfs_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; +{ + struct denode *dep = VTODE(vp); + struct defid *defhp = (struct defid *) fhp; + + defhp->defid_len = sizeof(struct defid); + defhp->defid_dirclust = dep->de_dirclust; + defhp->defid_dirofs = dep->de_diroffset; + /* defhp->defid_gen = ip->i_gen; */ + return 0; +} + +int +msdosfs_vget(mp, ino, vpp) + struct mount *mp; + ino_t ino; + struct vnode **vpp; +{ + return EOPNOTSUPP; +} + +struct vfsops msdosfs_vfsops = { + msdosfs_mount, + msdosfs_start, + msdosfs_unmount, + msdosfs_root, + msdosfs_quotactl, + msdosfs_statfs, + msdosfs_sync, + msdosfs_vget, + msdosfs_fhtovp, + msdosfs_vptofh, + msdosfs_init +}; |