1*c6c16cd0Sdholland /* $NetBSD: ntfs_vnops.c,v 1.66 2021/06/29 22:34:07 dholland Exp $ */
29accf4dfSjdolecek
39accf4dfSjdolecek /*
49accf4dfSjdolecek * Copyright (c) 1992, 1993
59accf4dfSjdolecek * The Regents of the University of California. All rights reserved.
69accf4dfSjdolecek *
79accf4dfSjdolecek * This code is derived from software contributed to Berkeley by
89accf4dfSjdolecek * John Heidemann of the UCLA Ficus project.
99accf4dfSjdolecek *
109accf4dfSjdolecek * Redistribution and use in source and binary forms, with or without
119accf4dfSjdolecek * modification, are permitted provided that the following conditions
129accf4dfSjdolecek * are met:
139accf4dfSjdolecek * 1. Redistributions of source code must retain the above copyright
149accf4dfSjdolecek * notice, this list of conditions and the following disclaimer.
159accf4dfSjdolecek * 2. Redistributions in binary form must reproduce the above copyright
169accf4dfSjdolecek * notice, this list of conditions and the following disclaimer in the
179accf4dfSjdolecek * documentation and/or other materials provided with the distribution.
18aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
199accf4dfSjdolecek * may be used to endorse or promote products derived from this software
209accf4dfSjdolecek * without specific prior written permission.
219accf4dfSjdolecek *
229accf4dfSjdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
239accf4dfSjdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249accf4dfSjdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259accf4dfSjdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
269accf4dfSjdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
279accf4dfSjdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289accf4dfSjdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
299accf4dfSjdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
309accf4dfSjdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
319accf4dfSjdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329accf4dfSjdolecek * SUCH DAMAGE.
339accf4dfSjdolecek *
349accf4dfSjdolecek * Id: ntfs_vnops.c,v 1.5 1999/05/12 09:43:06 semenu Exp
359accf4dfSjdolecek *
369accf4dfSjdolecek */
379accf4dfSjdolecek
389accf4dfSjdolecek #include <sys/cdefs.h>
39*c6c16cd0Sdholland __KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.66 2021/06/29 22:34:07 dholland Exp $");
4079b00c49Smartin
419accf4dfSjdolecek #include <sys/param.h>
429accf4dfSjdolecek #include <sys/systm.h>
439accf4dfSjdolecek #include <sys/kernel.h>
449accf4dfSjdolecek #include <sys/time.h>
459accf4dfSjdolecek #include <sys/stat.h>
469accf4dfSjdolecek #include <sys/vnode.h>
479accf4dfSjdolecek #include <sys/mount.h>
489accf4dfSjdolecek #include <sys/namei.h>
499accf4dfSjdolecek #include <sys/malloc.h>
509accf4dfSjdolecek #include <sys/buf.h>
519accf4dfSjdolecek #include <sys/dirent.h>
52fc9422c9Selad #include <sys/kauth.h>
539accf4dfSjdolecek #include <sys/sysctl.h>
549accf4dfSjdolecek
559accf4dfSjdolecek
569accf4dfSjdolecek #include <fs/ntfs/ntfs.h>
579accf4dfSjdolecek #include <fs/ntfs/ntfs_inode.h>
589accf4dfSjdolecek #include <fs/ntfs/ntfs_subr.h>
590bac6265Shannken #include <fs/ntfs/ntfs_vfsops.h>
609accf4dfSjdolecek #include <miscfs/specfs/specdev.h>
619accf4dfSjdolecek #include <miscfs/genfs/genfs.h>
629accf4dfSjdolecek
639accf4dfSjdolecek #include <sys/unistd.h> /* for pathconf(2) constants */
649accf4dfSjdolecek
654d595fd7Schristos static int ntfs_bypass(void *);
664d595fd7Schristos static int ntfs_read(void *);
674d595fd7Schristos static int ntfs_write(void *);
684d595fd7Schristos static int ntfs_getattr(void *);
694d595fd7Schristos static int ntfs_inactive(void *);
704d595fd7Schristos static int ntfs_print(void *);
714d595fd7Schristos static int ntfs_reclaim(void *);
724d595fd7Schristos static int ntfs_strategy(void *);
734d595fd7Schristos static int ntfs_access(void *);
744d595fd7Schristos static int ntfs_open(void *);
754d595fd7Schristos static int ntfs_close(void *);
764d595fd7Schristos static int ntfs_readdir(void *);
774d595fd7Schristos static int ntfs_lookup(void *);
784d595fd7Schristos static int ntfs_bmap(void *);
794d595fd7Schristos static int ntfs_fsync(void *);
8008fcacf4Sxtraeme static int ntfs_pathconf(void *);
819accf4dfSjdolecek
829accf4dfSjdolecek /*
839accf4dfSjdolecek * This is a noop, simply returning what one has been given.
849accf4dfSjdolecek */
859accf4dfSjdolecek int
ntfs_bmap(void * v)864d595fd7Schristos ntfs_bmap(void *v)
874d595fd7Schristos {
889accf4dfSjdolecek struct vop_bmap_args /* {
899accf4dfSjdolecek struct vnode *a_vp;
909accf4dfSjdolecek daddr_t a_bn;
919accf4dfSjdolecek struct vnode **a_vpp;
929accf4dfSjdolecek daddr_t *a_bnp;
939accf4dfSjdolecek int *a_runp;
949accf4dfSjdolecek int *a_runb;
954d595fd7Schristos } */ *ap = v;
969accf4dfSjdolecek dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
979accf4dfSjdolecek if (ap->a_vpp != NULL)
989accf4dfSjdolecek *ap->a_vpp = ap->a_vp;
999accf4dfSjdolecek if (ap->a_bnp != NULL)
1009accf4dfSjdolecek *ap->a_bnp = ap->a_bn;
1019accf4dfSjdolecek if (ap->a_runp != NULL)
1029accf4dfSjdolecek *ap->a_runp = 0;
1039accf4dfSjdolecek return (0);
1049accf4dfSjdolecek }
1059accf4dfSjdolecek
1069accf4dfSjdolecek static int
ntfs_read(void * v)1074d595fd7Schristos ntfs_read(void *v)
1084d595fd7Schristos {
1099accf4dfSjdolecek struct vop_read_args /* {
1109accf4dfSjdolecek struct vnode *a_vp;
1119accf4dfSjdolecek struct uio *a_uio;
1129accf4dfSjdolecek int a_ioflag;
113fc9422c9Selad kauth_cred_t a_cred;
1144d595fd7Schristos } */ *ap = v;
1159accf4dfSjdolecek struct vnode *vp = ap->a_vp;
1169accf4dfSjdolecek struct fnode *fp = VTOF(vp);
1179accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
1189accf4dfSjdolecek struct uio *uio = ap->a_uio;
1199accf4dfSjdolecek struct ntfsmount *ntmp = ip->i_mp;
1209accf4dfSjdolecek u_int64_t toread;
1219accf4dfSjdolecek int error;
1229accf4dfSjdolecek
123ec5a9318Syamt dprintf(("ntfs_read: ino: %llu, off: %qd resid: %qd\n",
124f229ea7fSchristos (unsigned long long)ip->i_number, (long long)uio->uio_offset,
125ec5a9318Syamt (long long)uio->uio_resid));
1269accf4dfSjdolecek
127aa112c89Schristos dprintf(("ntfs_read: filesize: %qu",(long long)fp->f_size));
1289accf4dfSjdolecek
1299accf4dfSjdolecek /* don't allow reading after end of file */
1309accf4dfSjdolecek if (uio->uio_offset > fp->f_size)
1319accf4dfSjdolecek toread = 0;
1329accf4dfSjdolecek else
13328302c22Sjdolecek toread = MIN(uio->uio_resid, fp->f_size - uio->uio_offset );
1349accf4dfSjdolecek
135aa112c89Schristos dprintf((", toread: %qu\n",(long long)toread));
1369accf4dfSjdolecek
1379accf4dfSjdolecek if (toread == 0)
1389accf4dfSjdolecek return (0);
1399accf4dfSjdolecek
1409accf4dfSjdolecek error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
1419accf4dfSjdolecek fp->f_attrname, uio->uio_offset, toread, NULL, uio);
1429accf4dfSjdolecek if (error) {
1439accf4dfSjdolecek printf("ntfs_read: ntfs_readattr failed: %d\n",error);
1449accf4dfSjdolecek return (error);
1459accf4dfSjdolecek }
1469accf4dfSjdolecek
1479accf4dfSjdolecek return (0);
1489accf4dfSjdolecek }
1499accf4dfSjdolecek
1509accf4dfSjdolecek static int
ntfs_bypass(void * v)1514d595fd7Schristos ntfs_bypass(void *v)
1524d595fd7Schristos {
1539accf4dfSjdolecek struct vop_generic_args /* {
1549accf4dfSjdolecek struct vnodeop_desc *a_desc;
1559accf4dfSjdolecek <other random data follows, presumably>
1564d595fd7Schristos } */ *ap __unused = v;
1579accf4dfSjdolecek int error = ENOTTY;
1589accf4dfSjdolecek dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name));
1599accf4dfSjdolecek return (error);
1609accf4dfSjdolecek }
1619accf4dfSjdolecek
1629accf4dfSjdolecek
1639accf4dfSjdolecek static int
ntfs_getattr(void * v)1644d595fd7Schristos ntfs_getattr(void *v)
1654d595fd7Schristos {
1669accf4dfSjdolecek struct vop_getattr_args /* {
1679accf4dfSjdolecek struct vnode *a_vp;
1689accf4dfSjdolecek struct vattr *a_vap;
169fc9422c9Selad kauth_cred_t a_cred;
1704d595fd7Schristos } */ *ap = v;
1719accf4dfSjdolecek struct vnode *vp = ap->a_vp;
1729accf4dfSjdolecek struct fnode *fp = VTOF(vp);
1739accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
1749accf4dfSjdolecek struct vattr *vap = ap->a_vap;
1759accf4dfSjdolecek
176f229ea7fSchristos dprintf(("ntfs_getattr: %llu, flags: %d\n",
177f229ea7fSchristos (unsigned long long)ip->i_number, ip->i_flag));
1789accf4dfSjdolecek
1799accf4dfSjdolecek vap->va_fsid = ip->i_dev;
1809accf4dfSjdolecek vap->va_fileid = ip->i_number;
1819accf4dfSjdolecek vap->va_mode = ip->i_mp->ntm_mode;
1829accf4dfSjdolecek vap->va_nlink = ip->i_nlink;
1839accf4dfSjdolecek vap->va_uid = ip->i_mp->ntm_uid;
1849accf4dfSjdolecek vap->va_gid = ip->i_mp->ntm_gid;
1859accf4dfSjdolecek vap->va_rdev = 0; /* XXX UNODEV ? */
1869accf4dfSjdolecek vap->va_size = fp->f_size;
1879accf4dfSjdolecek vap->va_bytes = fp->f_allocated;
1889accf4dfSjdolecek vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
1899accf4dfSjdolecek vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
1909accf4dfSjdolecek vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
1919accf4dfSjdolecek vap->va_flags = ip->i_flag;
1929accf4dfSjdolecek vap->va_gen = 0;
1939accf4dfSjdolecek vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
1949accf4dfSjdolecek vap->va_type = vp->v_type;
1959accf4dfSjdolecek vap->va_filerev = 0;
1969accf4dfSjdolecek return (0);
1979accf4dfSjdolecek }
1989accf4dfSjdolecek
1999accf4dfSjdolecek
2009accf4dfSjdolecek /*
2019accf4dfSjdolecek * Last reference to an ntnode. If necessary, write or delete it.
2029accf4dfSjdolecek */
2039accf4dfSjdolecek int
ntfs_inactive(void * v)2044d595fd7Schristos ntfs_inactive(void *v)
2054d595fd7Schristos {
20687fb3229Sriastradh struct vop_inactive_v2_args /* {
2079accf4dfSjdolecek struct vnode *a_vp;
20887fb3229Sriastradh bool *a_recycle;
2094d595fd7Schristos } */ *ap = v;
21087fb3229Sriastradh struct vnode *vp __unused = ap->a_vp;
2119accf4dfSjdolecek #ifdef NTFS_DEBUG
2129accf4dfSjdolecek struct ntnode *ip = VTONT(vp);
2139accf4dfSjdolecek #endif
2149accf4dfSjdolecek
215f229ea7fSchristos dprintf(("ntfs_inactive: vnode: %p, ntnode: %llu\n", vp,
216f229ea7fSchristos (unsigned long long)ip->i_number));
2179accf4dfSjdolecek
2189accf4dfSjdolecek /* XXX since we don't support any filesystem changes
2199accf4dfSjdolecek * right now, nothing more needs to be done
2209accf4dfSjdolecek */
2219accf4dfSjdolecek return (0);
2229accf4dfSjdolecek }
2239accf4dfSjdolecek
2249accf4dfSjdolecek /*
2259accf4dfSjdolecek * Reclaim an fnode/ntnode so that it can be used for other purposes.
2269accf4dfSjdolecek */
2279accf4dfSjdolecek int
ntfs_reclaim(void * v)2284d595fd7Schristos ntfs_reclaim(void *v)
2294d595fd7Schristos {
2307f7aad09Sriastradh struct vop_reclaim_v2_args /* {
2319accf4dfSjdolecek struct vnode *a_vp;
2324d595fd7Schristos } */ *ap = v;
2339accf4dfSjdolecek struct vnode *vp = ap->a_vp;
2349accf4dfSjdolecek struct fnode *fp = VTOF(vp);
2359accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
2360bac6265Shannken const int attrlen = strlen(fp->f_attrname);
2379accf4dfSjdolecek int error;
2389accf4dfSjdolecek
2397f7aad09Sriastradh VOP_UNLOCK(vp);
2407f7aad09Sriastradh
241f229ea7fSchristos dprintf(("ntfs_reclaim: vnode: %p, ntnode: %llu\n", vp,
242f229ea7fSchristos (unsigned long long)ip->i_number));
2439accf4dfSjdolecek
2449accf4dfSjdolecek if ((error = ntfs_ntget(ip)) != 0)
2459accf4dfSjdolecek return (error);
2469accf4dfSjdolecek
2479accf4dfSjdolecek if (ip->i_devvp) {
2489accf4dfSjdolecek vrele(ip->i_devvp);
2499accf4dfSjdolecek ip->i_devvp = NULL;
2509accf4dfSjdolecek }
251adbb9ec2Sad genfs_node_destroy(vp);
2529accf4dfSjdolecek vp->v_data = NULL;
2539accf4dfSjdolecek
2540bac6265Shannken /* Destroy fnode. */
2550bac6265Shannken if (fp->f_key != &fp->f_smallkey)
2560bac6265Shannken kmem_free(fp->f_key, NTKEY_SIZE(attrlen));
2570bac6265Shannken if (fp->f_dirblbuf)
2580bac6265Shannken free(fp->f_dirblbuf, M_NTFSDIR);
2590bac6265Shannken kmem_free(fp, sizeof(*fp));
2600bac6265Shannken ntfs_ntrele(ip);
2610bac6265Shannken
2620bac6265Shannken ntfs_ntput(ip);
2630bac6265Shannken
2649accf4dfSjdolecek return (0);
2659accf4dfSjdolecek }
2669accf4dfSjdolecek
2679accf4dfSjdolecek static int
ntfs_print(void * v)2684d595fd7Schristos ntfs_print(void *v)
2694d595fd7Schristos {
2709accf4dfSjdolecek struct vop_print_args /* {
2719accf4dfSjdolecek struct vnode *a_vp;
2724d595fd7Schristos } */ *ap = v;
27381d7a920Sjdolecek struct ntnode *ip = VTONT(ap->a_vp);
27481d7a920Sjdolecek
275758a209dSchristos printf("tag VT_NTFS, ino %llu, flag %#x, usecount %d, nlink %ld\n",
276758a209dSchristos (unsigned long long)ip->i_number, ip->i_flag, ip->i_usecount,
277758a209dSchristos ip->i_nlink);
27881d7a920Sjdolecek printf(" ");
27981d7a920Sjdolecek printf("\n");
2809accf4dfSjdolecek return (0);
2819accf4dfSjdolecek }
2829accf4dfSjdolecek
2839accf4dfSjdolecek /*
2849accf4dfSjdolecek * Calculate the logical to physical mapping if not done already,
2859accf4dfSjdolecek * then call the device strategy routine.
2869accf4dfSjdolecek */
2879accf4dfSjdolecek int
ntfs_strategy(void * v)2884d595fd7Schristos ntfs_strategy(void *v)
2894d595fd7Schristos {
2909accf4dfSjdolecek struct vop_strategy_args /* {
291d6170777Shannken struct vnode *a_vp;
2929accf4dfSjdolecek struct buf *a_bp;
2934d595fd7Schristos } */ *ap = v;
2949accf4dfSjdolecek struct buf *bp = ap->a_bp;
295d6170777Shannken struct vnode *vp = ap->a_vp;
2969accf4dfSjdolecek struct fnode *fp = VTOF(vp);
2979accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
2989accf4dfSjdolecek struct ntfsmount *ntmp = ip->i_mp;
2999accf4dfSjdolecek int error;
3009accf4dfSjdolecek
3019accf4dfSjdolecek dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n",
3029accf4dfSjdolecek (u_int32_t)bp->b_blkno,
3039accf4dfSjdolecek (u_int32_t)bp->b_lblkno));
3049accf4dfSjdolecek
30528302c22Sjdolecek dprintf(("strategy: bcount: %u flags: 0x%x\n",
3069accf4dfSjdolecek (u_int32_t)bp->b_bcount,bp->b_flags));
3079accf4dfSjdolecek
3089accf4dfSjdolecek if (bp->b_flags & B_READ) {
3099accf4dfSjdolecek u_int32_t toread;
3109accf4dfSjdolecek
3119accf4dfSjdolecek if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
3129accf4dfSjdolecek clrbuf(bp);
3139accf4dfSjdolecek error = 0;
3149accf4dfSjdolecek } else {
31528302c22Sjdolecek toread = MIN(bp->b_bcount,
3169accf4dfSjdolecek fp->f_size - ntfs_cntob(bp->b_blkno));
3179accf4dfSjdolecek dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
3189accf4dfSjdolecek toread,(u_int32_t)fp->f_size));
3199accf4dfSjdolecek
3209accf4dfSjdolecek error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
3219accf4dfSjdolecek fp->f_attrname, ntfs_cntob(bp->b_blkno),
3229accf4dfSjdolecek toread, bp->b_data, NULL);
3239accf4dfSjdolecek
3249accf4dfSjdolecek if (error) {
3259accf4dfSjdolecek printf("ntfs_strategy: ntfs_readattr failed\n");
3269accf4dfSjdolecek bp->b_error = error;
3279accf4dfSjdolecek }
3289accf4dfSjdolecek
32953524e44Schristos memset((char *)bp->b_data + toread, 0,
33053524e44Schristos bp->b_bcount - toread);
3319accf4dfSjdolecek }
3329accf4dfSjdolecek } else {
3339accf4dfSjdolecek size_t tmp;
3349accf4dfSjdolecek u_int32_t towrite;
3359accf4dfSjdolecek
3369accf4dfSjdolecek if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
3379accf4dfSjdolecek printf("ntfs_strategy: CAN'T EXTEND FILE\n");
3389accf4dfSjdolecek bp->b_error = error = EFBIG;
3399accf4dfSjdolecek } else {
34028302c22Sjdolecek towrite = MIN(bp->b_bcount,
3419accf4dfSjdolecek fp->f_size - ntfs_cntob(bp->b_blkno));
3429accf4dfSjdolecek dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
3439accf4dfSjdolecek towrite,(u_int32_t)fp->f_size));
3449accf4dfSjdolecek
3459accf4dfSjdolecek error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
3469accf4dfSjdolecek fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
3479accf4dfSjdolecek bp->b_data, &tmp, NULL);
3489accf4dfSjdolecek
3499accf4dfSjdolecek if (error) {
3509accf4dfSjdolecek printf("ntfs_strategy: ntfs_writeattr fail\n");
3519accf4dfSjdolecek bp->b_error = error;
3529accf4dfSjdolecek }
3539accf4dfSjdolecek }
3549accf4dfSjdolecek }
3559accf4dfSjdolecek biodone(bp);
3569accf4dfSjdolecek return (error);
3579accf4dfSjdolecek }
3589accf4dfSjdolecek
3599accf4dfSjdolecek static int
ntfs_write(void * v)3604d595fd7Schristos ntfs_write(void *v)
3614d595fd7Schristos {
3629accf4dfSjdolecek struct vop_write_args /* {
3639accf4dfSjdolecek struct vnode *a_vp;
3649accf4dfSjdolecek struct uio *a_uio;
3659accf4dfSjdolecek int a_ioflag;
366fc9422c9Selad kauth_cred_t a_cred;
3674d595fd7Schristos } */ *ap = v;
3689accf4dfSjdolecek struct vnode *vp = ap->a_vp;
3699accf4dfSjdolecek struct fnode *fp = VTOF(vp);
3709accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
3719accf4dfSjdolecek struct uio *uio = ap->a_uio;
3729accf4dfSjdolecek struct ntfsmount *ntmp = ip->i_mp;
3739accf4dfSjdolecek u_int64_t towrite;
3749accf4dfSjdolecek size_t written;
3759accf4dfSjdolecek int error;
3769accf4dfSjdolecek
377ec5a9318Syamt dprintf(("ntfs_write: ino: %llu, off: %qd resid: %qd\n",
378f229ea7fSchristos (unsigned long long)ip->i_number, (long long)uio->uio_offset,
379ec5a9318Syamt (long long)uio->uio_resid));
380aa112c89Schristos dprintf(("ntfs_write: filesize: %qu",(long long)fp->f_size));
3819accf4dfSjdolecek
3829accf4dfSjdolecek if (uio->uio_resid + uio->uio_offset > fp->f_size) {
3839accf4dfSjdolecek printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
3849accf4dfSjdolecek return (EFBIG);
3859accf4dfSjdolecek }
3869accf4dfSjdolecek
38728302c22Sjdolecek towrite = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
3889accf4dfSjdolecek
389aa112c89Schristos dprintf((", towrite: %qu\n",(long long)towrite));
3909accf4dfSjdolecek
3919accf4dfSjdolecek error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
3929accf4dfSjdolecek fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
3939accf4dfSjdolecek #ifdef NTFS_DEBUG
3949accf4dfSjdolecek if (error)
3959accf4dfSjdolecek printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
3969accf4dfSjdolecek #endif
3979accf4dfSjdolecek
3989accf4dfSjdolecek return (error);
3999accf4dfSjdolecek }
4009accf4dfSjdolecek
401009f5d2fSelad static int
ntfs_check_possible(struct vnode * vp,struct ntnode * ip,accmode_t accmode)4029aa2a9c3Schristos ntfs_check_possible(struct vnode *vp, struct ntnode *ip, accmode_t accmode)
4034d595fd7Schristos {
4049accf4dfSjdolecek
4059accf4dfSjdolecek /*
4069accf4dfSjdolecek * Disallow write attempts on read-only file systems;
4079accf4dfSjdolecek * unless the file is a socket, fifo, or a block or
4089accf4dfSjdolecek * character device resident on the file system.
4099accf4dfSjdolecek */
4109aa2a9c3Schristos if (accmode & VWRITE) {
4119accf4dfSjdolecek switch ((int)vp->v_type) {
4129accf4dfSjdolecek case VDIR:
4139accf4dfSjdolecek case VLNK:
4149accf4dfSjdolecek case VREG:
4159accf4dfSjdolecek if (vp->v_mount->mnt_flag & MNT_RDONLY)
4169accf4dfSjdolecek return (EROFS);
4179accf4dfSjdolecek break;
4189accf4dfSjdolecek }
4199accf4dfSjdolecek }
4209accf4dfSjdolecek
421009f5d2fSelad return 0;
422009f5d2fSelad }
423009f5d2fSelad
424009f5d2fSelad static int
ntfs_check_permitted(struct vnode * vp,struct ntnode * ip,accmode_t accmode,kauth_cred_t cred)4259aa2a9c3Schristos ntfs_check_permitted(struct vnode *vp, struct ntnode *ip, accmode_t accmode,
426009f5d2fSelad kauth_cred_t cred)
427009f5d2fSelad {
428009f5d2fSelad mode_t file_mode;
429009f5d2fSelad
43069db27dcSelad file_mode = ip->i_mp->ntm_mode | (S_IXUSR|S_IXGRP|S_IXOTH);
4319accf4dfSjdolecek
4329aa2a9c3Schristos return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
4339aa2a9c3Schristos vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred,
4349aa2a9c3Schristos ip->i_mp->ntm_uid, ip->i_mp->ntm_gid, file_mode, NULL, accmode));
435009f5d2fSelad }
436009f5d2fSelad
437009f5d2fSelad int
ntfs_access(void * v)438009f5d2fSelad ntfs_access(void *v)
439009f5d2fSelad {
440009f5d2fSelad struct vop_access_args /* {
441009f5d2fSelad struct vnode *a_vp;
4429aa2a9c3Schristos accmode_t a_accmode;
443009f5d2fSelad kauth_cred_t a_cred;
444009f5d2fSelad } */ *ap = v;
445009f5d2fSelad struct vnode *vp = ap->a_vp;
446009f5d2fSelad struct ntnode *ip = VTONT(vp);
447009f5d2fSelad int error;
448009f5d2fSelad
449009f5d2fSelad dprintf(("ntfs_access: %llu\n", (unsigned long long)ip->i_number));
450009f5d2fSelad
4519aa2a9c3Schristos error = ntfs_check_possible(vp, ip, ap->a_accmode);
452009f5d2fSelad if (error)
453009f5d2fSelad return error;
454009f5d2fSelad
4559aa2a9c3Schristos error = ntfs_check_permitted(vp, ip, ap->a_accmode, ap->a_cred);
456009f5d2fSelad
457009f5d2fSelad return error;
4589accf4dfSjdolecek }
4599accf4dfSjdolecek
4609accf4dfSjdolecek /*
4619accf4dfSjdolecek * Open called.
4629accf4dfSjdolecek *
4639accf4dfSjdolecek * Nothing to do.
4649accf4dfSjdolecek */
4659accf4dfSjdolecek /* ARGSUSED */
4669accf4dfSjdolecek static int
ntfs_open(void * v)4674d595fd7Schristos ntfs_open(void *v)
4684d595fd7Schristos {
4699accf4dfSjdolecek struct vop_open_args /* {
4709accf4dfSjdolecek struct vnode *a_vp;
4719accf4dfSjdolecek int a_mode;
472fc9422c9Selad kauth_cred_t a_cred;
4734d595fd7Schristos } */ *ap __unused = v;
474f229ea7fSchristos #ifdef NTFS_DEBUG
4759accf4dfSjdolecek struct vnode *vp = ap->a_vp;
4769accf4dfSjdolecek struct ntnode *ip = VTONT(vp);
4779accf4dfSjdolecek
4786f8e2ffeShannken dprintf(("ntfs_open: %llu\n", (unsigned long long)ip->i_number));
4799accf4dfSjdolecek #endif
4809accf4dfSjdolecek
4819accf4dfSjdolecek /*
4829accf4dfSjdolecek * Files marked append-only must be opened for appending.
4839accf4dfSjdolecek */
4849accf4dfSjdolecek
4859accf4dfSjdolecek return (0);
4869accf4dfSjdolecek }
4879accf4dfSjdolecek
4889accf4dfSjdolecek /*
4899accf4dfSjdolecek * Close called.
4909accf4dfSjdolecek *
4919accf4dfSjdolecek * Update the times on the inode.
4929accf4dfSjdolecek */
4939accf4dfSjdolecek /* ARGSUSED */
4949accf4dfSjdolecek static int
ntfs_close(void * v)4954d595fd7Schristos ntfs_close(void *v)
4964d595fd7Schristos {
4979accf4dfSjdolecek struct vop_close_args /* {
4989accf4dfSjdolecek struct vnode *a_vp;
4999accf4dfSjdolecek int a_fflag;
500fc9422c9Selad kauth_cred_t a_cred;
5014d595fd7Schristos } */ *ap __unused = v;
502f229ea7fSchristos #ifdef NTFS_DEBUG
5039accf4dfSjdolecek struct vnode *vp = ap->a_vp;
5049accf4dfSjdolecek struct ntnode *ip = VTONT(vp);
5059accf4dfSjdolecek
5066f8e2ffeShannken dprintf(("ntfs_close: %llu\n", (unsigned long long)ip->i_number));
5079accf4dfSjdolecek #endif
5089accf4dfSjdolecek
5099accf4dfSjdolecek return (0);
5109accf4dfSjdolecek }
5119accf4dfSjdolecek
5129accf4dfSjdolecek int
ntfs_readdir(void * v)5134d595fd7Schristos ntfs_readdir(void *v)
5144d595fd7Schristos {
5159accf4dfSjdolecek struct vop_readdir_args /* {
5169accf4dfSjdolecek struct vnode *a_vp;
5179accf4dfSjdolecek struct uio *a_uio;
518fc9422c9Selad kauth_cred_t a_cred;
5199accf4dfSjdolecek int *a_ncookies;
5209accf4dfSjdolecek u_int **cookies;
5214d595fd7Schristos } */ *ap = v;
5229accf4dfSjdolecek struct vnode *vp = ap->a_vp;
5239accf4dfSjdolecek struct fnode *fp = VTOF(vp);
5249accf4dfSjdolecek struct ntnode *ip = FTONT(fp);
5259accf4dfSjdolecek struct uio *uio = ap->a_uio;
5269accf4dfSjdolecek struct ntfsmount *ntmp = ip->i_mp;
5279accf4dfSjdolecek int i, error = 0;
5289accf4dfSjdolecek u_int32_t faked = 0, num;
5299accf4dfSjdolecek int ncookies = 0;
5309accf4dfSjdolecek struct dirent *cde;
5319accf4dfSjdolecek off_t off;
5329accf4dfSjdolecek
533f229ea7fSchristos dprintf(("ntfs_readdir %llu off: %qd resid: %qd\n",
534f229ea7fSchristos (unsigned long long)ip->i_number, (long long)uio->uio_offset,
535f229ea7fSchristos (long long)uio->uio_resid));
5369accf4dfSjdolecek
5379accf4dfSjdolecek off = uio->uio_offset;
5389accf4dfSjdolecek
5399b87d582Scegger cde = malloc(sizeof(struct dirent), M_TEMP, M_WAITOK);
5409accf4dfSjdolecek
5419accf4dfSjdolecek /* Simulate . in every dir except ROOT */
5429accf4dfSjdolecek if (ip->i_number != NTFS_ROOTINO
5439accf4dfSjdolecek && uio->uio_offset < sizeof(struct dirent)) {
5449accf4dfSjdolecek cde->d_fileno = ip->i_number;
5459accf4dfSjdolecek cde->d_reclen = sizeof(struct dirent);
5469accf4dfSjdolecek cde->d_type = DT_DIR;
5479accf4dfSjdolecek cde->d_namlen = 1;
5489accf4dfSjdolecek strncpy(cde->d_name, ".", 2);
5499accf4dfSjdolecek error = uiomove((void *)cde, sizeof(struct dirent), uio);
5509accf4dfSjdolecek if (error)
5519accf4dfSjdolecek goto out;
5529accf4dfSjdolecek
5539accf4dfSjdolecek ncookies++;
5549accf4dfSjdolecek }
5559accf4dfSjdolecek
5569accf4dfSjdolecek /* Simulate .. in every dir including ROOT */
5579accf4dfSjdolecek if (uio->uio_offset < 2 * sizeof(struct dirent)) {
5589accf4dfSjdolecek cde->d_fileno = NTFS_ROOTINO; /* XXX */
5599accf4dfSjdolecek cde->d_reclen = sizeof(struct dirent);
5609accf4dfSjdolecek cde->d_type = DT_DIR;
5619accf4dfSjdolecek cde->d_namlen = 2;
5629accf4dfSjdolecek strncpy(cde->d_name, "..", 3);
5639accf4dfSjdolecek
5649accf4dfSjdolecek error = uiomove((void *) cde, sizeof(struct dirent), uio);
5659accf4dfSjdolecek if (error)
5669accf4dfSjdolecek goto out;
5679accf4dfSjdolecek
5689accf4dfSjdolecek ncookies++;
5699accf4dfSjdolecek }
5709accf4dfSjdolecek
5719accf4dfSjdolecek faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
5729accf4dfSjdolecek num = uio->uio_offset / sizeof(struct dirent) - faked;
5739accf4dfSjdolecek
5749accf4dfSjdolecek while (uio->uio_resid >= sizeof(struct dirent)) {
5759accf4dfSjdolecek struct attr_indexentry *iep;
5769accf4dfSjdolecek char *fname;
5779accf4dfSjdolecek size_t remains;
5789accf4dfSjdolecek int sz;
5799accf4dfSjdolecek
5809accf4dfSjdolecek error = ntfs_ntreaddir(ntmp, fp, num, &iep);
5819accf4dfSjdolecek if (error)
5829accf4dfSjdolecek goto out;
5839accf4dfSjdolecek
5849accf4dfSjdolecek if (NULL == iep)
5859accf4dfSjdolecek break;
5869accf4dfSjdolecek
5879accf4dfSjdolecek for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
5889accf4dfSjdolecek iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
5899accf4dfSjdolecek {
5909accf4dfSjdolecek if(!ntfs_isnamepermitted(ntmp,iep))
5919accf4dfSjdolecek continue;
5929accf4dfSjdolecek
5939accf4dfSjdolecek remains = sizeof(cde->d_name) - 1;
5949accf4dfSjdolecek fname = cde->d_name;
5959accf4dfSjdolecek for(i=0; i<iep->ie_fnamelen; i++) {
5969accf4dfSjdolecek sz = (*ntmp->ntm_wput)(fname, remains,
5979accf4dfSjdolecek iep->ie_fname[i]);
5989accf4dfSjdolecek fname += sz;
5999accf4dfSjdolecek remains -= sz;
6009accf4dfSjdolecek }
6019accf4dfSjdolecek *fname = '\0';
6029accf4dfSjdolecek dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
6039accf4dfSjdolecek num, cde->d_name, iep->ie_fnametype,
6049accf4dfSjdolecek iep->ie_flag));
6059accf4dfSjdolecek cde->d_namlen = fname - (char *) cde->d_name;
6069accf4dfSjdolecek cde->d_fileno = iep->ie_number;
6079accf4dfSjdolecek cde->d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
6089accf4dfSjdolecek cde->d_reclen = sizeof(struct dirent);
6099accf4dfSjdolecek dprintf(("%s\n", (cde->d_type == DT_DIR) ? "dir":"reg"));
6109accf4dfSjdolecek
6119accf4dfSjdolecek error = uiomove((void *)cde, sizeof(struct dirent), uio);
6129accf4dfSjdolecek if (error)
6139accf4dfSjdolecek goto out;
6149accf4dfSjdolecek
6159accf4dfSjdolecek ncookies++;
6169accf4dfSjdolecek num++;
6179accf4dfSjdolecek }
6189accf4dfSjdolecek }
6199accf4dfSjdolecek
6209accf4dfSjdolecek dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
6219accf4dfSjdolecek ncookies,(u_int)(uio->uio_offset - off)));
622aa112c89Schristos dprintf(("ntfs_readdir: off: %qd resid: %qu\n",
623aa112c89Schristos (long long)uio->uio_offset,(long long)uio->uio_resid));
6249accf4dfSjdolecek
6259accf4dfSjdolecek if (!error && ap->a_ncookies != NULL) {
6269accf4dfSjdolecek struct dirent* dpStart;
6279accf4dfSjdolecek struct dirent* dp;
6289accf4dfSjdolecek off_t *cookies;
6299accf4dfSjdolecek off_t *cookiep;
6309accf4dfSjdolecek
63187f9bd72Sjdolecek dprintf(("ntfs_readdir: %d cookies\n",ncookies));
6329accf4dfSjdolecek dpStart = (struct dirent *)
63353524e44Schristos ((char *)uio->uio_iov->iov_base -
6349accf4dfSjdolecek (uio->uio_offset - off));
6359accf4dfSjdolecek cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
6369accf4dfSjdolecek for (dp = dpStart, cookiep = cookies, i=0;
6379accf4dfSjdolecek i < ncookies;
63853524e44Schristos dp = (struct dirent *)((char *) dp + dp->d_reclen), i++) {
6399accf4dfSjdolecek off += dp->d_reclen;
6409accf4dfSjdolecek *cookiep++ = (u_int) off;
6419accf4dfSjdolecek }
6429accf4dfSjdolecek *ap->a_ncookies = ncookies;
6439accf4dfSjdolecek *ap->a_cookies = cookies;
6449accf4dfSjdolecek }
6459accf4dfSjdolecek /*
6469accf4dfSjdolecek if (ap->a_eofflag)
6479accf4dfSjdolecek *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
6489accf4dfSjdolecek */
6499accf4dfSjdolecek out:
6509b87d582Scegger free(cde, M_TEMP);
6519accf4dfSjdolecek return (error);
6529accf4dfSjdolecek }
6539accf4dfSjdolecek
6549accf4dfSjdolecek int
ntfs_lookup(void * v)6554d595fd7Schristos ntfs_lookup(void *v)
6564d595fd7Schristos {
65797834f7bShannken struct vop_lookup_v2_args /* {
6589accf4dfSjdolecek struct vnode *a_dvp;
6599accf4dfSjdolecek struct vnode **a_vpp;
6609accf4dfSjdolecek struct componentname *a_cnp;
6614d595fd7Schristos } */ *ap = v;
6629accf4dfSjdolecek struct vnode *dvp = ap->a_dvp;
6639accf4dfSjdolecek struct ntnode *dip = VTONT(dvp);
6649accf4dfSjdolecek struct ntfsmount *ntmp = dip->i_mp;
6659accf4dfSjdolecek struct componentname *cnp = ap->a_cnp;
666fc9422c9Selad kauth_cred_t cred = cnp->cn_cred;
6679accf4dfSjdolecek int error;
668c398ae97Schs
6691498ad22Sad dprintf(("ntfs_lookup: \"%.*s\" (%lld bytes) in %llu\n",
6701498ad22Sad (int)cnp->cn_namelen, cnp->cn_nameptr, (long long)cnp->cn_namelen,
671c398ae97Schs (unsigned long long)dip->i_number));
6729accf4dfSjdolecek
67361e8303eSpooka error = VOP_ACCESS(dvp, VEXEC, cred);
6749accf4dfSjdolecek if(error)
6759accf4dfSjdolecek return (error);
6769accf4dfSjdolecek
6779accf4dfSjdolecek if ((cnp->cn_flags & ISLASTCN) &&
6789accf4dfSjdolecek (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
6799accf4dfSjdolecek (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
6809accf4dfSjdolecek return (EROFS);
6819accf4dfSjdolecek
6829accf4dfSjdolecek /*
6839accf4dfSjdolecek * We now have a segment name to search for, and a directory
6849accf4dfSjdolecek * to search.
6859accf4dfSjdolecek *
6869accf4dfSjdolecek * Before tediously performing a linear scan of the directory,
6879accf4dfSjdolecek * check the name cache to see if the directory/name pair
6889accf4dfSjdolecek * we are looking for is known already.
6899accf4dfSjdolecek */
69035ed6905Sdholland if (cache_lookup(ap->a_dvp, cnp->cn_nameptr, cnp->cn_namelen,
69135ed6905Sdholland cnp->cn_nameiop, cnp->cn_flags, NULL, ap->a_vpp)) {
6921617a81dSdholland return *ap->a_vpp == NULLVP ? ENOENT : 0;
6931617a81dSdholland }
6949accf4dfSjdolecek
6959accf4dfSjdolecek if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
696f229ea7fSchristos dprintf(("ntfs_lookup: faking . directory in %llu\n",
697f229ea7fSchristos (unsigned long long)dip->i_number));
6989accf4dfSjdolecek
699c3183f32Spooka vref(dvp);
7009accf4dfSjdolecek *ap->a_vpp = dvp;
7019accf4dfSjdolecek error = 0;
7029accf4dfSjdolecek } else if (cnp->cn_flags & ISDOTDOT) {
7039accf4dfSjdolecek struct ntvattr *vap;
7049accf4dfSjdolecek
705f229ea7fSchristos dprintf(("ntfs_lookup: faking .. directory in %llu\n",
706f229ea7fSchristos (unsigned long long)dip->i_number));
7079accf4dfSjdolecek
7089accf4dfSjdolecek error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
709c398ae97Schs if (error) {
7109accf4dfSjdolecek return (error);
711c398ae97Schs }
7129accf4dfSjdolecek
7139accf4dfSjdolecek dprintf(("ntfs_lookup: parentdir: %d\n",
7149accf4dfSjdolecek vap->va_a_name->n_pnumber));
7150bac6265Shannken error = ntfs_vgetex(ntmp->ntm_mountp,
7160bac6265Shannken vap->va_a_name->n_pnumber,
7170bac6265Shannken NTFS_A_DATA, "", 0, ap->a_vpp);
7189accf4dfSjdolecek ntfs_ntvattrrele(vap);
7199accf4dfSjdolecek if (error) {
7209accf4dfSjdolecek return (error);
7219accf4dfSjdolecek }
7229accf4dfSjdolecek } else {
7239accf4dfSjdolecek error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
7249accf4dfSjdolecek if (error) {
7259accf4dfSjdolecek dprintf(("ntfs_ntlookupfile: returned %d\n", error));
7269accf4dfSjdolecek return (error);
7279accf4dfSjdolecek }
7289accf4dfSjdolecek
729f229ea7fSchristos dprintf(("ntfs_lookup: found ino: %llu\n",
730f229ea7fSchristos (unsigned long long)VTONT(*ap->a_vpp)->i_number));
7319accf4dfSjdolecek }
7329accf4dfSjdolecek
73335ed6905Sdholland cache_enter(dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
73435ed6905Sdholland cnp->cn_flags);
7359accf4dfSjdolecek
736d65753d9Srmind return error;
7379accf4dfSjdolecek }
7389accf4dfSjdolecek
7399accf4dfSjdolecek /*
7409accf4dfSjdolecek * Flush the blocks of a file to disk.
7419accf4dfSjdolecek *
7429accf4dfSjdolecek * This function is worthless for vnodes that represent directories. Maybe we
7439accf4dfSjdolecek * could just do a sync if they try an fsync on a directory file.
7449accf4dfSjdolecek */
7459accf4dfSjdolecek static int
ntfs_fsync(void * v)7464d595fd7Schristos ntfs_fsync(void *v)
7474d595fd7Schristos {
7489accf4dfSjdolecek struct vop_fsync_args /* {
7499accf4dfSjdolecek struct vnode *a_vp;
750fc9422c9Selad kauth_cred_t a_cred;
751a748ea88Syamt int a_flags;
7529accf4dfSjdolecek off_t offlo;
7539accf4dfSjdolecek off_t offhi;
7544d595fd7Schristos } */ *ap = v;
755a748ea88Syamt struct vnode *vp = ap->a_vp;
756a748ea88Syamt
757a748ea88Syamt if (ap->a_flags & FSYNC_CACHE) {
758a748ea88Syamt return EOPNOTSUPP;
7599accf4dfSjdolecek }
760a748ea88Syamt
7618306a9edSchs return vflushbuf(vp, ap->a_flags);
762a748ea88Syamt }
7639accf4dfSjdolecek
7649accf4dfSjdolecek /*
7659accf4dfSjdolecek * Return POSIX pathconf information applicable to NTFS filesystem
7669accf4dfSjdolecek */
7676810b562Sjdolecek static int
ntfs_pathconf(void * v)7684d595fd7Schristos ntfs_pathconf(void *v)
7699accf4dfSjdolecek {
7709accf4dfSjdolecek struct vop_pathconf_args /* {
7719accf4dfSjdolecek struct vnode *a_vp;
7729accf4dfSjdolecek int a_name;
7739accf4dfSjdolecek register_t *a_retval;
7749accf4dfSjdolecek } */ *ap = v;
7759accf4dfSjdolecek
7769accf4dfSjdolecek switch (ap->a_name) {
7779accf4dfSjdolecek case _PC_LINK_MAX:
7789accf4dfSjdolecek *ap->a_retval = 1;
7799accf4dfSjdolecek return (0);
7809accf4dfSjdolecek case _PC_NAME_MAX:
781caffd8efSjdolecek *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_namemax;
7829accf4dfSjdolecek return (0);
7839accf4dfSjdolecek case _PC_PATH_MAX:
7849accf4dfSjdolecek *ap->a_retval = PATH_MAX;
7859accf4dfSjdolecek return (0);
7869accf4dfSjdolecek case _PC_CHOWN_RESTRICTED:
7879accf4dfSjdolecek *ap->a_retval = 1;
7889accf4dfSjdolecek return (0);
7899accf4dfSjdolecek case _PC_NO_TRUNC:
7909accf4dfSjdolecek *ap->a_retval = 0;
7919accf4dfSjdolecek return (0);
7929accf4dfSjdolecek case _PC_SYNC_IO:
7939accf4dfSjdolecek *ap->a_retval = 1;
7949accf4dfSjdolecek return (0);
7959accf4dfSjdolecek case _PC_FILESIZEBITS:
7969accf4dfSjdolecek *ap->a_retval = 64;
7979accf4dfSjdolecek return (0);
7989accf4dfSjdolecek default:
79979e3c74fSchristos return genfs_pathconf(ap);
8009accf4dfSjdolecek }
8019accf4dfSjdolecek /* NOTREACHED */
8029accf4dfSjdolecek }
8039accf4dfSjdolecek
8049accf4dfSjdolecek /*
8059accf4dfSjdolecek * Global vfs data structures
8069accf4dfSjdolecek */
8079accf4dfSjdolecek vop_t **ntfs_vnodeop_p;
8089accf4dfSjdolecek
8099accf4dfSjdolecek const struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
8109accf4dfSjdolecek { &vop_default_desc, (vop_t *) ntfs_bypass },
811*c6c16cd0Sdholland { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */
8129accf4dfSjdolecek { &vop_lookup_desc, (vop_t *) ntfs_lookup }, /* lookup */
8139accf4dfSjdolecek { &vop_create_desc, genfs_eopnotsupp }, /* create */
8149accf4dfSjdolecek { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */
8159accf4dfSjdolecek { &vop_open_desc, (vop_t *) ntfs_open }, /* open */
8169accf4dfSjdolecek { &vop_close_desc,(vop_t *) ntfs_close }, /* close */
8179accf4dfSjdolecek { &vop_access_desc, (vop_t *) ntfs_access }, /* access */
8189aa2a9c3Schristos { &vop_accessx_desc, (vop_t *) genfs_accessx }, /* accessx */
8199accf4dfSjdolecek { &vop_getattr_desc, (vop_t *) ntfs_getattr }, /* getattr */
8209accf4dfSjdolecek { &vop_setattr_desc, genfs_eopnotsupp }, /* setattr */
8219accf4dfSjdolecek { &vop_read_desc, (vop_t *) ntfs_read }, /* read */
8229accf4dfSjdolecek { &vop_write_desc, (vop_t *) ntfs_write }, /* write */
82305d075b3Sdholland { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
82405d075b3Sdholland { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
8259accf4dfSjdolecek { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
8269accf4dfSjdolecek { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */
8279accf4dfSjdolecek { &vop_poll_desc, genfs_poll }, /* poll */
8289accf4dfSjdolecek { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */
8299accf4dfSjdolecek { &vop_revoke_desc, genfs_revoke }, /* revoke */
8309accf4dfSjdolecek { &vop_mmap_desc, genfs_mmap }, /* mmap */
831a748ea88Syamt { &vop_fsync_desc, (vop_t *) ntfs_fsync }, /* fsync */
8329accf4dfSjdolecek { &vop_seek_desc, genfs_seek }, /* seek */
83339a063b6Sjdolecek { &vop_remove_desc, genfs_eopnotsupp }, /* remove */
83439a063b6Sjdolecek { &vop_link_desc, genfs_eopnotsupp }, /* link */
83539a063b6Sjdolecek { &vop_rename_desc, genfs_eopnotsupp }, /* rename */
83639a063b6Sjdolecek { &vop_mkdir_desc, genfs_eopnotsupp }, /* mkdir */
83739a063b6Sjdolecek { &vop_rmdir_desc, genfs_eopnotsupp }, /* rmdir */
8389accf4dfSjdolecek { &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */
8399accf4dfSjdolecek { &vop_readdir_desc, (vop_t *) ntfs_readdir }, /* readdir */
8409accf4dfSjdolecek { &vop_readlink_desc, genfs_eopnotsupp }, /* readlink */
8419accf4dfSjdolecek { &vop_abortop_desc, genfs_abortop }, /* abortop */
8429accf4dfSjdolecek { &vop_inactive_desc, (vop_t *) ntfs_inactive }, /* inactive */
8439accf4dfSjdolecek { &vop_reclaim_desc, (vop_t *) ntfs_reclaim }, /* reclaim */
8449accf4dfSjdolecek { &vop_lock_desc, genfs_lock }, /* lock */
8459accf4dfSjdolecek { &vop_unlock_desc, genfs_unlock }, /* unlock */
8469accf4dfSjdolecek { &vop_bmap_desc, (vop_t *) ntfs_bmap }, /* bmap */
8479accf4dfSjdolecek { &vop_strategy_desc, (vop_t *) ntfs_strategy }, /* strategy */
8489accf4dfSjdolecek { &vop_print_desc, (vop_t *) ntfs_print }, /* print */
8499accf4dfSjdolecek { &vop_islocked_desc, genfs_islocked }, /* islocked */
8509accf4dfSjdolecek { &vop_pathconf_desc, ntfs_pathconf }, /* pathconf */
8519accf4dfSjdolecek { &vop_advlock_desc, genfs_nullop }, /* advlock */
8529accf4dfSjdolecek { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
8539accf4dfSjdolecek { &vop_getpages_desc, genfs_compat_getpages }, /* getpages */
8549accf4dfSjdolecek { &vop_putpages_desc, genfs_putpages }, /* putpages */
8559accf4dfSjdolecek { NULL, NULL }
8569accf4dfSjdolecek };
8579accf4dfSjdolecek const struct vnodeopv_desc ntfs_vnodeop_opv_desc =
8589accf4dfSjdolecek { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
859