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/fs/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 /*      $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * John Heidemann of the UCLA Ficus project.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * $FreeBSD$
   35  *
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/time.h>
   42 #include <sys/types.h>
   43 #include <sys/stat.h>
   44 #include <sys/vnode.h>
   45 #include <sys/mount.h>
   46 #include <sys/namei.h>
   47 #include <sys/malloc.h>
   48 #include <sys/bio.h>
   49 #include <sys/buf.h>
   50 #include <sys/dirent.h>
   51 
   52 #include <vm/vm.h>
   53 #include <vm/vm_param.h>
   54 #include <vm/vm_page.h>
   55 #include <vm/vm_object.h>
   56 #include <vm/vm_pager.h>
   57 #include <vm/vnode_pager.h>
   58 #include <vm/vm_extern.h>
   59 
   60 #include <sys/sysctl.h>
   61 
   62 /*#define NTFS_DEBUG 1*/
   63 #include <fs/ntfs/ntfs.h>
   64 #include <fs/ntfs/ntfs_inode.h>
   65 #include <fs/ntfs/ntfs_subr.h>
   66 
   67 #include <sys/unistd.h> /* for pathconf(2) constants */
   68 
   69 static vop_read_t       ntfs_read;
   70 static vop_write_t      ntfs_write;
   71 static vop_getattr_t    ntfs_getattr;
   72 static vop_inactive_t   ntfs_inactive;
   73 static vop_reclaim_t    ntfs_reclaim;
   74 static vop_bmap_t       ntfs_bmap;
   75 static vop_strategy_t   ntfs_strategy;
   76 static vop_access_t     ntfs_access;
   77 static vop_open_t       ntfs_open;
   78 static vop_close_t      ntfs_close;
   79 static vop_readdir_t    ntfs_readdir;
   80 static vop_cachedlookup_t       ntfs_lookup;
   81 static vop_fsync_t      ntfs_fsync;
   82 static vop_pathconf_t   ntfs_pathconf;
   83 static vop_vptofh_t     ntfs_vptofh;
   84 
   85 /*
   86  * This is a noop, simply returning what one has been given.
   87  */
   88 int
   89 ntfs_bmap(ap)
   90         struct vop_bmap_args /* {
   91                 struct vnode *a_vp;
   92                 daddr_t  a_bn;
   93                 struct bufobj **a_bop;
   94                 daddr_t *a_bnp;
   95                 int *a_runp;
   96                 int *a_runb;
   97         } */ *ap;
   98 {
   99         struct vnode *vp = ap->a_vp;
  100 
  101         dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
  102         if (ap->a_bop != NULL)
  103                 *ap->a_bop = &vp->v_bufobj;
  104         if (ap->a_bnp != NULL)
  105                 *ap->a_bnp = ap->a_bn;
  106         if (ap->a_runp != NULL)
  107                 *ap->a_runp = 0;
  108         if (ap->a_runb != NULL)
  109                 *ap->a_runb = 0;
  110         return (0);
  111 }
  112 
  113 static int
  114 ntfs_read(ap)
  115         struct vop_read_args /* {
  116                 struct vnode *a_vp;
  117                 struct uio *a_uio;
  118                 int a_ioflag;
  119                 struct ucred *a_cred;
  120         } */ *ap;
  121 {
  122         register struct vnode *vp = ap->a_vp;
  123         register struct fnode *fp = VTOF(vp);
  124         register struct ntnode *ip = FTONT(fp);
  125         struct uio *uio = ap->a_uio;
  126         struct ntfsmount *ntmp = ip->i_mp;
  127         struct buf *bp;
  128         daddr_t cn;
  129         int resid, off, toread;
  130         int error;
  131 
  132         dprintf(("ntfs_read: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
  133 
  134         dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
  135 
  136         /* don't allow reading after end of file */
  137         if (uio->uio_offset > fp->f_size)
  138                 return (0);
  139 
  140         resid = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
  141 
  142         dprintf((", resid: %d\n", resid));
  143 
  144         error = 0;
  145         while (resid) {
  146                 cn = ntfs_btocn(uio->uio_offset);
  147                 off = ntfs_btocnoff(uio->uio_offset);
  148 
  149                 toread = MIN(off + resid, ntfs_cntob(1));
  150 
  151                 error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp);
  152                 if (error) {
  153                         brelse(bp);
  154                         break;
  155                 }
  156 
  157                 error = uiomove(bp->b_data + off, toread - off, uio);
  158                 if(error) {
  159                         brelse(bp);
  160                         break;
  161                 }
  162                 brelse(bp);
  163 
  164                 resid -= toread - off;
  165         }
  166 
  167         return (error);
  168 }
  169 
  170 static int
  171 ntfs_getattr(ap)
  172         struct vop_getattr_args /* {
  173                 struct vnode *a_vp;
  174                 struct vattr *a_vap;
  175                 struct ucred *a_cred;
  176                 struct thread *a_td;
  177         } */ *ap;
  178 {
  179         register struct vnode *vp = ap->a_vp;
  180         register struct fnode *fp = VTOF(vp);
  181         register struct ntnode *ip = FTONT(fp);
  182         register struct vattr *vap = ap->a_vap;
  183 
  184         dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
  185 
  186         vap->va_fsid = dev2udev(ip->i_dev);
  187         vap->va_fileid = ip->i_number;
  188         vap->va_mode = ip->i_mp->ntm_mode;
  189         vap->va_nlink = (ip->i_nlink || ip->i_flag & IN_LOADED ? ip->i_nlink : 1);
  190         vap->va_uid = ip->i_mp->ntm_uid;
  191         vap->va_gid = ip->i_mp->ntm_gid;
  192         vap->va_rdev = NODEV;
  193         vap->va_size = fp->f_size;
  194         vap->va_bytes = fp->f_allocated;
  195         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
  196         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
  197         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
  198         vap->va_flags = ip->i_flag;
  199         vap->va_gen = 0;
  200         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
  201         vap->va_type = vp->v_type;
  202         vap->va_filerev = 0;
  203         return (0);
  204 }
  205 
  206 /*
  207  * Last reference to an ntnode.  If necessary, write or delete it.
  208  */
  209 int
  210 ntfs_inactive(ap)
  211         struct vop_inactive_args /* {
  212                 struct vnode *a_vp;
  213         } */ *ap;
  214 {
  215 #ifdef NTFS_DEBUG
  216         register struct ntnode *ip = VTONT(ap->a_vp);
  217 #endif
  218 
  219         dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", ap->a_vp,
  220             ip->i_number));
  221 
  222         /* XXX since we don't support any filesystem changes
  223          * right now, nothing more needs to be done
  224          */
  225         return (0);
  226 }
  227 
  228 /*
  229  * Reclaim an fnode/ntnode so that it can be used for other purposes.
  230  */
  231 int
  232 ntfs_reclaim(ap)
  233         struct vop_reclaim_args /* {
  234                 struct vnode *a_vp;
  235         } */ *ap;
  236 {
  237         register struct vnode *vp = ap->a_vp;
  238         register struct fnode *fp = VTOF(vp);
  239         register struct ntnode *ip = FTONT(fp);
  240         int error;
  241 
  242         dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  243 
  244         /*
  245          * Destroy the vm object and flush associated pages.
  246          */
  247         vnode_destroy_vobject(vp);
  248 
  249         if ((error = ntfs_ntget(ip)) != 0)
  250                 return (error);
  251         
  252         /* Purge old data structures associated with the inode. */
  253         ntfs_frele(fp);
  254         ntfs_ntput(ip);
  255         vp->v_data = NULL;
  256 
  257         return (0);
  258 }
  259 
  260 /*
  261  * Calculate the logical to physical mapping if not done already,
  262  * then call the device strategy routine.
  263  */
  264 int
  265 ntfs_strategy(ap)
  266         struct vop_strategy_args /* {
  267                 struct buf *a_bp;
  268         } */ *ap;
  269 {
  270         register struct buf *bp = ap->a_bp;
  271         register struct vnode *vp = ap->a_vp;
  272         register struct fnode *fp = VTOF(vp);
  273         register struct ntnode *ip = FTONT(fp);
  274         struct ntfsmount *ntmp = ip->i_mp;
  275         int error;
  276 
  277         dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
  278                 (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
  279                 (u_int32_t)bp->b_lblkno));
  280 
  281         dprintf(("strategy: bcount: %d flags: 0x%x\n", 
  282                 (u_int32_t)bp->b_bcount,bp->b_flags));
  283 
  284         if (bp->b_iocmd == BIO_READ) {
  285                 u_int32_t toread;
  286 
  287                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
  288                         clrbuf(bp);
  289                         error = 0;
  290                 } else {
  291                         toread = MIN(bp->b_bcount,
  292                                  fp->f_size-ntfs_cntob(bp->b_blkno));
  293                         dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
  294                                 toread,(u_int32_t)fp->f_size));
  295 
  296                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  297                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
  298                                 toread, bp->b_data, NULL);
  299 
  300                         if (error) {
  301                                 printf("ntfs_strategy: ntfs_readattr failed\n");
  302                                 bp->b_error = error;
  303                                 bp->b_ioflags |= BIO_ERROR;
  304                         }
  305 
  306                         bzero(bp->b_data + toread, bp->b_bcount - toread);
  307                 }
  308         } else {
  309                 size_t tmp;
  310                 u_int32_t towrite;
  311 
  312                 if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
  313                         printf("ntfs_strategy: CAN'T EXTEND FILE\n");
  314                         bp->b_error = error = EFBIG;
  315                         bp->b_ioflags |= BIO_ERROR;
  316                 } else {
  317                         towrite = MIN(bp->b_bcount,
  318                                 fp->f_size-ntfs_cntob(bp->b_blkno));
  319                         dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
  320                                 towrite,(u_int32_t)fp->f_size));
  321 
  322                         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,  
  323                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
  324                                 bp->b_data, &tmp, NULL);
  325 
  326                         if (error) {
  327                                 printf("ntfs_strategy: ntfs_writeattr fail\n");
  328                                 bp->b_error = error;
  329                                 bp->b_ioflags |= BIO_ERROR;
  330                         }
  331                 }
  332         }
  333         bufdone(bp);
  334         return (0);
  335 }
  336 
  337 static int
  338 ntfs_write(ap)
  339         struct vop_write_args /* {
  340                 struct vnode *a_vp;
  341                 struct uio *a_uio;
  342                 int  a_ioflag;
  343                 struct ucred *a_cred;
  344         } */ *ap;
  345 {
  346         register struct vnode *vp = ap->a_vp;
  347         register struct fnode *fp = VTOF(vp);
  348         register struct ntnode *ip = FTONT(fp);
  349         struct uio *uio = ap->a_uio;
  350         struct ntfsmount *ntmp = ip->i_mp;
  351         u_int64_t towrite;
  352         size_t written;
  353         int error;
  354 
  355         dprintf(("ntfs_write: ino: %d, off: %d resid: %d, segflg: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
  356         dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size));
  357 
  358         if (uio->uio_resid + uio->uio_offset > fp->f_size) {
  359                 printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
  360                 return (EFBIG);
  361         }
  362 
  363         towrite = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
  364 
  365         dprintf((", towrite: %d\n",(u_int32_t)towrite));
  366 
  367         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
  368                 fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
  369 #ifdef NTFS_DEBUG
  370         if (error)
  371                 printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
  372 #endif
  373 
  374         return (error);
  375 }
  376 
  377 int
  378 ntfs_access(ap)
  379         struct vop_access_args /* {
  380                 struct vnode *a_vp;
  381                 accmode_t a_accmode;
  382                 struct ucred *a_cred;
  383                 struct thread *a_td;
  384         } */ *ap;
  385 {
  386         struct vnode *vp = ap->a_vp;
  387         struct ntnode *ip = VTONT(vp);
  388         accmode_t accmode = ap->a_accmode;
  389 
  390         dprintf(("ntfs_access: %d\n",ip->i_number));
  391 
  392         /*
  393          * Disallow write attempts on read-only filesystems;
  394          * unless the file is a socket, fifo, or a block or
  395          * character device resident on the filesystem.
  396          */
  397         if (accmode & VWRITE) {
  398                 switch ((int)vp->v_type) {
  399                 case VDIR:
  400                 case VLNK:
  401                 case VREG:
  402                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  403                                 return (EROFS);
  404                         break;
  405                 }
  406         }
  407 
  408         return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
  409             ip->i_mp->ntm_gid, ap->a_accmode, ap->a_cred, NULL));
  410 } 
  411 
  412 /*
  413  * Open called.
  414  *
  415  * Nothing to do.
  416  */
  417 /* ARGSUSED */
  418 static int
  419 ntfs_open(ap)
  420         struct vop_open_args /* {
  421                 struct vnode *a_vp;
  422                 int  a_mode;
  423                 struct ucred *a_cred;
  424                 struct thread *a_td;
  425         } */ *ap;
  426 {
  427 #ifdef NTFS_DEBUG
  428         register struct vnode *vp = ap->a_vp;
  429         register struct ntnode *ip = VTONT(vp);
  430 
  431         printf("ntfs_open: %d\n",ip->i_number);
  432 #endif
  433 
  434         vnode_create_vobject(ap->a_vp, VTOF(ap->a_vp)->f_size, ap->a_td);
  435 
  436         /*
  437          * Files marked append-only must be opened for appending.
  438          */
  439 
  440         return (0);
  441 }
  442 
  443 /*
  444  * Close called.
  445  *
  446  * Update the times on the inode.
  447  */
  448 /* ARGSUSED */
  449 static int
  450 ntfs_close(ap)
  451         struct vop_close_args /* {
  452                 struct vnode *a_vp;
  453                 int  a_fflag;
  454                 struct ucred *a_cred;
  455                 struct thread *a_td;
  456         } */ *ap;
  457 {
  458 #ifdef NTFS_DEBUG
  459         register struct vnode *vp = ap->a_vp;
  460         register struct ntnode *ip = VTONT(vp);
  461 
  462         printf("ntfs_close: %d\n",ip->i_number);
  463 #endif
  464 
  465         return (0);
  466 }
  467 
  468 int
  469 ntfs_readdir(ap)
  470         struct vop_readdir_args /* {
  471                 struct vnode *a_vp;
  472                 struct uio *a_uio;
  473                 struct ucred *a_cred;
  474                 int *a_ncookies;
  475                 u_int **cookies;
  476         } */ *ap;
  477 {
  478         register struct vnode *vp = ap->a_vp;
  479         register struct fnode *fp = VTOF(vp);
  480         register struct ntnode *ip = FTONT(fp);
  481         struct uio *uio = ap->a_uio;
  482         struct ntfsmount *ntmp = ip->i_mp;
  483         int i, j, error = 0;
  484         char *c, tmpbuf[5];
  485         u_int32_t faked = 0, num;
  486         int ncookies = 0;
  487         struct dirent cde;
  488         off_t off;
  489 
  490         dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
  491 
  492         off = uio->uio_offset;
  493 
  494         /* Simulate . in every dir except ROOT */
  495         if( ip->i_number != NTFS_ROOTINO ) {
  496                 struct dirent dot = { NTFS_ROOTINO,
  497                                 sizeof(struct dirent), DT_DIR, 1, "." };
  498 
  499                 if( uio->uio_offset < sizeof(struct dirent) ) {
  500                         dot.d_fileno = ip->i_number;
  501                         error = uiomove((char *)&dot,sizeof(struct dirent),uio);
  502                         if(error)
  503                                 return (error);
  504 
  505                         ncookies ++;
  506                 }
  507         }
  508 
  509         /* Simulate .. in every dir including ROOT */
  510         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
  511                 struct dirent dotdot = { NTFS_ROOTINO,
  512                                 sizeof(struct dirent), DT_DIR, 2, ".." };
  513 
  514                 error = uiomove((char *)&dotdot,sizeof(struct dirent),uio);
  515                 if(error)
  516                         return (error);
  517 
  518                 ncookies ++;
  519         }
  520 
  521         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
  522         num = uio->uio_offset / sizeof(struct dirent) - faked;
  523 
  524         while( uio->uio_resid >= sizeof(struct dirent) ) {
  525                 struct attr_indexentry *iep;
  526 
  527                 error = ntfs_ntreaddir(ntmp, fp, num, &iep);
  528 
  529                 if(error)
  530                         return (error);
  531 
  532                 if( NULL == iep )
  533                         break;
  534 
  535                 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
  536                         iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
  537                 {
  538                         if(!ntfs_isnamepermitted(ntmp,iep))
  539                                 continue;
  540 
  541                         for(i=0, j=0; i<iep->ie_fnamelen; i++) {
  542                                 c = NTFS_U28(iep->ie_fname[i]);
  543                                 while (*c != '\0')
  544                                         cde.d_name[j++] = *c++;
  545                         }
  546                         cde.d_name[j] = '\0';
  547                         dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
  548                                 num, cde.d_name, iep->ie_fnametype,
  549                                 iep->ie_flag));
  550                         cde.d_namlen = j;
  551                         cde.d_fileno = iep->ie_number;
  552                         cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
  553                         cde.d_reclen = sizeof(struct dirent);
  554                         dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
  555 
  556                         error = uiomove((char *)&cde, sizeof(struct dirent), uio);
  557                         if(error)
  558                                 return (error);
  559 
  560                         ncookies++;
  561                         num++;
  562                 }
  563         }
  564 
  565         dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
  566                 ncookies,(u_int)(uio->uio_offset - off)));
  567         dprintf(("ntfs_readdir: off: %d resid: %d\n",
  568                 (u_int32_t)uio->uio_offset,uio->uio_resid));
  569 
  570         if (!error && ap->a_ncookies != NULL) {
  571                 struct dirent* dpStart;
  572                 struct dirent* dp;
  573                 u_long *cookies;
  574                 u_long *cookiep;
  575 
  576                 ddprintf(("ntfs_readdir: %d cookies\n",ncookies));
  577                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
  578                         panic("ntfs_readdir: unexpected uio from NFS server");
  579                 dpStart = (struct dirent *)
  580                      ((caddr_t)uio->uio_iov->iov_base -
  581                          (uio->uio_offset - off));
  582                 cookies = malloc(ncookies * sizeof(u_long),
  583                        M_TEMP, M_WAITOK);
  584                 for (dp = dpStart, cookiep = cookies, i=0;
  585                      i < ncookies;
  586                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
  587                         off += dp->d_reclen;
  588                         *cookiep++ = (u_int) off;
  589                 }
  590                 *ap->a_ncookies = ncookies;
  591                 *ap->a_cookies = cookies;
  592         }
  593 /*
  594         if (ap->a_eofflag)
  595             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
  596 */
  597         return (error);
  598 }
  599 
  600 int
  601 ntfs_lookup(ap)
  602         struct vop_cachedlookup_args /* {
  603                 struct vnode *a_dvp;
  604                 struct vnode **a_vpp;
  605                 struct componentname *a_cnp;
  606         } */ *ap;
  607 {
  608         register struct vnode *dvp = ap->a_dvp;
  609         register struct ntnode *dip = VTONT(dvp);
  610         struct ntfsmount *ntmp = dip->i_mp;
  611         struct componentname *cnp = ap->a_cnp;
  612         struct ucred *cred = cnp->cn_cred;
  613         int error;
  614         dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d\n",
  615                 (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
  616                 dip->i_number));
  617 
  618         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
  619         if(error)
  620                 return (error);
  621 
  622         if ((cnp->cn_flags & ISLASTCN) &&
  623             (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
  624             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  625                 return (EROFS);
  626 
  627         if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  628                 dprintf(("ntfs_lookup: faking . directory in %d\n",
  629                         dip->i_number));
  630 
  631                 VREF(dvp);
  632                 *ap->a_vpp = dvp;
  633                 error = 0;
  634         } else if (cnp->cn_flags & ISDOTDOT) {
  635                 struct ntvattr *vap;
  636 
  637                 dprintf(("ntfs_lookup: faking .. directory in %d\n",
  638                          dip->i_number));
  639 
  640                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
  641                 if(error)
  642                         return (error);
  643 
  644                 VOP_UNLOCK(dvp,0);
  645                 dprintf(("ntfs_lookup: parentdir: %d\n",
  646                          vap->va_a_name->n_pnumber));
  647                 error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,
  648                                  LK_EXCLUSIVE, ap->a_vpp); 
  649                 ntfs_ntvattrrele(vap);
  650                 if (error) {
  651                         vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY);
  652                         return (error);
  653                 }
  654         } else {
  655                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
  656                 if (error) {
  657                         dprintf(("ntfs_ntlookupfile: returned %d\n", error));
  658                         return (error);
  659                 }
  660 
  661                 dprintf(("ntfs_lookup: found ino: %d\n", 
  662                         VTONT(*ap->a_vpp)->i_number));
  663         }
  664 
  665         if (cnp->cn_flags & MAKEENTRY)
  666                 cache_enter(dvp, *ap->a_vpp, cnp);
  667 
  668         return (error);
  669 }
  670 
  671 /*
  672  * Flush the blocks of a file to disk.
  673  *
  674  * This function is worthless for vnodes that represent directories. Maybe we
  675  * could just do a sync if they try an fsync on a directory file.
  676  */
  677 static int
  678 ntfs_fsync(ap)
  679         struct vop_fsync_args /* {
  680                 struct vnode *a_vp;
  681                 struct ucred *a_cred;
  682                 int a_waitfor;
  683                 struct thread *a_td;
  684         } */ *ap;
  685 {
  686         return (0);
  687 }
  688 
  689 /*
  690  * Return POSIX pathconf information applicable to NTFS filesystem
  691  */
  692 int
  693 ntfs_pathconf(ap)
  694         struct vop_pathconf_args *ap;
  695 {
  696 
  697         switch (ap->a_name) {
  698         case _PC_LINK_MAX:
  699                 *ap->a_retval = 1;
  700                 return (0);
  701         case _PC_NAME_MAX:
  702                 *ap->a_retval = NTFS_MAXFILENAME;
  703                 return (0);
  704         case _PC_PATH_MAX:
  705                 *ap->a_retval = PATH_MAX;
  706                 return (0);
  707         case _PC_CHOWN_RESTRICTED:
  708                 *ap->a_retval = 1;
  709                 return (0);
  710         case _PC_NO_TRUNC:
  711                 *ap->a_retval = 0;
  712                 return (0);
  713         default:
  714                 return (EINVAL);
  715         }
  716         /* NOTREACHED */
  717 }
  718 
  719 int
  720 ntfs_vptofh(ap)
  721         struct vop_vptofh_args /* {
  722                 struct vnode *a_vp;
  723                 struct fid *a_fhp;
  724         } */ *ap;
  725 {
  726         register struct ntnode *ntp;
  727         register struct ntfid *ntfhp;
  728 
  729         ddprintf(("ntfs_fhtovp(): %p\n", ap->a_vp));
  730 
  731         ntp = VTONT(ap->a_vp);
  732         ntfhp = (struct ntfid *)ap->a_fhp;
  733         ntfhp->ntfid_len = sizeof(struct ntfid);
  734         ntfhp->ntfid_ino = ntp->i_number;
  735         /* ntfhp->ntfid_gen = ntp->i_gen; */
  736         return (0);
  737 }
  738 
  739 /*
  740  * Global vfs data structures
  741  */
  742 struct vop_vector ntfs_vnodeops = {
  743         .vop_default =          &default_vnodeops,
  744 
  745         .vop_access =           ntfs_access,
  746         .vop_bmap =             ntfs_bmap,
  747         .vop_cachedlookup =     ntfs_lookup,
  748         .vop_close =            ntfs_close,
  749         .vop_fsync =            ntfs_fsync,
  750         .vop_getattr =          ntfs_getattr,
  751         .vop_inactive =         ntfs_inactive,
  752         .vop_lookup =           vfs_cache_lookup,
  753         .vop_open =             ntfs_open,
  754         .vop_pathconf =         ntfs_pathconf,
  755         .vop_read =             ntfs_read,
  756         .vop_readdir =          ntfs_readdir,
  757         .vop_reclaim =          ntfs_reclaim,
  758         .vop_strategy =         ntfs_strategy,
  759         .vop_write =            ntfs_write,
  760         .vop_vptofh =           ntfs_vptofh,
  761 };

Cache object: 5705784beb7e1eeb62e0c3461ca4d25a


[ 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.