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

Cache object: 5f86c1d41a570ac98b4beafd4c6cd001


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