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.18 2004/02/29 11:08:55 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  * 3. 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  *      Id: ntfs_vnops.c,v 1.5 1999/05/12 09:43:06 semenu Exp
   35  *
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.18 2004/02/29 11:08:55 jdolecek Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/time.h>
   45 #include <sys/stat.h>
   46 #include <sys/vnode.h>
   47 #include <sys/mount.h>
   48 #include <sys/namei.h>
   49 #include <sys/malloc.h>
   50 #include <sys/buf.h>
   51 #include <sys/dirent.h>
   52 
   53 #if !defined(__NetBSD__)
   54 #include <vm/vm.h>
   55 #endif
   56 
   57 #if defined(__FreeBSD__)
   58 #include <vm/vnode_pager.h>
   59 #endif
   60 
   61 #include <sys/sysctl.h>
   62 
   63 
   64 /*#define NTFS_DEBUG 1*/
   65 #include <fs/ntfs/ntfs.h>
   66 #include <fs/ntfs/ntfs_inode.h>
   67 #include <fs/ntfs/ntfs_subr.h>
   68 #include <miscfs/specfs/specdev.h>
   69 #include <miscfs/genfs/genfs.h>
   70 
   71 #include <sys/unistd.h> /* for pathconf(2) constants */
   72 
   73 static int      ntfs_bypass __P((struct vop_generic_args *ap));
   74 static int      ntfs_read __P((struct vop_read_args *));
   75 static int      ntfs_write __P((struct vop_write_args *ap));
   76 static int      ntfs_getattr __P((struct vop_getattr_args *ap));
   77 static int      ntfs_inactive __P((struct vop_inactive_args *ap));
   78 static int      ntfs_print __P((struct vop_print_args *ap));
   79 static int      ntfs_reclaim __P((struct vop_reclaim_args *ap));
   80 static int      ntfs_strategy __P((struct vop_strategy_args *ap));
   81 static int      ntfs_access __P((struct vop_access_args *ap));
   82 static int      ntfs_open __P((struct vop_open_args *ap));
   83 static int      ntfs_close __P((struct vop_close_args *ap));
   84 static int      ntfs_readdir __P((struct vop_readdir_args *ap));
   85 static int      ntfs_lookup __P((struct vop_lookup_args *ap));
   86 static int      ntfs_bmap __P((struct vop_bmap_args *ap));
   87 #if defined(__FreeBSD__)
   88 static int      ntfs_getpages __P((struct vop_getpages_args *ap));
   89 static int      ntfs_putpages __P((struct vop_putpages_args *));
   90 static int      ntfs_fsync __P((struct vop_fsync_args *ap));
   91 #endif
   92 static int      ntfs_pathconf __P((void *));
   93 
   94 extern int prtactive;
   95 
   96 #if defined(__FreeBSD__)
   97 int
   98 ntfs_getpages(ap)
   99         struct vop_getpages_args *ap;
  100 {
  101         return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
  102                 ap->a_reqpage);
  103 }
  104 
  105 int
  106 ntfs_putpages(ap)
  107         struct vop_putpages_args *ap;
  108 {
  109         return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
  110                 ap->a_sync, ap->a_rtvals);
  111 }
  112 #endif
  113 
  114 /*
  115  * This is a noop, simply returning what one has been given.
  116  */
  117 int
  118 ntfs_bmap(ap)
  119         struct vop_bmap_args /* {
  120                 struct vnode *a_vp;
  121                 daddr_t  a_bn;
  122                 struct vnode **a_vpp;
  123                 daddr_t *a_bnp;
  124                 int *a_runp;
  125                 int *a_runb;
  126         } */ *ap;
  127 {
  128         dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
  129         if (ap->a_vpp != NULL)
  130                 *ap->a_vpp = ap->a_vp;
  131         if (ap->a_bnp != NULL)
  132                 *ap->a_bnp = ap->a_bn;
  133         if (ap->a_runp != NULL)
  134                 *ap->a_runp = 0;
  135 #if !defined(__NetBSD__)
  136         if (ap->a_runb != NULL)
  137                 *ap->a_runb = 0;
  138 #endif
  139         return (0);
  140 }
  141 
  142 static int
  143 ntfs_read(ap)
  144         struct vop_read_args /* {
  145                 struct vnode *a_vp;
  146                 struct uio *a_uio;
  147                 int a_ioflag;
  148                 struct ucred *a_cred;
  149         } */ *ap;
  150 {
  151         struct vnode *vp = ap->a_vp;
  152         struct fnode *fp = VTOF(vp);
  153         struct ntnode *ip = FTONT(fp);
  154         struct uio *uio = ap->a_uio;
  155         struct ntfsmount *ntmp = ip->i_mp;
  156         u_int64_t toread;
  157         int error;
  158 
  159         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));
  160 
  161         dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
  162 
  163         /* don't allow reading after end of file */
  164         if (uio->uio_offset > fp->f_size)
  165                 toread = 0;
  166         else
  167                 toread = min( uio->uio_resid, fp->f_size - uio->uio_offset );
  168 
  169         dprintf((", toread: %d\n",(u_int32_t)toread));
  170 
  171         if (toread == 0)
  172                 return (0);
  173 
  174         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  175                 fp->f_attrname, uio->uio_offset, toread, NULL, uio);
  176         if (error) {
  177                 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
  178                 return (error);
  179         }
  180 
  181         return (0);
  182 }
  183 
  184 static int
  185 ntfs_bypass(ap)
  186         struct vop_generic_args /* {
  187                 struct vnodeop_desc *a_desc;
  188                 <other random data follows, presumably>
  189         } */ *ap;
  190 {
  191         int error = ENOTTY;
  192         dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name));
  193         return (error);
  194 }
  195 
  196 
  197 static int
  198 ntfs_getattr(ap)
  199         struct vop_getattr_args /* {
  200                 struct vnode *a_vp;
  201                 struct vattr *a_vap;
  202                 struct ucred *a_cred;
  203                 struct proc *a_p;
  204         } */ *ap;
  205 {
  206         struct vnode *vp = ap->a_vp;
  207         struct fnode *fp = VTOF(vp);
  208         struct ntnode *ip = FTONT(fp);
  209         struct vattr *vap = ap->a_vap;
  210 
  211         dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
  212 
  213 #if defined(__FreeBSD__)
  214         vap->va_fsid = dev2udev(ip->i_dev);
  215 #else /* NetBSD */
  216         vap->va_fsid = ip->i_dev;
  217 #endif
  218         vap->va_fileid = ip->i_number;
  219         vap->va_mode = ip->i_mp->ntm_mode;
  220         vap->va_nlink = ip->i_nlink;
  221         vap->va_uid = ip->i_mp->ntm_uid;
  222         vap->va_gid = ip->i_mp->ntm_gid;
  223         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  224         vap->va_size = fp->f_size;
  225         vap->va_bytes = fp->f_allocated;
  226         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
  227         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
  228         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
  229         vap->va_flags = ip->i_flag;
  230         vap->va_gen = 0;
  231         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
  232         vap->va_type = vp->v_type;
  233         vap->va_filerev = 0;
  234         return (0);
  235 }
  236 
  237 
  238 /*
  239  * Last reference to an ntnode.  If necessary, write or delete it.
  240  */
  241 int
  242 ntfs_inactive(ap)
  243         struct vop_inactive_args /* {
  244                 struct vnode *a_vp;
  245         } */ *ap;
  246 {
  247         struct vnode *vp = ap->a_vp;
  248 #ifdef NTFS_DEBUG
  249         struct ntnode *ip = VTONT(vp);
  250 #endif
  251 
  252         dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  253 
  254         if (prtactive && vp->v_usecount != 0)
  255                 vprint("ntfs_inactive: pushing active", vp);
  256 
  257         VOP_UNLOCK(vp, 0);
  258 
  259         /* XXX since we don't support any filesystem changes
  260          * right now, nothing more needs to be done
  261          */
  262         return (0);
  263 }
  264 
  265 /*
  266  * Reclaim an fnode/ntnode so that it can be used for other purposes.
  267  */
  268 int
  269 ntfs_reclaim(ap)
  270         struct vop_reclaim_args /* {
  271                 struct vnode *a_vp;
  272         } */ *ap;
  273 {
  274         struct vnode *vp = ap->a_vp;
  275         struct fnode *fp = VTOF(vp);
  276         struct ntnode *ip = FTONT(fp);
  277         int error;
  278 
  279         dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  280 
  281         if (prtactive && vp->v_usecount != 0)
  282                 vprint("ntfs_reclaim: pushing active", vp);
  283 
  284         if ((error = ntfs_ntget(ip)) != 0)
  285                 return (error);
  286         
  287         /* Purge old data structures associated with the inode. */
  288         cache_purge(vp);
  289         if (ip->i_devvp) {
  290                 vrele(ip->i_devvp);
  291                 ip->i_devvp = NULL;
  292         }
  293 
  294         ntfs_frele(fp);
  295         ntfs_ntput(ip);
  296         vp->v_data = NULL;
  297 
  298         return (0);
  299 }
  300 
  301 static int
  302 ntfs_print(ap)
  303         struct vop_print_args /* {
  304                 struct vnode *a_vp;
  305         } */ *ap;
  306 {
  307         struct ntnode *ip = VTONT(ap->a_vp);
  308 
  309         printf("tag VT_NTFS, ino %u, flag %#x, usecount %d, nlink %ld\n",
  310             ip->i_number, ip->i_flag, ip->i_usecount, ip->i_nlink);
  311         printf("       ");
  312         lockmgr_printinfo(ap->a_vp->v_vnlock);
  313         printf("\n");
  314         return (0);
  315 }
  316 
  317 /*
  318  * Calculate the logical to physical mapping if not done already,
  319  * then call the device strategy routine.
  320  */
  321 int
  322 ntfs_strategy(ap)
  323         struct vop_strategy_args /* {
  324                 struct vnode *a_vp;
  325                 struct buf *a_bp;
  326         } */ *ap;
  327 {
  328         struct buf *bp = ap->a_bp;
  329         struct vnode *vp = ap->a_vp;
  330         struct fnode *fp = VTOF(vp);
  331         struct ntnode *ip = FTONT(fp);
  332         struct ntfsmount *ntmp = ip->i_mp;
  333         int error;
  334 
  335 #ifdef __FreeBSD__
  336         dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
  337                 (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
  338                 (u_int32_t)bp->b_lblkno));
  339 #else
  340         dprintf(("ntfs_strategy: blkno: %d, lblkno: %d\n",
  341                 (u_int32_t)bp->b_blkno,
  342                 (u_int32_t)bp->b_lblkno));
  343 #endif
  344 
  345         dprintf(("strategy: bcount: %d flags: 0x%lx\n", 
  346                 (u_int32_t)bp->b_bcount,bp->b_flags));
  347 
  348         if (bp->b_flags & B_READ) {
  349                 u_int32_t toread;
  350 
  351                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
  352                         clrbuf(bp);
  353                         error = 0;
  354                 } else {
  355                         toread = min(bp->b_bcount,
  356                                  fp->f_size-ntfs_cntob(bp->b_blkno));
  357                         dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
  358                                 toread,(u_int32_t)fp->f_size));
  359 
  360                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  361                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
  362                                 toread, bp->b_data, NULL);
  363 
  364                         if (error) {
  365                                 printf("ntfs_strategy: ntfs_readattr failed\n");
  366                                 bp->b_error = error;
  367                                 bp->b_flags |= B_ERROR;
  368                         }
  369 
  370                         bzero(bp->b_data + toread, bp->b_bcount - toread);
  371                 }
  372         } else {
  373                 size_t tmp;
  374                 u_int32_t towrite;
  375 
  376                 if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
  377                         printf("ntfs_strategy: CAN'T EXTEND FILE\n");
  378                         bp->b_error = error = EFBIG;
  379                         bp->b_flags |= B_ERROR;
  380                 } else {
  381                         towrite = min(bp->b_bcount,
  382                                 fp->f_size-ntfs_cntob(bp->b_blkno));
  383                         dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
  384                                 towrite,(u_int32_t)fp->f_size));
  385 
  386                         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,  
  387                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
  388                                 bp->b_data, &tmp, NULL);
  389 
  390                         if (error) {
  391                                 printf("ntfs_strategy: ntfs_writeattr fail\n");
  392                                 bp->b_error = error;
  393                                 bp->b_flags |= B_ERROR;
  394                         }
  395                 }
  396         }
  397         biodone(bp);
  398         return (error);
  399 }
  400 
  401 static int
  402 ntfs_write(ap)
  403         struct vop_write_args /* {
  404                 struct vnode *a_vp;
  405                 struct uio *a_uio;
  406                 int  a_ioflag;
  407                 struct ucred *a_cred;
  408         } */ *ap;
  409 {
  410         struct vnode *vp = ap->a_vp;
  411         struct fnode *fp = VTOF(vp);
  412         struct ntnode *ip = FTONT(fp);
  413         struct uio *uio = ap->a_uio;
  414         struct ntfsmount *ntmp = ip->i_mp;
  415         u_int64_t towrite;
  416         size_t written;
  417         int error;
  418 
  419         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));
  420         dprintf(("ntfs_write: filesize: %d",(u_int32_t)fp->f_size));
  421 
  422         if (uio->uio_resid + uio->uio_offset > fp->f_size) {
  423                 printf("ntfs_write: CAN'T WRITE BEYOND END OF FILE\n");
  424                 return (EFBIG);
  425         }
  426 
  427         towrite = min(uio->uio_resid, fp->f_size - uio->uio_offset);
  428 
  429         dprintf((", towrite: %d\n",(u_int32_t)towrite));
  430 
  431         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
  432                 fp->f_attrname, uio->uio_offset, towrite, NULL, &written, uio);
  433 #ifdef NTFS_DEBUG
  434         if (error)
  435                 printf("ntfs_write: ntfs_writeattr failed: %d\n", error);
  436 #endif
  437 
  438         return (error);
  439 }
  440 
  441 int
  442 ntfs_access(ap)
  443         struct vop_access_args /* {
  444                 struct vnode *a_vp;
  445                 int  a_mode;
  446                 struct ucred *a_cred;
  447                 struct proc *a_p;
  448         } */ *ap;
  449 {
  450         struct vnode *vp = ap->a_vp;
  451         struct ntnode *ip = VTONT(vp);
  452         struct ucred *cred = ap->a_cred;
  453         mode_t mask, mode = ap->a_mode;
  454         gid_t *gp;
  455         int i;
  456 
  457         dprintf(("ntfs_access: %d\n",ip->i_number));
  458 
  459         /*
  460          * Disallow write attempts on read-only file systems;
  461          * unless the file is a socket, fifo, or a block or
  462          * character device resident on the file system.
  463          */
  464         if (mode & VWRITE) {
  465                 switch ((int)vp->v_type) {
  466                 case VDIR:
  467                 case VLNK:
  468                 case VREG:
  469                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  470                                 return (EROFS);
  471                         break;
  472                 }
  473         }
  474 
  475         /* Otherwise, user id 0 always gets access. */
  476         if (cred->cr_uid == 0)
  477                 return (0);
  478 
  479         mask = 0;
  480 
  481         /* Otherwise, check the owner. */
  482         if (cred->cr_uid == ip->i_mp->ntm_uid) {
  483                 if (mode & VEXEC)
  484                         mask |= S_IXUSR;
  485                 if (mode & VREAD)
  486                         mask |= S_IRUSR;
  487                 if (mode & VWRITE)
  488                         mask |= S_IWUSR;
  489                 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
  490         }
  491 
  492         /* Otherwise, check the groups. */
  493         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
  494                 if (ip->i_mp->ntm_gid == *gp) {
  495                         if (mode & VEXEC)
  496                                 mask |= S_IXGRP;
  497                         if (mode & VREAD)
  498                                 mask |= S_IRGRP;
  499                         if (mode & VWRITE)
  500                                 mask |= S_IWGRP;
  501                         return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES);
  502                 }
  503 
  504         /* Otherwise, check everyone else. */
  505         if (mode & VEXEC)
  506                 mask |= S_IXOTH;
  507         if (mode & VREAD)
  508                 mask |= S_IROTH;
  509         if (mode & VWRITE)
  510                 mask |= S_IWOTH;
  511         return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES);
  512 }
  513 
  514 /*
  515  * Open called.
  516  *
  517  * Nothing to do.
  518  */
  519 /* ARGSUSED */
  520 static int
  521 ntfs_open(ap)
  522         struct vop_open_args /* {
  523                 struct vnode *a_vp;
  524                 int  a_mode;
  525                 struct ucred *a_cred;
  526                 struct proc *a_p;
  527         } */ *ap;
  528 {
  529 #if NTFS_DEBUG
  530         struct vnode *vp = ap->a_vp;
  531         struct ntnode *ip = VTONT(vp);
  532 
  533         printf("ntfs_open: %d\n",ip->i_number);
  534 #endif
  535 
  536         /*
  537          * Files marked append-only must be opened for appending.
  538          */
  539 
  540         return (0);
  541 }
  542 
  543 /*
  544  * Close called.
  545  *
  546  * Update the times on the inode.
  547  */
  548 /* ARGSUSED */
  549 static int
  550 ntfs_close(ap)
  551         struct vop_close_args /* {
  552                 struct vnode *a_vp;
  553                 int  a_fflag;
  554                 struct ucred *a_cred;
  555                 struct proc *a_p;
  556         } */ *ap;
  557 {
  558 #if NTFS_DEBUG
  559         struct vnode *vp = ap->a_vp;
  560         struct ntnode *ip = VTONT(vp);
  561 
  562         printf("ntfs_close: %d\n",ip->i_number);
  563 #endif
  564 
  565         return (0);
  566 }
  567 
  568 int
  569 ntfs_readdir(ap)
  570         struct vop_readdir_args /* {
  571                 struct vnode *a_vp;
  572                 struct uio *a_uio;
  573                 struct ucred *a_cred;
  574                 int *a_ncookies;
  575                 u_int **cookies;
  576         } */ *ap;
  577 {
  578         struct vnode *vp = ap->a_vp;
  579         struct fnode *fp = VTOF(vp);
  580         struct ntnode *ip = FTONT(fp);
  581         struct uio *uio = ap->a_uio;
  582         struct ntfsmount *ntmp = ip->i_mp;
  583         int i, error = 0;
  584         u_int32_t faked = 0, num;
  585         int ncookies = 0;
  586         struct dirent *cde;
  587         off_t off;
  588 
  589         dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
  590 
  591         off = uio->uio_offset;
  592 
  593         MALLOC(cde, struct dirent *, sizeof(struct dirent), M_TEMP, M_WAITOK);
  594 
  595         /* Simulate . in every dir except ROOT */
  596         if (ip->i_number != NTFS_ROOTINO
  597             && uio->uio_offset < sizeof(struct dirent)) {
  598                 cde->d_fileno = ip->i_number;
  599                 cde->d_reclen = sizeof(struct dirent);
  600                 cde->d_type = DT_DIR;
  601                 cde->d_namlen = 1;
  602                 strncpy(cde->d_name, ".", 2);
  603                 error = uiomove((void *)cde, sizeof(struct dirent), uio);
  604                 if (error)
  605                         goto out;
  606 
  607                 ncookies++;
  608         }
  609 
  610         /* Simulate .. in every dir including ROOT */
  611         if (uio->uio_offset < 2 * sizeof(struct dirent)) {
  612                 cde->d_fileno = NTFS_ROOTINO;   /* XXX */
  613                 cde->d_reclen = sizeof(struct dirent);
  614                 cde->d_type = DT_DIR;
  615                 cde->d_namlen = 2;
  616                 strncpy(cde->d_name, "..", 3);
  617 
  618                 error = uiomove((void *) cde, sizeof(struct dirent), uio);
  619                 if (error)
  620                         goto out;
  621 
  622                 ncookies++;
  623         }
  624 
  625         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
  626         num = uio->uio_offset / sizeof(struct dirent) - faked;
  627 
  628         while (uio->uio_resid >= sizeof(struct dirent)) {
  629                 struct attr_indexentry *iep;
  630                 char *fname;
  631                 size_t remains;
  632                 int sz;
  633 
  634                 error = ntfs_ntreaddir(ntmp, fp, num, &iep);
  635                 if (error)
  636                         goto out;
  637 
  638                 if (NULL == iep)
  639                         break;
  640 
  641                 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
  642                         iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
  643                 {
  644                         if(!ntfs_isnamepermitted(ntmp,iep))
  645                                 continue;
  646 
  647                         remains = sizeof(cde->d_name) - 1;
  648                         fname = cde->d_name;
  649                         for(i=0; i<iep->ie_fnamelen; i++) {
  650                                 sz = (*ntmp->ntm_wput)(fname, remains,
  651                                                 iep->ie_fname[i]);
  652                                 fname += sz;
  653                                 remains -= sz;
  654                         }
  655                         *fname = '\0';
  656                         dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
  657                                 num, cde->d_name, iep->ie_fnametype,
  658                                 iep->ie_flag));
  659                         cde->d_namlen = fname - (char *) cde->d_name;
  660                         cde->d_fileno = iep->ie_number;
  661                         cde->d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
  662                         cde->d_reclen = sizeof(struct dirent);
  663                         dprintf(("%s\n", (cde->d_type == DT_DIR) ? "dir":"reg"));
  664 
  665                         error = uiomove((void *)cde, sizeof(struct dirent), uio);
  666                         if (error)
  667                                 goto out;
  668 
  669                         ncookies++;
  670                         num++;
  671                 }
  672         }
  673 
  674         dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
  675                 ncookies,(u_int)(uio->uio_offset - off)));
  676         dprintf(("ntfs_readdir: off: %d resid: %d\n",
  677                 (u_int32_t)uio->uio_offset,uio->uio_resid));
  678 
  679         if (!error && ap->a_ncookies != NULL) {
  680                 struct dirent* dpStart;
  681                 struct dirent* dp;
  682 #if defined(__FreeBSD__)
  683                 u_long *cookies;
  684                 u_long *cookiep;
  685 #else /* defined(__NetBSD__) */
  686                 off_t *cookies;
  687                 off_t *cookiep;
  688 #endif
  689 
  690                 dprintf(("ntfs_readdir: %d cookies\n",ncookies));
  691                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
  692                         panic("ntfs_readdir: unexpected uio from NFS server");
  693                 dpStart = (struct dirent *)
  694                      ((caddr_t)uio->uio_iov->iov_base -
  695                          (uio->uio_offset - off));
  696 #if defined(__FreeBSD__)
  697                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
  698                        M_TEMP, M_WAITOK);
  699 #else /* defined(__NetBSD__) */
  700                 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
  701 #endif
  702                 for (dp = dpStart, cookiep = cookies, i=0;
  703                      i < ncookies;
  704                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
  705                         off += dp->d_reclen;
  706                         *cookiep++ = (u_int) off;
  707                 }
  708                 *ap->a_ncookies = ncookies;
  709                 *ap->a_cookies = cookies;
  710         }
  711 /*
  712         if (ap->a_eofflag)
  713             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
  714 */
  715     out:
  716         FREE(cde, M_TEMP);
  717         return (error);
  718 }
  719 
  720 int
  721 ntfs_lookup(ap)
  722         struct vop_lookup_args /* {
  723                 struct vnode *a_dvp;
  724                 struct vnode **a_vpp;
  725                 struct componentname *a_cnp;
  726         } */ *ap;
  727 {
  728         struct vnode *dvp = ap->a_dvp;
  729         struct ntnode *dip = VTONT(dvp);
  730         struct ntfsmount *ntmp = dip->i_mp;
  731         struct componentname *cnp = ap->a_cnp;
  732         struct ucred *cred = cnp->cn_cred;
  733         int error;
  734         int lockparent = cnp->cn_flags & LOCKPARENT;
  735 #if NTFS_DEBUG
  736         int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
  737 #endif
  738         dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d, lp: %d, wp: %d \n",
  739                 (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
  740                 dip->i_number, lockparent, wantparent));
  741 
  742         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
  743         if(error)
  744                 return (error);
  745 
  746         if ((cnp->cn_flags & ISLASTCN) &&
  747             (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
  748             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  749                 return (EROFS);
  750 
  751 #ifdef __NetBSD__
  752         /*
  753          * We now have a segment name to search for, and a directory
  754          * to search.
  755          *
  756          * Before tediously performing a linear scan of the directory,
  757          * check the name cache to see if the directory/name pair
  758          * we are looking for is known already.
  759          */
  760         if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
  761                 return (error);
  762 #endif
  763 
  764         if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  765                 dprintf(("ntfs_lookup: faking . directory in %d\n",
  766                         dip->i_number));
  767 
  768                 VREF(dvp);
  769                 *ap->a_vpp = dvp;
  770                 error = 0;
  771         } else if (cnp->cn_flags & ISDOTDOT) {
  772                 struct ntvattr *vap;
  773 
  774                 dprintf(("ntfs_lookup: faking .. directory in %d\n",
  775                          dip->i_number));
  776 
  777                 VOP_UNLOCK(dvp, 0);
  778                 cnp->cn_flags |= PDIRUNLOCK;
  779 
  780                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
  781                 if(error)
  782                         return (error);
  783 
  784                 dprintf(("ntfs_lookup: parentdir: %d\n",
  785                          vap->va_a_name->n_pnumber));
  786                 error = VFS_VGET(ntmp->ntm_mountp,
  787                                  vap->va_a_name->n_pnumber,ap->a_vpp); 
  788                 ntfs_ntvattrrele(vap);
  789                 if (error) {
  790                         if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
  791                                 cnp->cn_flags &= ~PDIRUNLOCK;
  792                         return (error);
  793                 }
  794 
  795                 if (lockparent && (cnp->cn_flags & ISLASTCN)) {
  796                         error = vn_lock(dvp, LK_EXCLUSIVE);
  797                         if (error) {
  798                                 vput( *(ap->a_vpp) );
  799                                 return (error);
  800                         }
  801                         cnp->cn_flags &= ~PDIRUNLOCK;
  802                 }
  803         } else {
  804                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
  805                 if (error) {
  806                         dprintf(("ntfs_ntlookupfile: returned %d\n", error));
  807                         return (error);
  808                 }
  809 
  810                 dprintf(("ntfs_lookup: found ino: %d\n", 
  811                         VTONT(*ap->a_vpp)->i_number));
  812 
  813                 if(!lockparent || (cnp->cn_flags & ISLASTCN) == 0) {
  814                         VOP_UNLOCK(dvp, 0);
  815                         cnp->cn_flags |= PDIRUNLOCK;
  816                 }
  817         }
  818 
  819         if (cnp->cn_flags & MAKEENTRY)
  820                 cache_enter(dvp, *ap->a_vpp, cnp);
  821 
  822         return (error);
  823 }
  824 
  825 #if defined(__FreeBSD__)
  826 /*
  827  * Flush the blocks of a file to disk.
  828  *
  829  * This function is worthless for vnodes that represent directories. Maybe we
  830  * could just do a sync if they try an fsync on a directory file.
  831  */
  832 static int
  833 ntfs_fsync(ap)
  834         struct vop_fsync_args /* {
  835                 struct vnode *a_vp;
  836                 struct ucred *a_cred;
  837                 int a_waitfor;
  838                 off_t offlo;
  839                 off_t offhi;
  840                 struct proc *a_p;
  841         } */ *ap;
  842 {
  843         return (0);
  844 }
  845 #endif
  846 
  847 /*
  848  * Return POSIX pathconf information applicable to NTFS filesystem
  849  */
  850 static int
  851 ntfs_pathconf(v)
  852         void *v;
  853 {
  854         struct vop_pathconf_args /* {
  855                 struct vnode *a_vp;
  856                 int a_name;
  857                 register_t *a_retval;
  858         } */ *ap = v;
  859 
  860         switch (ap->a_name) {
  861         case _PC_LINK_MAX:
  862                 *ap->a_retval = 1;
  863                 return (0);
  864         case _PC_NAME_MAX:
  865                 *ap->a_retval = NTFS_MAXFILENAME;
  866                 return (0);
  867         case _PC_PATH_MAX:
  868                 *ap->a_retval = PATH_MAX;
  869                 return (0);
  870         case _PC_CHOWN_RESTRICTED:
  871                 *ap->a_retval = 1;
  872                 return (0);
  873         case _PC_NO_TRUNC:
  874                 *ap->a_retval = 0;
  875                 return (0);
  876         case _PC_SYNC_IO:
  877                 *ap->a_retval = 1;
  878                 return (0);
  879         case _PC_FILESIZEBITS:
  880                 *ap->a_retval = 64;
  881                 return (0);
  882         default:
  883                 return (EINVAL);
  884         }
  885         /* NOTREACHED */
  886 }
  887 
  888 /*
  889  * Global vfs data structures
  890  */
  891 vop_t **ntfs_vnodeop_p;
  892 #if defined(__FreeBSD__)
  893 static
  894 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
  895         { &vop_default_desc, (vop_t *)ntfs_bypass },
  896 
  897         { &vop_getattr_desc, (vop_t *)ntfs_getattr },
  898         { &vop_inactive_desc, (vop_t *)ntfs_inactive },
  899         { &vop_reclaim_desc, (vop_t *)ntfs_reclaim },
  900         { &vop_print_desc, (vop_t *)ntfs_print },
  901         { &vop_pathconf_desc, ntfs_pathconf },
  902 
  903         { &vop_islocked_desc, (vop_t *)vop_stdislocked },
  904         { &vop_unlock_desc, (vop_t *)vop_stdunlock },
  905         { &vop_lock_desc, (vop_t *)vop_stdlock },
  906         { &vop_cachedlookup_desc, (vop_t *)ntfs_lookup },
  907         { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
  908 
  909         { &vop_access_desc, (vop_t *)ntfs_access },
  910         { &vop_close_desc, (vop_t *)ntfs_close },
  911         { &vop_open_desc, (vop_t *)ntfs_open },
  912         { &vop_readdir_desc, (vop_t *)ntfs_readdir },
  913         { &vop_fsync_desc, (vop_t *)ntfs_fsync },
  914 
  915         { &vop_bmap_desc, (vop_t *)ntfs_bmap },
  916         { &vop_getpages_desc, (vop_t *) ntfs_getpages },
  917         { &vop_putpages_desc, (vop_t *) ntfs_putpages },
  918         { &vop_strategy_desc, (vop_t *)ntfs_strategy },
  919         { &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
  920         { &vop_read_desc, (vop_t *)ntfs_read },
  921         { &vop_write_desc, (vop_t *)ntfs_write },
  922 
  923         { NULL, NULL }
  924 };
  925 
  926 static
  927 struct vnodeopv_desc ntfs_vnodeop_opv_desc =
  928         { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
  929 
  930 VNODEOP_SET(ntfs_vnodeop_opv_desc);
  931 
  932 #else /* !FreeBSD */
  933 
  934 const struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
  935         { &vop_default_desc, (vop_t *) ntfs_bypass },
  936         { &vop_lookup_desc, (vop_t *) ntfs_lookup },    /* lookup */
  937         { &vop_create_desc, genfs_eopnotsupp },         /* create */
  938         { &vop_mknod_desc, genfs_eopnotsupp },          /* mknod */
  939         { &vop_open_desc, (vop_t *) ntfs_open },        /* open */
  940         { &vop_close_desc,(vop_t *)  ntfs_close },      /* close */
  941         { &vop_access_desc, (vop_t *) ntfs_access },    /* access */
  942         { &vop_getattr_desc, (vop_t *) ntfs_getattr },  /* getattr */
  943         { &vop_setattr_desc, genfs_eopnotsupp },        /* setattr */
  944         { &vop_read_desc, (vop_t *) ntfs_read },        /* read */
  945         { &vop_write_desc, (vop_t *) ntfs_write },      /* write */
  946         { &vop_lease_desc, genfs_lease_check },         /* lease */
  947         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  948         { &vop_ioctl_desc, genfs_enoioctl },            /* ioctl */
  949         { &vop_poll_desc, genfs_poll },                 /* poll */
  950         { &vop_kqfilter_desc, genfs_kqfilter },         /* kqfilter */
  951         { &vop_revoke_desc, genfs_revoke },             /* revoke */
  952         { &vop_mmap_desc, genfs_mmap },                 /* mmap */
  953         { &vop_fsync_desc, genfs_fsync },               /* fsync */
  954         { &vop_seek_desc, genfs_seek },                 /* seek */
  955         { &vop_remove_desc, genfs_eopnotsupp },         /* remove */
  956         { &vop_link_desc, genfs_eopnotsupp },           /* link */
  957         { &vop_rename_desc, genfs_eopnotsupp },         /* rename */
  958         { &vop_mkdir_desc, genfs_eopnotsupp },          /* mkdir */
  959         { &vop_rmdir_desc, genfs_eopnotsupp },          /* rmdir */
  960         { &vop_symlink_desc, genfs_eopnotsupp },        /* symlink */
  961         { &vop_readdir_desc, (vop_t *) ntfs_readdir },  /* readdir */
  962         { &vop_readlink_desc, genfs_eopnotsupp },       /* readlink */
  963         { &vop_abortop_desc, genfs_abortop },           /* abortop */
  964         { &vop_inactive_desc, (vop_t *) ntfs_inactive },        /* inactive */
  965         { &vop_reclaim_desc, (vop_t *) ntfs_reclaim },  /* reclaim */
  966         { &vop_lock_desc, genfs_lock },                 /* lock */
  967         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  968         { &vop_bmap_desc, (vop_t *) ntfs_bmap },        /* bmap */
  969         { &vop_strategy_desc, (vop_t *) ntfs_strategy },        /* strategy */
  970         { &vop_print_desc, (vop_t *) ntfs_print },      /* print */
  971         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  972         { &vop_pathconf_desc, ntfs_pathconf },          /* pathconf */
  973         { &vop_advlock_desc, genfs_nullop },            /* advlock */
  974         { &vop_blkatoff_desc, genfs_eopnotsupp },       /* blkatoff */
  975         { &vop_valloc_desc, genfs_eopnotsupp },         /* valloc */
  976         { &vop_reallocblks_desc, genfs_eopnotsupp },    /* reallocblks */
  977         { &vop_vfree_desc, genfs_eopnotsupp },          /* vfree */
  978         { &vop_truncate_desc, genfs_eopnotsupp },       /* truncate */
  979         { &vop_update_desc, genfs_nullop },             /* update */
  980         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
  981         { &vop_getpages_desc, genfs_compat_getpages },  /* getpages */
  982         { &vop_putpages_desc, genfs_putpages },         /* putpages */
  983         { NULL, NULL }
  984 };
  985 const struct vnodeopv_desc ntfs_vnodeop_opv_desc =
  986         { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
  987 
  988 #endif

Cache object: 78e750e31af71de35f3b7766002460a6


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