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

Cache object: e9f09ef2b7833c08dfbdab14ab41b39d


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