LCOV - code coverage report
Current view: top level - ntfs - ntfs_vnops.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 285 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ntfs_vnops.c,v 1.44 2018/05/02 02:24:56 visa Exp $    */
       2             : /*      $NetBSD: ntfs_vnops.c,v 1.6 2003/04/10 21:57:26 jdolecek Exp $  */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1992, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to Berkeley by
       9             :  * John Heidemann of the UCLA Ficus project.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  * 3. Neither the name of the University nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  *
      35             :  *      Id: ntfs_vnops.c,v 1.5 1999/05/12 09:43:06 semenu Exp
      36             :  *
      37             :  */
      38             : 
      39             : #include <sys/param.h>
      40             : #include <sys/systm.h>
      41             : #include <sys/time.h>
      42             : #include <sys/stat.h>
      43             : #include <sys/vnode.h>
      44             : #include <sys/lock.h>
      45             : #include <sys/mount.h>
      46             : #include <sys/namei.h>
      47             : #include <sys/malloc.h>
      48             : #include <sys/buf.h>
      49             : #include <sys/dirent.h>
      50             : #include <sys/specdev.h>
      51             : 
      52             : /*#define NTFS_DEBUG 1*/
      53             : #include <ntfs/ntfs.h>
      54             : #include <ntfs/ntfs_inode.h>
      55             : #include <ntfs/ntfs_subr.h>
      56             : 
      57             : #include <sys/unistd.h> /* for pathconf(2) constants */
      58             : 
      59             : int     ntfs_read(void *);
      60             : int     ntfs_getattr(void *);
      61             : int     ntfs_inactive(void *);
      62             : int     ntfs_print(void *);
      63             : int     ntfs_reclaim(void *);
      64             : int     ntfs_strategy(void *);
      65             : int     ntfs_access(void *v);
      66             : int     ntfs_open(void *v);
      67             : int     ntfs_close(void *);
      68             : int     ntfs_readdir(void *);
      69             : int     ntfs_lookup(void *);
      70             : int     ntfs_bmap(void *);
      71             : int     ntfs_fsync(void *);
      72             : int     ntfs_pathconf(void *);
      73             : 
      74             : int     ntfs_prtactive = 0;     /* 1 => print out reclaim of active vnodes */
      75             : 
      76             : /*
      77             :  * This is a noop, simply returning what one has been given.
      78             :  */
      79             : int
      80           0 : ntfs_bmap(void *v)
      81             : {
      82           0 :         struct vop_bmap_args *ap = v;
      83             :         DPRINTF("ntfs_bmap: vn: %p, blk: %lld\n",
      84             :             ap->a_vp, (long long)ap->a_bn);
      85           0 :         if (ap->a_vpp != NULL)
      86           0 :                 *ap->a_vpp = ap->a_vp;
      87           0 :         if (ap->a_bnp != NULL)
      88           0 :                 *ap->a_bnp = ap->a_bn;
      89           0 :         if (ap->a_runp != NULL)
      90           0 :                 *ap->a_runp = 0;
      91           0 :         return (0);
      92             : }
      93             : 
      94             : int
      95           0 : ntfs_read(void *v)
      96             : {
      97           0 :         struct vop_read_args *ap = v;
      98           0 :         struct vnode *vp = ap->a_vp;
      99           0 :         struct fnode *fp = VTOF(vp);
     100           0 :         struct ntnode *ip = FTONT(fp);
     101           0 :         struct uio *uio = ap->a_uio;
     102           0 :         struct ntfsmount *ntmp = ip->i_mp;
     103             :         u_int64_t toread;
     104             :         int error;
     105             : 
     106             :         DPRINTF("ntfs_read: ino: %u, off: %lld resid: %zu, segflg: %d\n",
     107             :             ip->i_number, uio->uio_offset, uio->uio_resid, uio->uio_segflg);
     108             : 
     109             :         DPRINTF("ntfs_read: filesize: %llu", fp->f_size);
     110             : 
     111             :         /* don't allow reading after end of file */
     112           0 :         if (uio->uio_offset > fp->f_size)
     113           0 :                 toread = 0;
     114             :         else
     115           0 :                 toread = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
     116             : 
     117             :         DPRINTF(", toread: %llu\n", toread);
     118             : 
     119           0 :         if (toread == 0)
     120           0 :                 return (0);
     121             : 
     122           0 :         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
     123           0 :                 fp->f_attrname, uio->uio_offset, toread, NULL, uio);
     124           0 :         if (error) {
     125           0 :                 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
     126           0 :                 return (error);
     127             :         }
     128             : 
     129           0 :         return (0);
     130           0 : }
     131             : 
     132             : int
     133           0 : ntfs_getattr(void *v)
     134             : {
     135           0 :         struct vop_getattr_args *ap = v;
     136           0 :         struct vnode *vp = ap->a_vp;
     137           0 :         struct fnode *fp = VTOF(vp);
     138           0 :         struct ntnode *ip = FTONT(fp);
     139           0 :         struct vattr *vap = ap->a_vap;
     140             : 
     141             :         DPRINTF("ntfs_getattr: %u, flags: %u\n", ip->i_number, ip->i_flag);
     142             : 
     143           0 :         vap->va_fsid = ip->i_dev;
     144           0 :         vap->va_fileid = ip->i_number;
     145           0 :         vap->va_mode = ip->i_mp->ntm_mode;
     146           0 :         vap->va_nlink = ip->i_nlink;
     147           0 :         vap->va_uid = ip->i_mp->ntm_uid;
     148           0 :         vap->va_gid = ip->i_mp->ntm_gid;
     149           0 :         vap->va_rdev = 0;                            /* XXX UNODEV ? */
     150           0 :         vap->va_size = fp->f_size;
     151           0 :         vap->va_bytes = fp->f_allocated;
     152           0 :         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
     153           0 :         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
     154           0 :         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
     155           0 :         vap->va_flags = ip->i_flag;
     156           0 :         vap->va_gen = 0;
     157           0 :         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
     158           0 :         vap->va_type = vp->v_type;
     159           0 :         vap->va_filerev = 0;
     160             : 
     161             :         /*
     162             :          * Ensure that a directory link count is always 1 so that things
     163             :          * like fts_read() do not try to be smart and end up skipping over
     164             :          * directories. Additionally, ip->i_nlink will not be initialised
     165             :          * until the ntnode has been loaded for the file.
     166             :          */
     167           0 :         if (vp->v_type == VDIR || ip->i_nlink < 1)
     168           0 :                 vap->va_nlink = 1;
     169             : 
     170           0 :         return (0);
     171             : }
     172             : 
     173             : 
     174             : /*
     175             :  * Last reference to an ntnode.  If necessary, write or delete it.
     176             :  */
     177             : int
     178           0 : ntfs_inactive(void *v)
     179             : {
     180           0 :         struct vop_inactive_args *ap = v;
     181           0 :         struct vnode *vp = ap->a_vp;
     182             : #ifdef NTFS_DEBUG
     183             :         struct ntnode *ip = VTONT(vp);
     184             : #endif
     185             : 
     186             :         DPRINTF("ntfs_inactive: vnode: %p, ntnode: %u\n", vp, ip->i_number);
     187             : 
     188             : #ifdef DIAGNOSTIC
     189           0 :         if (ntfs_prtactive && vp->v_usecount != 0)
     190           0 :                 vprint("ntfs_inactive: pushing active", vp);
     191             : #endif
     192             : 
     193           0 :         VOP_UNLOCK(vp);
     194             : 
     195             :         /* XXX since we don't support any filesystem changes
     196             :          * right now, nothing more needs to be done
     197             :          */
     198           0 :         return (0);
     199             : }
     200             : 
     201             : /*
     202             :  * Reclaim an fnode/ntnode so that it can be used for other purposes.
     203             :  */
     204             : int
     205           0 : ntfs_reclaim(void *v)
     206             : {
     207           0 :         struct vop_reclaim_args *ap = v;
     208           0 :         struct vnode *vp = ap->a_vp;
     209           0 :         struct fnode *fp = VTOF(vp);
     210           0 :         struct ntnode *ip = FTONT(fp);
     211           0 :         struct proc *p = ap->a_p;
     212             :         int error;
     213             : 
     214             :         DPRINTF("ntfs_reclaim: vnode: %p, ntnode: %u\n", vp, ip->i_number);
     215             : 
     216             : #ifdef DIAGNOSTIC
     217           0 :         if (ntfs_prtactive && vp->v_usecount != 0)
     218           0 :                 vprint("ntfs_reclaim: pushing active", vp);
     219             : #endif
     220             : 
     221           0 :         if ((error = ntfs_ntget(ip, p)) != 0)
     222           0 :                 return (error);
     223             :         
     224             :         /* Purge old data structures associated with the inode. */
     225           0 :         cache_purge(vp);
     226             : 
     227           0 :         ntfs_frele(fp);
     228           0 :         ntfs_ntput(ip, p);
     229             : 
     230           0 :         vp->v_data = NULL;
     231             : 
     232           0 :         return (0);
     233           0 : }
     234             : 
     235             : int
     236           0 : ntfs_print(void *v)
     237             : {
     238           0 :         struct vop_print_args *ap = v;
     239           0 :         struct ntnode *ip = VTONT(ap->a_vp);
     240             : 
     241           0 :         printf("tag VT_NTFS, ino %u, flag %#x, usecount %d, nlink %ld\n",
     242           0 :             ip->i_number, ip->i_flag, ip->i_usecount, ip->i_nlink);
     243             : 
     244           0 :         return (0);
     245             : }
     246             : 
     247             : /*
     248             :  * Calculate the logical to physical mapping if not done already,
     249             :  * then call the device strategy routine.
     250             :  */
     251             : int
     252           0 : ntfs_strategy(void *v)
     253             : {
     254           0 :         struct vop_strategy_args *ap = v;
     255           0 :         struct buf *bp = ap->a_bp;
     256           0 :         struct vnode *vp = bp->b_vp;
     257           0 :         struct fnode *fp = VTOF(vp);
     258           0 :         struct ntnode *ip = FTONT(fp);
     259           0 :         struct ntfsmount *ntmp = ip->i_mp;
     260             :         int error, s;
     261             : 
     262             :         DPRINTF("ntfs_strategy: blkno: %lld, lblkno: %lld\n",
     263             :             (long long)bp->b_blkno, (long long)bp->b_lblkno);
     264             : 
     265             :         DPRINTF("strategy: bcount: %ld flags: 0x%lx\n",
     266             :             bp->b_bcount, bp->b_flags);
     267             : 
     268           0 :         if (bp->b_flags & B_READ) {
     269             :                 u_int32_t toread;
     270             : 
     271           0 :                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
     272           0 :                         clrbuf(bp);
     273             :                         error = 0;
     274           0 :                 } else {
     275           0 :                         toread = MIN(bp->b_bcount,
     276             :                                  fp->f_size - ntfs_cntob(bp->b_blkno));
     277             :                         DPRINTF("ntfs_strategy: toread: %u, fsize: %llu\n",
     278             :                             toread, fp->f_size);
     279             : 
     280           0 :                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
     281           0 :                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
     282           0 :                                 toread, bp->b_data, NULL);
     283             : 
     284           0 :                         if (error) {
     285           0 :                                 printf("ntfs_strategy: ntfs_readattr failed\n");
     286           0 :                                 bp->b_error = error;
     287           0 :                                 bp->b_flags |= B_ERROR;
     288           0 :                         }
     289             : 
     290           0 :                         bzero(bp->b_data + toread, bp->b_bcount - toread);
     291             :                 }
     292           0 :         } else {
     293           0 :                 bp->b_error = error = EROFS;
     294           0 :                 bp->b_flags |= B_ERROR;
     295             :         }
     296           0 :         s = splbio();
     297           0 :         biodone(bp);
     298           0 :         splx(s);
     299           0 :         return (error);
     300             : }
     301             : 
     302             : int
     303           0 : ntfs_access(void *v)
     304             : {
     305           0 :         struct vop_access_args *ap = v;
     306           0 :         struct vnode *vp = ap->a_vp;
     307           0 :         struct ntnode *ip = VTONT(vp);
     308           0 :         struct ucred *cred = ap->a_cred;
     309           0 :         mode_t mask, mode = ap->a_mode;
     310             :         gid_t *gp;
     311             :         int i;
     312             : 
     313             :         DPRINTF("ntfs_access: %u\n", ip->i_number);
     314             : 
     315             :         /*
     316             :          * Disallow write attempts unless the file is a socket, fifo, or
     317             :          * a block or character device resident on the file system.
     318             :          */
     319           0 :         if (mode & VWRITE) {
     320           0 :                 switch ((int)vp->v_type) {
     321             :                 case VDIR:
     322             :                 case VLNK:
     323             :                 case VREG:
     324           0 :                         return (EROFS);
     325             :                 }
     326             :         }
     327             : 
     328             :         /* Otherwise, user id 0 always gets access. */
     329           0 :         if (cred->cr_uid == 0)
     330           0 :                 return (0);
     331             : 
     332             :         mask = 0;
     333             : 
     334             :         /* Otherwise, check the owner. */
     335           0 :         if (cred->cr_uid == ip->i_mp->ntm_uid) {
     336           0 :                 if (mode & VEXEC)
     337           0 :                         mask |= S_IXUSR;
     338           0 :                 if (mode & VREAD)
     339           0 :                         mask |= S_IRUSR;
     340           0 :                 if (mode & VWRITE)
     341           0 :                         mask |= S_IWUSR;
     342           0 :                 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
     343             :         }
     344             : 
     345             :         /* Otherwise, check the groups. */
     346           0 :         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
     347           0 :                 if (ip->i_mp->ntm_gid == *gp) {
     348           0 :                         if (mode & VEXEC)
     349           0 :                                 mask |= S_IXGRP;
     350           0 :                         if (mode & VREAD)
     351           0 :                                 mask |= S_IRGRP;
     352           0 :                         if (mode & VWRITE)
     353           0 :                                 mask |= S_IWGRP;
     354           0 :                         return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES);
     355             :                 }
     356             : 
     357             :         /* Otherwise, check everyone else. */
     358           0 :         if (mode & VEXEC)
     359           0 :                 mask |= S_IXOTH;
     360           0 :         if (mode & VREAD)
     361           0 :                 mask |= S_IROTH;
     362           0 :         if (mode & VWRITE)
     363           0 :                 mask |= S_IWOTH;
     364           0 :         return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
     365           0 : }
     366             : 
     367             : /*
     368             :  * Open called.
     369             :  *
     370             :  * Nothing to do.
     371             :  */
     372             : int
     373           0 : ntfs_open(void *v)
     374             : {
     375             : #if NTFS_DEBUG
     376             :         struct vop_open_args *ap = v;
     377             :         struct vnode *vp = ap->a_vp;
     378             :         struct ntnode *ip = VTONT(vp);
     379             : 
     380             :         printf("ntfs_open: %d\n",ip->i_number);
     381             : #endif
     382             : 
     383             :         /*
     384             :          * Files marked append-only must be opened for appending.
     385             :          */
     386             : 
     387           0 :         return (0);
     388             : }
     389             : 
     390             : /*
     391             :  * Close called.
     392             :  *
     393             :  * Update the times on the inode.
     394             :  */
     395             : int
     396           0 : ntfs_close(void *v)
     397             : {
     398             : #if NTFS_DEBUG
     399             :         struct vop_close_args *ap = v;
     400             :         struct vnode *vp = ap->a_vp;
     401             :         struct ntnode *ip = VTONT(vp);
     402             : 
     403             :         printf("ntfs_close: %d\n",ip->i_number);
     404             : #endif
     405             : 
     406           0 :         return (0);
     407             : }
     408             : 
     409             : int
     410           0 : ntfs_readdir(void *v)
     411             : {
     412           0 :         struct vop_readdir_args *ap = v;
     413           0 :         struct vnode *vp = ap->a_vp;
     414           0 :         struct fnode *fp = VTOF(vp);
     415           0 :         struct ntnode *ip = FTONT(fp);
     416           0 :         struct uio *uio = ap->a_uio;
     417           0 :         struct ntfsmount *ntmp = ip->i_mp;
     418             :         int i, error = 0;
     419             :         u_int32_t faked = 0, num;
     420           0 :         struct dirent cde;
     421             :         off_t off;
     422             : 
     423             :         DPRINTF("ntfs_readdir %u off: %lld resid: %zu\n", ip->i_number,
     424             :             uio->uio_offset, uio->uio_resid);
     425             : 
     426           0 :         off = uio->uio_offset;
     427           0 :         memset(&cde, 0, sizeof(cde));
     428             : 
     429             :         /* Simulate . in every dir except ROOT */
     430           0 :         if (ip->i_number != NTFS_ROOTINO && uio->uio_offset == 0) {
     431           0 :                 cde.d_fileno = ip->i_number;
     432           0 :                 cde.d_reclen = sizeof(struct dirent);
     433           0 :                 cde.d_type = DT_DIR;
     434           0 :                 cde.d_namlen = 1;
     435           0 :                 cde.d_off = sizeof(struct dirent);
     436           0 :                 cde.d_name[0] = '.';
     437           0 :                 cde.d_name[1] = '\0';
     438           0 :                 error = uiomove(&cde, sizeof(struct dirent), uio);
     439           0 :                 if (error)
     440             :                         goto out;
     441             :         }
     442             : 
     443             :         /* Simulate .. in every dir including ROOT */
     444           0 :         if (uio->uio_offset < 2 * sizeof(struct dirent)) {
     445           0 :                 cde.d_fileno = NTFS_ROOTINO;    /* XXX */
     446           0 :                 cde.d_reclen = sizeof(struct dirent);
     447           0 :                 cde.d_type = DT_DIR;
     448           0 :                 cde.d_namlen = 2;
     449           0 :                 cde.d_off = 2 * sizeof(struct dirent);
     450           0 :                 cde.d_name[0] = '.';
     451           0 :                 cde.d_name[1] = '.';
     452           0 :                 cde.d_name[2] = '\0';
     453           0 :                 error = uiomove(&cde, sizeof(struct dirent), uio);
     454           0 :                 if (error)
     455             :                         goto out;
     456             :         }
     457             : 
     458           0 :         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
     459           0 :         num = uio->uio_offset / sizeof(struct dirent) - faked;
     460             : 
     461           0 :         while (uio->uio_resid >= sizeof(struct dirent)) {
     462           0 :                 struct attr_indexentry *iep;
     463             :                 char *fname;
     464             :                 size_t remains;
     465             :                 int sz;
     466             : 
     467           0 :                 error = ntfs_ntreaddir(ntmp, fp, num, &iep, uio->uio_procp);
     468           0 :                 if (error)
     469           0 :                         goto out;
     470             : 
     471           0 :                 if (NULL == iep)
     472           0 :                         break;
     473             : 
     474           0 :                 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
     475           0 :                         iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
     476             :                 {
     477           0 :                         if(!ntfs_isnamepermitted(ntmp,iep))
     478             :                                 continue;
     479             : 
     480             :                         remains = sizeof(cde.d_name) - 1;
     481           0 :                         fname = cde.d_name;
     482           0 :                         for(i=0; i<iep->ie_fnamelen; i++) {
     483           0 :                                 sz = (*ntmp->ntm_wput)(fname, remains,
     484           0 :                                                 iep->ie_fname[i]);
     485           0 :                                 fname += sz;
     486           0 :                                 remains -= sz;
     487             :                         }
     488           0 :                         *fname = '\0';
     489             :                         DPRINTF("ntfs_readdir: elem: %u, fname:[%s] type: %u, "
     490             :                             "flag: %u, ",
     491             :                             num, cde.d_name, iep->ie_fnametype, iep->ie_flag);
     492           0 :                         cde.d_namlen = fname - (char *) cde.d_name;
     493           0 :                         cde.d_fileno = iep->ie_number;
     494           0 :                         cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
     495           0 :                         cde.d_reclen = sizeof(struct dirent);
     496           0 :                         cde.d_off = uio->uio_offset + sizeof(struct dirent);
     497             :                         DPRINTF("%s\n", cde.d_type == DT_DIR ? "dir" : "reg");
     498             : 
     499           0 :                         error = uiomove(&cde, sizeof(struct dirent), uio);
     500           0 :                         if (error)
     501           0 :                                 goto out;
     502           0 :                         num++;
     503           0 :                 }
     504           0 :         }
     505             : 
     506             :         DPRINTF("ntfs_readdir: %u entries (%lld bytes) read\n",
     507             :             num, uio->uio_offset - off);
     508             :         DPRINTF("ntfs_readdir: off: %lld resid: %zu\n",
     509             :             uio->uio_offset, uio->uio_resid);
     510             : 
     511             : /*
     512             :         if (ap->a_eofflag)
     513             :             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
     514             : */
     515             : out:
     516           0 :         if (fp->f_dirblbuf != NULL) {
     517           0 :                 free(fp->f_dirblbuf, M_NTFSDIR, 0);
     518           0 :                 fp->f_dirblbuf = NULL;
     519           0 :         }
     520           0 :         return (error);
     521           0 : }
     522             : 
     523             : int
     524           0 : ntfs_lookup(void *v)
     525             : {
     526           0 :         struct vop_lookup_args *ap = v;
     527           0 :         struct vnode *dvp = ap->a_dvp;
     528           0 :         struct ntnode *dip = VTONT(dvp);
     529           0 :         struct ntfsmount *ntmp = dip->i_mp;
     530           0 :         struct componentname *cnp = ap->a_cnp;
     531           0 :         struct ucred *cred = cnp->cn_cred;
     532             :         int error;
     533           0 :         int lockparent = cnp->cn_flags & LOCKPARENT;
     534           0 :         struct proc *p = cnp->cn_proc;
     535             : #if NTFS_DEBUG
     536             :         int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
     537             : #endif
     538             :         DPRINTF("ntfs_lookup: \"%.*s\" (%ld bytes) in %u, lp: %d, wp: %d \n",
     539             :             (unsigned int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
     540             :             dip->i_number, lockparent, wantparent);
     541             : 
     542           0 :         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
     543           0 :         if(error)
     544           0 :                 return (error);
     545             : 
     546           0 :         if ((cnp->cn_flags & ISLASTCN) &&
     547           0 :             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
     548           0 :                 return (EROFS);
     549             : 
     550             :         /*
     551             :          * We now have a segment name to search for, and a directory
     552             :          * to search.
     553             :          *
     554             :          * Before tediously performing a linear scan of the directory,
     555             :          * check the name cache to see if the directory/name pair
     556             :          * we are looking for is known already.
     557             :          */
     558           0 :         if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
     559           0 :                 return (error);
     560             : 
     561           0 :         if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
     562             :                 DPRINTF("ntfs_lookup: faking . directory in %u\n",
     563             :                     dip->i_number);
     564             : 
     565           0 :                 vref(dvp);
     566           0 :                 *ap->a_vpp = dvp;
     567             :                 error = 0;
     568           0 :         } else if (cnp->cn_flags & ISDOTDOT) {
     569           0 :                 struct ntvattr *vap;
     570             : 
     571             :                 DPRINTF("ntfs_lookup: faking .. directory in %u\n",
     572             :                     dip->i_number);
     573             : 
     574           0 :                 VOP_UNLOCK(dvp);
     575           0 :                 cnp->cn_flags |= PDIRUNLOCK;
     576             : 
     577           0 :                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
     578           0 :                 if(error)
     579           0 :                         return (error);
     580             : 
     581             :                 DPRINTF("ntfs_lookup: parentdir: %u\n",
     582             :                     vap->va_a_name->n_pnumber);
     583           0 :                 error = VFS_VGET(ntmp->ntm_mountp,
     584             :                                  vap->va_a_name->n_pnumber,ap->a_vpp); 
     585           0 :                 ntfs_ntvattrrele(vap);
     586           0 :                 if (error) {
     587           0 :                         if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
     588           0 :                                 cnp->cn_flags &= ~PDIRUNLOCK;
     589           0 :                         return (error);
     590             :                 }
     591             : 
     592           0 :                 if (lockparent && (cnp->cn_flags & ISLASTCN)) {
     593           0 :                         error = vn_lock(dvp, LK_EXCLUSIVE);
     594           0 :                         if (error) {
     595           0 :                                 vput( *(ap->a_vpp) );
     596           0 :                                 return (error);
     597             :                         }
     598           0 :                         cnp->cn_flags &= ~PDIRUNLOCK;
     599           0 :                 }
     600           0 :         } else {
     601           0 :                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp, p);
     602           0 :                 if (error) {
     603             :                         DPRINTF("ntfs_ntlookupfile: returned %d\n", error);
     604           0 :                         return (error);
     605             :                 }
     606             : 
     607             :                 DPRINTF("ntfs_lookup: found ino: %u\n",
     608             :                     VTONT(*ap->a_vpp)->i_number);
     609             : 
     610           0 :                 if(!lockparent || (cnp->cn_flags & ISLASTCN) == 0) {
     611           0 :                         VOP_UNLOCK(dvp);
     612           0 :                         cnp->cn_flags |= PDIRUNLOCK;
     613           0 :                 }
     614             :         }
     615             : 
     616           0 :         if (cnp->cn_flags & MAKEENTRY)
     617           0 :                 cache_enter(dvp, *ap->a_vpp, cnp);
     618             : 
     619           0 :         return (error);
     620           0 : }
     621             : 
     622             : /*
     623             :  * Flush the blocks of a file to disk.
     624             :  *
     625             :  * This function is worthless for vnodes that represent directories. Maybe we
     626             :  * could just do a sync if they try an fsync on a directory file.
     627             :  */
     628             : int
     629           0 : ntfs_fsync(void *v)
     630             : {
     631           0 :         return (0);
     632             : }
     633             : 
     634             : /*
     635             :  * Return POSIX pathconf information applicable to NTFS filesystem
     636             :  */
     637             : int
     638           0 : ntfs_pathconf(void *v)
     639             : {
     640           0 :         struct vop_pathconf_args *ap = v;
     641             :         int error = 0;
     642             : 
     643           0 :         switch (ap->a_name) {
     644             :         case _PC_LINK_MAX:
     645           0 :                 *ap->a_retval = 1;
     646           0 :                 break;
     647             :         case _PC_NAME_MAX:
     648           0 :                 *ap->a_retval = NTFS_MAXFILENAME;
     649           0 :                 break;
     650             :         case _PC_CHOWN_RESTRICTED:
     651           0 :                 *ap->a_retval = 1;
     652           0 :                 break;
     653             :         case _PC_NO_TRUNC:
     654           0 :                 *ap->a_retval = 0;
     655           0 :                 break;
     656             :         default:
     657             :                 error = EINVAL;
     658           0 :                 break;
     659             :         }
     660             : 
     661           0 :         return (error);
     662             : }
     663             : 
     664             : /*
     665             :  * Global vfs data structures
     666             :  */
     667             : struct vops ntfs_vops = {
     668             :         .vop_getattr    = ntfs_getattr,
     669             :         .vop_inactive   = ntfs_inactive,
     670             :         .vop_reclaim    = ntfs_reclaim,
     671             :         .vop_print      = ntfs_print,
     672             :         .vop_pathconf   = ntfs_pathconf,
     673             :         .vop_islocked   = vop_generic_islocked,
     674             :         .vop_unlock     = vop_generic_unlock,
     675             :         .vop_lock       = vop_generic_lock,
     676             :         .vop_lookup     = ntfs_lookup,
     677             :         .vop_access     = ntfs_access,
     678             :         .vop_close      = ntfs_close,
     679             :         .vop_open       = ntfs_open,
     680             :         .vop_readdir    = ntfs_readdir,
     681             :         .vop_fsync      = ntfs_fsync,
     682             :         .vop_bmap       = ntfs_bmap,
     683             :         .vop_strategy   = ntfs_strategy,
     684             :         .vop_bwrite     = vop_generic_bwrite,
     685             :         .vop_read       = ntfs_read,
     686             : };

Generated by: LCOV version 1.13