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: releng/6.0/sys/fs/ntfs/ntfs_vnops.c 144230 2005-03-28 14:26:01Z jeff $
   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 
   84 int     ntfs_prtactive = 1;     /* 1 => print out reclaim of active vnodes */
   85 
   86 /*
   87  * This is a noop, simply returning what one has been given.
   88  */
   89 int
   90 ntfs_bmap(ap)
   91         struct vop_bmap_args /* {
   92                 struct vnode *a_vp;
   93                 daddr_t  a_bn;
   94                 struct bufobj **a_bop;
   95                 daddr_t *a_bnp;
   96                 int *a_runp;
   97                 int *a_runb;
   98         } */ *ap;
   99 {
  100         struct vnode *vp = ap->a_vp;
  101 
  102         dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
  103         if (ap->a_bop != NULL)
  104                 *ap->a_bop = &vp->v_bufobj;
  105         if (ap->a_bnp != NULL)
  106                 *ap->a_bnp = ap->a_bn;
  107         if (ap->a_runp != NULL)
  108                 *ap->a_runp = 0;
  109         if (ap->a_runb != NULL)
  110                 *ap->a_runb = 0;
  111         return (0);
  112 }
  113 
  114 static int
  115 ntfs_read(ap)
  116         struct vop_read_args /* {
  117                 struct vnode *a_vp;
  118                 struct uio *a_uio;
  119                 int a_ioflag;
  120                 struct ucred *a_cred;
  121         } */ *ap;
  122 {
  123         register struct vnode *vp = ap->a_vp;
  124         register struct fnode *fp = VTOF(vp);
  125         register struct ntnode *ip = FTONT(fp);
  126         struct uio *uio = ap->a_uio;
  127         struct ntfsmount *ntmp = ip->i_mp;
  128         struct buf *bp;
  129         daddr_t cn;
  130         int resid, off, toread;
  131         int error;
  132 
  133         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));
  134 
  135         dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
  136 
  137         /* don't allow reading after end of file */
  138         if (uio->uio_offset > fp->f_size)
  139                 return (0);
  140 
  141         resid = min(uio->uio_resid, fp->f_size - uio->uio_offset);
  142 
  143         dprintf((", resid: %d\n", resid));
  144 
  145         error = 0;
  146         while (resid) {
  147                 cn = ntfs_btocn(uio->uio_offset);
  148                 off = ntfs_btocnoff(uio->uio_offset);
  149 
  150                 toread = min(off + resid, ntfs_cntob(1));
  151 
  152                 error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp);
  153                 if (error) {
  154                         brelse(bp);
  155                         break;
  156                 }
  157 
  158                 error = uiomove(bp->b_data + off, toread - off, uio);
  159                 if(error) {
  160                         brelse(bp);
  161                         break;
  162                 }
  163                 brelse(bp);
  164 
  165                 resid -= toread - off;
  166         }
  167 
  168         return (error);
  169 }
  170 
  171 static int
  172 ntfs_getattr(ap)
  173         struct vop_getattr_args /* {
  174                 struct vnode *a_vp;
  175                 struct vattr *a_vap;
  176                 struct ucred *a_cred;
  177                 struct thread *a_td;
  178         } */ *ap;
  179 {
  180         register struct vnode *vp = ap->a_vp;
  181         register struct fnode *fp = VTOF(vp);
  182         register struct ntnode *ip = FTONT(fp);
  183         register struct vattr *vap = ap->a_vap;
  184 
  185         dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
  186 
  187         vap->va_fsid = dev2udev(ip->i_dev);
  188         vap->va_fileid = ip->i_number;
  189         vap->va_mode = ip->i_mp->ntm_mode;
  190         vap->va_nlink = ip->i_nlink;
  191         vap->va_uid = ip->i_mp->ntm_uid;
  192         vap->va_gid = ip->i_mp->ntm_gid;
  193         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  194         vap->va_size = fp->f_size;
  195         vap->va_bytes = fp->f_allocated;
  196         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
  197         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
  198         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
  199         vap->va_flags = ip->i_flag;
  200         vap->va_gen = 0;
  201         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
  202         vap->va_type = vp->v_type;
  203         vap->va_filerev = 0;
  204         return (0);
  205 }
  206 
  207 /*
  208  * Last reference to an ntnode.  If necessary, write or delete it.
  209  */
  210 int
  211 ntfs_inactive(ap)
  212         struct vop_inactive_args /* {
  213                 struct vnode *a_vp;
  214         } */ *ap;
  215 {
  216         register struct vnode *vp = ap->a_vp;
  217 #ifdef NTFS_DEBUG
  218         register struct ntnode *ip = VTONT(vp);
  219 #endif
  220 
  221         dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  222 
  223         if (ntfs_prtactive && vrefcnt(vp) != 0)
  224                 vprint("ntfs_inactive: pushing active", vp);
  225 
  226         /* XXX since we don't support any filesystem changes
  227          * right now, nothing more needs to be done
  228          */
  229         return (0);
  230 }
  231 
  232 /*
  233  * Reclaim an fnode/ntnode so that it can be used for other purposes.
  234  */
  235 int
  236 ntfs_reclaim(ap)
  237         struct vop_reclaim_args /* {
  238                 struct vnode *a_vp;
  239         } */ *ap;
  240 {
  241         register struct vnode *vp = ap->a_vp;
  242         register struct fnode *fp = VTOF(vp);
  243         register struct ntnode *ip = FTONT(fp);
  244         int error;
  245 
  246         dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  247 
  248         if (ntfs_prtactive && vrefcnt(vp) != 0)
  249                 vprint("ntfs_reclaim: pushing active", vp);
  250 
  251         if ((error = ntfs_ntget(ip)) != 0)
  252                 return (error);
  253         
  254         /* Purge old data structures associated with the inode. */
  255         ntfs_frele(fp);
  256         ntfs_ntput(ip);
  257         vp->v_data = NULL;
  258         vnode_destroy_vobject(vp);
  259 
  260         return (0);
  261 }
  262 
  263 /*
  264  * Calculate the logical to physical mapping if not done already,
  265  * then call the device strategy routine.
  266  */
  267 int
  268 ntfs_strategy(ap)
  269         struct vop_strategy_args /* {
  270                 struct buf *a_bp;
  271         } */ *ap;
  272 {
  273         register struct buf *bp = ap->a_bp;
  274         register struct vnode *vp = ap->a_vp;
  275         register struct fnode *fp = VTOF(vp);
  276         register struct ntnode *ip = FTONT(fp);
  277         struct ntfsmount *ntmp = ip->i_mp;
  278         int error;
  279 
  280         dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
  281                 (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
  282                 (u_int32_t)bp->b_lblkno));
  283 
  284         dprintf(("strategy: bcount: %d flags: 0x%lx\n", 
  285                 (u_int32_t)bp->b_bcount,bp->b_flags));
  286 
  287         if (bp->b_iocmd == BIO_READ) {
  288                 u_int32_t toread;
  289 
  290                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
  291                         clrbuf(bp);
  292                         error = 0;
  293                 } else {
  294                         toread = min(bp->b_bcount,
  295                                  fp->f_size-ntfs_cntob(bp->b_blkno));
  296                         dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
  297                                 toread,(u_int32_t)fp->f_size));
  298 
  299                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  300                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
  301                                 toread, bp->b_data, NULL);
  302 
  303                         if (error) {
  304                                 printf("ntfs_strategy: ntfs_readattr failed\n");
  305                                 bp->b_error = error;
  306                                 bp->b_ioflags |= BIO_ERROR;
  307                         }
  308 
  309                         bzero(bp->b_data + toread, bp->b_bcount - toread);
  310                 }
  311         } else {
  312                 size_t tmp;
  313                 u_int32_t towrite;
  314 
  315                 if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
  316                         printf("ntfs_strategy: CAN'T EXTEND FILE\n");
  317                         bp->b_error = error = EFBIG;
  318                         bp->b_ioflags |= BIO_ERROR;
  319                 } else {
  320                         towrite = min(bp->b_bcount,
  321                                 fp->f_size-ntfs_cntob(bp->b_blkno));
  322                         dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
  323                                 towrite,(u_int32_t)fp->f_size));
  324 
  325                         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,  
  326                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
  327                                 bp->b_data, &tmp, NULL);
  328 
  329                         if (error) {
  330                                 printf("ntfs_strategy: ntfs_writeattr fail\n");
  331                                 bp->b_error = error;
  332                                 bp->b_ioflags |= BIO_ERROR;
  333                         }
  334                 }
  335         }
  336         bufdone(bp);
  337         return (error);
  338 }
  339 
  340 static int
  341 ntfs_write(ap)
  342         struct vop_write_args /* {
  343                 struct vnode *a_vp;
  344                 struct uio *a_uio;
  345                 int  a_ioflag;
  346                 struct ucred *a_cred;
  347         } */ *ap;
  348 {
  349         register struct vnode *vp = ap->a_vp;
  350         register struct fnode *fp = VTOF(vp);
  351         register struct ntnode *ip = FTONT(fp);
  352         struct uio *uio = ap->a_uio;
  353         struct ntfsmount *ntmp = ip->i_mp;
  354         u_int64_t towrite;
  355         size_t written;
  356         int error;
  357 
  358         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));
  359         dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size));
  360 
  361         if (uio->uio_resid + uio->uio_offset > fp->f_size) {
  362                 printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
  363                 return (EFBIG);
  364         }
  365 
  366         towrite = min(uio->uio_resid, fp->f_size - uio->uio_offset);
  367 
  368         dprintf((", towrite: %d\n",(u_int32_t)towrite));
  369 
  370         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
  371                 fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
  372 #ifdef NTFS_DEBUG
  373         if (error)
  374                 printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
  375 #endif
  376 
  377         return (error);
  378 }
  379 
  380 int
  381 ntfs_access(ap)
  382         struct vop_access_args /* {
  383                 struct vnode *a_vp;
  384                 int  a_mode;
  385                 struct ucred *a_cred;
  386                 struct thread *a_td;
  387         } */ *ap;
  388 {
  389         struct vnode *vp = ap->a_vp;
  390         struct ntnode *ip = VTONT(vp);
  391         mode_t mode = ap->a_mode;
  392 #ifdef QUOTA
  393         int error;
  394 #endif
  395 
  396         dprintf(("ntfs_access: %d\n",ip->i_number));
  397 
  398         /*
  399          * Disallow write attempts on read-only filesystems;
  400          * unless the file is a socket, fifo, or a block or
  401          * character device resident on the filesystem.
  402          */
  403         if (mode & VWRITE) {
  404                 switch ((int)vp->v_type) {
  405                 case VDIR:
  406                 case VLNK:
  407                 case VREG:
  408                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  409                                 return (EROFS);
  410 #ifdef QUOTA
  411                         if (error = getinoquota(ip))
  412                                 return (error);
  413 #endif
  414                         break;
  415                 }
  416         }
  417 
  418         return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
  419             ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred, NULL));
  420 } 
  421 
  422 /*
  423  * Open called.
  424  *
  425  * Nothing to do.
  426  */
  427 /* ARGSUSED */
  428 static int
  429 ntfs_open(ap)
  430         struct vop_open_args /* {
  431                 struct vnode *a_vp;
  432                 int  a_mode;
  433                 struct ucred *a_cred;
  434                 struct thread *a_td;
  435         } */ *ap;
  436 {
  437 #if NTFS_DEBUG
  438         register struct vnode *vp = ap->a_vp;
  439         register struct ntnode *ip = VTONT(vp);
  440 
  441         printf("ntfs_open: %d\n",ip->i_number);
  442 #endif
  443 
  444         vnode_create_vobject(ap->a_vp, VTOF(ap->a_vp)->f_size, ap->a_td);
  445 
  446         /*
  447          * Files marked append-only must be opened for appending.
  448          */
  449 
  450         return (0);
  451 }
  452 
  453 /*
  454  * Close called.
  455  *
  456  * Update the times on the inode.
  457  */
  458 /* ARGSUSED */
  459 static int
  460 ntfs_close(ap)
  461         struct vop_close_args /* {
  462                 struct vnode *a_vp;
  463                 int  a_fflag;
  464                 struct ucred *a_cred;
  465                 struct thread *a_td;
  466         } */ *ap;
  467 {
  468 #if NTFS_DEBUG
  469         register struct vnode *vp = ap->a_vp;
  470         register struct ntnode *ip = VTONT(vp);
  471 
  472         printf("ntfs_close: %d\n",ip->i_number);
  473 #endif
  474 
  475         return (0);
  476 }
  477 
  478 int
  479 ntfs_readdir(ap)
  480         struct vop_readdir_args /* {
  481                 struct vnode *a_vp;
  482                 struct uio *a_uio;
  483                 struct ucred *a_cred;
  484                 int *a_ncookies;
  485                 u_int **cookies;
  486         } */ *ap;
  487 {
  488         register struct vnode *vp = ap->a_vp;
  489         register struct fnode *fp = VTOF(vp);
  490         register struct ntnode *ip = FTONT(fp);
  491         struct uio *uio = ap->a_uio;
  492         struct ntfsmount *ntmp = ip->i_mp;
  493         int i, j, error = 0;
  494         wchar c;
  495         u_int32_t faked = 0, num;
  496         int ncookies = 0;
  497         struct dirent cde;
  498         off_t off;
  499 
  500         dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
  501 
  502         off = uio->uio_offset;
  503 
  504         /* Simulate . in every dir except ROOT */
  505         if( ip->i_number != NTFS_ROOTINO ) {
  506                 struct dirent dot = { NTFS_ROOTINO,
  507                                 sizeof(struct dirent), DT_DIR, 1, "." };
  508 
  509                 if( uio->uio_offset < sizeof(struct dirent) ) {
  510                         dot.d_fileno = ip->i_number;
  511                         error = uiomove((char *)&dot,sizeof(struct dirent),uio);
  512                         if(error)
  513                                 return (error);
  514 
  515                         ncookies ++;
  516                 }
  517         }
  518 
  519         /* Simulate .. in every dir including ROOT */
  520         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
  521                 struct dirent dotdot = { NTFS_ROOTINO,
  522                                 sizeof(struct dirent), DT_DIR, 2, ".." };
  523 
  524                 error = uiomove((char *)&dotdot,sizeof(struct dirent),uio);
  525                 if(error)
  526                         return (error);
  527 
  528                 ncookies ++;
  529         }
  530 
  531         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
  532         num = uio->uio_offset / sizeof(struct dirent) - faked;
  533 
  534         while( uio->uio_resid >= sizeof(struct dirent) ) {
  535                 struct attr_indexentry *iep;
  536 
  537                 error = ntfs_ntreaddir(ntmp, fp, num, &iep);
  538 
  539                 if(error)
  540                         return (error);
  541 
  542                 if( NULL == iep )
  543                         break;
  544 
  545                 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
  546                         iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
  547                 {
  548                         if(!ntfs_isnamepermitted(ntmp,iep))
  549                                 continue;
  550 
  551                         for(i=0, j=0; i<iep->ie_fnamelen; i++, j++) {
  552                                 c = NTFS_U28(iep->ie_fname[i]);
  553                                 if (c&0xFF00)
  554                                         cde.d_name[j++] = (char)(c>>8);
  555                                 cde.d_name[j] = (char)c&0xFF;
  556                         }
  557                         cde.d_name[j] = '\0';
  558                         dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
  559                                 num, cde.d_name, iep->ie_fnametype,
  560                                 iep->ie_flag));
  561                         cde.d_namlen = j;
  562                         cde.d_fileno = iep->ie_number;
  563                         cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
  564                         cde.d_reclen = sizeof(struct dirent);
  565                         dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
  566 
  567                         error = uiomove((char *)&cde, sizeof(struct dirent), uio);
  568                         if(error)
  569                                 return (error);
  570 
  571                         ncookies++;
  572                         num++;
  573                 }
  574         }
  575 
  576         dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
  577                 ncookies,(u_int)(uio->uio_offset - off)));
  578         dprintf(("ntfs_readdir: off: %d resid: %d\n",
  579                 (u_int32_t)uio->uio_offset,uio->uio_resid));
  580 
  581         if (!error && ap->a_ncookies != NULL) {
  582                 struct dirent* dpStart;
  583                 struct dirent* dp;
  584                 u_long *cookies;
  585                 u_long *cookiep;
  586 
  587                 ddprintf(("ntfs_readdir: %d cookies\n",ncookies));
  588                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
  589                         panic("ntfs_readdir: unexpected uio from NFS server");
  590                 dpStart = (struct dirent *)
  591                      ((caddr_t)uio->uio_iov->iov_base -
  592                          (uio->uio_offset - off));
  593                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
  594                        M_TEMP, M_WAITOK);
  595                 for (dp = dpStart, cookiep = cookies, i=0;
  596                      i < ncookies;
  597                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
  598                         off += dp->d_reclen;
  599                         *cookiep++ = (u_int) off;
  600                 }
  601                 *ap->a_ncookies = ncookies;
  602                 *ap->a_cookies = cookies;
  603         }
  604 /*
  605         if (ap->a_eofflag)
  606             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
  607 */
  608         return (error);
  609 }
  610 
  611 int
  612 ntfs_lookup(ap)
  613         struct vop_cachedlookup_args /* {
  614                 struct vnode *a_dvp;
  615                 struct vnode **a_vpp;
  616                 struct componentname *a_cnp;
  617         } */ *ap;
  618 {
  619         register struct vnode *dvp = ap->a_dvp;
  620         register struct ntnode *dip = VTONT(dvp);
  621         struct ntfsmount *ntmp = dip->i_mp;
  622         struct componentname *cnp = ap->a_cnp;
  623         struct ucred *cred = cnp->cn_cred;
  624         int error;
  625         dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d\n",
  626                 (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
  627                 dip->i_number));
  628 
  629         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
  630         if(error)
  631                 return (error);
  632 
  633         if ((cnp->cn_flags & ISLASTCN) &&
  634             (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
  635             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  636                 return (EROFS);
  637 
  638         if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  639                 dprintf(("ntfs_lookup: faking . directory in %d\n",
  640                         dip->i_number));
  641 
  642                 VREF(dvp);
  643                 *ap->a_vpp = dvp;
  644                 error = 0;
  645         } else if (cnp->cn_flags & ISDOTDOT) {
  646                 struct ntvattr *vap;
  647 
  648                 dprintf(("ntfs_lookup: faking .. directory in %d\n",
  649                          dip->i_number));
  650 
  651                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
  652                 if(error)
  653                         return (error);
  654 
  655                 VOP_UNLOCK(dvp,0,cnp->cn_thread);
  656                 dprintf(("ntfs_lookup: parentdir: %d\n",
  657                          vap->va_a_name->n_pnumber));
  658                 error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,
  659                                  LK_EXCLUSIVE, ap->a_vpp); 
  660                 ntfs_ntvattrrele(vap);
  661                 if (error) {
  662                         vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY,cnp->cn_thread);
  663                         return (error);
  664                 }
  665         } else {
  666                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
  667                 if (error) {
  668                         dprintf(("ntfs_ntlookupfile: returned %d\n", error));
  669                         return (error);
  670                 }
  671 
  672                 dprintf(("ntfs_lookup: found ino: %d\n", 
  673                         VTONT(*ap->a_vpp)->i_number));
  674         }
  675 
  676         if (cnp->cn_flags & MAKEENTRY)
  677                 cache_enter(dvp, *ap->a_vpp, cnp);
  678 
  679         return (error);
  680 }
  681 
  682 /*
  683  * Flush the blocks of a file to disk.
  684  *
  685  * This function is worthless for vnodes that represent directories. Maybe we
  686  * could just do a sync if they try an fsync on a directory file.
  687  */
  688 static int
  689 ntfs_fsync(ap)
  690         struct vop_fsync_args /* {
  691                 struct vnode *a_vp;
  692                 struct ucred *a_cred;
  693                 int a_waitfor;
  694                 struct thread *a_td;
  695         } */ *ap;
  696 {
  697         return (0);
  698 }
  699 
  700 /*
  701  * Return POSIX pathconf information applicable to NTFS filesystem
  702  */
  703 int
  704 ntfs_pathconf(ap)
  705         struct vop_pathconf_args *ap;
  706 {
  707 
  708         switch (ap->a_name) {
  709         case _PC_LINK_MAX:
  710                 *ap->a_retval = 1;
  711                 return (0);
  712         case _PC_NAME_MAX:
  713                 *ap->a_retval = NTFS_MAXFILENAME;
  714                 return (0);
  715         case _PC_PATH_MAX:
  716                 *ap->a_retval = PATH_MAX;
  717                 return (0);
  718         case _PC_CHOWN_RESTRICTED:
  719                 *ap->a_retval = 1;
  720                 return (0);
  721         case _PC_NO_TRUNC:
  722                 *ap->a_retval = 0;
  723                 return (0);
  724         default:
  725                 return (EINVAL);
  726         }
  727         /* NOTREACHED */
  728 }
  729 
  730 /*
  731  * Global vfs data structures
  732  */
  733 struct vop_vector ntfs_vnodeops = {
  734         .vop_default =          &default_vnodeops,
  735 
  736         .vop_access =           ntfs_access,
  737         .vop_bmap =             ntfs_bmap,
  738         .vop_cachedlookup =     ntfs_lookup,
  739         .vop_close =            ntfs_close,
  740         .vop_fsync =            ntfs_fsync,
  741         .vop_getattr =          ntfs_getattr,
  742         .vop_inactive =         ntfs_inactive,
  743         .vop_lookup =           vfs_cache_lookup,
  744         .vop_open =             ntfs_open,
  745         .vop_pathconf =         ntfs_pathconf,
  746         .vop_read =             ntfs_read,
  747         .vop_readdir =          ntfs_readdir,
  748         .vop_reclaim =          ntfs_reclaim,
  749         .vop_strategy =         ntfs_strategy,
  750         .vop_write =            ntfs_write,
  751 };

Cache object: 1ab36aed13d78a4030f88a76d20d0ee1


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