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


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

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

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

    1 /*      $NetBSD: ntfs_vnops.c,v 1.2 1999/05/06 15:43:20 christos 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. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  * $FreeBSD$
   39  *
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/proc.h>
   46 #include <sys/time.h>
   47 #include <sys/types.h>
   48 #include <sys/stat.h>
   49 #include <sys/vnode.h>
   50 #include <sys/mount.h>
   51 #include <sys/namei.h>
   52 #include <sys/malloc.h>
   53 #include <sys/buf.h>
   54 #include <sys/dirent.h>
   55 
   56 #include <vm/vm.h>
   57 #include <vm/vm_param.h>
   58 #include <vm/vm_prot.h>
   59 #include <vm/vm_page.h>
   60 #include <vm/vm_object.h>
   61 #include <vm/vm_pager.h>
   62 #if defined(__FreeBSD__)
   63 #include <vm/vnode_pager.h>
   64 #endif
   65 #include <vm/vm_extern.h>
   66 
   67 #include <sys/sysctl.h>
   68 
   69 
   70 /*#define NTFS_DEBUG 1*/
   71 #include <ntfs/ntfs.h>
   72 #include <ntfs/ntfs_inode.h>
   73 #include <ntfs/ntfs_subr.h>
   74 #include <ntfs/ntfs_extern.h>
   75 #include <miscfs/specfs/specdev.h>
   76 
   77 static int      ntfs_bypass __P((struct vop_generic_args *ap));
   78 static int      ntfs_read __P((struct vop_read_args *));
   79 static int      ntfs_write __P((struct vop_write_args *ap));
   80 static int      ntfs_getattr __P((struct vop_getattr_args *ap));
   81 static int      ntfs_inactive __P((struct vop_inactive_args *ap));
   82 static int      ntfs_print __P((struct vop_print_args *ap));
   83 static int      ntfs_reclaim __P((struct vop_reclaim_args *ap));
   84 static int      ntfs_strategy __P((struct vop_strategy_args *ap));
   85 #if defined(__NetBSD__)
   86 static int      ntfs_islocked __P((struct vop_islocked_args *ap));
   87 static int      ntfs_unlock __P((struct vop_unlock_args *ap));
   88 static int      ntfs_lock __P((struct vop_lock_args *ap));
   89 #endif
   90 static int      ntfs_access __P((struct vop_access_args *ap));
   91 static int      ntfs_open __P((struct vop_open_args *ap));
   92 static int      ntfs_close __P((struct vop_close_args *ap));
   93 static int      ntfs_readdir __P((struct vop_readdir_args *ap));
   94 static int      ntfs_lookup __P((struct vop_lookup_args *ap));
   95 static int      ntfs_bmap __P((struct vop_bmap_args *ap));
   96 #if defined(__FreeBSD__)
   97 static int      ntfs_getpages __P((struct vop_getpages_args *ap));
   98 static int      ntfs_putpages __P((struct vop_putpages_args *));
   99 #endif
  100 static int      ntfs_fsync __P((struct vop_fsync_args *ap));
  101 
  102 int     ntfs_prtactive = 1;     /* 1 => print out reclaim of active vnodes */
  103 
  104 #if defined(__FreeBSD__)
  105 int
  106 ntfs_getpages(ap)
  107         struct vop_getpages_args *ap;
  108 {
  109         return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
  110                 ap->a_reqpage);
  111 }
  112 
  113 int
  114 ntfs_putpages(ap)
  115         struct vop_putpages_args *ap;
  116 {
  117         return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
  118                 ap->a_sync, ap->a_rtvals);
  119 }
  120 #endif
  121 
  122 /*
  123  * This is a noop, simply returning what one has been given.
  124  */
  125 int
  126 ntfs_bmap(ap)
  127         struct vop_bmap_args /* {
  128                 struct vnode *a_vp;
  129                 daddr_t  a_bn;
  130                 struct vnode **a_vpp;
  131                 daddr_t *a_bnp;
  132                 int *a_runp;
  133                 int *a_runb;
  134         } */ *ap;
  135 {
  136         dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
  137         if (ap->a_vpp != NULL)
  138                 *ap->a_vpp = ap->a_vp;
  139         if (ap->a_bnp != NULL)
  140                 *ap->a_bnp = ap->a_bn;
  141         if (ap->a_runp != NULL)
  142                 *ap->a_runp = 0;
  143 #if !defined(__NetBSD__)
  144         if (ap->a_runb != NULL)
  145                 *ap->a_runb = 0;
  146 #endif
  147         return (0);
  148 }
  149 
  150 static int
  151 ntfs_read(ap)
  152         struct vop_read_args /* {
  153                 struct vnode *a_vp;
  154                 struct uio *a_uio;
  155                 int a_ioflag;
  156                 struct ucred *a_cred;
  157         } */ *ap;
  158 {
  159         register struct vnode *vp = ap->a_vp;
  160         register struct fnode *fp = VTOF(vp);
  161         register struct ntnode *ip = FTONT(fp);
  162         struct uio *uio = ap->a_uio;
  163         struct ntfsmount *ntmp = ip->i_mp;
  164         u_int8_t *data;
  165         u_int64_t toread;
  166         int error;
  167 
  168         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));
  169 
  170         toread = fp->f_size;
  171 
  172         dprintf(("ntfs_read: filesize: %d",(u_int32_t)toread));
  173 
  174         toread = min( uio->uio_resid, toread - uio->uio_offset );
  175 
  176         dprintf((", toread: %d\n",(u_int32_t)toread));
  177 
  178         MALLOC(data, u_int8_t *, toread, M_TEMP,M_WAITOK);
  179 
  180         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  181                 fp->f_attrname, uio->uio_offset, toread, data);
  182         if(error) {
  183                 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
  184                 FREE(data, M_TEMP);
  185                 return (error);
  186         }
  187 
  188         error = uiomove(data, (int) toread, uio);
  189         if(error) {
  190                 printf("ntfs_read: uiomove failed: %d\n",error);
  191                 FREE(data, M_TEMP);
  192                 return (error);
  193         }
  194 
  195         FREE(data, M_TEMP);
  196 
  197         return (0);
  198 }
  199 
  200 static int
  201 ntfs_bypass(ap)
  202         struct vop_generic_args /* {
  203                 struct vnodeop_desc *a_desc;
  204                 <other random data follows, presumably>
  205         } */ *ap;
  206 {
  207         int error = ENOTTY;
  208         dprintf(("ntfs_bypass: %s\n", ap->a_desc->vdesc_name));
  209         return (error);
  210 }
  211 
  212 
  213 static int
  214 ntfs_getattr(ap)
  215         struct vop_getattr_args /* {
  216                 struct vnode *a_vp;
  217                 struct vattr *a_vap;
  218                 struct ucred *a_cred;
  219                 struct proc *a_p;
  220         } */ *ap;
  221 {
  222         register struct vnode *vp = ap->a_vp;
  223         register struct fnode *fp = VTOF(vp);
  224         register struct ntnode *ip = FTONT(fp);
  225         register struct vattr *vap = ap->a_vap;
  226 
  227         dprintf(("ntfs_getattr: %d, flags: %d\n",ip->i_number,ip->i_flag));
  228 
  229         vap->va_fsid = (long)(fp->f_dev);
  230         vap->va_fileid = ip->i_number;
  231         vap->va_mode = ip->i_mode;
  232         vap->va_nlink = ip->i_nlink;
  233         vap->va_uid = ip->i_uid;
  234         vap->va_gid = ip->i_gid;
  235         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  236         vap->va_size = fp->f_size;
  237         vap->va_bytes = fp->f_allocated;
  238         vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
  239         vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
  240         vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
  241         vap->va_flags = ip->i_flag;
  242         vap->va_gen = 0;
  243         vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
  244         vap->va_type = fp->f_type;
  245         vap->va_filerev = 0;
  246         return (0);
  247 }
  248 
  249 
  250 /*
  251  * Last reference to an ntnode.  If necessary, write or delete it.
  252  */
  253 int
  254 ntfs_inactive(ap)
  255         struct vop_inactive_args /* {
  256                 struct vnode *a_vp;
  257         } */ *ap;
  258 {
  259         register struct vnode *vp = ap->a_vp;
  260         register struct ntnode *ip = VTONT(vp);
  261         int error;
  262 
  263         dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  264 
  265         if (ntfs_prtactive && vp->v_usecount != 0)
  266                 vprint("ntfs_inactive: pushing active", vp);
  267 
  268         error = 0;
  269 
  270         VOP__UNLOCK(vp,0,ap->a_p);
  271 
  272         /*
  273          * If we are done with the ntnode, reclaim it
  274          * so that it can be reused immediately.
  275          */
  276         if (vp->v_usecount == 0 && ip->i_mode == 0)
  277 #if defined(__FreeBSD__)
  278                 vrecycle(vp, (struct simplelock *)0, ap->a_p);
  279 #else /* defined(__NetBSD__) */
  280                 vgone(vp);
  281 #endif
  282         return (error);
  283 }
  284 
  285 /*
  286  * Reclaim an inode so that it can be used for other purposes.
  287  */
  288 int
  289 ntfs_reclaim(ap)
  290         struct vop_reclaim_args /* {
  291                 struct vnode *a_vp;
  292         } */ *ap;
  293 {
  294         register struct vnode *vp = ap->a_vp;
  295         register struct fnode *fp = VTOF(vp);
  296         register struct ntnode *ip = FTONT(fp);
  297         int error;
  298 
  299         dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
  300 
  301         error = ntfs_ntget(ip);
  302         if (error)
  303                 return (error);
  304 
  305 #if defined(__FreeBSD__)
  306         VOP__UNLOCK(vp,0,ap->a_p);
  307 #endif
  308 
  309         /* Purge old data structures associated with the inode. */
  310         cache_purge(vp);
  311         if (fp->f_devvp) {
  312                 vrele(fp->f_devvp);
  313                 fp->f_devvp = NULL;
  314         }
  315 
  316         ntfs_frele(fp);
  317 
  318         vp->v_data = NULL;
  319 
  320         ntfs_ntput(ip);
  321 
  322         return (0);
  323 }
  324 
  325 static int
  326 ntfs_print(ap)
  327         struct vop_print_args /* {
  328                 struct vnode *a_vp;
  329         } */ *ap;
  330 {
  331 /*      printf("[ntfs_print]");*/
  332         
  333         return (0);
  334 }
  335 
  336 /*
  337  * Calculate the logical to physical mapping if not done already,
  338  * then call the device strategy routine.
  339  */
  340 int
  341 ntfs_strategy(ap)
  342         struct vop_strategy_args /* {
  343                 struct buf *a_bp;
  344         } */ *ap;
  345 {
  346         register struct buf *bp = ap->a_bp;
  347         register struct vnode *vp = bp->b_vp;
  348         register struct fnode *fp = VTOF(vp);
  349         register struct ntnode *ip = FTONT(fp);
  350         struct ntfsmount *ntmp = ip->i_mp;
  351         int error;
  352 
  353         dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
  354                 (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
  355                 (u_int32_t)bp->b_lblkno));
  356         dprintf(("strategy: bcount: %d flags: 0x%x\n", 
  357                 (u_int32_t)bp->b_bcount,bp->b_flags));
  358 
  359         if (bp->b_flags & B_READ) {
  360                 u_int32_t toread;
  361 
  362                 if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
  363                         clrbuf(bp);
  364                         error = 0;
  365                 } else {
  366                         toread = min(bp->b_bcount,
  367                                  fp->f_size-ntfs_cntob(bp->b_blkno));
  368                         dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
  369                                 toread,(u_int32_t)fp->f_size));
  370 
  371                         error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
  372                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),
  373                                 toread, bp->b_data);
  374 
  375                         if (error) {
  376                                 printf("ntfs_strategy: ntfs_readattr failed\n");
  377                                 bp->b_error = error;
  378                                 bp->b_flags |= B_ERROR;
  379                         }
  380 
  381                         bzero(bp->b_data + toread, bp->b_bcount - toread);
  382                 }
  383         } else {
  384                 size_t tmp;
  385                 u_int32_t towrite;
  386 
  387                 if (ntfs_cntob(bp->b_blkno) + bp->b_bcount >= fp->f_size) {
  388                         printf("ntfs_strategy: CAN'T EXTEND FILE\n");
  389                         bp->b_error = error = EFBIG;
  390                         bp->b_flags |= B_ERROR;
  391                 } else {
  392                         towrite = min(bp->b_bcount,
  393                                 fp->f_size-ntfs_cntob(bp->b_blkno));
  394                         dprintf(("ntfs_strategy: towrite: %d, fsize: %d\n",
  395                                 towrite,(u_int32_t)fp->f_size));
  396 
  397                         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,  
  398                                 fp->f_attrname, ntfs_cntob(bp->b_blkno),towrite,
  399                                 bp->b_data, &tmp);
  400 
  401                         if (error) {
  402                                 printf("ntfs_strategy: ntfs_writeattr fail\n");
  403                                 bp->b_error = error;
  404                                 bp->b_flags |= B_ERROR;
  405                         }
  406                 }
  407         }
  408         biodone(bp);
  409         return (error);
  410 }
  411 
  412 static int
  413 ntfs_write(ap)
  414         struct vop_write_args /* {
  415                 struct vnode *a_vp;
  416                 struct uio *a_uio;
  417                 int  a_ioflag;
  418                 struct ucred *a_cred;
  419         } */ *ap;
  420 {
  421         register struct vnode *vp = ap->a_vp;
  422         register struct fnode *fp = VTOF(vp);
  423         register struct ntnode *ip = FTONT(fp);
  424         struct uio *uio = ap->a_uio;
  425         struct ntfsmount *ntmp = ip->i_mp;
  426         u_int8_t *data;
  427         u_int64_t towrite;
  428         off_t off;
  429         size_t written;
  430         int error;
  431 
  432         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));
  433 
  434         towrite = fp->f_size;
  435 
  436         dprintf(("ntfs_write: filesize: %d",(u_int32_t)towrite));
  437 
  438         if (uio->uio_resid + uio->uio_offset > towrite) {
  439                 printf("ntfs_write: CAN'T WRITE BEYOND OF FILE\n");
  440                 return (EFBIG);
  441         }
  442 
  443         towrite = min(uio->uio_resid, towrite - uio->uio_offset);
  444         off = uio->uio_offset;
  445 
  446         dprintf((", towrite: %d\n",(u_int32_t)towrite));
  447 
  448         MALLOC(data, u_int8_t *, towrite, M_TEMP,M_WAITOK);
  449 
  450         error = uiomove(data, (int) towrite, uio);
  451         if(error) {
  452                 FREE(data, M_TEMP);
  453                 return (error);
  454         }
  455 
  456         error = ntfs_writeattr_plain(ntmp, ip, fp->f_attrtype,
  457                 fp->f_attrname, off, towrite, data, &written);
  458         if(error) {
  459                 printf("ntfs_write: ntfs_writeattr failed: %d\n",error);
  460                 FREE(data, M_TEMP);
  461                 return (error);
  462         }
  463 
  464         FREE(data, M_TEMP);
  465 
  466         return (0);
  467 }
  468 
  469 #if defined(__NetBSD__)
  470 /*
  471  * Check for a locked ntnode.
  472  */
  473 int
  474 ntfs_islocked(ap)
  475         struct vop_islocked_args /* {
  476                 struct vnode *a_vp;
  477         } */ *ap;
  478 {
  479         register struct ntnode *ip = VTONT(ap->a_vp);
  480 
  481         dprintf(("ntfs_islocked %d\n",ip->i_number));
  482 
  483         if (ip->i_flag & IN_LOCKED)
  484                 return (1);
  485         return (0);
  486 }
  487 
  488 /*
  489  * Unlock an ntnode.  If WANT bit is on, wakeup.
  490  */
  491 int ntfs_lockcount = 90;
  492 int
  493 ntfs_unlock(ap)
  494         struct vop_unlock_args /* {
  495                 struct vnode *a_vp;
  496         } */ *ap;
  497 {
  498         register struct ntnode *ip = VTONT(ap->a_vp);
  499 #ifdef DIAGNOSTIC
  500         struct proc *p = curproc;
  501 #endif
  502 
  503         dprintf(("ntfs_unlock %d\n",ip->i_number));
  504 
  505 #ifdef DIAGNOSTIC
  506 
  507         if ((ip->i_flag & IN_LOCKED) == 0) {
  508                 vprint("ntfs_unlock: unlocked ntnode", ap->a_vp);
  509                 panic("ntfs_unlock NOT LOCKED");
  510         }
  511         if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 &&
  512             ip->i_lockholder > -1 && ntfs_lockcount++ < 100)
  513                 panic("unlocker (%d) != lock holder (%d)",
  514                     p->p_pid, ip->i_lockholder);
  515 #endif
  516 
  517         if (--ip->i_lockcount > 0) {
  518                 if ((ip->i_flag & IN_RECURSE) == 0)
  519                         panic("ntfs_unlock: recursive lock prematurely released, pid=%d\n", ip->i_lockholder);
  520                 return (0);
  521         }
  522         ip->i_lockholder = 0;
  523         ip->i_flag &= ~(IN_LOCKED|IN_RECURSE);
  524         if (ip->i_flag & IN_WANTED) {
  525                 ip->i_flag &= ~IN_WANTED;
  526                 wakeup((caddr_t)ip);
  527         }
  528         return (0);
  529 }
  530 
  531 /*
  532  * Lock an ntnode. If its already locked, set the WANT bit and sleep.
  533  */
  534 int
  535 ntfs_lock(ap)
  536         struct vop_lock_args /* {
  537                 struct vnode *a_vp;
  538         } */ *ap;
  539 {
  540         struct proc *p = curproc;
  541         register struct vnode *vp = ap->a_vp;
  542         register struct ntnode *ip = VTONT(vp);
  543 
  544         dprintf(("ntfs_lock %d (%d locks)\n",ip->i_number,ip->i_lockcount));
  545 
  546 start:
  547         while (vp->v_flag & VXLOCK) {
  548                 vp->v_flag |= VXWANT;
  549                 (void) tsleep((caddr_t)vp, PINOD, "ntflk1", 0);
  550         }
  551         if (vp->v_tag == VT_NON)
  552                 return (ENOENT);
  553         ip = VTONT(vp);
  554         if (ip->i_flag & IN_LOCKED) {
  555                 if (p->p_pid == ip->i_lockholder) {
  556                         if( (ip->i_flag & IN_RECURSE) == 0)
  557                                 panic("ntfs_lock: recursive lock not expected, pid: %d\n",
  558                                         ip->i_lockholder);
  559                 } else {
  560                         ip->i_flag |= IN_WANTED;
  561 #ifdef DIAGNOSTIC
  562                         if (p)
  563                                 ip->i_lockwaiter = p->p_pid;
  564                         else
  565                                 ip->i_lockwaiter = -1;
  566 #endif
  567                         (void) tsleep((caddr_t)ip, PINOD, "ntflk2", 0);
  568                         goto start;
  569                 }
  570         }
  571 #ifdef DIAGNOSTIC
  572         ip->i_lockwaiter = 0;
  573         if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0))
  574                 panic("lockholder (%d) != 0", ip->i_lockholder);
  575         if (p && p->p_pid == 0)
  576                 printf("locking by process 0\n");
  577 #endif
  578 
  579         if ((ip->i_flag & IN_RECURSE) == 0)
  580                 ip->i_lockcount = 1;
  581         else
  582                 ++ip->i_lockcount;
  583 
  584         if (p)
  585                 ip->i_lockholder = p->p_pid;
  586         else
  587                 ip->i_lockholder = -1;
  588         ip->i_flag |= IN_LOCKED;
  589         return (0);
  590 }
  591 #endif
  592 
  593 int
  594 ntfs_access(ap)
  595         struct vop_access_args /* {
  596                 struct vnode *a_vp;
  597                 int  a_mode;
  598                 struct ucred *a_cred;
  599                 struct proc *a_p;
  600         } */ *ap;
  601 {
  602         struct vnode *vp = ap->a_vp;
  603         struct ntnode *ip = VTONT(vp);
  604         struct ucred *cred = ap->a_cred;
  605         mode_t mask, mode = ap->a_mode;
  606         register gid_t *gp;
  607         int i;
  608 #ifdef QUOTA
  609         int error;
  610 #endif
  611 
  612         dprintf(("ntfs_access: %d\n",ip->i_number));
  613 
  614         /*
  615          * Disallow write attempts on read-only file systems;
  616          * unless the file is a socket, fifo, or a block or
  617          * character device resident on the file system.
  618          */
  619         if (mode & VWRITE) {
  620                 switch ((int)vp->v_type) {
  621                 case VDIR:
  622                 case VLNK:
  623                 case VREG:
  624                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  625                                 return (EROFS);
  626 #ifdef QUOTA
  627                         if (error = getinoquota(ip))
  628                                 return (error);
  629 #endif
  630                         break;
  631                 }
  632         }
  633 
  634         /* If immutable bit set, nobody gets to write it. */
  635 /*
  636         if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
  637                 return (EPERM);
  638 */
  639 
  640         /* Otherwise, user id 0 always gets access. */
  641         if (cred->cr_uid == 0)
  642                 return (0);
  643 
  644         mask = 0;
  645 
  646         /* Otherwise, check the owner. */
  647         if (cred->cr_uid == ip->i_uid) {
  648                 if (mode & VEXEC)
  649                         mask |= S_IXUSR;
  650                 if (mode & VREAD)
  651                         mask |= S_IRUSR;
  652                 if (mode & VWRITE)
  653                         mask |= S_IWUSR;
  654                 return ((ip->i_mode & mask) == mask ? 0 : EACCES);
  655         }
  656 
  657         /* Otherwise, check the groups. */
  658         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
  659                 if (ip->i_gid == *gp) {
  660                         if (mode & VEXEC)
  661                                 mask |= S_IXGRP;
  662                         if (mode & VREAD)
  663                                 mask |= S_IRGRP;
  664                         if (mode & VWRITE)
  665                                 mask |= S_IWGRP;
  666                         return ((ip->i_mode & mask) == mask ? 0 : EACCES);
  667                 }
  668 
  669         /* Otherwise, check everyone else. */
  670         if (mode & VEXEC)
  671                 mask |= S_IXOTH;
  672         if (mode & VREAD)
  673                 mask |= S_IROTH;
  674         if (mode & VWRITE)
  675                 mask |= S_IWOTH;
  676         return ((ip->i_mode & mask) == mask ? 0 : EACCES);
  677 }
  678 
  679 /*
  680  * Open called.
  681  *
  682  * Nothing to do.
  683  */
  684 /* ARGSUSED */
  685 static int
  686 ntfs_open(ap)
  687         struct vop_open_args /* {
  688                 struct vnode *a_vp;
  689                 int  a_mode;
  690                 struct ucred *a_cred;
  691                 struct proc *a_p;
  692         } */ *ap;
  693 {
  694 #if NTFS_DEBUG
  695         register struct vnode *vp = ap->a_vp;
  696         register struct ntnode *ip = VTONT(vp);
  697 
  698         printf("ntfs_open: %d\n",ip->i_number);
  699 #endif
  700 
  701         /*
  702          * Files marked append-only must be opened for appending.
  703          */
  704 
  705         return (0);
  706 }
  707 
  708 /*
  709  * Close called.
  710  *
  711  * Update the times on the inode.
  712  */
  713 /* ARGSUSED */
  714 static int
  715 ntfs_close(ap)
  716         struct vop_close_args /* {
  717                 struct vnode *a_vp;
  718                 int  a_fflag;
  719                 struct ucred *a_cred;
  720                 struct proc *a_p;
  721         } */ *ap;
  722 {
  723 #if NTFS_DEBUG
  724         register struct vnode *vp = ap->a_vp;
  725         register struct ntnode *ip = VTONT(vp);
  726 
  727         printf("ntfs_close: %d\n",ip->i_number);
  728 #endif
  729 
  730         return (0);
  731 }
  732 
  733 int
  734 ntfs_readdir(ap)
  735         struct vop_readdir_args /* {
  736                 struct vnode *a_vp;
  737                 struct uio *a_uio;
  738                 struct ucred *a_cred;
  739                 int *a_ncookies;
  740                 u_int **cookies;
  741         } */ *ap;
  742 {
  743         register struct vnode *vp = ap->a_vp;
  744         register struct fnode *fp = VTOF(vp);
  745         register struct ntnode *ip = FTONT(fp);
  746         struct uio *uio = ap->a_uio;
  747         struct ntfsmount *ntmp = ip->i_mp;
  748         int i, error = 0;
  749         u_int32_t faked = 0, num;
  750         int ncookies = 0;
  751         struct dirent cde;
  752         off_t off;
  753 
  754         dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
  755 
  756         off = uio->uio_offset;
  757 
  758         /* Simulate . in every dir except ROOT */
  759         if( ip->i_number != NTFS_ROOTINO ) {
  760                 struct dirent dot = { NTFS_ROOTINO,
  761                                 sizeof(struct dirent), DT_DIR, 1, "." };
  762 
  763                 if( uio->uio_offset < sizeof(struct dirent) ) {
  764                         dot.d_fileno = ip->i_number;
  765                         error = uiomove((char *)&dot,sizeof(struct dirent),uio);
  766                         if(error)
  767                                 return (error);
  768 
  769                         ncookies ++;
  770                 }
  771         }
  772 
  773         /* Simulate .. in every dir including ROOT */
  774         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
  775                 struct dirent dotdot = { NTFS_ROOTINO,
  776                                 sizeof(struct dirent), DT_DIR, 2, ".." };
  777 
  778                 error = uiomove((char *)&dotdot,sizeof(struct dirent),uio);
  779                 if(error)
  780                         return (error);
  781 
  782                 ncookies ++;
  783         }
  784 
  785         faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
  786         num = uio->uio_offset / sizeof(struct dirent) - faked;
  787 
  788         while( uio->uio_resid >= sizeof(struct dirent) ) {
  789                 struct attr_indexentry *iep;
  790 
  791                 error = ntfs_ntreaddir(ntmp, fp, num, &iep);
  792 
  793                 if(error)
  794                         return (error);
  795 
  796                 if( NULL == iep )
  797                         break;
  798 
  799                 while( !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)) ) {
  800 
  801                         if( ntfs_isnamepermitted(ntmp,iep) ) {
  802                                 dprintf(("ntfs_readdir: elem: %d, fname:[",num));
  803                                 for(i=0;i<iep->ie_fnamelen;i++) {
  804                                         cde.d_name[i] = (char)iep->ie_fname[i];
  805                                         dprintf(("%c", cde.d_name[i]));
  806                                 }
  807                                 dprintf(("] type: %d, flag: %d, ",iep->ie_fnametype, iep->ie_flag));
  808                                 cde.d_name[i] = '\0';
  809                                 cde.d_namlen = iep->ie_fnamelen;
  810                                 cde.d_fileno = iep->ie_number;
  811                                 cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
  812                                 cde.d_reclen = sizeof(struct dirent);
  813                                 dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
  814 
  815                                 error = uiomove((char *)&cde, sizeof(struct dirent), uio);
  816                                 if(error)
  817                                         return (error);
  818 
  819                                 ncookies++;
  820                                 num++;
  821                         }
  822 
  823                         iep = NTFS_NEXTREC(iep,struct attr_indexentry *);
  824                 }
  825         }
  826 
  827         dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
  828                 ncookies,(u_int)(uio->uio_offset - off)));
  829         dprintf(("ntfs_readdir: off: %d resid: %d\n",
  830                 (u_int32_t)uio->uio_offset,uio->uio_resid));
  831 
  832         if (!error && ap->a_ncookies != NULL) {
  833                 struct dirent* dpStart;
  834                 struct dirent* dp;
  835 #if defined(__FreeBSD__)
  836                 u_long *cookies;
  837                 u_long *cookiep;
  838 #else /* defined(__NetBSD__) */
  839                 off_t *cookies;
  840                 off_t *cookiep;
  841 #endif
  842 
  843                 printf("ntfs_readdir: %d cookies\n",ncookies);
  844                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
  845                         panic("ntfs_readdir: unexpected uio from NFS server");
  846                 dpStart = (struct dirent *)
  847                      ((caddr_t)uio->uio_iov->iov_base -
  848                          (uio->uio_offset - off));
  849 #if defined(__FreeBSD__)
  850                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
  851                        M_TEMP, M_WAITOK);
  852 #else /* defined(__NetBSD__) */
  853                 MALLOC(cookies, off_t *, ncookies * sizeof(off_t),
  854                        M_TEMP, M_WAITOK);
  855 #endif
  856                 for (dp = dpStart, cookiep = cookies, i=0;
  857                      i < ncookies;
  858                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
  859                         off += dp->d_reclen;
  860                         *cookiep++ = (u_int) off;
  861                 }
  862                 *ap->a_ncookies = ncookies;
  863                 *ap->a_cookies = cookies;
  864         }
  865 /*
  866         if (ap->a_eofflag)
  867             *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
  868 */
  869         return (error);
  870 }
  871 
  872 int
  873 ntfs_lookup(ap)
  874         struct vop_lookup_args /* {
  875                 struct vnode *a_dvp;
  876                 struct vnode **a_vpp;
  877                 struct componentname *a_cnp;
  878         } */ *ap;
  879 {
  880         register struct vnode *dvp = ap->a_dvp;
  881         register struct ntnode *dip = VTONT(dvp);
  882         struct ntfsmount *ntmp = dip->i_mp;
  883         struct componentname *cnp = ap->a_cnp;
  884         struct ucred *cred = cnp->cn_cred;
  885         int error;
  886         int lockparent = cnp->cn_flags & LOCKPARENT;
  887 #if NTFS_DEBUG
  888         int wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
  889 #endif
  890         dprintf(("ntfs_lookup: %s (%ld bytes) in %d, lp: %d, wp: %d \n",
  891                 cnp->cn_nameptr, cnp->cn_namelen,
  892                 dip->i_number,lockparent, wantparent));
  893 
  894         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
  895         if(error)
  896                 return (error);
  897 
  898         if( (cnp->cn_namelen == 1) &&
  899             !strncmp(cnp->cn_nameptr,".",1) ) {
  900                 dprintf(("ntfs_lookup: faking . directory in %d\n",
  901                         dip->i_number));
  902 
  903                 VREF(dvp);
  904                 *ap->a_vpp = dvp;
  905                 return (0);
  906         } else if( (cnp->cn_namelen == 2) &&
  907             !strncmp(cnp->cn_nameptr,"..",2) &&
  908             (cnp->cn_flags & ISDOTDOT) ) {
  909                 struct ntvattr *vap;
  910 
  911                 dprintf(("ntfs_lookup: faking .. directory in %d\n",
  912                          dip->i_number));
  913 
  914                 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
  915                 if(error)
  916                         return (error);
  917 
  918                 VOP__UNLOCK(dvp,0,cnp->cn_proc);
  919 
  920                 dprintf(("ntfs_lookup: parentdir: %d\n",
  921                          vap->va_a_name->n_pnumber));
  922                 error = VFS_VGET(ntmp->ntm_mountp,
  923                                  vap->va_a_name->n_pnumber,ap->a_vpp); 
  924                 ntfs_ntvattrrele(vap);
  925                 if(error) {
  926                         VOP__LOCK(dvp, 0, cnp->cn_proc);
  927                         return(error);
  928                 }
  929 
  930                 if( lockparent && (cnp->cn_flags & ISLASTCN) && 
  931                     (error = VOP__LOCK(dvp, 0, cnp->cn_proc)) ) {
  932                         vput( *(ap->a_vpp) );
  933                         return (error);
  934                 }
  935                 return (error);
  936         } else {
  937                 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
  938                 if(error)
  939                         return (error);
  940 
  941                 dprintf(("ntfs_lookup: found ino: %d\n", 
  942                         VTONT(*ap->a_vpp)->i_number));
  943 
  944                 if(!lockparent || !(cnp->cn_flags & ISLASTCN))
  945                         VOP__UNLOCK(dvp, 0, cnp->cn_proc);
  946                 if (cnp->cn_flags & MAKEENTRY)
  947                         cache_enter(dvp, *ap->a_vpp, cnp);
  948 
  949         }
  950         return (error);
  951 }
  952 
  953 /*
  954  * Flush the blocks of a file to disk.
  955  *
  956  * This function is worthless for vnodes that represent directories. Maybe we
  957  * could just do a sync if they try an fsync on a directory file.
  958  */
  959 static int
  960 ntfs_fsync(ap)
  961         struct vop_fsync_args /* {
  962                 struct vnode *a_vp;
  963                 struct ucred *a_cred;
  964                 int a_waitfor;
  965                 struct proc *a_p;
  966         } */ *ap;
  967 {
  968         return (0);
  969 }
  970 
  971 /*
  972  * Global vfs data structures
  973  */
  974 vop_t **ntfs_vnodeop_p;
  975 #if defined(__FreeBSD__)
  976 static
  977 #endif
  978 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
  979         { &vop_default_desc, (vop_t *)ntfs_bypass },
  980 
  981         { &vop_getattr_desc, (vop_t *)ntfs_getattr },
  982         { &vop_inactive_desc, (vop_t *)ntfs_inactive },
  983         { &vop_reclaim_desc, (vop_t *)ntfs_reclaim },
  984         { &vop_print_desc, (vop_t *)ntfs_print },
  985 
  986 #if defined(__FreeBSD__)
  987         { &vop_islocked_desc, (vop_t *)vop_stdislocked },
  988         { &vop_unlock_desc, (vop_t *)vop_stdunlock },
  989         { &vop_lock_desc, (vop_t *)vop_stdlock },
  990         { &vop_cachedlookup_desc, (vop_t *)ntfs_lookup },
  991         { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
  992 #else
  993         { &vop_islocked_desc, (vop_t *)ntfs_islocked },
  994         { &vop_unlock_desc, (vop_t *)ntfs_unlock },
  995         { &vop_lock_desc, (vop_t *)ntfs_lock },
  996         { &vop_lookup_desc, (vop_t *)ntfs_lookup },
  997 #endif
  998 
  999         { &vop_access_desc, (vop_t *)ntfs_access },
 1000         { &vop_close_desc, (vop_t *)ntfs_close },
 1001         { &vop_open_desc, (vop_t *)ntfs_open },
 1002         { &vop_readdir_desc, (vop_t *)ntfs_readdir },
 1003         { &vop_fsync_desc, (vop_t *)ntfs_fsync },
 1004 
 1005         { &vop_bmap_desc, (vop_t *)ntfs_bmap },
 1006 #if defined(__FreeBSD__)
 1007         { &vop_getpages_desc, (vop_t *) ntfs_getpages },
 1008         { &vop_putpages_desc, (vop_t *) ntfs_putpages },
 1009 #endif
 1010         { &vop_strategy_desc, (vop_t *)ntfs_strategy },
 1011 #if defined(__FreeBSD__)
 1012         { &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
 1013 #else /* defined(__NetBSD__) */
 1014         { &vop_bwrite_desc, (vop_t *)vn_bwrite },
 1015 #endif
 1016         { &vop_read_desc, (vop_t *)ntfs_read },
 1017         { &vop_write_desc, (vop_t *)ntfs_write },
 1018 
 1019         { NULL, NULL }
 1020 };
 1021 
 1022 #if defined(__FreeBSD__)
 1023 static
 1024 #endif
 1025 struct vnodeopv_desc ntfs_vnodeop_opv_desc =
 1026         { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
 1027 
 1028 #if defined(__FreeBSD__)
 1029 VNODEOP_SET(ntfs_vnodeop_opv_desc);
 1030 #endif

Cache object: 79ce99b7b895bd4abf689f8bd2bfc936


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