2002-07-30 11:40:07 +04:00
|
|
|
/* $NetBSD: msdosfs_vfsops.c,v 1.82 2002/07/30 07:40:11 soren Exp $ */
|
1994-07-19 01:38:08 +04:00
|
|
|
|
|
|
|
/*-
|
1997-10-17 15:23:29 +04:00
|
|
|
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
|
|
|
|
* Copyright (C) 1994, 1995, 1997 TooLs GmbH.
|
1994-07-19 01:38:08 +04:00
|
|
|
* All rights reserved.
|
1994-08-21 22:43:49 +04:00
|
|
|
* Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
|
1994-07-19 01:38:08 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
|
|
|
* Written by Paul Popelka (paulp@uts.amdahl.com)
|
1997-11-17 18:36:17 +03:00
|
|
|
*
|
1993-08-13 15:35:13 +04:00
|
|
|
* You can do anything you want with this software, just don't say you wrote
|
|
|
|
* it, and don't remove this notice.
|
1997-11-17 18:36:17 +03:00
|
|
|
*
|
1993-08-13 15:35:13 +04:00
|
|
|
* This software is provided "as is".
|
1997-11-17 18:36:17 +03:00
|
|
|
*
|
1993-08-13 15:35:13 +04:00
|
|
|
* 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.
|
1997-11-17 18:36:17 +03:00
|
|
|
*
|
1993-08-13 15:35:13 +04:00
|
|
|
* October 1992
|
|
|
|
*/
|
|
|
|
|
2001-11-10 16:22:20 +03:00
|
|
|
#include <sys/cdefs.h>
|
2002-07-30 11:40:07 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.82 2002/07/30 07:40:11 soren Exp $");
|
2001-11-10 16:22:20 +03:00
|
|
|
|
2001-05-30 15:40:35 +04:00
|
|
|
#if defined(_KERNEL_OPT)
|
1998-06-08 08:27:50 +04:00
|
|
|
#include "opt_quota.h"
|
1998-07-05 12:49:30 +04:00
|
|
|
#include "opt_compat_netbsd.h"
|
1998-06-09 11:46:31 +04:00
|
|
|
#endif
|
1998-06-08 08:27:50 +04:00
|
|
|
|
1993-12-18 03:50:51 +03:00
|
|
|
#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>
|
1997-07-29 03:41:04 +04:00
|
|
|
#include <sys/device.h>
|
1994-09-28 14:31:23 +03:00
|
|
|
#include <sys/disklabel.h>
|
|
|
|
#include <sys/ioctl.h>
|
1993-12-18 03:50:51 +03:00
|
|
|
#include <sys/malloc.h>
|
1995-10-15 18:34:19 +03:00
|
|
|
#include <sys/dirent.h>
|
1997-05-08 20:53:06 +04:00
|
|
|
#include <sys/stat.h>
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1993-12-18 03:50:51 +03:00
|
|
|
#include <msdosfs/bpb.h>
|
|
|
|
#include <msdosfs/bootsect.h>
|
|
|
|
#include <msdosfs/direntry.h>
|
|
|
|
#include <msdosfs/denode.h>
|
|
|
|
#include <msdosfs/msdosfsmount.h>
|
|
|
|
#include <msdosfs/fat.h>
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1997-07-29 03:41:04 +04:00
|
|
|
int msdosfs_mountroot __P((void));
|
1996-12-22 13:10:12 +03:00
|
|
|
int msdosfs_mount __P((struct mount *, const char *, void *,
|
1997-07-29 03:41:04 +04:00
|
|
|
struct nameidata *, struct proc *));
|
1996-02-09 22:13:39 +03:00
|
|
|
int msdosfs_start __P((struct mount *, int, struct proc *));
|
|
|
|
int msdosfs_unmount __P((struct mount *, int, struct proc *));
|
|
|
|
int msdosfs_root __P((struct mount *, struct vnode **));
|
|
|
|
int msdosfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
|
|
|
|
int msdosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
|
|
|
|
int msdosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
|
|
|
|
int msdosfs_vget __P((struct mount *, ino_t, struct vnode **));
|
1999-02-27 02:44:43 +03:00
|
|
|
int msdosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
|
|
|
|
int msdosfs_checkexp __P((struct mount *, struct mbuf *, int *,
|
|
|
|
struct ucred **));
|
1996-02-09 22:13:39 +03:00
|
|
|
int msdosfs_vptofh __P((struct vnode *, struct fid *));
|
1998-03-01 05:20:01 +03:00
|
|
|
int msdosfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
|
|
|
|
struct proc *));
|
1996-02-09 22:13:39 +03:00
|
|
|
|
|
|
|
int msdosfs_mountfs __P((struct vnode *, struct mount *, struct proc *,
|
1997-07-29 03:41:04 +04:00
|
|
|
struct msdosfs_args *));
|
|
|
|
|
|
|
|
static int update_mp __P((struct mount *, struct msdosfs_args *));
|
|
|
|
|
|
|
|
#define ROOTNAME "root_device"
|
|
|
|
|
2001-01-22 15:17:35 +03:00
|
|
|
extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc;
|
1998-02-18 10:05:47 +03:00
|
|
|
|
2001-01-22 15:17:35 +03:00
|
|
|
const struct vnodeopv_desc * const msdosfs_vnodeopv_descs[] = {
|
1998-02-18 10:05:47 +03:00
|
|
|
&msdosfs_vnodeop_opv_desc,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
1997-07-29 03:41:04 +04:00
|
|
|
struct vfsops msdosfs_vfsops = {
|
|
|
|
MOUNT_MSDOS,
|
|
|
|
msdosfs_mount,
|
|
|
|
msdosfs_start,
|
|
|
|
msdosfs_unmount,
|
|
|
|
msdosfs_root,
|
|
|
|
msdosfs_quotactl,
|
|
|
|
msdosfs_statfs,
|
|
|
|
msdosfs_sync,
|
|
|
|
msdosfs_vget,
|
|
|
|
msdosfs_fhtovp,
|
|
|
|
msdosfs_vptofh,
|
|
|
|
msdosfs_init,
|
2001-09-15 20:12:54 +04:00
|
|
|
msdosfs_reinit,
|
2000-03-16 21:08:17 +03:00
|
|
|
msdosfs_done,
|
1998-03-01 05:20:01 +03:00
|
|
|
msdosfs_sysctl,
|
1998-02-18 10:05:47 +03:00
|
|
|
msdosfs_mountroot,
|
1999-02-27 02:44:43 +03:00
|
|
|
msdosfs_checkexp,
|
1998-02-18 10:05:47 +03:00
|
|
|
msdosfs_vnodeopv_descs,
|
1997-07-29 03:41:04 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
update_mp(mp, argp)
|
|
|
|
struct mount *mp;
|
|
|
|
struct msdosfs_args *argp;
|
|
|
|
{
|
|
|
|
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
|
|
|
|
int error;
|
|
|
|
|
|
|
|
pmp->pm_gid = argp->gid;
|
|
|
|
pmp->pm_uid = argp->uid;
|
|
|
|
pmp->pm_mask = argp->mask & ALLPERMS;
|
|
|
|
pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GEMDOS knows nothing (yet) about win95
|
|
|
|
*/
|
|
|
|
if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS)
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_NOWIN95;
|
1997-11-17 18:36:17 +03:00
|
|
|
|
1997-07-29 03:41:04 +04:00
|
|
|
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
|
|
|
|
else if (!(pmp->pm_flags &
|
|
|
|
(MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
|
|
|
|
struct vnode *rootvp;
|
1997-11-17 18:36:17 +03:00
|
|
|
|
1997-07-29 03:41:04 +04:00
|
|
|
/*
|
|
|
|
* Try to divine whether to support Win'95 long filenames
|
|
|
|
*/
|
1997-10-17 15:23:29 +04:00
|
|
|
if (FAT32(pmp))
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
|
|
|
|
else {
|
|
|
|
if ((error = msdosfs_root(mp, &rootvp)) != 0)
|
|
|
|
return error;
|
|
|
|
pmp->pm_flags |= findwin95(VTODE(rootvp))
|
|
|
|
? MSDOSFSMNT_LONGNAME
|
|
|
|
: MSDOSFSMNT_SHORTNAME;
|
|
|
|
vput(rootvp);
|
|
|
|
}
|
1997-07-29 03:41:04 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_mountroot()
|
|
|
|
{
|
1998-03-01 05:20:01 +03:00
|
|
|
struct mount *mp;
|
1997-07-29 03:41:04 +04:00
|
|
|
struct proc *p = curproc; /* XXX */
|
|
|
|
int error;
|
|
|
|
struct msdosfs_args args;
|
|
|
|
|
|
|
|
if (root_device->dv_class != DV_DISK)
|
|
|
|
return (ENODEV);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get vnodes for swapdev and rootdev.
|
|
|
|
*/
|
|
|
|
if (bdevvp(rootdev, &rootvp))
|
|
|
|
panic("msdosfs_mountroot: can't setup rootvp");
|
|
|
|
|
1999-07-17 05:08:28 +04:00
|
|
|
if ((error = vfs_rootmountalloc(MOUNT_MSDOS, "root_device", &mp))) {
|
|
|
|
vrele(rootvp);
|
1998-03-01 05:20:01 +03:00
|
|
|
return (error);
|
1999-07-17 05:08:28 +04:00
|
|
|
}
|
1997-07-29 03:41:04 +04:00
|
|
|
|
|
|
|
args.flags = 0;
|
|
|
|
args.uid = 0;
|
|
|
|
args.gid = 0;
|
|
|
|
args.mask = 0777;
|
|
|
|
|
|
|
|
if ((error = msdosfs_mountfs(rootvp, mp, p, &args)) != 0) {
|
1998-03-01 05:20:01 +03:00
|
|
|
mp->mnt_op->vfs_refcount--;
|
|
|
|
vfs_unbusy(mp);
|
1997-07-29 03:41:04 +04:00
|
|
|
free(mp, M_MOUNT);
|
1999-07-17 05:08:28 +04:00
|
|
|
vrele(rootvp);
|
1997-07-29 03:41:04 +04:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((error = update_mp(mp, &args)) != 0) {
|
|
|
|
(void)msdosfs_unmount(mp, 0, p);
|
1998-03-01 05:20:01 +03:00
|
|
|
vfs_unbusy(mp);
|
1997-07-29 03:41:04 +04:00
|
|
|
free(mp, M_MOUNT);
|
1999-07-17 05:08:28 +04:00
|
|
|
vrele(rootvp);
|
1997-07-29 03:41:04 +04:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_lock(&mountlist_slock);
|
1997-07-29 03:41:04 +04:00
|
|
|
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_unlock(&mountlist_slock);
|
1997-07-29 03:41:04 +04:00
|
|
|
(void)msdosfs_statfs(mp, &mp->mnt_stat, p);
|
1998-03-01 05:20:01 +03:00
|
|
|
vfs_unbusy(mp);
|
1997-07-29 03:41:04 +04:00
|
|
|
return (0);
|
|
|
|
}
|
1996-02-09 22:13:39 +03:00
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
1997-11-17 18:36:17 +03:00
|
|
|
* mp - path - addr in user space of mount point (ie /usr or whatever)
|
1993-08-13 15:35:13 +04:00
|
|
|
* data - addr in user space of mount params including the name of the block
|
1997-11-17 18:36:17 +03:00
|
|
|
* special file to treat as a filesystem.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
msdosfs_mount(mp, path, data, ndp, p)
|
|
|
|
struct mount *mp;
|
1996-12-22 13:10:12 +03:00
|
|
|
const char *path;
|
|
|
|
void *data;
|
1993-08-13 15:35:13 +04:00
|
|
|
struct nameidata *ndp;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1994-04-07 11:30:23 +04:00
|
|
|
struct vnode *devvp; /* vnode for blk device to mount */
|
|
|
|
struct msdosfs_args args; /* will hold data from mount request */
|
1996-02-09 22:13:39 +03:00
|
|
|
/* msdosfs specific mount control block */
|
|
|
|
struct msdosfsmount *pmp = NULL;
|
1995-03-09 15:05:21 +03:00
|
|
|
size_t size;
|
1994-09-28 14:31:23 +03:00
|
|
|
int error, flags;
|
1994-12-14 19:33:18 +03:00
|
|
|
mode_t accessmode;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1996-02-09 22:13:39 +03:00
|
|
|
error = copyin(data, (caddr_t)&args, sizeof(struct msdosfs_args));
|
|
|
|
if (error)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
1994-12-14 19:33:18 +03:00
|
|
|
* If updating, check whether changing from read-only to
|
|
|
|
* read/write; if there is no device name, that's all we do.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
|
|
|
if (mp->mnt_flag & MNT_UPDATE) {
|
1994-09-22 06:34:49 +04:00
|
|
|
pmp = VFSTOMSDOSFS(mp);
|
1994-07-17 01:32:06 +04:00
|
|
|
error = 0;
|
1995-10-15 18:34:19 +03:00
|
|
|
if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) {
|
1994-07-17 01:32:06 +04:00
|
|
|
flags = WRITECLOSE;
|
|
|
|
if (mp->mnt_flag & MNT_FORCE)
|
|
|
|
flags |= FORCECLOSE;
|
|
|
|
error = vflush(mp, NULLVP, flags);
|
|
|
|
}
|
|
|
|
if (!error && (mp->mnt_flag & MNT_RELOAD))
|
|
|
|
/* not yet implemented */
|
1994-09-28 14:31:23 +03:00
|
|
|
error = EOPNOTSUPP;
|
1994-07-17 01:32:06 +04:00
|
|
|
if (error)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1995-10-15 18:34:19 +03:00
|
|
|
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_WANTRDWR)) {
|
1994-12-14 19:33:18 +03:00
|
|
|
/*
|
|
|
|
* If upgrade to read-write by non-root, then verify
|
|
|
|
* that user has necessary permissions on the device.
|
|
|
|
*/
|
|
|
|
if (p->p_ucred->cr_uid != 0) {
|
|
|
|
devvp = pmp->pm_devvp;
|
1998-03-01 05:20:01 +03:00
|
|
|
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
1996-02-09 22:13:39 +03:00
|
|
|
error = VOP_ACCESS(devvp, VREAD | VWRITE,
|
|
|
|
p->p_ucred, p);
|
1998-03-01 05:20:01 +03:00
|
|
|
VOP_UNLOCK(devvp, 0);
|
|
|
|
if (error)
|
1994-12-14 19:33:18 +03:00
|
|
|
return (error);
|
|
|
|
}
|
1995-10-15 18:34:19 +03:00
|
|
|
pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
|
1994-12-14 19:33:18 +03:00
|
|
|
}
|
1994-07-17 01:32:06 +04:00
|
|
|
if (args.fspec == 0) {
|
1995-10-15 18:34:19 +03:00
|
|
|
#ifdef __notyet__ /* doesn't work correctly with current mountd XXX */
|
|
|
|
if (args.flags & MSDOSFSMNT_MNTOPT) {
|
|
|
|
pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT;
|
|
|
|
pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
|
|
|
|
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
|
|
|
|
}
|
|
|
|
#endif
|
1994-07-17 01:32:06 +04:00
|
|
|
/*
|
|
|
|
* Process export requests.
|
|
|
|
*/
|
1994-09-28 14:31:23 +03:00
|
|
|
return (vfs_export(mp, &pmp->pm_export, &args.export));
|
1994-07-17 01:32:06 +04:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
/*
|
1994-09-28 14:31:23 +03:00
|
|
|
* Not an update, or updating the name: look up the name
|
1994-12-14 19:33:18 +03:00
|
|
|
* and verify that it refers to a sensible block device.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1994-07-17 01:32:06 +04:00
|
|
|
NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = namei(ndp)) != 0)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
devvp = ndp->ni_vp;
|
1994-12-14 19:33:18 +03:00
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
if (devvp->v_type != VBLK) {
|
1994-07-17 01:32:06 +04:00
|
|
|
vrele(devvp);
|
1994-09-28 14:31:23 +03:00
|
|
|
return (ENOTBLK);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
if (major(devvp->v_rdev) >= nblkdev) {
|
|
|
|
vrele(devvp);
|
1994-09-28 14:31:23 +03:00
|
|
|
return (ENXIO);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
/*
|
1994-12-14 19:33:18 +03:00
|
|
|
* If mount by non-root, then verify that user has necessary
|
|
|
|
* permissions on the device.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1994-12-14 19:33:18 +03:00
|
|
|
if (p->p_ucred->cr_uid != 0) {
|
|
|
|
accessmode = VREAD;
|
|
|
|
if ((mp->mnt_flag & MNT_RDONLY) == 0)
|
|
|
|
accessmode |= VWRITE;
|
1998-03-01 05:20:01 +03:00
|
|
|
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
1996-02-09 22:13:39 +03:00
|
|
|
error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
|
1998-03-01 05:20:01 +03:00
|
|
|
VOP_UNLOCK(devvp, 0);
|
1996-02-09 22:13:39 +03:00
|
|
|
if (error) {
|
1998-03-01 05:20:01 +03:00
|
|
|
vrele(devvp);
|
1994-12-14 19:33:18 +03:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
}
|
1997-11-17 18:36:17 +03:00
|
|
|
if ((mp->mnt_flag & MNT_UPDATE) == 0) {
|
1996-01-21 19:35:29 +03:00
|
|
|
error = msdosfs_mountfs(devvp, mp, p, &args);
|
1997-11-17 18:36:17 +03:00
|
|
|
#ifdef MSDOSFS_DEBUG /* only needed for the printf below */
|
|
|
|
pmp = VFSTOMSDOSFS(mp);
|
|
|
|
#endif
|
|
|
|
} else {
|
1993-08-13 15:35:13 +04:00
|
|
|
if (devvp != pmp->pm_devvp)
|
1994-12-14 19:33:18 +03:00
|
|
|
error = EINVAL; /* needs translation */
|
1993-08-13 15:35:13 +04:00
|
|
|
else
|
|
|
|
vrele(devvp);
|
1994-12-14 19:33:18 +03:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
if (error) {
|
|
|
|
vrele(devvp);
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1997-07-29 03:41:04 +04:00
|
|
|
if ((error = update_mp(mp, &args)) != 0) {
|
|
|
|
msdosfs_unmount(mp, MNT_FORCE, p);
|
|
|
|
return error;
|
1995-10-15 18:34:19 +03:00
|
|
|
}
|
1997-07-29 03:41:04 +04:00
|
|
|
|
1995-01-18 12:14:37 +03:00
|
|
|
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
|
1998-08-10 00:51:08 +04:00
|
|
|
memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
|
1994-09-28 14:31:23 +03:00
|
|
|
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
|
|
|
|
&size);
|
1998-08-10 00:51:08 +04:00
|
|
|
memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef MSDOSFS_DEBUG
|
1997-11-17 18:36:17 +03:00
|
|
|
printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap);
|
1994-07-19 01:38:08 +04:00
|
|
|
#endif
|
1994-09-28 14:31:23 +03:00
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-01-21 19:35:29 +03:00
|
|
|
msdosfs_mountfs(devvp, mp, p, argp)
|
1993-08-13 15:35:13 +04:00
|
|
|
struct vnode *devvp;
|
|
|
|
struct mount *mp;
|
|
|
|
struct proc *p;
|
1996-01-21 19:35:29 +03:00
|
|
|
struct msdosfs_args *argp;
|
1993-08-13 15:35:13 +04:00
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
struct msdosfsmount *pmp;
|
|
|
|
struct buf *bp;
|
1993-08-13 15:35:13 +04:00
|
|
|
dev_t dev = devvp->v_rdev;
|
1994-09-28 14:31:23 +03:00
|
|
|
struct partinfo dpart;
|
1993-08-13 15:35:13 +04:00
|
|
|
union bootsector *bsp;
|
|
|
|
struct byte_bpb33 *b33;
|
|
|
|
struct byte_bpb50 *b50;
|
1997-10-17 15:23:29 +04:00
|
|
|
struct byte_bpb710 *b710;
|
1995-10-15 18:34:19 +03:00
|
|
|
u_int8_t SecPerClust;
|
1995-07-24 10:36:23 +04:00
|
|
|
int ronly, error;
|
1996-02-09 22:13:39 +03:00
|
|
|
int bsize = 0, dtype = 0, tmp;
|
1999-03-07 16:57:20 +03:00
|
|
|
u_long dirsperblk;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
/*
|
1994-09-28 14:31:23 +03:00
|
|
|
* Disallow multiple mounts of the same device.
|
|
|
|
* Disallow mounting of a device that is currently in use
|
|
|
|
* (except for root, which might share swap device for miniroot).
|
|
|
|
* Flush out any old buffers remaining from a previous use.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = vfs_mountedon(devvp)) != 0)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
|
|
|
if (vcount(devvp) > 1 && devvp != rootvp)
|
|
|
|
return (EBUSY);
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1994-09-28 14:31:23 +03:00
|
|
|
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
|
1996-02-09 22:13:39 +03:00
|
|
|
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
|
|
|
|
if (error)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1995-07-24 10:36:23 +04:00
|
|
|
bp = NULL; /* both used in error_exit */
|
|
|
|
pmp = NULL;
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1996-01-21 19:35:29 +03:00
|
|
|
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
|
1996-01-19 17:28:05 +03:00
|
|
|
/*
|
|
|
|
* We need the disklabel to calculate the size of a FAT entry
|
|
|
|
* later on. Also make sure the partition contains a filesystem
|
|
|
|
* of type FS_MSDOS. This doesn't work for floppies, so we have
|
|
|
|
* to check for them too.
|
|
|
|
*
|
|
|
|
* At least some parts of the msdos fs driver seem to assume
|
|
|
|
* that the size of a disk block will always be 512 bytes.
|
|
|
|
* Let's check it...
|
|
|
|
*/
|
1996-02-09 22:13:39 +03:00
|
|
|
error = VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart,
|
|
|
|
FREAD, NOCRED, p);
|
|
|
|
if (error)
|
1996-01-19 17:28:05 +03:00
|
|
|
goto error_exit;
|
|
|
|
tmp = dpart.part->p_fstype;
|
|
|
|
dtype = dpart.disklab->d_type;
|
|
|
|
bsize = dpart.disklab->d_secsize;
|
|
|
|
if (bsize != 512 || (dtype!=DTYPE_FLOPPY && tmp!=FS_MSDOS)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
1995-07-24 10:36:23 +04:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
/*
|
1996-01-19 17:28:05 +03:00
|
|
|
* Read the boot sector of the filesystem, and then check the
|
|
|
|
* boot signature. If not a dos boot sector then error out.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = bread(devvp, 0, 512, NOCRED, &bp)) != 0)
|
1993-08-13 15:35:13 +04:00
|
|
|
goto error_exit;
|
1994-09-28 14:31:23 +03:00
|
|
|
bp->b_flags |= B_AGE;
|
|
|
|
bsp = (union bootsector *)bp->b_data;
|
|
|
|
b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
|
|
|
|
b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
|
1997-10-17 15:23:29 +04:00
|
|
|
b710 = (struct byte_bpb710 *)bsp->bs710.bsPBP;
|
|
|
|
|
|
|
|
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
|
|
|
|
if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
|
|
|
|
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
|
1998-08-10 00:51:08 +04:00
|
|
|
memset((caddr_t)pmp, 0, sizeof *pmp);
|
1993-08-13 15:35:13 +04:00
|
|
|
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.
|
|
|
|
*/
|
1995-10-15 18:34:19 +03:00
|
|
|
SecPerClust = b50->bpbSecPerClust;
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
|
|
|
|
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_FATsecs = getushort(b50->bpbFATsecs);
|
|
|
|
pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
|
|
|
|
pmp->pm_Heads = getushort(b50->bpbHeads);
|
1995-07-24 10:36:23 +04:00
|
|
|
pmp->pm_Media = b50->bpbMedia;
|
1993-12-01 13:35:21 +03:00
|
|
|
|
1996-01-21 19:35:29 +03:00
|
|
|
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
|
1996-01-19 17:28:05 +03:00
|
|
|
/* XXX - We should probably check more values here */
|
|
|
|
if (!pmp->pm_BytesPerSec || !SecPerClust
|
|
|
|
|| pmp->pm_Heads > 255 || pmp->pm_SecPerTrack > 63) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
1993-12-01 13:35:21 +03:00
|
|
|
}
|
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
if (pmp->pm_Sectors == 0) {
|
|
|
|
pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
|
|
|
|
pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
|
1994-07-17 01:32:06 +04:00
|
|
|
} else {
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
|
|
|
|
pmp->pm_HugeSectors = pmp->pm_Sectors;
|
|
|
|
}
|
1999-03-07 16:57:20 +03:00
|
|
|
dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);
|
|
|
|
if (pmp->pm_HugeSectors > 0xffffffff / dirsperblk + 1) {
|
1997-10-17 15:23:29 +04:00
|
|
|
/*
|
|
|
|
* We cannot deal currently with this size of disk
|
|
|
|
* due to fileid limitations (see msdosfs_getattr and
|
|
|
|
* msdosfs_readdir)
|
|
|
|
*/
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pmp->pm_RootDirEnts == 0) {
|
|
|
|
if (bsp->bs710.bsBootSectSig2 != BOOTSIG2
|
|
|
|
|| bsp->bs710.bsBootSectSig3 != BOOTSIG3
|
|
|
|
|| pmp->pm_Sectors
|
|
|
|
|| pmp->pm_FATsecs
|
|
|
|
|| getushort(b710->bpbFSVers)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
pmp->pm_fatmask = FAT32_MASK;
|
|
|
|
pmp->pm_fatmult = 4;
|
|
|
|
pmp->pm_fatdiv = 1;
|
|
|
|
pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
|
2000-04-03 22:12:12 +04:00
|
|
|
|
|
|
|
/* mirrorring is enabled if the FATMIRROR bit is not set */
|
|
|
|
if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
|
1997-10-17 15:23:29 +04:00
|
|
|
pmp->pm_flags |= MSDOSFS_FATMIRROR;
|
2000-04-03 22:12:12 +04:00
|
|
|
else
|
|
|
|
pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
|
1997-10-17 15:23:29 +04:00
|
|
|
} else
|
|
|
|
pmp->pm_flags |= MSDOSFS_FATMIRROR;
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1996-01-21 19:35:29 +03:00
|
|
|
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
|
1997-10-17 15:23:29 +04:00
|
|
|
if (FAT32(pmp)) {
|
|
|
|
/*
|
|
|
|
* GEMDOS doesn't know fat32.
|
|
|
|
*/
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
1996-01-19 17:28:05 +03:00
|
|
|
/*
|
|
|
|
* Check a few values (could do some more):
|
|
|
|
* - logical sector size: power of 2, >= block size
|
|
|
|
* - sectors per cluster: power of 2, >= 1
|
|
|
|
* - number of sectors: >= 1, <= size of partition
|
|
|
|
*/
|
|
|
|
if ( (SecPerClust == 0)
|
|
|
|
|| (SecPerClust & (SecPerClust - 1))
|
|
|
|
|| (pmp->pm_BytesPerSec < bsize)
|
|
|
|
|| (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
|
|
|
|
|| (pmp->pm_HugeSectors == 0)
|
|
|
|
|| (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
|
|
|
|
> dpart.part->p_size)
|
|
|
|
) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* XXX - Many parts of the msdos fs driver seem to assume that
|
|
|
|
* the number of bytes per logical sector (BytesPerSec) will
|
|
|
|
* always be the same as the number of bytes per disk block
|
|
|
|
* Let's pretend it is.
|
|
|
|
*/
|
|
|
|
tmp = pmp->pm_BytesPerSec / bsize;
|
|
|
|
pmp->pm_BytesPerSec = bsize;
|
|
|
|
pmp->pm_HugeSectors *= tmp;
|
|
|
|
pmp->pm_HiddenSects *= tmp;
|
|
|
|
pmp->pm_ResSectors *= tmp;
|
|
|
|
pmp->pm_Sectors *= tmp;
|
|
|
|
pmp->pm_FATsecs *= tmp;
|
|
|
|
SecPerClust *= tmp;
|
1995-07-24 10:36:23 +04:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_fatblk = pmp->pm_ResSectors;
|
1997-10-17 15:23:29 +04:00
|
|
|
if (FAT32(pmp)) {
|
|
|
|
pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
|
|
|
|
pmp->pm_firstcluster = pmp->pm_fatblk
|
|
|
|
+ (pmp->pm_FATs * pmp->pm_FATsecs);
|
|
|
|
pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
|
|
|
|
} else {
|
|
|
|
pmp->pm_rootdirblk = pmp->pm_fatblk +
|
|
|
|
(pmp->pm_FATs * pmp->pm_FATsecs);
|
|
|
|
pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
|
|
|
|
+ pmp->pm_BytesPerSec - 1)
|
|
|
|
/ pmp->pm_BytesPerSec;/* in sectors */
|
|
|
|
pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
|
|
|
|
}
|
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
|
1995-10-15 18:34:19 +03:00
|
|
|
SecPerClust;
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
|
|
|
|
pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1996-01-21 19:35:29 +03:00
|
|
|
if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
|
2002-03-24 19:30:11 +03:00
|
|
|
if (pmp->pm_nmbrofclusters <= (0xff0 - 2)
|
2002-03-25 23:42:40 +03:00
|
|
|
&& (dtype == DTYPE_FLOPPY
|
|
|
|
|| (dtype == DTYPE_VND
|
|
|
|
&& (pmp->pm_Heads == 1 || pmp->pm_Heads == 2)))
|
1997-10-17 15:23:29 +04:00
|
|
|
) {
|
|
|
|
pmp->pm_fatmask = FAT12_MASK;
|
|
|
|
pmp->pm_fatmult = 3;
|
|
|
|
pmp->pm_fatdiv = 2;
|
|
|
|
} else {
|
|
|
|
pmp->pm_fatmask = FAT16_MASK;
|
|
|
|
pmp->pm_fatmult = 2;
|
|
|
|
pmp->pm_fatdiv = 1;
|
|
|
|
}
|
|
|
|
} else if (pmp->pm_fatmask == 0) {
|
1996-02-12 01:48:14 +03:00
|
|
|
if (pmp->pm_maxcluster
|
1997-10-17 15:23:29 +04:00
|
|
|
<= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
|
1996-01-19 17:28:05 +03:00
|
|
|
/*
|
|
|
|
* This will usually be a floppy disk. This size makes
|
|
|
|
* sure that one fat entry will not be split across
|
|
|
|
* multiple blocks.
|
|
|
|
*/
|
1997-10-17 15:23:29 +04:00
|
|
|
pmp->pm_fatmask = FAT12_MASK;
|
|
|
|
pmp->pm_fatmult = 3;
|
|
|
|
pmp->pm_fatdiv = 2;
|
|
|
|
} else {
|
|
|
|
pmp->pm_fatmask = FAT16_MASK;
|
|
|
|
pmp->pm_fatmult = 2;
|
|
|
|
pmp->pm_fatdiv = 1;
|
|
|
|
}
|
1996-01-19 17:28:05 +03:00
|
|
|
}
|
1996-02-12 01:48:14 +03:00
|
|
|
if (FAT12(pmp))
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
|
1996-02-12 01:48:14 +03:00
|
|
|
else
|
|
|
|
pmp->pm_fatblocksize = MAXBSIZE;
|
1996-01-19 17:28:05 +03:00
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
|
1995-10-15 18:34:19 +03:00
|
|
|
pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1995-07-24 10:36:23 +04:00
|
|
|
/*
|
1995-10-15 18:34:19 +03:00
|
|
|
* Compute mask and shift value for isolating cluster relative byte
|
|
|
|
* offsets and cluster numbers from a file offset.
|
1995-07-24 10:36:23 +04:00
|
|
|
*/
|
1995-10-15 18:34:19 +03:00
|
|
|
pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
|
|
|
|
pmp->pm_crbomask = pmp->pm_bpcluster - 1;
|
|
|
|
pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;
|
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
1995-10-15 18:34:19 +03:00
|
|
|
* Check for valid cluster size
|
|
|
|
* must be a power of 2
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1995-10-15 18:34:19 +03:00
|
|
|
if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
|
1993-08-13 15:35:13 +04:00
|
|
|
error = EINVAL;
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Release the bootsector buffer.
|
|
|
|
*/
|
1994-09-28 14:31:23 +03:00
|
|
|
brelse(bp);
|
|
|
|
bp = NULL;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1997-10-17 15:23:29 +04:00
|
|
|
/*
|
|
|
|
* Check FSInfo.
|
|
|
|
*/
|
|
|
|
if (pmp->pm_fsinfo) {
|
|
|
|
struct fsinfo *fp;
|
|
|
|
|
|
|
|
if ((error = bread(devvp, pmp->pm_fsinfo, 1024, NOCRED, &bp)) != 0)
|
|
|
|
goto error_exit;
|
|
|
|
fp = (struct fsinfo *)bp->b_data;
|
1998-08-10 00:51:08 +04:00
|
|
|
if (!memcmp(fp->fsisig1, "RRaA", 4)
|
|
|
|
&& !memcmp(fp->fsisig2, "rrAa", 4)
|
|
|
|
&& !memcmp(fp->fsisig3, "\0\0\125\252", 4)
|
|
|
|
&& !memcmp(fp->fsisig4, "\0\0\125\252", 4))
|
1997-10-17 15:23:29 +04:00
|
|
|
pmp->pm_nxtfree = getulong(fp->fsinxtfree);
|
|
|
|
else
|
|
|
|
pmp->pm_fsinfo = 0;
|
|
|
|
brelse(bp);
|
|
|
|
bp = NULL;
|
|
|
|
}
|
1997-11-17 18:36:17 +03:00
|
|
|
|
1997-10-17 15:23:29 +04:00
|
|
|
/*
|
2001-12-22 22:45:54 +03:00
|
|
|
* Check and validate (or perhaps invalidate?) the fsinfo structure?
|
|
|
|
* XXX
|
1997-10-17 15:23:29 +04:00
|
|
|
*/
|
2001-12-22 22:45:54 +03:00
|
|
|
if (pmp->pm_fsinfo) {
|
|
|
|
if (pmp->pm_nxtfree == (u_long)-1)
|
|
|
|
pmp->pm_fsinfo = 0;
|
|
|
|
}
|
1997-10-17 15:23:29 +04:00
|
|
|
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
|
|
|
* Allocate memory for the bitmap of allocated clusters, and then
|
|
|
|
* fill it in.
|
|
|
|
*/
|
1994-07-19 01:38:08 +04:00
|
|
|
pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1)
|
|
|
|
/ N_INUSEBITS)
|
|
|
|
* sizeof(*pmp->pm_inusemap),
|
|
|
|
M_MSDOSFSFAT, M_WAITOK);
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* fillinusemap() needs pm_devvp.
|
|
|
|
*/
|
|
|
|
pmp->pm_dev = dev;
|
|
|
|
pmp->pm_devvp = devvp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Have the inuse map filled in.
|
|
|
|
*/
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = fillinusemap(pmp)) != 0)
|
1993-08-13 15:35:13 +04:00
|
|
|
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.
|
|
|
|
*/
|
1995-10-15 18:34:19 +03:00
|
|
|
if (mp->mnt_flag & MNT_SYNCHRONOUS)
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Finish up.
|
|
|
|
*/
|
1995-10-15 18:34:19 +03:00
|
|
|
if (ronly)
|
|
|
|
pmp->pm_flags |= MSDOSFSMNT_RONLY;
|
|
|
|
else
|
1993-08-13 15:35:13 +04:00
|
|
|
pmp->pm_fmod = 1;
|
2002-07-30 11:40:07 +04:00
|
|
|
mp->mnt_data = pmp;
|
1994-04-14 08:05:45 +04:00
|
|
|
mp->mnt_stat.f_fsid.val[0] = (long)dev;
|
1994-04-23 11:54:38 +04:00
|
|
|
mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_MSDOS);
|
1993-08-13 15:35:13 +04:00
|
|
|
mp->mnt_flag |= MNT_LOCAL;
|
2000-11-27 11:39:39 +03:00
|
|
|
mp->mnt_dev_bshift = pmp->pm_bnshift;
|
|
|
|
mp->mnt_fs_bshift = pmp->pm_cnshift;
|
|
|
|
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef QUOTA
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1994-07-19 01:38:08 +04:00
|
|
|
#endif
|
1999-11-15 21:49:07 +03:00
|
|
|
devvp->v_specmountpoint = mp;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1994-09-28 14:31:23 +03:00
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
error_exit:;
|
1994-09-28 14:31:23 +03:00
|
|
|
if (bp)
|
|
|
|
brelse(bp);
|
1999-10-17 03:53:26 +04:00
|
|
|
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
|
1994-09-28 14:31:23 +03:00
|
|
|
(void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
|
1999-10-17 03:53:26 +04:00
|
|
|
VOP_UNLOCK(devvp, 0);
|
1993-08-13 15:35:13 +04:00
|
|
|
if (pmp) {
|
|
|
|
if (pmp->pm_inusemap)
|
1994-09-28 14:31:23 +03:00
|
|
|
free(pmp->pm_inusemap, M_MSDOSFSFAT);
|
|
|
|
free(pmp, M_MSDOSFSMNT);
|
2002-07-30 11:40:07 +04:00
|
|
|
mp->mnt_data = NULL;
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_start(mp, flags, p)
|
|
|
|
struct mount *mp;
|
|
|
|
int flags;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
|
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unmount the filesystem described by mp.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
msdosfs_unmount(mp, mntflags, p)
|
|
|
|
struct mount *mp;
|
|
|
|
int mntflags;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1994-12-14 19:33:18 +03:00
|
|
|
struct msdosfsmount *pmp;
|
1994-09-28 14:31:23 +03:00
|
|
|
int error, flags;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1994-09-28 14:31:23 +03:00
|
|
|
flags = 0;
|
1995-01-18 12:14:37 +03:00
|
|
|
if (mntflags & MNT_FORCE)
|
1993-08-13 15:35:13 +04:00
|
|
|
flags |= FORCECLOSE;
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef QUOTA
|
|
|
|
#endif
|
1996-02-09 22:13:39 +03:00
|
|
|
if ((error = vflush(mp, NULLVP, flags)) != 0)
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1994-12-14 19:33:18 +03:00
|
|
|
pmp = VFSTOMSDOSFS(mp);
|
1999-10-20 18:32:09 +04:00
|
|
|
if (pmp->pm_devvp->v_type != VBAD)
|
1999-11-15 21:49:07 +03:00
|
|
|
pmp->pm_devvp->v_specmountpoint = NULL;
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef MSDOSFS_DEBUG
|
1997-11-17 18:36:17 +03:00
|
|
|
{
|
|
|
|
struct vnode *vp = pmp->pm_devvp;
|
|
|
|
|
|
|
|
printf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
|
2002-01-08 23:11:00 +03:00
|
|
|
printf("flag %08x, usecount %d, writecount %ld, holdcnt %ld\n",
|
1997-11-17 18:36:17 +03:00
|
|
|
vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
|
2002-01-08 23:11:00 +03:00
|
|
|
printf("id %lu, mount %p, op %p\n",
|
|
|
|
vp->v_id, vp->v_mount, vp->v_op);
|
1997-11-17 18:36:17 +03:00
|
|
|
printf("freef %p, freeb %p, mount %p\n",
|
|
|
|
vp->v_freelist.tqe_next, vp->v_freelist.tqe_prev,
|
|
|
|
vp->v_mount);
|
2002-01-08 23:11:00 +03:00
|
|
|
printf("cleanblkhd %p, dirtyblkhd %p, numoutput %d, type %d\n",
|
1997-11-17 18:36:17 +03:00
|
|
|
vp->v_cleanblkhd.lh_first,
|
|
|
|
vp->v_dirtyblkhd.lh_first,
|
|
|
|
vp->v_numoutput, vp->v_type);
|
|
|
|
printf("union %p, tag %d, data[0] %08x, data[1] %08x\n",
|
|
|
|
vp->v_socket, vp->v_tag,
|
|
|
|
((u_int *)vp->v_data)[0],
|
|
|
|
((u_int *)vp->v_data)[1]);
|
|
|
|
}
|
1994-07-19 01:38:08 +04:00
|
|
|
#endif
|
1999-10-17 03:53:26 +04:00
|
|
|
vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY);
|
1995-10-30 22:06:15 +03:00
|
|
|
error = VOP_CLOSE(pmp->pm_devvp,
|
|
|
|
pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED, p);
|
1999-10-17 03:53:26 +04:00
|
|
|
vput(pmp->pm_devvp);
|
1994-09-28 14:31:23 +03:00
|
|
|
free(pmp->pm_inusemap, M_MSDOSFSFAT);
|
|
|
|
free(pmp, M_MSDOSFSMNT);
|
2002-07-30 11:40:07 +04:00
|
|
|
mp->mnt_data = NULL;
|
1993-08-13 15:35:13 +04:00
|
|
|
mp->mnt_flag &= ~MNT_LOCAL;
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_root(mp, vpp)
|
|
|
|
struct mount *mp;
|
|
|
|
struct vnode **vpp;
|
|
|
|
{
|
1994-09-22 06:34:49 +04:00
|
|
|
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
|
1994-09-28 14:31:23 +03:00
|
|
|
struct denode *ndep;
|
1993-08-13 15:35:13 +04:00
|
|
|
int error;
|
|
|
|
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef MSDOSFS_DEBUG
|
1997-11-17 18:36:17 +03:00
|
|
|
printf("msdosfs_root(); mp %p, pmp %p\n", mp, pmp);
|
1994-07-19 01:38:08 +04:00
|
|
|
#endif
|
1997-11-17 18:36:17 +03:00
|
|
|
if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0)
|
|
|
|
return (error);
|
1994-09-28 14:31:23 +03:00
|
|
|
*vpp = DETOV(ndep);
|
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_quotactl(mp, cmds, uid, arg, p)
|
|
|
|
struct mount *mp;
|
|
|
|
int cmds;
|
|
|
|
uid_t uid;
|
|
|
|
caddr_t arg;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
|
1994-07-19 01:38:08 +04:00
|
|
|
#ifdef QUOTA
|
1994-09-28 14:31:23 +03:00
|
|
|
return (EOPNOTSUPP);
|
1993-08-13 15:35:13 +04:00
|
|
|
#else
|
1994-09-28 14:31:23 +03:00
|
|
|
return (EOPNOTSUPP);
|
1994-07-19 01:38:08 +04:00
|
|
|
#endif
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_statfs(mp, sbp, p)
|
|
|
|
struct mount *mp;
|
|
|
|
struct statfs *sbp;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
struct msdosfsmount *pmp;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1994-09-28 14:31:23 +03:00
|
|
|
pmp = VFSTOMSDOSFS(mp);
|
1994-04-14 08:05:45 +04:00
|
|
|
#ifdef COMPAT_09
|
|
|
|
sbp->f_type = 4;
|
|
|
|
#else
|
|
|
|
sbp->f_type = 0;
|
|
|
|
#endif
|
1993-08-13 15:35:13 +04:00
|
|
|
sbp->f_bsize = pmp->pm_bpcluster;
|
1994-04-21 11:47:31 +04:00
|
|
|
sbp->f_iosize = pmp->pm_bpcluster;
|
1993-08-13 15:35:13 +04:00
|
|
|
sbp->f_blocks = pmp->pm_nmbrofclusters;
|
|
|
|
sbp->f_bfree = pmp->pm_freeclustercount;
|
|
|
|
sbp->f_bavail = pmp->pm_freeclustercount;
|
1994-07-17 01:32:06 +04:00
|
|
|
sbp->f_files = pmp->pm_RootDirEnts; /* XXX */
|
1993-08-13 15:35:13 +04:00
|
|
|
sbp->f_ffree = 0; /* what to put in here? */
|
|
|
|
if (sbp != &mp->mnt_stat) {
|
1998-08-10 00:51:08 +04:00
|
|
|
memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
|
|
|
|
memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
1995-01-18 12:14:37 +03:00
|
|
|
strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
|
1994-09-28 14:31:23 +03:00
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1994-07-17 01:32:06 +04:00
|
|
|
msdosfs_sync(mp, waitfor, cred, p)
|
1993-08-13 15:35:13 +04:00
|
|
|
struct mount *mp;
|
|
|
|
int waitfor;
|
1994-07-17 01:32:06 +04:00
|
|
|
struct ucred *cred;
|
|
|
|
struct proc *p;
|
1993-08-13 15:35:13 +04:00
|
|
|
{
|
1998-03-01 05:20:01 +03:00
|
|
|
struct vnode *vp, *nvp;
|
1993-08-13 15:35:13 +04:00
|
|
|
struct denode *dep;
|
1994-09-19 23:28:07 +04:00
|
|
|
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
|
1994-09-28 14:31:23 +03:00
|
|
|
int error, allerror = 0;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1998-08-18 10:27:01 +04:00
|
|
|
if (pmp->pm_fmod != 0) {
|
1995-10-15 18:34:19 +03:00
|
|
|
if (pmp->pm_flags & MSDOSFSMNT_RONLY)
|
1994-02-08 02:14:16 +03:00
|
|
|
panic("msdosfs_sync: rofs mod");
|
1993-08-13 15:35:13 +04:00
|
|
|
else {
|
|
|
|
/* update fats here */
|
|
|
|
}
|
1998-08-18 10:27:01 +04:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
1994-09-19 23:28:07 +04:00
|
|
|
* Write back each (modified) denode.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_lock(&mntvnode_slock);
|
1993-08-13 15:35:13 +04:00
|
|
|
loop:
|
1998-03-01 05:20:01 +03:00
|
|
|
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
|
1994-09-19 23:28:07 +04:00
|
|
|
/*
|
|
|
|
* If the vnode that we are about to sync is no longer
|
|
|
|
* assoicated with this mount point, start over.
|
|
|
|
*/
|
|
|
|
if (vp->v_mount != mp)
|
1993-08-13 15:35:13 +04:00
|
|
|
goto loop;
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_lock(&vp->v_interlock);
|
|
|
|
nvp = vp->v_mntvnodes.le_next;
|
1993-08-13 15:35:13 +04:00
|
|
|
dep = VTODE(vp);
|
2000-12-10 22:36:31 +03:00
|
|
|
if (waitfor == MNT_LAZY || vp->v_type == VNON ||
|
|
|
|
(((dep->de_flag &
|
1999-11-15 21:49:07 +03:00
|
|
|
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) &&
|
2000-12-10 22:36:31 +03:00
|
|
|
(LIST_EMPTY(&vp->v_dirtyblkhd) &&
|
a whole bunch of changes to improve performance and robustness under load:
- remove special treatment of pager_map mappings in pmaps. this is
required now, since I've removed the globals that expose the address range.
pager_map now uses pmap_kenter_pa() instead of pmap_enter(), so there's
no longer any need to special-case it.
- eliminate struct uvm_vnode by moving its fields into struct vnode.
- rewrite the pageout path. the pager is now responsible for handling the
high-level requests instead of only getting control after a bunch of work
has already been done on its behalf. this will allow us to UBCify LFS,
which needs tighter control over its pages than other filesystems do.
writing a page to disk no longer requires making it read-only, which
allows us to write wired pages without causing all kinds of havoc.
- use a new PG_PAGEOUT flag to indicate that a page should be freed
on behalf of the pagedaemon when it's unlocked. this flag is very similar
to PG_RELEASED, but unlike PG_RELEASED, PG_PAGEOUT can be cleared if the
pageout fails due to eg. an indirect-block buffer being locked.
this allows us to remove the "version" field from struct vm_page,
and together with shrinking "loan_count" from 32 bits to 16,
struct vm_page is now 4 bytes smaller.
- no longer use PG_RELEASED for swap-backed pages. if the page is busy
because it's being paged out, we can't release the swap slot to be
reallocated until that write is complete, but unlike with vnodes we
don't keep a count of in-progress writes so there's no good way to
know when the write is done. instead, when we need to free a busy
swap-backed page, just sleep until we can get it busy ourselves.
- implement a fast-path for extending writes which allows us to avoid
zeroing new pages. this substantially reduces cpu usage.
- encapsulate the data used by the genfs code in a struct genfs_node,
which must be the first element of the filesystem-specific vnode data
for filesystems which use genfs_{get,put}pages().
- eliminate many of the UVM pagerops, since they aren't needed anymore
now that the pager "put" operation is a higher-level operation.
- enhance the genfs code to allow NFS to use the genfs_{get,put}pages
instead of a modified copy.
- clean up struct vnode by removing all the fields that used to be used by
the vfs_cluster.c code (which we don't use anymore with UBC).
- remove kmem_object and mb_object since they were useless.
instead of allocating pages to these objects, we now just allocate
pages with no object. such pages are mapped in the kernel until they
are freed, so we can use the mapping to find the page to free it.
this allows us to remove splvm() protection in several places.
The sum of all these changes improves write throughput on my
decstation 5000/200 to within 1% of the rate of NetBSD 1.5
and reduces the elapsed time for "make release" of a NetBSD 1.5
source tree on my 128MB pc to 10% less than a 1.5 kernel took.
2001-09-16 00:36:31 +04:00
|
|
|
vp->v_uobj.uo_npages == 0))) {
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_unlock(&vp->v_interlock);
|
1993-08-13 15:35:13 +04:00
|
|
|
continue;
|
1998-03-01 05:20:01 +03:00
|
|
|
}
|
|
|
|
simple_unlock(&mntvnode_slock);
|
|
|
|
error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
|
|
|
|
if (error) {
|
|
|
|
simple_lock(&mntvnode_slock);
|
|
|
|
if (error == ENOENT)
|
|
|
|
goto loop;
|
|
|
|
continue;
|
|
|
|
}
|
1998-06-05 23:53:00 +04:00
|
|
|
if ((error = VOP_FSYNC(vp, cred,
|
2000-09-20 02:01:59 +04:00
|
|
|
waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0)
|
1993-08-13 15:35:13 +04:00
|
|
|
allerror = error;
|
1994-09-19 23:28:07 +04:00
|
|
|
vput(vp);
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_lock(&mntvnode_slock);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
1998-03-01 05:20:01 +03:00
|
|
|
simple_unlock(&mntvnode_slock);
|
1993-08-13 15:35:13 +04:00
|
|
|
/*
|
1994-09-19 23:28:07 +04:00
|
|
|
* Force stale file system control information to be flushed.
|
1993-08-13 15:35:13 +04:00
|
|
|
*/
|
1998-06-05 23:53:00 +04:00
|
|
|
if ((error = VOP_FSYNC(pmp->pm_devvp, cred,
|
2000-09-20 02:01:59 +04:00
|
|
|
waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0)
|
1994-09-19 23:28:07 +04:00
|
|
|
allerror = error;
|
1994-09-28 14:31:23 +03:00
|
|
|
#ifdef QUOTA
|
1999-11-15 21:49:07 +03:00
|
|
|
/* qsync(mp); */
|
1994-09-28 14:31:23 +03:00
|
|
|
#endif
|
|
|
|
return (allerror);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1999-02-27 02:44:43 +03:00
|
|
|
msdosfs_fhtovp(mp, fhp, vpp)
|
1993-08-13 15:35:13 +04:00
|
|
|
struct mount *mp;
|
|
|
|
struct fid *fhp;
|
|
|
|
struct vnode **vpp;
|
|
|
|
{
|
1994-09-22 06:34:49 +04:00
|
|
|
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
|
1993-08-13 15:35:13 +04:00
|
|
|
struct defid *defhp = (struct defid *) fhp;
|
|
|
|
struct denode *dep;
|
|
|
|
int error;
|
|
|
|
|
1995-11-05 21:47:48 +03:00
|
|
|
error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, &dep);
|
1994-07-17 01:32:06 +04:00
|
|
|
if (error) {
|
|
|
|
*vpp = NULLVP;
|
1994-09-28 14:31:23 +03:00
|
|
|
return (error);
|
1994-07-17 01:32:06 +04:00
|
|
|
}
|
1993-08-13 15:35:13 +04:00
|
|
|
*vpp = DETOV(dep);
|
1999-02-27 02:44:43 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_checkexp(mp, nam, exflagsp, credanonp)
|
|
|
|
struct mount *mp;
|
|
|
|
struct mbuf *nam;
|
|
|
|
int *exflagsp;
|
|
|
|
struct ucred **credanonp;
|
|
|
|
{
|
|
|
|
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
|
|
|
|
struct netcred *np;
|
|
|
|
|
|
|
|
np = vfs_export_lookup(mp, &pmp->pm_export, nam);
|
|
|
|
if (np == NULL)
|
|
|
|
return (EACCES);
|
1994-07-17 01:32:06 +04:00
|
|
|
*exflagsp = np->netc_exflags;
|
|
|
|
*credanonp = &np->netc_anon;
|
1994-09-28 14:31:23 +03:00
|
|
|
return (0);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_vptofh(vp, fhp)
|
|
|
|
struct vnode *vp;
|
|
|
|
struct fid *fhp;
|
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
struct denode *dep;
|
|
|
|
struct defid *defhp;
|
1993-08-13 15:35:13 +04:00
|
|
|
|
1994-09-28 14:31:23 +03:00
|
|
|
dep = VTODE(vp);
|
|
|
|
defhp = (struct defid *)fhp;
|
1993-08-13 15:35:13 +04:00
|
|
|
defhp->defid_len = sizeof(struct defid);
|
|
|
|
defhp->defid_dirclust = dep->de_dirclust;
|
|
|
|
defhp->defid_dirofs = dep->de_diroffset;
|
1994-09-28 14:31:23 +03:00
|
|
|
/* defhp->defid_gen = dep->de_gen; */
|
|
|
|
return (0);
|
1994-07-17 01:32:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_vget(mp, ino, vpp)
|
|
|
|
struct mount *mp;
|
|
|
|
ino_t ino;
|
|
|
|
struct vnode **vpp;
|
|
|
|
{
|
1994-09-28 14:31:23 +03:00
|
|
|
|
|
|
|
return (EOPNOTSUPP);
|
1993-08-13 15:35:13 +04:00
|
|
|
}
|
1998-03-01 05:20:01 +03:00
|
|
|
|
|
|
|
int
|
|
|
|
msdosfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
|
|
int *name;
|
|
|
|
u_int namelen;
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|