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/hpfs/hpfs_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 /*-
    2  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/5.0/sys/fs/hpfs/hpfs_vnops.c 105077 2002-10-14 03:20:36Z mckusick $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/proc.h>
   33 #include <sys/time.h>
   34 #include <sys/types.h>
   35 #include <sys/stat.h>
   36 #include <sys/vnode.h>
   37 #include <sys/mount.h>
   38 #include <sys/namei.h>
   39 #include <sys/malloc.h>
   40 #include <sys/bio.h>
   41 #include <sys/buf.h>
   42 #include <sys/dirent.h>
   43 
   44 #include <vm/vm.h>
   45 #include <vm/vm_param.h>
   46 #include <vm/vm_page.h>
   47 #include <vm/vm_object.h>
   48 #include <vm/vm_pager.h>
   49 #include <vm/vnode_pager.h>
   50 #include <vm/vm_extern.h>
   51 
   52 #include <sys/unistd.h> /* for pathconf(2) constants */
   53 
   54 #include <fs/hpfs/hpfs.h>
   55 #include <fs/hpfs/hpfsmount.h>
   56 #include <fs/hpfs/hpfs_subr.h>
   57 #include <fs/hpfs/hpfs_ioctl.h>
   58 
   59 static int      hpfs_de_uiomove(struct hpfsmount *, struct hpfsdirent *,
   60                                      struct uio *);
   61 static int      hpfs_ioctl(struct vop_ioctl_args *ap);
   62 static int      hpfs_read(struct vop_read_args *);
   63 static int      hpfs_write(struct vop_write_args *ap);
   64 static int      hpfs_getattr(struct vop_getattr_args *ap);
   65 static int      hpfs_setattr(struct vop_setattr_args *ap);
   66 static int      hpfs_inactive(struct vop_inactive_args *ap);
   67 static int      hpfs_print(struct vop_print_args *ap);
   68 static int      hpfs_reclaim(struct vop_reclaim_args *ap);
   69 static int      hpfs_strategy(struct vop_strategy_args *ap);
   70 static int      hpfs_access(struct vop_access_args *ap);
   71 static int      hpfs_open(struct vop_open_args *ap);
   72 static int      hpfs_close(struct vop_close_args *ap);
   73 static int      hpfs_readdir(struct vop_readdir_args *ap);
   74 static int      hpfs_lookup(struct vop_lookup_args *ap);
   75 static int      hpfs_create(struct vop_create_args *);
   76 static int      hpfs_remove(struct vop_remove_args *);
   77 static int      hpfs_bmap(struct vop_bmap_args *ap);
   78 static int      hpfs_fsync(struct vop_fsync_args *ap);
   79 static int      hpfs_pathconf(struct vop_pathconf_args *ap);
   80 
   81 static int
   82 hpfs_fsync(ap)
   83         struct vop_fsync_args /* {
   84                 struct vnode *a_vp;
   85                 struct ucred *a_cred;
   86                 int a_waitfor;
   87                 struct thread *a_td;
   88         } */ *ap;
   89 {
   90         struct vnode *vp = ap->a_vp;
   91         int s;
   92         struct buf *bp, *nbp;
   93 
   94         /*
   95          * Flush all dirty buffers associated with a vnode.
   96          */
   97 loop:
   98         VI_LOCK(vp);
   99         s = splbio();
  100         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  101                 nbp = TAILQ_NEXT(bp, b_vnbufs);
  102                 VI_UNLOCK(vp);
  103                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
  104                         VI_LOCK(vp);
  105                         continue;
  106                 }
  107                 if ((bp->b_flags & B_DELWRI) == 0)
  108                         panic("hpfs_fsync: not dirty");
  109                 bremfree(bp);
  110                 splx(s);
  111                 (void) bwrite(bp);
  112                 goto loop;
  113         }
  114         while (vp->v_numoutput) {
  115                 vp->v_iflag |= VI_BWAIT;
  116                 msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), PRIBIO + 1,
  117                     "hpfsn", 0);
  118         }
  119 #ifdef DIAGNOSTIC
  120         if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
  121                 vprint("hpfs_fsync: dirty", vp);
  122                 goto loop;
  123         }
  124 #endif
  125         VI_UNLOCK(vp);
  126         splx(s);
  127 
  128         /*
  129          * Write out the on-disc version of the vnode.
  130          */
  131         return hpfs_update(VTOHP(vp));
  132 }
  133 
  134 static int
  135 hpfs_ioctl (
  136         struct vop_ioctl_args /* {
  137                 struct vnode *a_vp;
  138                 u_long a_command;
  139                 caddr_t a_data;
  140                 int a_fflag;
  141                 struct ucred *a_cred;
  142                 struct thread *a_td;
  143         } */ *ap)
  144 {
  145         register struct vnode *vp = ap->a_vp;
  146         register struct hpfsnode *hp = VTOHP(vp);
  147         int error;
  148 
  149         printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
  150                 hp->h_no, ap->a_command, ap->a_data, ap->a_fflag);
  151 
  152         switch (ap->a_command) {
  153         case HPFSIOCGEANUM: {
  154                 u_long eanum;
  155                 u_long passed;
  156                 struct ea *eap;
  157 
  158                 eanum = 0;
  159 
  160                 if (hp->h_fn.fn_ealen > 0) {
  161                         eap = (struct ea *)&(hp->h_fn.fn_int);
  162                         passed = 0;
  163 
  164                         while (passed < hp->h_fn.fn_ealen) {
  165 
  166                                 printf("EAname: %s\n", EA_NAME(eap));
  167 
  168                                 eanum++;
  169                                 passed += sizeof(struct ea) +
  170                                           eap->ea_namelen + 1 + eap->ea_vallen;
  171                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  172                                                 passed);
  173                         }
  174                         error = 0;
  175                 } else {
  176                         error = ENOENT;
  177                 }
  178 
  179                 printf("%lu eas\n", eanum);
  180 
  181                 *(u_long *)ap->a_data = eanum;
  182 
  183                 break;
  184         }
  185         case HPFSIOCGEASZ: {
  186                 u_long eanum;
  187                 u_long passed;
  188                 struct ea *eap;
  189 
  190                 printf("EA%ld\n", *(u_long *)ap->a_data);
  191 
  192                 eanum = 0;
  193                 if (hp->h_fn.fn_ealen > 0) {
  194                         eap = (struct ea *)&(hp->h_fn.fn_int);
  195                         passed = 0;
  196 
  197                         error = ENOENT;
  198                         while (passed < hp->h_fn.fn_ealen) {
  199                                 printf("EAname: %s\n", EA_NAME(eap));
  200 
  201                                 if (eanum == *(u_long *)ap->a_data) {
  202                                         *(u_long *)ap->a_data =
  203                                                 eap->ea_namelen + 1 +
  204                                                 eap->ea_vallen;
  205 
  206                                         error = 0;
  207                                         break;
  208                                 }
  209 
  210                                 eanum++;
  211                                 passed += sizeof(struct ea) +
  212                                           eap->ea_namelen + 1 + eap->ea_vallen;
  213                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  214                                                 passed);
  215                         }
  216                 } else {
  217                         error = ENOENT;
  218                 }
  219 
  220                 break;
  221         }
  222         case HPFSIOCRDEA: {
  223                 u_long eanum;
  224                 u_long passed;
  225                 struct hpfs_rdea *rdeap;
  226                 struct ea *eap;
  227 
  228                 rdeap = (struct hpfs_rdea *)ap->a_data;
  229                 printf("EA%ld\n", rdeap->ea_no);
  230 
  231                 eanum = 0;
  232                 if (hp->h_fn.fn_ealen > 0) {
  233                         eap = (struct ea *)&(hp->h_fn.fn_int);
  234                         passed = 0;
  235 
  236                         error = ENOENT;
  237                         while (passed < hp->h_fn.fn_ealen) {
  238                                 printf("EAname: %s\n", EA_NAME(eap));
  239 
  240                                 if (eanum == rdeap->ea_no) {
  241                                         rdeap->ea_sz = eap->ea_namelen + 1 +
  242                                                         eap->ea_vallen;
  243                                         copyout(EA_NAME(eap),rdeap->ea_data,
  244                                                 rdeap->ea_sz);
  245                                         error = 0;
  246                                         break;
  247                                 }
  248 
  249                                 eanum++;
  250                                 passed += sizeof(struct ea) +
  251                                           eap->ea_namelen + 1 + eap->ea_vallen;
  252                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  253                                                 passed);
  254                         }
  255                 } else {
  256                         error = ENOENT;
  257                 }
  258 
  259                 break;
  260         }
  261         default:
  262                 error = ENOTTY;
  263                 break;
  264         }
  265         return (error);
  266 }
  267 
  268 /*
  269  * Map file offset to disk offset.
  270  */
  271 int
  272 hpfs_bmap(ap)
  273         struct vop_bmap_args /* {
  274                 struct vnode *a_vp;
  275                 daddr_t  a_bn;
  276                 struct vnode **a_vpp;
  277                 daddr_t *a_bnp;
  278                 int *a_runp;
  279                 int *a_runb;
  280         } */ *ap;
  281 {
  282         register struct hpfsnode *hp = VTOHP(ap->a_vp);
  283         daddr_t blkno;
  284         int error;
  285 
  286         if (ap->a_vpp != NULL) 
  287                 *ap->a_vpp = hp->h_devvp;
  288         if (ap->a_runb != NULL)
  289                 *ap->a_runb = 0;
  290         if (ap->a_bnp == NULL)
  291                 return (0);
  292 
  293         dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn));
  294 
  295         error = hpfs_hpbmap (hp, ap->a_bn, &blkno, ap->a_runp);
  296         *ap->a_bnp = blkno;
  297 
  298         return (error);
  299 }
  300 
  301 static int
  302 hpfs_read(ap)
  303         struct vop_read_args /* {
  304                 struct vnode *a_vp;
  305                 struct uio *a_uio;
  306                 int a_ioflag;
  307                 struct ucred *a_cred;
  308         } */ *ap;
  309 {
  310         register struct vnode *vp = ap->a_vp;
  311         register struct hpfsnode *hp = VTOHP(vp);
  312         struct uio *uio = ap->a_uio;
  313         struct buf *bp;
  314         u_int xfersz, toread;
  315         u_int off;
  316         daddr_t lbn, bn;
  317         int resid;
  318         int runl;
  319         int error = 0;
  320 
  321         resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset);
  322 
  323         dprintf(("hpfs_read(0x%x, off: %d resid: %d, segflg: %d): [resid: 0x%x]\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg, resid));
  324 
  325         while (resid) {
  326                 lbn = uio->uio_offset >> DEV_BSHIFT;
  327                 off = uio->uio_offset & (DEV_BSIZE - 1);
  328                 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
  329                         uio->uio_resid, lbn, off));
  330                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
  331                 if (error)
  332                         return (error);
  333 
  334                 toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
  335                 xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
  336                 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
  337                         bn, runl, toread, xfersz));
  338 
  339                 if (toread == 0) 
  340                         break;
  341 
  342                 error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
  343                 if (error) {
  344                         brelse(bp);
  345                         break;
  346                 }
  347 
  348                 error = uiomove(bp->b_data + off, toread - off, uio);
  349                 if(error) {
  350                         brelse(bp);
  351                         break;
  352                 }
  353                 brelse(bp);
  354                 resid -= toread;
  355         }
  356         dprintf(("hpfs_read: successful\n"));
  357         return (error);
  358 }
  359 
  360 static int
  361 hpfs_write(ap)
  362         struct vop_write_args /* {
  363                 struct vnode *a_vp;
  364                 struct uio *a_uio;
  365                 int  a_ioflag;
  366                 struct ucred *a_cred;
  367         } */ *ap;
  368 {
  369         register struct vnode *vp = ap->a_vp;
  370         register struct hpfsnode *hp = VTOHP(vp);
  371         struct uio *uio = ap->a_uio;
  372         struct buf *bp;
  373         u_int xfersz, towrite;
  374         u_int off;
  375         daddr_t lbn, bn;
  376         int runl;
  377         int error = 0;
  378 
  379         dprintf(("hpfs_write(0x%x, off: %d resid: %d, segflg: %d):\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
  380 
  381         if (ap->a_ioflag & IO_APPEND) {
  382                 dprintf(("hpfs_write: APPEND mode\n"));
  383                 uio->uio_offset = hp->h_fn.fn_size;
  384         }
  385         if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) {
  386                 error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid);
  387                 if (error) {
  388                         printf("hpfs_write: hpfs_extend FAILED %d\n", error);
  389                         return (error);
  390                 }
  391         }
  392 
  393         while (uio->uio_resid) {
  394                 lbn = uio->uio_offset >> DEV_BSHIFT;
  395                 off = uio->uio_offset & (DEV_BSIZE - 1);
  396                 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
  397                         uio->uio_resid, lbn, off));
  398                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
  399                 if (error)
  400                         return (error);
  401 
  402                 towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
  403                 xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
  404                 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
  405                         bn, runl, towrite, xfersz));
  406 
  407                 if ((off == 0) && (towrite == xfersz)) {
  408                         bp = getblk(hp->h_devvp, bn, xfersz, 0, 0);
  409                         clrbuf(bp);
  410                 } else {
  411                         error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
  412                         if (error) {
  413                                 brelse(bp);
  414                                 return (error);
  415                         }
  416                 }
  417 
  418                 error = uiomove(bp->b_data + off, towrite - off, uio);
  419                 if(error) {
  420                         brelse(bp);
  421                         return (error);
  422                 }
  423 
  424                 if (ap->a_ioflag & IO_SYNC)
  425                         bwrite(bp);
  426                 else
  427                         bawrite(bp);
  428         }
  429 
  430         dprintf(("hpfs_write: successful\n"));
  431         return (0);
  432 }
  433 
  434 /*
  435  * XXXXX do we need hpfsnode locking inside?
  436  */
  437 static int
  438 hpfs_getattr(ap)
  439         struct vop_getattr_args /* {
  440                 struct vnode *a_vp;
  441                 struct vattr *a_vap;
  442                 struct ucred *a_cred;
  443                 struct thread *a_td;
  444         } */ *ap;
  445 {
  446         register struct vnode *vp = ap->a_vp;
  447         register struct hpfsnode *hp = VTOHP(vp);
  448         register struct vattr *vap = ap->a_vap;
  449         int error;
  450 
  451         dprintf(("hpfs_getattr(0x%x):\n", hp->h_no));
  452 
  453         vap->va_fsid = dev2udev(hp->h_dev);
  454         vap->va_fileid = hp->h_no;
  455         vap->va_mode = hp->h_mode;
  456         vap->va_nlink = 1;
  457         vap->va_uid = hp->h_uid;
  458         vap->va_gid = hp->h_gid;
  459         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  460         vap->va_size = hp->h_fn.fn_size;
  461         vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) +
  462                         DEV_BSIZE;
  463 
  464         if (!(hp->h_flag & H_PARVALID)) {
  465                 error = hpfs_validateparent(hp);
  466                 if (error) 
  467                         return (error);
  468         }
  469         vap->va_atime = hpfstimetounix(hp->h_atime);
  470         vap->va_mtime = hpfstimetounix(hp->h_mtime);
  471         vap->va_ctime = hpfstimetounix(hp->h_ctime);
  472 
  473         vap->va_flags = 0;
  474         vap->va_gen = 0;
  475         vap->va_blocksize = DEV_BSIZE;
  476         vap->va_type = vp->v_type;
  477         vap->va_filerev = 0;
  478 
  479         return (0);
  480 }
  481 
  482 /*
  483  * XXXXX do we need hpfsnode locking inside?
  484  */
  485 static int
  486 hpfs_setattr(ap)
  487         struct vop_setattr_args /* {
  488                 struct vnode *a_vp;
  489                 struct vattr *a_vap;
  490                 struct ucred *a_cred;
  491                 struct thread *a_td;
  492         } */ *ap;
  493 {
  494         struct vnode *vp = ap->a_vp;
  495         struct hpfsnode *hp = VTOHP(vp);
  496         struct vattr *vap = ap->a_vap;
  497         struct ucred *cred = ap->a_cred;
  498         struct thread *td = ap->a_td;
  499         int error;
  500 
  501         dprintf(("hpfs_setattr(0x%x):\n", hp->h_no));
  502 
  503         /*
  504          * Check for unsettable attributes.
  505          */
  506         if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
  507             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
  508             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
  509             (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
  510                 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
  511                 return (EINVAL);
  512         }
  513 
  514         /* Can't change flags XXX Could be implemented */
  515         if (vap->va_flags != VNOVAL) {
  516                 printf("hpfs_setattr: FLAGS CANNOT BE SET\n");
  517                 return (EINVAL);
  518         }
  519 
  520         /* Can't change uid/gid XXX Could be implemented */
  521         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
  522                 printf("hpfs_setattr: UID/GID CANNOT BE SET\n");
  523                 return (EINVAL);
  524         }
  525 
  526         /* Can't change mode XXX Could be implemented */
  527         if (vap->va_mode != (mode_t)VNOVAL) {
  528                 printf("hpfs_setattr: MODE CANNOT BE SET\n");
  529                 return (EINVAL);
  530         }
  531 
  532         /* Update times */
  533         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  534                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  535                         return (EROFS);
  536                 if (cred->cr_uid != hp->h_uid &&
  537                     (error = suser_cred(cred, PRISON_ROOT)) &&
  538                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
  539                     (error = VOP_ACCESS(vp, VWRITE, cred, td))))
  540                         return (error);
  541                 if (vap->va_atime.tv_sec != VNOVAL)
  542                         hp->h_atime = vap->va_atime.tv_sec;
  543                 if (vap->va_mtime.tv_sec != VNOVAL)
  544                         hp->h_mtime = vap->va_mtime.tv_sec;
  545 
  546                 hp->h_flag |= H_PARCHANGE;
  547         }
  548 
  549         if (vap->va_size != VNOVAL) {
  550                 switch (vp->v_type) {
  551                 case VDIR:
  552                         return (EISDIR);
  553                 case VREG:
  554                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  555                                 return (EROFS);
  556                         break;
  557                 default:
  558                         printf("hpfs_setattr: WRONG v_type\n");
  559                         return (EINVAL);
  560                 }
  561 
  562                 if (vap->va_size < hp->h_fn.fn_size) {
  563                         error = vtruncbuf(vp, cred, td, vap->va_size, DEV_BSIZE);
  564                         if (error)
  565                                 return (error);
  566                         error = hpfs_truncate(hp, vap->va_size);
  567                         if (error)
  568                                 return (error);
  569 
  570                 } else if (vap->va_size > hp->h_fn.fn_size) {
  571                         vnode_pager_setsize(vp, vap->va_size);
  572                         error = hpfs_extend(hp, vap->va_size);
  573                         if (error)
  574                                 return (error);
  575                 }
  576         }
  577 
  578         return (0);
  579 }
  580 
  581 /*
  582  * Last reference to an node.  If necessary, write or delete it.
  583  */
  584 int
  585 hpfs_inactive(ap)
  586         struct vop_inactive_args /* {
  587                 struct vnode *a_vp;
  588         } */ *ap;
  589 {
  590         register struct vnode *vp = ap->a_vp;
  591         register struct hpfsnode *hp = VTOHP(vp);
  592         int error;
  593 
  594         dprintf(("hpfs_inactive(0x%x): \n", hp->h_no));
  595 
  596         if (hp->h_flag & H_CHANGE) {
  597                 dprintf(("hpfs_inactive: node changed, update\n"));
  598                 error = hpfs_update (hp);
  599                 if (error)
  600                         return (error);
  601         }
  602 
  603         if (hp->h_flag & H_PARCHANGE) {
  604                 dprintf(("hpfs_inactive: parent node changed, update\n"));
  605                 error = hpfs_updateparent (hp);
  606                 if (error)
  607                         return (error);
  608         }
  609 
  610         if (prtactive && vrefcnt(vp) != 0)
  611                 vprint("hpfs_inactive: pushing active", vp);
  612 
  613         if (hp->h_flag & H_INVAL) {
  614                 VOP_UNLOCK(vp,0,ap->a_td);
  615                 vrecycle(vp, NULL, ap->a_td);
  616                 return (0);
  617         }
  618 
  619         VOP_UNLOCK(vp,0,ap->a_td);
  620         return (0);
  621 }
  622 
  623 /*
  624  * Reclaim an inode so that it can be used for other purposes.
  625  */
  626 int
  627 hpfs_reclaim(ap)
  628         struct vop_reclaim_args /* {
  629                 struct vnode *a_vp;
  630         } */ *ap;
  631 {
  632         register struct vnode *vp = ap->a_vp;
  633         register struct hpfsnode *hp = VTOHP(vp);
  634 
  635         dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no));
  636 
  637         hpfs_hphashrem(hp);
  638 
  639         /* Purge old data structures associated with the inode. */
  640         cache_purge(vp);
  641         if (hp->h_devvp) {
  642                 vrele(hp->h_devvp);
  643                 hp->h_devvp = NULL;
  644         }
  645 
  646         mtx_destroy(&hp->h_interlock);
  647 
  648         vp->v_data = NULL;
  649 
  650         FREE(hp, M_HPFSNO);
  651 
  652         return (0);
  653 }
  654 
  655 static int
  656 hpfs_print(ap)
  657         struct vop_print_args /* {
  658                 struct vnode *a_vp;
  659         } */ *ap;
  660 {
  661         register struct vnode *vp = ap->a_vp;
  662         register struct hpfsnode *hp = VTOHP(vp);
  663 
  664         printf("ino 0x%x\n", hp->h_no);
  665         return (0);
  666 }
  667 
  668 /*
  669  * Calculate the logical to physical mapping if not done already,
  670  * then call the device strategy routine.
  671  *
  672  * In order to be able to swap to a file, the hpfs_hpbmap operation may not
  673  * deadlock on memory.  See hpfs_bmap() for details. XXXXXXX (not impl)
  674  */
  675 int
  676 hpfs_strategy(ap)
  677         struct vop_strategy_args /* {
  678                 struct buf *a_bp;
  679         } */ *ap;
  680 {
  681         register struct buf *bp = ap->a_bp;
  682         register struct vnode *vp = ap->a_vp;
  683         register struct hpfsnode *hp = VTOHP(ap->a_vp);
  684         daddr_t blkno;
  685         int error;
  686 
  687         dprintf(("hpfs_strategy(): \n"));
  688 
  689         if (vp->v_type == VBLK || vp->v_type == VCHR)
  690                 panic("hpfs_strategy: spec");
  691         if (bp->b_blkno == bp->b_lblkno) {
  692                 error = hpfs_hpbmap (hp, bp->b_lblkno, &blkno, NULL);
  693                 bp->b_blkno = blkno;
  694                 if (error) {
  695                         printf("hpfs_strategy: hpfs_bpbmap FAILED %d\n", error);
  696                         bp->b_error = error;
  697                         bp->b_ioflags |= BIO_ERROR;
  698                         biodone(&bp->b_io);
  699                         return (error);
  700                 }
  701                 if ((long)bp->b_blkno == -1)
  702                         vfs_bio_clrbuf(bp);
  703         }
  704         if ((long)bp->b_blkno == -1) {
  705                 biodone(&bp->b_io);
  706                 return (0);
  707         }
  708         bp->b_dev = hp->h_devvp->v_rdev;
  709         VOP_STRATEGY(hp->h_devvp, bp);
  710         return (0);
  711 }
  712 
  713 /*
  714  * XXXXX do we need hpfsnode locking inside?
  715  */
  716 int
  717 hpfs_access(ap)
  718         struct vop_access_args /* {
  719                 struct vnode *a_vp;
  720                 int  a_mode;
  721                 struct ucred *a_cred;
  722                 struct thread *a_td;
  723         } */ *ap;
  724 {
  725         struct vnode *vp = ap->a_vp;
  726         struct hpfsnode *hp = VTOHP(vp);
  727         mode_t mode = ap->a_mode;
  728 
  729         dprintf(("hpfs_access(0x%x):\n", hp->h_no));
  730 
  731         /*
  732          * Disallow write attempts on read-only filesystems;
  733          * unless the file is a socket, fifo, or a block or
  734          * character device resident on the filesystem.
  735          */
  736         if (mode & VWRITE) {
  737                 switch ((int)vp->v_type) {
  738                 case VDIR:
  739                 case VLNK:
  740                 case VREG:
  741                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  742                                 return (EROFS);
  743                         break;
  744                 }
  745         }
  746 
  747         return (vaccess(vp->v_type, hp->h_mode, hp->h_uid, hp->h_gid,
  748             ap->a_mode, ap->a_cred, NULL));
  749 }
  750 
  751 /*
  752  * Open called.
  753  *
  754  * Nothing to do.
  755  */
  756 /* ARGSUSED */
  757 static int
  758 hpfs_open(ap)
  759         struct vop_open_args /* {
  760                 struct vnode *a_vp;
  761                 int  a_mode;
  762                 struct ucred *a_cred;
  763                 struct thread *a_td;
  764         } */ *ap;
  765 {
  766 #if HPFS_DEBUG
  767         register struct vnode *vp = ap->a_vp;
  768         register struct hpfsnode *hp = VTOHP(vp);
  769 
  770         printf("hpfs_open(0x%x):\n",hp->h_no);
  771 #endif
  772 
  773         /*
  774          * Files marked append-only must be opened for appending.
  775          */
  776 
  777         return (0);
  778 }
  779 
  780 /*
  781  * Close called.
  782  *
  783  * Update the times on the inode.
  784  */
  785 /* ARGSUSED */
  786 static int
  787 hpfs_close(ap)
  788         struct vop_close_args /* {
  789                 struct vnode *a_vp;
  790                 int  a_fflag;
  791                 struct ucred *a_cred;
  792                 struct thread *a_td;
  793         } */ *ap;
  794 {
  795 #if HPFS_DEBUG
  796         register struct vnode *vp = ap->a_vp;
  797         register struct hpfsnode *hp = VTOHP(vp);
  798 
  799         printf("hpfs_close: %d\n",hp->h_no);
  800 #endif
  801 
  802         return (0);
  803 }
  804 
  805 static int
  806 hpfs_de_uiomove (
  807         struct hpfsmount *hpmp,
  808         struct hpfsdirent *dep,
  809         struct uio *uio)
  810 {
  811         struct dirent cde;
  812         int i, error;
  813 
  814         dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
  815                 dep->de_fnode, dep->de_size, dep->de_namelen,
  816                 dep->de_namelen, dep->de_name, dep->de_flag));
  817 
  818         /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
  819         for (i=0; i<dep->de_namelen; i++) 
  820                 cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]);
  821 
  822         cde.d_name[dep->de_namelen] = '\0';
  823         cde.d_namlen = dep->de_namelen;
  824         cde.d_fileno = dep->de_fnode;
  825         cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG;
  826         cde.d_reclen = sizeof(struct dirent);
  827 
  828         error = uiomove((char *)&cde, sizeof(struct dirent), uio);
  829         if (error)
  830                 return (error);
  831         
  832         dprintf(("[0x%x] ", uio->uio_resid));
  833         return (error);
  834 }
  835 
  836 
  837 static struct dirent hpfs_de_dot =
  838         { 0, sizeof(struct dirent), DT_DIR, 1, "." };
  839 static struct dirent hpfs_de_dotdot =
  840         { 0, sizeof(struct dirent), DT_DIR, 2, ".." };
  841 int
  842 hpfs_readdir(ap)
  843         struct vop_readdir_args /* {
  844                 struct vnode *a_vp;
  845                 struct uio *a_uio;
  846                 struct ucred *a_cred;
  847                 int *a_ncookies;
  848                 u_int **cookies;
  849         } */ *ap;
  850 {
  851         register struct vnode *vp = ap->a_vp;
  852         register struct hpfsnode *hp = VTOHP(vp);
  853         struct hpfsmount *hpmp = hp->h_hpmp;
  854         struct uio *uio = ap->a_uio;
  855         int ncookies = 0, i, num, cnum;
  856         int error = 0;
  857         off_t off;
  858         struct buf *bp;
  859         struct dirblk *dp;
  860         struct hpfsdirent *dep;
  861         lsn_t olsn;
  862         lsn_t lsn;
  863         int level;
  864 
  865         dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid));
  866 
  867         off = uio->uio_offset;
  868 
  869         if( uio->uio_offset < sizeof(struct dirent) ) {
  870                 dprintf((". faked, "));
  871                 hpfs_de_dot.d_fileno = hp->h_no;
  872                 error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio);
  873                 if(error) {
  874                         return (error);
  875                 }
  876 
  877                 ncookies ++;
  878         }
  879 
  880         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
  881                 dprintf((".. faked, "));
  882                 hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent;
  883 
  884                 error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent),
  885                                 uio);
  886                 if(error) {
  887                         return (error);
  888                 }
  889 
  890                 ncookies ++;
  891         }
  892 
  893         num = uio->uio_offset / sizeof(struct dirent) - 2;
  894         cnum = 0;
  895 
  896         lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn;
  897 
  898         olsn = 0;
  899         level = 1;
  900 
  901 dive:
  902         dprintf(("[dive 0x%x] ", lsn));
  903         error = bread(hp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
  904         if (error) {
  905                 brelse(bp);
  906                 return (error);
  907         }
  908 
  909         dp = (struct dirblk *) bp->b_data;
  910         if (dp->d_magic != D_MAGIC) {
  911                 printf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
  912                 brelse(bp);
  913                 return (EINVAL);
  914         }
  915 
  916         dep = D_DIRENT(dp);
  917 
  918         if (olsn) {
  919                 dprintf(("[restore 0x%x] ", olsn));
  920 
  921                 while(!(dep->de_flag & DE_END) ) {
  922                         if((dep->de_flag & DE_DOWN) &&
  923                            (olsn == DE_DOWNLSN(dep)))
  924                                          break;
  925                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
  926                 }
  927 
  928                 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
  929                         if (dep->de_flag & DE_END)
  930                                 goto blockdone;
  931 
  932                         if (!(dep->de_flag & DE_SPECIAL)) {
  933                                 if (num <= cnum) {
  934                                         if (uio->uio_resid < sizeof(struct dirent)) {
  935                                                 brelse(bp);
  936                                                 dprintf(("[resid] "));
  937                                                 goto readdone;
  938                                         }
  939 
  940                                         error = hpfs_de_uiomove(hpmp, dep, uio);
  941                                         if (error) {
  942                                                 brelse (bp);
  943                                                 return (error);
  944                                         }
  945                                         ncookies++;
  946 
  947                                         if (uio->uio_resid < sizeof(struct dirent)) {
  948                                                 brelse(bp);
  949                                                 dprintf(("[resid] "));
  950                                                 goto readdone;
  951                                         }
  952                                 }
  953                                 cnum++;
  954                         }
  955 
  956                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
  957                 } else {
  958                         printf("hpfs_readdir: ERROR! oLSN not found\n");
  959                         brelse(bp);
  960                         return (EINVAL);
  961                 }
  962         }
  963 
  964         olsn = 0;
  965 
  966         while(!(dep->de_flag & DE_END)) {
  967                 if(dep->de_flag & DE_DOWN) {
  968                         lsn = DE_DOWNLSN(dep);
  969                         brelse(bp);
  970                         level++;
  971                         goto dive;
  972                 }
  973 
  974                 if (!(dep->de_flag & DE_SPECIAL)) {
  975                         if (num <= cnum) {
  976                                 if (uio->uio_resid < sizeof(struct dirent)) {
  977                                         brelse(bp);
  978                                         dprintf(("[resid] "));
  979                                         goto readdone;
  980                                 }
  981 
  982                                 error = hpfs_de_uiomove(hpmp, dep, uio);
  983                                 if (error) {
  984                                         brelse (bp);
  985                                         return (error);
  986                                 }
  987                                 ncookies++;
  988                                 
  989                                 if (uio->uio_resid < sizeof(struct dirent)) {
  990                                         brelse(bp);
  991                                         dprintf(("[resid] "));
  992                                         goto readdone;
  993                                 }
  994                         }
  995                         cnum++;
  996                 }
  997 
  998                 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
  999         }
 1000 
 1001         if(dep->de_flag & DE_DOWN) {
 1002                 dprintf(("[enddive] "));
 1003                 lsn = DE_DOWNLSN(dep);
 1004                 brelse(bp);
 1005                 level++;
 1006                 goto dive;
 1007         }
 1008 
 1009 blockdone:
 1010         dprintf(("[EOB] "));
 1011         olsn = lsn;
 1012         lsn = dp->d_parent;
 1013         brelse(bp);
 1014         level--;
 1015 
 1016         dprintf(("[level %d] ", level));
 1017 
 1018         if (level > 0)
 1019                 goto dive;      /* undive really */
 1020 
 1021         if (ap->a_eofflag) {
 1022             dprintf(("[EOF] "));
 1023             *ap->a_eofflag = 1;
 1024         }
 1025 
 1026 readdone:
 1027         dprintf(("[readdone]\n"));
 1028         if (!error && ap->a_ncookies != NULL) {
 1029                 struct dirent* dpStart;
 1030                 struct dirent* dp;
 1031                 u_long *cookies;
 1032                 u_long *cookiep;
 1033 
 1034                 dprintf(("%d cookies, ",ncookies));
 1035                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
 1036                         panic("hpfs_readdir: unexpected uio from NFS server");
 1037                 dpStart = (struct dirent *)
 1038                      ((caddr_t)uio->uio_iov->iov_base -
 1039                          (uio->uio_offset - off));
 1040                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
 1041                        M_TEMP, M_WAITOK);
 1042                 for (dp = dpStart, cookiep = cookies, i=0;
 1043                      i < ncookies;
 1044                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
 1045                         off += dp->d_reclen;
 1046                         *cookiep++ = (u_int) off;
 1047                 }
 1048                 *ap->a_ncookies = ncookies;
 1049                 *ap->a_cookies = cookies;
 1050         }
 1051 
 1052         return (0);
 1053 }
 1054 
 1055 int
 1056 hpfs_lookup(ap)
 1057         struct vop_lookup_args /* {
 1058                 struct vnode *a_dvp;
 1059                 struct vnode **a_vpp;
 1060                 struct componentname *a_cnp;
 1061         } */ *ap;
 1062 {
 1063         register struct vnode *dvp = ap->a_dvp;
 1064         register struct hpfsnode *dhp = VTOHP(dvp);
 1065         struct hpfsmount *hpmp = dhp->h_hpmp;
 1066         struct componentname *cnp = ap->a_cnp;
 1067         struct ucred *cred = cnp->cn_cred;
 1068         int error;
 1069         int nameiop = cnp->cn_nameiop;
 1070         int flags = cnp->cn_flags;
 1071         int lockparent = flags & LOCKPARENT;
 1072 #if HPFS_DEBUG
 1073         int wantparent = flags & (LOCKPARENT|WANTPARENT);
 1074 #endif
 1075         dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
 1076                 dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen,
 1077                 lockparent, wantparent));
 1078 
 1079         if (nameiop != CREATE && nameiop != DELETE && nameiop != LOOKUP) {
 1080                 printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
 1081                 return (EOPNOTSUPP);
 1082         }
 1083 
 1084         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
 1085         if(error)
 1086                 return (error);
 1087 
 1088         if( (cnp->cn_namelen == 1) &&
 1089             !strncmp(cnp->cn_nameptr,".",1) ) {
 1090                 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no));
 1091 
 1092                 VREF(dvp);
 1093                 *ap->a_vpp = dvp;
 1094 
 1095                 return (0);
 1096         } else if( (cnp->cn_namelen == 2) &&
 1097             !strncmp(cnp->cn_nameptr,"..",2) && (flags & ISDOTDOT) ) {
 1098                 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
 1099                         dhp->h_no, dhp->h_fn.fn_parent));
 1100 
 1101                 if (VFS_VGET(hpmp->hpm_mp, dhp->h_fn.fn_parent,
 1102                     LK_NOWAIT | LK_EXCLUSIVE, ap->a_vpp)) {
 1103                         VOP_UNLOCK(dvp,0,cnp->cn_thread);
 1104                         error = VFS_VGET(hpmp->hpm_mp,
 1105                                  dhp->h_fn.fn_parent, LK_EXCLUSIVE, ap->a_vpp); 
 1106                         VOP_LOCK(dvp, 0, cnp->cn_thread);
 1107                         if(error)
 1108                                 return(error);
 1109                 }
 1110                 if (!lockparent || !(flags & ISLASTCN))
 1111                         VOP_UNLOCK(dvp,0,cnp->cn_thread);
 1112                 return (0);
 1113         } else {
 1114                 struct buf *bp;
 1115                 struct hpfsdirent *dep;
 1116                 struct hpfsnode *hp;
 1117 
 1118                 error = hpfs_genlookupbyname(dhp,
 1119                                 cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep);
 1120                 if (error) {
 1121                         if ((error == ENOENT) && (flags & ISLASTCN) &&
 1122                             (nameiop == CREATE || nameiop == RENAME)) {
 1123                                 if(!lockparent)
 1124                                         VOP_UNLOCK(dvp, 0, cnp->cn_thread);
 1125                                 cnp->cn_flags |= SAVENAME;
 1126                                 return (EJUSTRETURN);
 1127                         }
 1128 
 1129                         return (error);
 1130                 }
 1131 
 1132                 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
 1133                          dep->de_fnode, dep->de_cpid));
 1134 
 1135                 if (nameiop == DELETE && (flags & ISLASTCN)) {
 1136                         error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread);
 1137                         if (error) {
 1138                                 brelse(bp);
 1139                                 return (error);
 1140                         }
 1141                 }
 1142 
 1143                 if (dhp->h_no == dep->de_fnode) {
 1144                         brelse(bp);
 1145                         VREF(dvp);
 1146                         *ap->a_vpp = dvp;
 1147                         return (0);
 1148                 }
 1149 
 1150                 error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, LK_EXCLUSIVE,
 1151                                  ap->a_vpp);
 1152                 if (error) {
 1153                         printf("hpfs_lookup: VFS_VGET FAILED %d\n", error);
 1154                         brelse(bp);
 1155                         return(error);
 1156                 }
 1157 
 1158                 hp = VTOHP(*ap->a_vpp);
 1159 
 1160                 hp->h_mtime = dep->de_mtime;
 1161                 hp->h_ctime = dep->de_ctime;
 1162                 hp->h_atime = dep->de_atime;
 1163                 bcopy(dep->de_name, hp->h_name, dep->de_namelen);
 1164                 hp->h_name[dep->de_namelen] = '\0';
 1165                 hp->h_namelen = dep->de_namelen;
 1166                 hp->h_flag |= H_PARVALID;
 1167 
 1168                 brelse(bp);
 1169 
 1170                 if(!lockparent || !(flags & ISLASTCN))
 1171                         VOP_UNLOCK(dvp, 0, cnp->cn_thread);
 1172                 if ((flags & MAKEENTRY) &&
 1173                     (!(flags & ISLASTCN) || 
 1174                      (nameiop != DELETE && nameiop != CREATE)))
 1175                         cache_enter(dvp, *ap->a_vpp, cnp);
 1176         }
 1177         return (error);
 1178 }
 1179 
 1180 int
 1181 hpfs_remove(ap)
 1182         struct vop_remove_args /* {
 1183                 struct vnode *a_dvp;
 1184                 struct vnode *a_vp;
 1185                 struct componentname *a_cnp;
 1186         } */ *ap;
 1187 {
 1188         int error;
 1189 
 1190         dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no,
 1191                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
 1192 
 1193         if (ap->a_vp->v_type == VDIR)
 1194                 return (EPERM);
 1195 
 1196         error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp);
 1197         return (error);
 1198 }
 1199 
 1200 int
 1201 hpfs_create(ap)
 1202         struct vop_create_args /* {
 1203                 struct vnode *a_dvp;
 1204                 struct vnode **a_vpp;
 1205                 struct componentname *a_cnp;
 1206                 struct vattr *a_vap;
 1207         } */ *ap;
 1208 {
 1209         int error;
 1210 
 1211         dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no,
 1212                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
 1213 
 1214         if (!(ap->a_cnp->cn_flags & HASBUF)) 
 1215                 panic ("hpfs_create: no name\n");
 1216 
 1217         error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
 1218 
 1219         return (error);
 1220 }
 1221 
 1222 /*
 1223  * Return POSIX pathconf information applicable to NTFS filesystem
 1224  */
 1225 int
 1226 hpfs_pathconf(ap)
 1227         struct vop_pathconf_args /* {
 1228                 struct vnode *a_vp;
 1229                 int a_name;
 1230                 register_t *a_retval;
 1231         } */ *ap;
 1232 {
 1233         switch (ap->a_name) {
 1234         case _PC_LINK_MAX:
 1235                 *ap->a_retval = 1;
 1236                 return (0);
 1237         case _PC_NAME_MAX:
 1238                 *ap->a_retval = HPFS_MAXFILENAME;
 1239                 return (0);
 1240         case _PC_PATH_MAX:
 1241                 *ap->a_retval = PATH_MAX;
 1242                 return (0);
 1243         case _PC_CHOWN_RESTRICTED:
 1244                 *ap->a_retval = 1;
 1245                 return (0);
 1246         case _PC_NO_TRUNC:
 1247                 *ap->a_retval = 0;
 1248                 return (0);
 1249         default:
 1250                 return (EINVAL);
 1251         }
 1252         /* NOTREACHED */
 1253 }
 1254 
 1255 
 1256 /*
 1257  * Global vfs data structures
 1258  */
 1259 vop_t **hpfs_vnodeop_p;
 1260 struct vnodeopv_entry_desc hpfs_vnodeop_entries[] = {
 1261         { &vop_default_desc, (vop_t *)vop_defaultop },
 1262 
 1263         { &vop_getattr_desc, (vop_t *)hpfs_getattr },
 1264         { &vop_setattr_desc, (vop_t *)hpfs_setattr },
 1265         { &vop_inactive_desc, (vop_t *)hpfs_inactive },
 1266         { &vop_reclaim_desc, (vop_t *)hpfs_reclaim },
 1267         { &vop_print_desc, (vop_t *)hpfs_print },
 1268         { &vop_create_desc, (vop_t *)hpfs_create },
 1269         { &vop_remove_desc, (vop_t *)hpfs_remove },
 1270         { &vop_islocked_desc, (vop_t *)vop_stdislocked },
 1271         { &vop_unlock_desc, (vop_t *)vop_stdunlock },
 1272         { &vop_lock_desc, (vop_t *)vop_stdlock },
 1273         { &vop_cachedlookup_desc, (vop_t *)hpfs_lookup },
 1274         { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
 1275         { &vop_access_desc, (vop_t *)hpfs_access },
 1276         { &vop_close_desc, (vop_t *)hpfs_close },
 1277         { &vop_open_desc, (vop_t *)hpfs_open },
 1278         { &vop_readdir_desc, (vop_t *)hpfs_readdir },
 1279         { &vop_fsync_desc, (vop_t *)hpfs_fsync },
 1280         { &vop_bmap_desc, (vop_t *)hpfs_bmap },
 1281         { &vop_strategy_desc, (vop_t *)hpfs_strategy },
 1282         { &vop_read_desc, (vop_t *)hpfs_read },
 1283         { &vop_write_desc, (vop_t *)hpfs_write },
 1284         { &vop_ioctl_desc, (vop_t *)hpfs_ioctl },
 1285         { &vop_pathconf_desc, (vop_t *)hpfs_pathconf },
 1286         { NULL, NULL }
 1287 };
 1288 
 1289 static
 1290 struct vnodeopv_desc hpfs_vnodeop_opv_desc =
 1291         { &hpfs_vnodeop_p, hpfs_vnodeop_entries };
 1292 
 1293 VNODEOP_SET(hpfs_vnodeop_opv_desc);

Cache object: 5071f9ff9a1c2fc987100553f6c10216


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