The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ntfs/ntfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: ntfs_vnops.c,v 1.47 2021/10/15 06:30:06 semarie 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 ntfs_bmap(void *v)
   81 {
   82         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         if (ap->a_vpp != NULL)
   86                 *ap->a_vpp = ap->a_vp;
   87         if (ap->a_bnp != NULL)
   88                 *ap->a_bnp = ap->a_bn;
   89         if (ap->a_runp != NULL)
   90                 *ap->a_runp = 0;
   91         return (0);
   92 }
   93 
   94 int
   95 ntfs_read(void *v)
   96 {
   97         struct vop_read_args *ap = v;
   98         struct vnode *vp = ap->a_vp;
   99         struct fnode *fp = VTOF(vp);
  100         struct ntnode *ip = FTONT(fp);
  101         struct uio *uio = ap->a_uio;
  102         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         if (uio->uio_offset > fp->f_size)
  113                 toread = 0;
  114         else
  115                 toread = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
  116 
  117         DPRINTF(", toread: %llu\n", toread);
  118 
  119         if (toread == 0)
  120                 return (0);
  121 
  122         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  123                 fp->f_attrname, uio->uio_offset, toread, NULL, uio);
  124         if (error) {
  125                 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
  126                 return (error);
  127         }
  128 
  129         return (0);
  130 }
  131 
  132 int
  133 ntfs_getattr(void *v)
  134 {
  135         struct vop_getattr_args *ap = v;
  136         struct vnode *vp = ap->a_vp;
  137         struct fnode *fp = VTOF(vp);
  138         struct ntnode *ip = FTONT(fp);
  139         struct vattr *vap = ap->a_vap;
  140 
  141         DPRINTF("ntfs_getattr: %u, flags: %u\n", ip->i_number, ip->i_flag);
  142 
  143         vap->va_fsid = ip->i_dev;
  144         vap->va_fileid = ip->i_number;
  145         vap->va_mode = ip->i_mp->ntm_mode;
  146         vap->va_nlink = ip->i_nlink;
  147         vap->va_uid = ip->i_mp->ntm_uid;
  148         vap->va_gid = ip->i_mp->ntm_gid;
  149         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  150         vap->va_size = fp->f_size;
  151         vap->va_bytes = fp->f_allocated;
  152         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
  153         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
  154         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
  155         vap->va_flags = ip->i_flag;
  156         vap->va_gen = 0;
  157         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
  158         vap->va_type = vp->v_type;
  159         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         if (vp->v_type == VDIR || ip->i_nlink < 1)
  168                 vap->va_nlink = 1;
  169 
  170         return (0);
  171 }
  172 
  173 
  174 /*
  175  * Last reference to an ntnode.  If necessary, write or delete it.
  176  */
  177 int
  178 ntfs_inactive(void *v)
  179 {
  180         struct vop_inactive_args *ap = v;
  181         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         if (ntfs_prtactive && vp->v_usecount != 0)
  190                 vprint("ntfs_inactive: pushing active", vp);
  191 #endif
  192 
  193         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         return (0);
  199 }
  200 
  201 /*
  202  * Reclaim an fnode/ntnode so that it can be used for other purposes.
  203  */
  204 int
  205 ntfs_reclaim(void *v)
  206 {
  207         struct vop_reclaim_args *ap = v;
  208         struct vnode *vp = ap->a_vp;
  209         struct fnode *fp = VTOF(vp);
  210         struct ntnode *ip = FTONT(fp);
  211         int error;
  212 
  213         DPRINTF("ntfs_reclaim: vnode: %p, ntnode: %u\n", vp, ip->i_number);
  214 
  215 #ifdef DIAGNOSTIC
  216         if (ntfs_prtactive && vp->v_usecount != 0)
  217                 vprint("ntfs_reclaim: pushing active", vp);
  218 #endif
  219 
  220         if ((error = ntfs_ntget(ip)) != 0)
  221                 return (error);
  222         
  223         /* Purge old data structures associated with the inode. */
  224         cache_purge(vp);
  225 
  226         ntfs_frele(fp);
  227         ntfs_ntput(ip);
  228 
  229         vp->v_data = NULL;
  230 
  231         return (0);
  232 }
  233 
  234 int
  235 ntfs_print(void *v)
  236 {
  237         struct vop_print_args *ap = v;
  238         struct ntnode *ip = VTONT(ap->a_vp);
  239 
  240         printf("tag VT_NTFS, ino %u, flag %#x, usecount %d, nlink %ld\n",
  241             ip->i_number, ip->i_flag, ip->i_usecount, ip->i_nlink);
  242 
  243         return (0);
  244 }
  245 
  246 /*
  247  * Calculate the logical to physical mapping if not done already,
  248  * then call the device strategy routine.
  249  */
  250 int
  251 ntfs_strategy(void *v)
  252 {
  253         struct vop_strategy_args *ap = v;
  254         struct buf *bp = ap->a_bp;
  255         struct vnode *vp = bp->b_vp;
  256         struct fnode *fp = VTOF(vp);
  257         struct ntnode *ip = FTONT(fp);
  258         struct ntfsmount *ntmp = ip->i_mp;
  259         int error, s;
  260 
  261         DPRINTF("ntfs_strategy: blkno: %lld, lblkno: %lld\n",
  262             (long long)bp->b_blkno, (long long)bp->b_lblkno);
  263 
  264         DPRINTF("strategy: bcount: %ld flags: 0x%lx\n",
  265             bp->b_bcount, bp->b_flags);
  266 
  267         if (bp->b_flags & B_READ) {
  268                 u_int32_t toread;
  269 
  270                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
  271                         clrbuf(bp);
  272                         error = 0;
  273                 } else {
  274                         toread = MIN(bp->b_bcount,
  275                                  fp->f_size - ntfs_cntob(bp->b_blkno));
  276                         DPRINTF("ntfs_strategy: toread: %u, fsize: %llu\n",
  277                             toread, fp->f_size);
  278 
  279                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  280                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
  281                                 toread, bp->b_data, NULL);
  282 
  283                         if (error) {
  284                                 printf("ntfs_strategy: ntfs_readattr failed\n");
  285                                 bp->b_error = error;
  286                                 bp->b_flags |= B_ERROR;
  287                         }
  288 
  289                         bzero(bp->b_data + toread, bp->b_bcount - toread);
  290                 }
  291         } else {
  292                 bp->b_error = error = EROFS;
  293                 bp->b_flags |= B_ERROR;
  294         }
  295         s = splbio();
  296         biodone(bp);
  297         splx(s);
  298         return (error);
  299 }
  300 
  301 int
  302 ntfs_access(void *v)
  303 {
  304         struct vop_access_args *ap = v;
  305         struct vnode *vp = ap->a_vp;
  306         struct ntnode *ip = VTONT(vp);
  307         struct ucred *cred = ap->a_cred;
  308         mode_t mask, mode = ap->a_mode;
  309         gid_t *gp;
  310         int i;
  311 
  312         DPRINTF("ntfs_access: %u\n", ip->i_number);
  313 
  314         /*
  315          * Disallow write attempts unless the file is a socket, fifo, or
  316          * a block or character device resident on the file system.
  317          */
  318         if (mode & VWRITE) {
  319                 switch ((int)vp->v_type) {
  320                 case VDIR:
  321                 case VLNK:
  322                 case VREG:
  323                         return (EROFS);
  324                 }
  325         }
  326 
  327         /* Otherwise, user id 0 always gets access. */
  328         if (cred->cr_uid == 0)
  329                 return (0);
  330 
  331         mask = 0;
  332 
  333         /* Otherwise, check the owner. */
  334         if (cred->cr_uid == ip->i_mp->ntm_uid) {
  335                 if (mode & VEXEC)
  336                         mask |= S_IXUSR;
  337                 if (mode & VREAD)
  338                         mask |= S_IRUSR;
  339                 if (mode & VWRITE)
  340                         mask |= S_IWUSR;
  341                 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
  342         }
  343 
  344         /* Otherwise, check the groups. */
  345         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
  346                 if (ip->i_mp->ntm_gid == *gp) {
  347                         if (mode & VEXEC)
  348                                 mask |= S_IXGRP;
  349                         if (mode & VREAD)
  350                                 mask |= S_IRGRP;
  351                         if (mode & VWRITE)
  352                                 mask |= S_IWGRP;
  353                         return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES);
  354                 }
  355 
  356         /* Otherwise, check everyone else. */
  357         if (mode & VEXEC)
  358                 mask |= S_IXOTH;
  359         if (mode & VREAD)
  360                 mask |= S_IROTH;
  361         if (mode & VWRITE)
  362                 mask |= S_IWOTH;
  363         return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
  364 }
  365 
  366 /*
  367  * Open called.
  368  *
  369  * Nothing to do.
  370  */
  371 int
  372 ntfs_open(void *v)
  373 {
  374 #if NTFS_DEBUG
  375         struct vop_open_args *ap = v;
  376         struct vnode *vp = ap->a_vp;
  377         struct ntnode *ip = VTONT(vp);
  378 
  379         printf("ntfs_open: %d\n",ip->i_number);
  380 #endif
  381 
  382         /*
  383          * Files marked append-only must be opened for appending.
  384          */
  385 
  386         return (0);
  387 }
  388 
  389 /*
  390  * Close called.
  391  *
  392  * Update the times on the inode.
  393  */
  394 int
  395 ntfs_close(void *v)
  396 {
  397 #if NTFS_DEBUG
  398         struct vop_close_args *ap = v;
  399         struct vnode *vp = ap->a_vp;
  400         struct ntnode *ip = VTONT(vp);
  401 
  402         printf("ntfs_close: %d\n",ip->i_number);
  403 #endif
  404 
  405         return (0);
  406 }
  407 
  408 int
  409 ntfs_readdir(void *v)
  410 {
  411         struct vop_readdir_args *ap = v;
  412         struct vnode *vp = ap->a_vp;
  413         struct fnode *fp = VTOF(vp);
  414         struct ntnode *ip = FTONT(fp);
  415         struct uio *uio = ap->a_uio;
  416         struct ntfsmount *ntmp = ip->i_mp;
  417         int i, error = 0;
  418         u_int32_t faked = 0, num;
  419         struct dirent cde;
  420         off_t off;
  421 
  422         DPRINTF("ntfs_readdir %u off: %lld resid: %zu\n", ip->i_number,
  423             uio->uio_offset, uio->uio_resid);
  424 
  425         off = uio->uio_offset;
  426         memset(&cde, 0, sizeof(cde));
  427 
  428         /* Simulate . in every dir except ROOT */
  429         if (ip->i_number != NTFS_ROOTINO && uio->uio_offset == 0) {
  430                 cde.d_fileno = ip->i_number;
  431                 cde.d_reclen = sizeof(struct dirent);
  432                 cde.d_type = DT_DIR;
  433                 cde.d_namlen = 1;
  434                 cde.d_off = sizeof(struct dirent);
  435                 cde.d_name[0] = '.';
  436                 cde.d_name[1] = '\0';
  437                 error = uiomove(&cde, sizeof(struct dirent), uio);
  438                 if (error)
  439                         goto out;
  440         }
  441 
  442         /* Simulate .. in every dir including ROOT */
  443         if (uio->uio_offset < 2 * sizeof(struct dirent)) {
  444                 cde.d_fileno = NTFS_ROOTINO;    /* XXX */
  445                 cde.d_reclen = sizeof(struct dirent);
  446                 cde.d_type = DT_DIR;
  447                 cde.d_namlen = 2;
  448                 cde.d_off = 2 * sizeof(struct dirent);
  449                 cde.d_name[0] = '.';
  450                 cde.d_name[1] = '.';
  451                 cde.d_name[2] = '\0';
  452                 error = uiomove(&cde, sizeof(struct dirent), uio);
  453                 if (error)
  454                         goto out;
  455         }
  456 
  457         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
  458         num = uio->uio_offset / sizeof(struct dirent) - faked;
  459 
  460         while (uio->uio_resid >= sizeof(struct dirent)) {
  461                 struct attr_indexentry *iep;
  462                 char *fname;
  463                 size_t remains;
  464                 int sz;
  465 
  466                 error = ntfs_ntreaddir(ntmp, fp, num, &iep, uio->uio_procp);
  467                 if (error)
  468                         goto out;
  469 
  470                 if (NULL == iep)
  471                         break;
  472 
  473                 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
  474                         iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
  475                 {
  476                         if(!ntfs_isnamepermitted(ntmp,iep))
  477                                 continue;
  478 
  479                         remains = sizeof(cde.d_name) - 1;
  480                         fname = cde.d_name;
  481                         for(i=0; i<iep->ie_fnamelen; i++) {
  482                                 sz = (*ntmp->ntm_wput)(fname, remains,
  483                                                 iep->ie_fname[i]);
  484                                 fname += sz;
  485                                 remains -= sz;
  486                         }
  487                         *fname = '\0';
  488                         DPRINTF("ntfs_readdir: elem: %u, fname:[%s] type: %u, "
  489                             "flag: %u, ",
  490                             num, cde.d_name, iep->ie_fnametype, iep->ie_flag);
  491                         cde.d_namlen = fname - (char *) cde.d_name;
  492                         cde.d_fileno = iep->ie_number;
  493                         cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
  494                         cde.d_reclen = sizeof(struct dirent);
  495                         cde.d_off = uio->uio_offset + sizeof(struct dirent);
  496                         DPRINTF("%s\n", cde.d_type == DT_DIR ? "dir" : "reg");
  497 
  498                         error = uiomove(&cde, sizeof(struct dirent), uio);
  499                         if (error)
  500                                 goto out;
  501                         num++;
  502                 }
  503         }
  504 
  505         DPRINTF("ntfs_readdir: %u entries (%lld bytes) read\n",
  506             num, uio->uio_offset - off);
  507         DPRINTF("ntfs_readdir: off: %lld resid: %zu\n",
  508             uio->uio_offset, uio->uio_resid);
  509 
  510 /*
  511         if (ap->a_eofflag)
  512             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
  513 */
  514 out:
  515         if (fp->f_dirblbuf != NULL) {
  516                 free(fp->f_dirblbuf, M_NTFSDIR, 0);
  517                 fp->f_dirblbuf = NULL;
  518         }
  519         return (error);
  520 }
  521 
  522 int
  523 ntfs_lookup(void *v)
  524 {
  525         struct vop_lookup_args *ap = v;
  526         struct vnode *dvp = ap->a_dvp;
  527         struct ntnode *dip = VTONT(dvp);
  528         struct ntfsmount *ntmp = dip->i_mp;
  529         struct componentname *cnp = ap->a_cnp;
  530         struct ucred *cred = cnp->cn_cred;
  531         int error;
  532         int lockparent = cnp->cn_flags & LOCKPARENT;
  533 #if NTFS_DEBUG
  534         int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
  535 #endif
  536         DPRINTF("ntfs_lookup: \"%.*s\" (%ld bytes) in %u, lp: %d, wp: %d \n",
  537             (unsigned int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
  538             dip->i_number, lockparent, wantparent);
  539 
  540         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
  541         if(error)
  542                 return (error);
  543 
  544         if ((cnp->cn_flags & ISLASTCN) &&
  545             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  546                 return (EROFS);
  547 
  548         /*
  549          * We now have a segment name to search for, and a directory
  550          * to search.
  551          *
  552          * Before tediously performing a linear scan of the directory,
  553          * check the name cache to see if the directory/name pair
  554          * we are looking for is known already.
  555          */
  556         if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
  557                 return (error);
  558 
  559         if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  560                 DPRINTF("ntfs_lookup: faking . directory in %u\n",
  561                     dip->i_number);
  562 
  563                 vref(dvp);
  564                 *ap->a_vpp = dvp;
  565                 error = 0;
  566         } else if (cnp->cn_flags & ISDOTDOT) {
  567                 struct ntvattr *vap;
  568 
  569                 DPRINTF("ntfs_lookup: faking .. directory in %u\n",
  570                     dip->i_number);
  571 
  572                 VOP_UNLOCK(dvp);
  573                 cnp->cn_flags |= PDIRUNLOCK;
  574 
  575                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
  576                 if(error)
  577                         return (error);
  578 
  579                 DPRINTF("ntfs_lookup: parentdir: %u\n",
  580                     vap->va_a_name->n_pnumber);
  581                 error = VFS_VGET(ntmp->ntm_mountp,
  582                                  vap->va_a_name->n_pnumber,ap->a_vpp); 
  583                 ntfs_ntvattrrele(vap);
  584                 if (error) {
  585                         if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
  586                                 cnp->cn_flags &= ~PDIRUNLOCK;
  587                         return (error);
  588                 }
  589 
  590                 if (lockparent && (cnp->cn_flags & ISLASTCN)) {
  591                         error = vn_lock(dvp, LK_EXCLUSIVE);
  592                         if (error) {
  593                                 vput( *(ap->a_vpp) );
  594                                 return (error);
  595                         }
  596                         cnp->cn_flags &= ~PDIRUNLOCK;
  597                 }
  598         } else {
  599                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
  600                 if (error) {
  601                         DPRINTF("ntfs_ntlookupfile: returned %d\n", error);
  602                         return (error);
  603                 }
  604 
  605                 DPRINTF("ntfs_lookup: found ino: %u\n",
  606                     VTONT(*ap->a_vpp)->i_number);
  607 
  608                 if(!lockparent || (cnp->cn_flags & ISLASTCN) == 0) {
  609                         VOP_UNLOCK(dvp);
  610                         cnp->cn_flags |= PDIRUNLOCK;
  611                 }
  612         }
  613 
  614         if (cnp->cn_flags & MAKEENTRY)
  615                 cache_enter(dvp, *ap->a_vpp, cnp);
  616 
  617         return (error);
  618 }
  619 
  620 /*
  621  * Flush the blocks of a file to disk.
  622  *
  623  * This function is worthless for vnodes that represent directories. Maybe we
  624  * could just do a sync if they try an fsync on a directory file.
  625  */
  626 int
  627 ntfs_fsync(void *v)
  628 {
  629         return (0);
  630 }
  631 
  632 /*
  633  * Return POSIX pathconf information applicable to NTFS filesystem
  634  */
  635 int
  636 ntfs_pathconf(void *v)
  637 {
  638         struct vop_pathconf_args *ap = v;
  639         int error = 0;
  640 
  641         switch (ap->a_name) {
  642         case _PC_LINK_MAX:
  643                 *ap->a_retval = 1;
  644                 break;
  645         case _PC_NAME_MAX:
  646                 *ap->a_retval = NTFS_MAXFILENAME;
  647                 break;
  648         case _PC_CHOWN_RESTRICTED:
  649                 *ap->a_retval = 1;
  650                 break;
  651         case _PC_NO_TRUNC:
  652                 *ap->a_retval = 0;
  653                 break;
  654         default:
  655                 error = EINVAL;
  656                 break;
  657         }
  658 
  659         return (error);
  660 }
  661 
  662 /*
  663  * Global vfs data structures
  664  */
  665 const struct vops ntfs_vops = {
  666         .vop_getattr    = ntfs_getattr,
  667         .vop_inactive   = ntfs_inactive,
  668         .vop_reclaim    = ntfs_reclaim,
  669         .vop_print      = ntfs_print,
  670         .vop_pathconf   = ntfs_pathconf,
  671         .vop_lock       = nullop,
  672         .vop_unlock     = nullop,
  673         .vop_islocked   = nullop,
  674         .vop_lookup     = ntfs_lookup,
  675         .vop_access     = ntfs_access,
  676         .vop_close      = ntfs_close,
  677         .vop_open       = ntfs_open,
  678         .vop_readdir    = ntfs_readdir,
  679         .vop_fsync      = ntfs_fsync,
  680         .vop_bmap       = ntfs_bmap,
  681         .vop_strategy   = ntfs_strategy,
  682         .vop_bwrite     = vop_generic_bwrite,
  683         .vop_read       = ntfs_read,
  684 };

Cache object: 56c42006c38228f1dbb24fed66838fa0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.