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$
   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/buf.h>
   41 #include <sys/dirent.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/vm_param.h>
   45 #if !defined(__FreeBSD__)
   46 #include <vm/vm_prot.h>
   47 #endif
   48 #include <vm/vm_page.h>
   49 #include <vm/vm_object.h>
   50 #include <vm/vm_pager.h>
   51 #include <vm/vm_zone.h>
   52 #if defined(__FreeBSD__)
   53 #include <vm/vnode_pager.h>
   54 #endif
   55 #include <vm/vm_extern.h>
   56 
   57 #if !defined(__FreeBSD__)
   58 #include <miscfs/specfs/specdev.h>
   59 #include <miscfs/genfs/genfs.h>
   60 #endif
   61 
   62 #include <sys/unistd.h> /* for pathconf(2) constants */
   63 
   64 #include <fs/hpfs/hpfs.h>
   65 #include <fs/hpfs/hpfsmount.h>
   66 #include <fs/hpfs/hpfs_subr.h>
   67 #include <fs/hpfs/hpfs_ioctl.h>
   68 
   69 static int      hpfs_de_uiomove __P((struct hpfsmount *, struct hpfsdirent *,
   70                                      struct uio *));
   71 static int      hpfs_ioctl __P((struct vop_ioctl_args *ap));
   72 static int      hpfs_read __P((struct vop_read_args *));
   73 static int      hpfs_write __P((struct vop_write_args *ap));
   74 static int      hpfs_getattr __P((struct vop_getattr_args *ap));
   75 static int      hpfs_setattr __P((struct vop_setattr_args *ap));
   76 static int      hpfs_inactive __P((struct vop_inactive_args *ap));
   77 static int      hpfs_print __P((struct vop_print_args *ap));
   78 static int      hpfs_reclaim __P((struct vop_reclaim_args *ap));
   79 static int      hpfs_strategy __P((struct vop_strategy_args *ap));
   80 static int      hpfs_access __P((struct vop_access_args *ap));
   81 static int      hpfs_open __P((struct vop_open_args *ap));
   82 static int      hpfs_close __P((struct vop_close_args *ap));
   83 static int      hpfs_readdir __P((struct vop_readdir_args *ap));
   84 static int      hpfs_lookup __P((struct vop_lookup_args *ap));
   85 static int      hpfs_create __P((struct vop_create_args *));
   86 static int      hpfs_remove __P((struct vop_remove_args *));
   87 static int      hpfs_bmap __P((struct vop_bmap_args *ap));
   88 #if defined(__FreeBSD__)
   89 static int      hpfs_getpages __P((struct vop_getpages_args *ap));
   90 static int      hpfs_putpages __P((struct vop_putpages_args *));
   91 static int      hpfs_fsync __P((struct vop_fsync_args *ap));
   92 #endif
   93 static int      hpfs_pathconf __P((struct vop_pathconf_args *ap));
   94 
   95 #if defined(__FreeBSD__)
   96 int
   97 hpfs_getpages(ap)
   98         struct vop_getpages_args *ap;
   99 {
  100         return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
  101                 ap->a_reqpage);
  102 }
  103 
  104 int
  105 hpfs_putpages(ap)
  106         struct vop_putpages_args *ap;
  107 {
  108         return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
  109                 ap->a_sync, ap->a_rtvals);
  110 }
  111 
  112 static int
  113 hpfs_fsync(ap)
  114         struct vop_fsync_args /* {
  115                 struct vnode *a_vp;
  116                 struct ucred *a_cred;
  117                 int a_waitfor;
  118                 struct proc *a_p;
  119         } */ *ap;
  120 {
  121         struct vnode *vp = ap->a_vp;
  122         int s;
  123         struct buf *bp, *nbp;
  124 
  125         /*
  126          * Flush all dirty buffers associated with a vnode.
  127          */
  128 loop:
  129         s = splbio();
  130         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
  131                 nbp = TAILQ_NEXT(bp, b_vnbufs);
  132                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
  133                         continue;
  134                 if ((bp->b_flags & B_DELWRI) == 0)
  135                         panic("hpfs_fsync: not dirty");
  136                 bremfree(bp);
  137                 splx(s);
  138                 (void) bwrite(bp);
  139                 goto loop;
  140         }
  141         while (vp->v_numoutput) {
  142                 vp->v_flag |= VBWAIT;
  143                 (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "hpfsn", 0);
  144         }
  145 #ifdef DIAGNOSTIC
  146         if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
  147                 vprint("hpfs_fsync: dirty", vp);
  148                 goto loop;
  149         }
  150 #endif
  151         splx(s);
  152 
  153         /*
  154          * Write out the on-disc version of the vnode.
  155          */
  156         return hpfs_update(VTOHP(vp));
  157 }
  158 
  159 #endif
  160 
  161 static int
  162 hpfs_ioctl (
  163         struct vop_ioctl_args /* {
  164                 struct vnode *a_vp;
  165                 u_long a_command;
  166                 caddr_t a_data;
  167                 int a_fflag;
  168                 struct ucred *a_cred;
  169                 struct proc *a_p;
  170         } */ *ap)
  171 {
  172         register struct vnode *vp = ap->a_vp;
  173         register struct hpfsnode *hp = VTOHP(vp);
  174         int error;
  175 
  176         printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
  177                 hp->h_no, ap->a_command, ap->a_data, ap->a_fflag);
  178 
  179         switch (ap->a_command) {
  180         case HPFSIOCGEANUM: {
  181                 u_long eanum;
  182                 u_long passed;
  183                 struct ea *eap;
  184 
  185                 eanum = 0;
  186 
  187                 if (hp->h_fn.fn_ealen > 0) {
  188                         eap = (struct ea *)&(hp->h_fn.fn_int);
  189                         passed = 0;
  190 
  191                         while (passed < hp->h_fn.fn_ealen) {
  192 
  193                                 printf("EAname: %s\n", EA_NAME(eap));
  194 
  195                                 eanum++;
  196                                 passed += sizeof(struct ea) +
  197                                           eap->ea_namelen + 1 + eap->ea_vallen;
  198                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  199                                                 passed);
  200                         }
  201                         error = 0;
  202                 } else {
  203                         error = ENOENT;
  204                 }
  205 
  206                 printf("%lu eas\n", eanum);
  207 
  208                 *(u_long *)ap->a_data = eanum;
  209 
  210                 break;
  211         }
  212         case HPFSIOCGEASZ: {
  213                 u_long eanum;
  214                 u_long passed;
  215                 struct ea *eap;
  216 
  217                 printf("EA%ld\n", *(u_long *)ap->a_data);
  218 
  219                 eanum = 0;
  220                 if (hp->h_fn.fn_ealen > 0) {
  221                         eap = (struct ea *)&(hp->h_fn.fn_int);
  222                         passed = 0;
  223 
  224                         error = ENOENT;
  225                         while (passed < hp->h_fn.fn_ealen) {
  226                                 printf("EAname: %s\n", EA_NAME(eap));
  227 
  228                                 if (eanum == *(u_long *)ap->a_data) {
  229                                         *(u_long *)ap->a_data =
  230                                                 eap->ea_namelen + 1 +
  231                                                 eap->ea_vallen;
  232 
  233                                         error = 0;
  234                                         break;
  235                                 }
  236 
  237                                 eanum++;
  238                                 passed += sizeof(struct ea) +
  239                                           eap->ea_namelen + 1 + eap->ea_vallen;
  240                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  241                                                 passed);
  242                         }
  243                 } else {
  244                         error = ENOENT;
  245                 }
  246 
  247                 break;
  248         }
  249         case HPFSIOCRDEA: {
  250                 u_long eanum;
  251                 u_long passed;
  252                 struct hpfs_rdea *rdeap;
  253                 struct ea *eap;
  254 
  255                 rdeap = (struct hpfs_rdea *)ap->a_data;
  256                 printf("EA%ld\n", rdeap->ea_no);
  257 
  258                 eanum = 0;
  259                 if (hp->h_fn.fn_ealen > 0) {
  260                         eap = (struct ea *)&(hp->h_fn.fn_int);
  261                         passed = 0;
  262 
  263                         error = ENOENT;
  264                         while (passed < hp->h_fn.fn_ealen) {
  265                                 printf("EAname: %s\n", EA_NAME(eap));
  266 
  267                                 if (eanum == rdeap->ea_no) {
  268                                         rdeap->ea_sz = eap->ea_namelen + 1 +
  269                                                         eap->ea_vallen;
  270                                         copyout(EA_NAME(eap),rdeap->ea_data,
  271                                                 rdeap->ea_sz);
  272                                         error = 0;
  273                                         break;
  274                                 }
  275 
  276                                 eanum++;
  277                                 passed += sizeof(struct ea) +
  278                                           eap->ea_namelen + 1 + eap->ea_vallen;
  279                                 eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
  280                                                 passed);
  281                         }
  282                 } else {
  283                         error = ENOENT;
  284                 }
  285 
  286                 break;
  287         }
  288         default:
  289                 error = EOPNOTSUPP;
  290                 break;
  291         }
  292         return (error);
  293 }
  294 
  295 /*
  296  * Map file offset to disk offset.
  297  */
  298 int
  299 hpfs_bmap(ap)
  300         struct vop_bmap_args /* {
  301                 struct vnode *a_vp;
  302                 daddr_t  a_bn;
  303                 struct vnode **a_vpp;
  304                 daddr_t *a_bnp;
  305                 int *a_runp;
  306                 int *a_runb;
  307         } */ *ap;
  308 {
  309         register struct hpfsnode *hp = VTOHP(ap->a_vp);
  310         int error;
  311 
  312         if (ap->a_vpp != NULL) 
  313                 *ap->a_vpp = hp->h_devvp;
  314 #if defined(__FreeBSD__)
  315         if (ap->a_runb != NULL)
  316                 *ap->a_runb = 0;
  317 #endif
  318         if (ap->a_bnp == NULL)
  319                 return (0);
  320 
  321         dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn));
  322 
  323         error = hpfs_hpbmap (hp, ap->a_bn, ap->a_bnp, ap->a_runp);
  324 
  325         return (error);
  326 }
  327 
  328 static int
  329 hpfs_read(ap)
  330         struct vop_read_args /* {
  331                 struct vnode *a_vp;
  332                 struct uio *a_uio;
  333                 int a_ioflag;
  334                 struct ucred *a_cred;
  335         } */ *ap;
  336 {
  337         register struct vnode *vp = ap->a_vp;
  338         register struct hpfsnode *hp = VTOHP(vp);
  339         struct uio *uio = ap->a_uio;
  340         struct buf *bp;
  341         u_int xfersz, toread;
  342         u_int off;
  343         daddr_t lbn, bn;
  344         int resid;
  345         int runl;
  346         int error = 0;
  347 
  348         resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset);
  349 
  350         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));
  351 
  352         while (resid) {
  353                 lbn = uio->uio_offset >> DEV_BSHIFT;
  354                 off = uio->uio_offset & (DEV_BSIZE - 1);
  355                 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
  356                         uio->uio_resid, lbn, off));
  357                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
  358                 if (error)
  359                         return (error);
  360 
  361                 toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
  362                 xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
  363                 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
  364                         bn, runl, toread, xfersz));
  365 
  366                 if (toread == 0) 
  367                         break;
  368 
  369                 error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
  370                 if (error) {
  371                         brelse(bp);
  372                         break;
  373                 }
  374 
  375                 error = uiomove(bp->b_data + off, toread - off, uio);
  376                 if(error) {
  377                         brelse(bp);
  378                         break;
  379                 }
  380                 brelse(bp);
  381                 resid -= toread;
  382         }
  383         dprintf(("hpfs_read: successful\n"));
  384         return (error);
  385 }
  386 
  387 static int
  388 hpfs_write(ap)
  389         struct vop_write_args /* {
  390                 struct vnode *a_vp;
  391                 struct uio *a_uio;
  392                 int  a_ioflag;
  393                 struct ucred *a_cred;
  394         } */ *ap;
  395 {
  396         register struct vnode *vp = ap->a_vp;
  397         register struct hpfsnode *hp = VTOHP(vp);
  398         struct uio *uio = ap->a_uio;
  399         struct buf *bp;
  400         u_int xfersz, towrite;
  401         u_int off;
  402         daddr_t lbn, bn;
  403         int runl;
  404         int error = 0;
  405 
  406         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));
  407 
  408         if (ap->a_ioflag & IO_APPEND) {
  409                 dprintf(("hpfs_write: APPEND mode\n"));
  410                 uio->uio_offset = hp->h_fn.fn_size;
  411         }
  412         if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) {
  413                 error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid);
  414                 if (error) {
  415                         printf("hpfs_write: hpfs_extend FAILED %d\n", error);
  416                         return (error);
  417                 }
  418         }
  419 
  420         while (uio->uio_resid) {
  421                 lbn = uio->uio_offset >> DEV_BSHIFT;
  422                 off = uio->uio_offset & (DEV_BSIZE - 1);
  423                 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
  424                         uio->uio_resid, lbn, off));
  425                 error = hpfs_hpbmap(hp, lbn, &bn, &runl);
  426                 if (error)
  427                         return (error);
  428 
  429                 towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
  430                 xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
  431                 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
  432                         bn, runl, towrite, xfersz));
  433 
  434                 if ((off == 0) && (towrite == xfersz)) {
  435                         bp = getblk(hp->h_devvp, bn, xfersz, 0, 0);
  436                         clrbuf(bp);
  437                 } else {
  438                         error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
  439                         if (error) {
  440                                 brelse(bp);
  441                                 return (error);
  442                         }
  443                 }
  444 
  445                 error = uiomove(bp->b_data + off, towrite - off, uio);
  446                 if(error) {
  447                         brelse(bp);
  448                         return (error);
  449                 }
  450 
  451                 if (ap->a_ioflag & IO_SYNC)
  452                         bwrite(bp);
  453                 else
  454                         bawrite(bp);
  455         }
  456 
  457         dprintf(("hpfs_write: successful\n"));
  458         return (0);
  459 }
  460 
  461 /*
  462  * XXXXX do we need hpfsnode locking inside?
  463  */
  464 static int
  465 hpfs_getattr(ap)
  466         struct vop_getattr_args /* {
  467                 struct vnode *a_vp;
  468                 struct vattr *a_vap;
  469                 struct ucred *a_cred;
  470                 struct proc *a_p;
  471         } */ *ap;
  472 {
  473         register struct vnode *vp = ap->a_vp;
  474         register struct hpfsnode *hp = VTOHP(vp);
  475         register struct vattr *vap = ap->a_vap;
  476         int error;
  477 
  478         dprintf(("hpfs_getattr(0x%x):\n", hp->h_no));
  479 
  480 #if defined(__FreeBSD__)
  481         vap->va_fsid = dev2udev(hp->h_dev);
  482 #else /* defined(__NetBSD__) */
  483         vap->va_fsid = ip->i_dev;
  484 #endif
  485         vap->va_fileid = hp->h_no;
  486         vap->va_mode = hp->h_mode;
  487         vap->va_nlink = 1;
  488         vap->va_uid = hp->h_uid;
  489         vap->va_gid = hp->h_gid;
  490         vap->va_rdev = 0;                               /* XXX UNODEV ? */
  491         vap->va_size = hp->h_fn.fn_size;
  492         vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) +
  493                         DEV_BSIZE;
  494 
  495         if (!(hp->h_flag & H_PARVALID)) {
  496                 error = hpfs_validateparent(hp);
  497                 if (error) 
  498                         return (error);
  499         }
  500         vap->va_atime = hpfstimetounix(hp->h_atime);
  501         vap->va_mtime = hpfstimetounix(hp->h_mtime);
  502         vap->va_ctime = hpfstimetounix(hp->h_ctime);
  503 
  504         vap->va_flags = 0;
  505         vap->va_gen = 0;
  506         vap->va_blocksize = DEV_BSIZE;
  507         vap->va_type = vp->v_type;
  508         vap->va_filerev = 0;
  509 
  510         return (0);
  511 }
  512 
  513 /*
  514  * XXXXX do we need hpfsnode locking inside?
  515  */
  516 static int
  517 hpfs_setattr(ap)
  518         struct vop_setattr_args /* {
  519                 struct vnode *a_vp;
  520                 struct vattr *a_vap;
  521                 struct ucred *a_cred;
  522                 struct proc *a_p;
  523         } */ *ap;
  524 {
  525         struct vnode *vp = ap->a_vp;
  526         struct hpfsnode *hp = VTOHP(vp);
  527         struct vattr *vap = ap->a_vap;
  528         struct ucred *cred = ap->a_cred;
  529         struct proc *p = ap->a_p;
  530         int error;
  531 
  532         dprintf(("hpfs_setattr(0x%x):\n", hp->h_no));
  533 
  534         /*
  535          * Check for unsettable attributes.
  536          */
  537         if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
  538             (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
  539             (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
  540             (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
  541                 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
  542                 return (EINVAL);
  543         }
  544 
  545         /* Can't change flags XXX Could be implemented */
  546         if (vap->va_flags != VNOVAL) {
  547                 printf("hpfs_setattr: FLAGS CANNOT BE SET\n");
  548                 return (EINVAL);
  549         }
  550 
  551         /* Can't change uid/gid XXX Could be implemented */
  552         if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
  553                 printf("hpfs_setattr: UID/GID CANNOT BE SET\n");
  554                 return (EINVAL);
  555         }
  556 
  557         /* Can't change mode XXX Could be implemented */
  558         if (vap->va_mode != (mode_t)VNOVAL) {
  559                 printf("hpfs_setattr: MODE CANNOT BE SET\n");
  560                 return (EINVAL);
  561         }
  562 
  563         /* Update times */
  564         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
  565                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
  566                         return (EROFS);
  567                 if (cred->cr_uid != hp->h_uid &&
  568                     (error = suser_xxx(cred, p, PRISON_ROOT)) &&
  569                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
  570                     (error = VOP_ACCESS(vp, VWRITE, cred, p))))
  571                         return (error);
  572                 if (vap->va_atime.tv_sec != VNOVAL)
  573                         hp->h_atime = vap->va_atime.tv_sec;
  574                 if (vap->va_mtime.tv_sec != VNOVAL)
  575                         hp->h_mtime = vap->va_mtime.tv_sec;
  576 
  577                 hp->h_flag |= H_PARCHANGE;
  578         }
  579 
  580         if (vap->va_size != VNOVAL) {
  581                 switch (vp->v_type) {
  582                 case VDIR:
  583                         return (EISDIR);
  584                 case VREG:
  585                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  586                                 return (EROFS);
  587                         break;
  588                 default:
  589                         printf("hpfs_setattr: WRONG v_type\n");
  590                         return (EINVAL);
  591                 }
  592 
  593                 if (vap->va_size < hp->h_fn.fn_size) {
  594 #if defined(__FreeBSD__)
  595                         error = vtruncbuf(vp, cred, p, vap->va_size, DEV_BSIZE);
  596                         if (error)
  597                                 return (error);
  598 #else /* defined(__NetBSD__) */
  599 #error Need alternation for vtruncbuf()
  600 #endif
  601                         error = hpfs_truncate(hp, vap->va_size);
  602                         if (error)
  603                                 return (error);
  604 
  605                 } else if (vap->va_size > hp->h_fn.fn_size) {
  606 #if defined(__FreeBSD__)
  607                         vnode_pager_setsize(vp, vap->va_size);
  608 #endif
  609                         error = hpfs_extend(hp, vap->va_size);
  610                         if (error)
  611                                 return (error);
  612                 }
  613         }
  614 
  615         return (0);
  616 }
  617 
  618 /*
  619  * Last reference to an node.  If necessary, write or delete it.
  620  */
  621 int
  622 hpfs_inactive(ap)
  623         struct vop_inactive_args /* {
  624                 struct vnode *a_vp;
  625         } */ *ap;
  626 {
  627         register struct vnode *vp = ap->a_vp;
  628         register struct hpfsnode *hp = VTOHP(vp);
  629         int error;
  630 
  631         dprintf(("hpfs_inactive(0x%x): \n", hp->h_no));
  632 
  633         if (hp->h_flag & H_CHANGE) {
  634                 dprintf(("hpfs_inactive: node changed, update\n"));
  635                 error = hpfs_update (hp);
  636                 if (error)
  637                         return (error);
  638         }
  639 
  640         if (hp->h_flag & H_PARCHANGE) {
  641                 dprintf(("hpfs_inactive: parent node changed, update\n"));
  642                 error = hpfs_updateparent (hp);
  643                 if (error)
  644                         return (error);
  645         }
  646 
  647         if (prtactive && vp->v_usecount != 0)
  648                 vprint("hpfs_inactive: pushing active", vp);
  649 
  650         if (hp->h_flag & H_INVAL) {
  651                 VOP__UNLOCK(vp,0,ap->a_p);
  652 #if defined(__FreeBSD__)
  653                 vrecycle(vp, (struct simplelock *)0, ap->a_p);
  654 #else /* defined(__NetBSD__) */
  655                 vgone(vp);
  656 #endif
  657                 return (0);
  658         }
  659 
  660         VOP__UNLOCK(vp,0,ap->a_p);
  661         return (0);
  662 }
  663 
  664 /*
  665  * Reclaim an inode so that it can be used for other purposes.
  666  */
  667 int
  668 hpfs_reclaim(ap)
  669         struct vop_reclaim_args /* {
  670                 struct vnode *a_vp;
  671         } */ *ap;
  672 {
  673         register struct vnode *vp = ap->a_vp;
  674         register struct hpfsnode *hp = VTOHP(vp);
  675 
  676         dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no));
  677 
  678         hpfs_hphashrem(hp);
  679 
  680         /* Purge old data structures associated with the inode. */
  681         cache_purge(vp);
  682         if (hp->h_devvp) {
  683                 vrele(hp->h_devvp);
  684                 hp->h_devvp = NULL;
  685         }
  686 
  687         vp->v_data = NULL;
  688 
  689         FREE(hp, M_HPFSNO);
  690 
  691         return (0);
  692 }
  693 
  694 static int
  695 hpfs_print(ap)
  696         struct vop_print_args /* {
  697                 struct vnode *a_vp;
  698         } */ *ap;
  699 {
  700         register struct vnode *vp = ap->a_vp;
  701         register struct hpfsnode *hp = VTOHP(vp);
  702 
  703         printf("tag VT_HPFS, ino 0x%x",hp->h_no);
  704         lockmgr_printinfo(&hp->h_lock);
  705         printf("\n");
  706         return (0);
  707 }
  708 
  709 /*
  710  * Calculate the logical to physical mapping if not done already,
  711  * then call the device strategy routine.
  712  *
  713  * In order to be able to swap to a file, the VOP_BMAP operation may not
  714  * deadlock on memory.  See hpfs_bmap() for details. XXXXXXX (not impl)
  715  */
  716 int
  717 hpfs_strategy(ap)
  718         struct vop_strategy_args /* {
  719                 struct buf *a_bp;
  720         } */ *ap;
  721 {
  722         register struct buf *bp = ap->a_bp;
  723         register struct vnode *vp = ap->a_vp;
  724         struct vnode *nvp;
  725         int error;
  726 
  727         dprintf(("hpfs_strategy(): \n"));
  728 
  729         if (vp->v_type == VBLK || vp->v_type == VCHR)
  730                 panic("hpfs_strategy: spec");
  731         if (bp->b_blkno == bp->b_lblkno) {
  732                 error = VOP_BMAP(vp, bp->b_lblkno, &nvp, &bp->b_blkno, NULL, NULL);
  733                 if (error) {
  734                         printf("hpfs_strategy: VOP_BMAP FAILED %d\n", error);
  735                         bp->b_error = error;
  736                         bp->b_flags |= B_ERROR;
  737                         biodone(bp);
  738                         return (error);
  739                 }
  740                 if ((long)bp->b_blkno == -1)
  741                         vfs_bio_clrbuf(bp);
  742         }
  743         if ((long)bp->b_blkno == -1) {
  744                 biodone(bp);
  745                 return (0);
  746         }
  747         bp->b_dev = nvp->v_rdev;
  748         VOP_STRATEGY(nvp, bp);
  749         return (0);
  750 }
  751 
  752 /*
  753  * XXXXX do we need hpfsnode locking inside?
  754  */
  755 int
  756 hpfs_access(ap)
  757         struct vop_access_args /* {
  758                 struct vnode *a_vp;
  759                 int  a_mode;
  760                 struct ucred *a_cred;
  761                 struct proc *a_p;
  762         } */ *ap;
  763 {
  764         struct vnode *vp = ap->a_vp;
  765         struct hpfsnode *hp = VTOHP(vp);
  766         struct ucred *cred = ap->a_cred;
  767         mode_t mask, mode = ap->a_mode;
  768         register gid_t *gp;
  769         int i;
  770 
  771         dprintf(("hpfs_access(0x%x):\n", hp->h_no));
  772 
  773         /*
  774          * Disallow write attempts on read-only file systems;
  775          * unless the file is a socket, fifo, or a block or
  776          * character device resident on the file system.
  777          */
  778         if (mode & VWRITE) {
  779                 switch ((int)vp->v_type) {
  780                 case VDIR:
  781                 case VLNK:
  782                 case VREG:
  783                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  784                                 return (EROFS);
  785                         break;
  786                 }
  787         }
  788 
  789         /* Otherwise, user id 0 always gets access. */
  790         if (cred->cr_uid == 0)
  791                 return (0);
  792 
  793         mask = 0;
  794 
  795         /* Otherwise, check the owner. */
  796         if (cred->cr_uid == hp->h_uid) {
  797                 if (mode & VEXEC)
  798                         mask |= S_IXUSR;
  799                 if (mode & VREAD)
  800                         mask |= S_IRUSR;
  801                 if (mode & VWRITE)
  802                         mask |= S_IWUSR;
  803                 return ((hp->h_mode & mask) == mask ? 0 : EACCES);
  804         }
  805 
  806         /* Otherwise, check the groups. */
  807         for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
  808                 if (hp->h_gid == *gp) {
  809                         if (mode & VEXEC)
  810                                 mask |= S_IXGRP;
  811                         if (mode & VREAD)
  812                                 mask |= S_IRGRP;
  813                         if (mode & VWRITE)
  814                                 mask |= S_IWGRP;
  815                         return ((hp->h_mode & mask) == mask ? 0 : EACCES);
  816                 }
  817 
  818         /* Otherwise, check everyone else. */
  819         if (mode & VEXEC)
  820                 mask |= S_IXOTH;
  821         if (mode & VREAD)
  822                 mask |= S_IROTH;
  823         if (mode & VWRITE)
  824                 mask |= S_IWOTH;
  825         return ((hp->h_mode & mask) == mask ? 0 : EACCES);
  826 }
  827 
  828 /*
  829  * Open called.
  830  *
  831  * Nothing to do.
  832  */
  833 /* ARGSUSED */
  834 static int
  835 hpfs_open(ap)
  836         struct vop_open_args /* {
  837                 struct vnode *a_vp;
  838                 int  a_mode;
  839                 struct ucred *a_cred;
  840                 struct proc *a_p;
  841         } */ *ap;
  842 {
  843 #if HPFS_DEBUG
  844         register struct vnode *vp = ap->a_vp;
  845         register struct hpfsnode *hp = VTOHP(vp);
  846 
  847         printf("hpfs_open(0x%x):\n",hp->h_no);
  848 #endif
  849 
  850         /*
  851          * Files marked append-only must be opened for appending.
  852          */
  853 
  854         return (0);
  855 }
  856 
  857 /*
  858  * Close called.
  859  *
  860  * Update the times on the inode.
  861  */
  862 /* ARGSUSED */
  863 static int
  864 hpfs_close(ap)
  865         struct vop_close_args /* {
  866                 struct vnode *a_vp;
  867                 int  a_fflag;
  868                 struct ucred *a_cred;
  869                 struct proc *a_p;
  870         } */ *ap;
  871 {
  872 #if HPFS_DEBUG
  873         register struct vnode *vp = ap->a_vp;
  874         register struct hpfsnode *hp = VTOHP(vp);
  875 
  876         printf("hpfs_close: %d\n",hp->h_no);
  877 #endif
  878 
  879         return (0);
  880 }
  881 
  882 static int
  883 hpfs_de_uiomove (
  884         struct hpfsmount *hpmp,
  885         struct hpfsdirent *dep,
  886         struct uio *uio)
  887 {
  888         struct dirent cde;
  889         int i, error;
  890 
  891         dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
  892                 dep->de_fnode, dep->de_size, dep->de_namelen,
  893                 dep->de_namelen, dep->de_name, dep->de_flag));
  894 
  895         /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
  896         for (i=0; i<dep->de_namelen; i++) 
  897                 cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]);
  898 
  899         cde.d_name[dep->de_namelen] = '\0';
  900         cde.d_namlen = dep->de_namelen;
  901         cde.d_fileno = dep->de_fnode;
  902         cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG;
  903         cde.d_reclen = sizeof(struct dirent);
  904 
  905         error = uiomove((char *)&cde, sizeof(struct dirent), uio);
  906         if (error)
  907                 return (error);
  908         
  909         dprintf(("[0x%x] ", uio->uio_resid));
  910         return (error);
  911 }
  912 
  913 
  914 static struct dirent hpfs_de_dot =
  915         { 0, sizeof(struct dirent), DT_DIR, 1, "." };
  916 static struct dirent hpfs_de_dotdot =
  917         { 0, sizeof(struct dirent), DT_DIR, 2, ".." };
  918 int
  919 hpfs_readdir(ap)
  920         struct vop_readdir_args /* {
  921                 struct vnode *a_vp;
  922                 struct uio *a_uio;
  923                 struct ucred *a_cred;
  924                 int *a_ncookies;
  925                 u_int **cookies;
  926         } */ *ap;
  927 {
  928         register struct vnode *vp = ap->a_vp;
  929         register struct hpfsnode *hp = VTOHP(vp);
  930         struct hpfsmount *hpmp = hp->h_hpmp;
  931         struct uio *uio = ap->a_uio;
  932         int ncookies = 0, i, num, cnum;
  933         int error = 0;
  934         off_t off;
  935         struct buf *bp;
  936         struct dirblk *dp;
  937         struct hpfsdirent *dep;
  938         lsn_t olsn;
  939         lsn_t lsn;
  940         int level;
  941 
  942         dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid));
  943 
  944         off = uio->uio_offset;
  945 
  946         if( uio->uio_offset < sizeof(struct dirent) ) {
  947                 dprintf((". faked, "));
  948                 hpfs_de_dot.d_fileno = hp->h_no;
  949                 error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio);
  950                 if(error) {
  951                         return (error);
  952                 }
  953 
  954                 ncookies ++;
  955         }
  956 
  957         if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
  958                 dprintf((".. faked, "));
  959                 hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent;
  960 
  961                 error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent),
  962                                 uio);
  963                 if(error) {
  964                         return (error);
  965                 }
  966 
  967                 ncookies ++;
  968         }
  969 
  970         num = uio->uio_offset / sizeof(struct dirent) - 2;
  971         cnum = 0;
  972 
  973         lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn;
  974 
  975         olsn = 0;
  976         level = 1;
  977 
  978 dive:
  979         dprintf(("[dive 0x%x] ", lsn));
  980         error = bread(hp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
  981         if (error) {
  982                 brelse(bp);
  983                 return (error);
  984         }
  985 
  986         dp = (struct dirblk *) bp->b_data;
  987         if (dp->d_magic != D_MAGIC) {
  988                 printf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
  989                 brelse(bp);
  990                 return (EINVAL);
  991         }
  992 
  993         dep = D_DIRENT(dp);
  994 
  995         if (olsn) {
  996                 dprintf(("[restore 0x%x] ", olsn));
  997 
  998                 while(!(dep->de_flag & DE_END) ) {
  999                         if((dep->de_flag & DE_DOWN) &&
 1000                            (olsn == DE_DOWNLSN(dep)))
 1001                                          break;
 1002                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
 1003                 }
 1004 
 1005                 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
 1006                         if (dep->de_flag & DE_END)
 1007                                 goto blockdone;
 1008 
 1009                         if (!(dep->de_flag & DE_SPECIAL)) {
 1010                                 if (num <= cnum) {
 1011                                         if (uio->uio_resid < sizeof(struct dirent)) {
 1012                                                 brelse(bp);
 1013                                                 dprintf(("[resid] "));
 1014                                                 goto readdone;
 1015                                         }
 1016 
 1017                                         error = hpfs_de_uiomove(hpmp, dep, uio);
 1018                                         if (error) {
 1019                                                 brelse (bp);
 1020                                                 return (error);
 1021                                         }
 1022                                         ncookies++;
 1023 
 1024                                         if (uio->uio_resid < sizeof(struct dirent)) {
 1025                                                 brelse(bp);
 1026                                                 dprintf(("[resid] "));
 1027                                                 goto readdone;
 1028                                         }
 1029                                 }
 1030                                 cnum++;
 1031                         }
 1032 
 1033                         dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
 1034                 } else {
 1035                         printf("hpfs_readdir: ERROR! oLSN not found\n");
 1036                         brelse(bp);
 1037                         return (EINVAL);
 1038                 }
 1039         }
 1040 
 1041         olsn = 0;
 1042 
 1043         while(!(dep->de_flag & DE_END)) {
 1044                 if(dep->de_flag & DE_DOWN) {
 1045                         lsn = DE_DOWNLSN(dep);
 1046                         brelse(bp);
 1047                         level++;
 1048                         goto dive;
 1049                 }
 1050 
 1051                 if (!(dep->de_flag & DE_SPECIAL)) {
 1052                         if (num <= cnum) {
 1053                                 if (uio->uio_resid < sizeof(struct dirent)) {
 1054                                         brelse(bp);
 1055                                         dprintf(("[resid] "));
 1056                                         goto readdone;
 1057                                 }
 1058 
 1059                                 error = hpfs_de_uiomove(hpmp, dep, uio);
 1060                                 if (error) {
 1061                                         brelse (bp);
 1062                                         return (error);
 1063                                 }
 1064                                 ncookies++;
 1065                                 
 1066                                 if (uio->uio_resid < sizeof(struct dirent)) {
 1067                                         brelse(bp);
 1068                                         dprintf(("[resid] "));
 1069                                         goto readdone;
 1070                                 }
 1071                         }
 1072                         cnum++;
 1073                 }
 1074 
 1075                 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
 1076         }
 1077 
 1078         if(dep->de_flag & DE_DOWN) {
 1079                 dprintf(("[enddive] "));
 1080                 lsn = DE_DOWNLSN(dep);
 1081                 brelse(bp);
 1082                 level++;
 1083                 goto dive;
 1084         }
 1085 
 1086 blockdone:
 1087         dprintf(("[EOB] "));
 1088         olsn = lsn;
 1089         lsn = dp->d_parent;
 1090         brelse(bp);
 1091         level--;
 1092 
 1093         dprintf(("[level %d] ", level));
 1094 
 1095         if (level > 0)
 1096                 goto dive;      /* undive really */
 1097 
 1098         if (ap->a_eofflag) {
 1099             dprintf(("[EOF] "));
 1100             *ap->a_eofflag = 1;
 1101         }
 1102 
 1103 readdone:
 1104         dprintf(("[readdone]\n"));
 1105         if (!error && ap->a_ncookies != NULL) {
 1106                 struct dirent* dpStart;
 1107                 struct dirent* dp;
 1108 #if defined(__FreeBSD__)
 1109                 u_long *cookies;
 1110                 u_long *cookiep;
 1111 #else /* defined(__NetBSD__) */
 1112                 off_t *cookies;
 1113                 off_t *cookiep;
 1114 #endif
 1115 
 1116                 dprintf(("%d cookies, ",ncookies));
 1117                 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
 1118                         panic("hpfs_readdir: unexpected uio from NFS server");
 1119                 dpStart = (struct dirent *)
 1120                      ((caddr_t)uio->uio_iov->iov_base -
 1121                          (uio->uio_offset - off));
 1122 #if defined(__FreeBSD__)
 1123                 MALLOC(cookies, u_long *, ncookies * sizeof(u_long),
 1124                        M_TEMP, M_WAITOK);
 1125 #else /* defined(__NetBSD__) */
 1126                 MALLOC(cookies, off_t *, ncookies * sizeof(off_t),
 1127                        M_TEMP, M_WAITOK);
 1128 #endif
 1129                 for (dp = dpStart, cookiep = cookies, i=0;
 1130                      i < ncookies;
 1131                      dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
 1132                         off += dp->d_reclen;
 1133                         *cookiep++ = (u_int) off;
 1134                 }
 1135                 *ap->a_ncookies = ncookies;
 1136                 *ap->a_cookies = cookies;
 1137         }
 1138 
 1139         return (0);
 1140 }
 1141 
 1142 int
 1143 hpfs_lookup(ap)
 1144         struct vop_lookup_args /* {
 1145                 struct vnode *a_dvp;
 1146                 struct vnode **a_vpp;
 1147                 struct componentname *a_cnp;
 1148         } */ *ap;
 1149 {
 1150         register struct vnode *dvp = ap->a_dvp;
 1151         register struct hpfsnode *dhp = VTOHP(dvp);
 1152         struct hpfsmount *hpmp = dhp->h_hpmp;
 1153         struct componentname *cnp = ap->a_cnp;
 1154         struct ucred *cred = cnp->cn_cred;
 1155         int error;
 1156         int nameiop = cnp->cn_nameiop;
 1157         int flags = cnp->cn_flags;
 1158         int lockparent = flags & LOCKPARENT;
 1159 #if HPFS_DEBUG
 1160         int wantparent = flags & (LOCKPARENT|WANTPARENT);
 1161 #endif
 1162         dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
 1163                 dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen,
 1164                 lockparent, wantparent));
 1165 
 1166         if (nameiop != CREATE && nameiop != DELETE && nameiop != LOOKUP) {
 1167                 printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
 1168                 return (EOPNOTSUPP);
 1169         }
 1170 
 1171         error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
 1172         if(error)
 1173                 return (error);
 1174 
 1175         if( (cnp->cn_namelen == 1) &&
 1176             !strncmp(cnp->cn_nameptr,".",1) ) {
 1177                 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no));
 1178 
 1179                 VREF(dvp);
 1180                 *ap->a_vpp = dvp;
 1181 
 1182                 return (0);
 1183         } else if( (cnp->cn_namelen == 2) &&
 1184             !strncmp(cnp->cn_nameptr,"..",2) && (flags & ISDOTDOT) ) {
 1185                 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
 1186                         dhp->h_no, dhp->h_fn.fn_parent));
 1187 
 1188                 VOP__UNLOCK(dvp,0,cnp->cn_proc);
 1189 
 1190                 error = VFS_VGET(hpmp->hpm_mp,
 1191                                  dhp->h_fn.fn_parent, ap->a_vpp); 
 1192                 if(error) {
 1193                         VOP__LOCK(dvp, 0, cnp->cn_proc);
 1194                         return(error);
 1195                 }
 1196 
 1197                 if( lockparent && (flags & ISLASTCN) && 
 1198                     (error = VOP__LOCK(dvp, 0, cnp->cn_proc)) ) {
 1199                         vput( *(ap->a_vpp) );
 1200                         return (error);
 1201                 }
 1202                 return (error);
 1203         } else {
 1204                 struct buf *bp;
 1205                 struct hpfsdirent *dep;
 1206                 struct hpfsnode *hp;
 1207 
 1208                 error = hpfs_genlookupbyname(dhp,
 1209                                 cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep);
 1210                 if (error) {
 1211                         if ((error == ENOENT) && (flags & ISLASTCN) &&
 1212                             (nameiop == CREATE || nameiop == RENAME)) {
 1213                                 if(!lockparent)
 1214                                         VOP__UNLOCK(dvp, 0, cnp->cn_proc);
 1215                                 cnp->cn_flags |= SAVENAME;
 1216                                 return (EJUSTRETURN);
 1217                         }
 1218 
 1219                         return (error);
 1220                 }
 1221 
 1222                 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
 1223                          dep->de_fnode, dep->de_cpid));
 1224 
 1225                 if (nameiop == DELETE && (flags & ISLASTCN)) {
 1226                         error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_proc);
 1227                         if (error) {
 1228                                 brelse(bp);
 1229                                 return (error);
 1230                         }
 1231                 }
 1232 
 1233                 if (dhp->h_no == dep->de_fnode) {
 1234                         brelse(bp);
 1235                         VREF(dvp);
 1236                         *ap->a_vpp = dvp;
 1237                         return (0);
 1238                 }
 1239 
 1240                 error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, ap->a_vpp);
 1241                 if (error) {
 1242                         printf("hpfs_lookup: VFS_VGET FAILED %d\n", error);
 1243                         brelse(bp);
 1244                         return(error);
 1245                 }
 1246 
 1247                 hp = VTOHP(*ap->a_vpp);
 1248 
 1249                 hp->h_mtime = dep->de_mtime;
 1250                 hp->h_ctime = dep->de_ctime;
 1251                 hp->h_atime = dep->de_atime;
 1252                 bcopy(dep->de_name, hp->h_name, dep->de_namelen);
 1253                 hp->h_name[dep->de_namelen] = '\0';
 1254                 hp->h_namelen = dep->de_namelen;
 1255                 hp->h_flag |= H_PARVALID;
 1256 
 1257                 brelse(bp);
 1258 
 1259                 if(!lockparent || !(flags & ISLASTCN))
 1260                         VOP__UNLOCK(dvp, 0, cnp->cn_proc);
 1261                 if ((flags & MAKEENTRY) &&
 1262                     (!(flags & ISLASTCN) || 
 1263                      (nameiop != DELETE && nameiop != CREATE)))
 1264                         cache_enter(dvp, *ap->a_vpp, cnp);
 1265         }
 1266         return (error);
 1267 }
 1268 
 1269 int
 1270 hpfs_remove(ap)
 1271         struct vop_remove_args /* {
 1272                 struct vnode *a_dvp;
 1273                 struct vnode *a_vp;
 1274                 struct componentname *a_cnp;
 1275         } */ *ap;
 1276 {
 1277         int error;
 1278 
 1279         dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no,
 1280                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
 1281 
 1282         if (ap->a_vp->v_type == VDIR)
 1283                 return (EPERM);
 1284 
 1285         error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp);
 1286         return (error);
 1287 }
 1288 
 1289 int
 1290 hpfs_create(ap)
 1291         struct vop_create_args /* {
 1292                 struct vnode *a_dvp;
 1293                 struct vnode **a_vpp;
 1294                 struct componentname *a_cnp;
 1295                 struct vattr *a_vap;
 1296         } */ *ap;
 1297 {
 1298         int error;
 1299 
 1300         dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no,
 1301                 ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
 1302 
 1303         if (!(ap->a_cnp->cn_flags & HASBUF)) 
 1304                 panic ("hpfs_create: no name\n");
 1305 
 1306         error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
 1307 
 1308         return (error);
 1309 }
 1310 
 1311 /*
 1312  * Return POSIX pathconf information applicable to NTFS filesystem
 1313  */
 1314 int
 1315 hpfs_pathconf(ap)
 1316         struct vop_pathconf_args /* {
 1317                 struct vnode *a_vp;
 1318                 int a_name;
 1319                 register_t *a_retval;
 1320         } */ *ap;
 1321 {
 1322         switch (ap->a_name) {
 1323         case _PC_LINK_MAX:
 1324                 *ap->a_retval = 1;
 1325                 return (0);
 1326         case _PC_NAME_MAX:
 1327                 *ap->a_retval = HPFS_MAXFILENAME;
 1328                 return (0);
 1329         case _PC_PATH_MAX:
 1330                 *ap->a_retval = PATH_MAX;
 1331                 return (0);
 1332         case _PC_CHOWN_RESTRICTED:
 1333                 *ap->a_retval = 1;
 1334                 return (0);
 1335         case _PC_NO_TRUNC:
 1336                 *ap->a_retval = 0;
 1337                 return (0);
 1338 #if defined(__NetBSD__)
 1339         case _PC_SYNC_IO:
 1340                 *ap->a_retval = 1;
 1341                 return (0);
 1342         case _PC_FILESIZEBITS:
 1343                 *ap->a_retval = 32;
 1344                 return (0);
 1345 #endif
 1346         default:
 1347                 return (EINVAL);
 1348         }
 1349         /* NOTREACHED */
 1350 }
 1351 
 1352 
 1353 /*
 1354  * Global vfs data structures
 1355  */
 1356 vop_t **hpfs_vnodeop_p;
 1357 #if defined(__FreeBSD__)
 1358 struct vnodeopv_entry_desc hpfs_vnodeop_entries[] = {
 1359         { &vop_default_desc, (vop_t *)vop_defaultop },
 1360 
 1361         { &vop_getattr_desc, (vop_t *)hpfs_getattr },
 1362         { &vop_setattr_desc, (vop_t *)hpfs_setattr },
 1363         { &vop_inactive_desc, (vop_t *)hpfs_inactive },
 1364         { &vop_reclaim_desc, (vop_t *)hpfs_reclaim },
 1365         { &vop_print_desc, (vop_t *)hpfs_print },
 1366         { &vop_create_desc, (vop_t *)hpfs_create },
 1367         { &vop_remove_desc, (vop_t *)hpfs_remove },
 1368         { &vop_islocked_desc, (vop_t *)vop_stdislocked },
 1369         { &vop_unlock_desc, (vop_t *)vop_stdunlock },
 1370         { &vop_lock_desc, (vop_t *)vop_stdlock },
 1371         { &vop_cachedlookup_desc, (vop_t *)hpfs_lookup },
 1372         { &vop_lookup_desc, (vop_t *)vfs_cache_lookup },
 1373         { &vop_access_desc, (vop_t *)hpfs_access },
 1374         { &vop_close_desc, (vop_t *)hpfs_close },
 1375         { &vop_open_desc, (vop_t *)hpfs_open },
 1376         { &vop_readdir_desc, (vop_t *)hpfs_readdir },
 1377         { &vop_fsync_desc, (vop_t *)hpfs_fsync },
 1378         { &vop_bmap_desc, (vop_t *)hpfs_bmap },
 1379         { &vop_getpages_desc, (vop_t *) hpfs_getpages },
 1380         { &vop_putpages_desc, (vop_t *) hpfs_putpages },
 1381         { &vop_strategy_desc, (vop_t *)hpfs_strategy },
 1382         { &vop_bwrite_desc, (vop_t *)vop_stdbwrite },
 1383         { &vop_read_desc, (vop_t *)hpfs_read },
 1384         { &vop_write_desc, (vop_t *)hpfs_write },
 1385         { &vop_ioctl_desc, (vop_t *)hpfs_ioctl },
 1386         { &vop_pathconf_desc, (vop_t *)hpfs_pathconf },
 1387         { NULL, NULL }
 1388 };
 1389 
 1390 static
 1391 struct vnodeopv_desc hpfs_vnodeop_opv_desc =
 1392         { &hpfs_vnodeop_p, hpfs_vnodeop_entries };
 1393 
 1394 VNODEOP_SET(hpfs_vnodeop_opv_desc);
 1395 #else /* defined(__NetBSD__) */
 1396 struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {
 1397         { &vop_default_desc, (vop_t *) genfs_badop },   /* XXX */
 1398         { &vop_lookup_desc, (vop_t *) hpfs_lookup },    /* lookup */
 1399         { &vop_create_desc, genfs_eopnotsupp },         /* create */
 1400         { &vop_mknod_desc, genfs_eopnotsupp },          /* mknod */
 1401         { &vop_open_desc, (vop_t *) hpfs_open },        /* open */
 1402         { &vop_close_desc,(vop_t *) hpfs_close },       /* close */
 1403         { &vop_access_desc, (vop_t *) hpfs_access },    /* access */
 1404         { &vop_getattr_desc, (vop_t *) hpfs_getattr },  /* getattr */
 1405         { &vop_setattr_desc, genfs_eopnotsupp },        /* setattr */
 1406         { &vop_read_desc, (vop_t *) hpfs_read },        /* read */
 1407         { &vop_write_desc, (vop_t *) hpfs_write },      /* write */
 1408         { &vop_lease_desc, genfs_lease_check },         /* lease */
 1409         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
 1410         { &vop_ioctl_desc, genfs_enoioctl },            /* ioctl */
 1411         { &vop_poll_desc, genfs_poll },                 /* poll */
 1412         { &vop_revoke_desc, genfs_revoke },             /* revoke */
 1413         { &vop_mmap_desc, genfs_eopnotsupp },           /* mmap */
 1414         { &vop_fsync_desc, genfs_fsync },               /* fsync */
 1415         { &vop_seek_desc, genfs_seek },                 /* seek */
 1416         { &vop_remove_desc, genfs_eopnotsupp },         /* remove */
 1417         { &vop_link_desc, genfs_eopnotsupp },           /* link */
 1418         { &vop_rename_desc, genfs_eopnotsupp },         /* rename */
 1419         { &vop_mkdir_desc, genfs_eopnotsupp },          /* mkdir */
 1420         { &vop_rmdir_desc, genfs_eopnotsupp },          /* rmdir */
 1421         { &vop_symlink_desc, genfs_eopnotsupp },        /* symlink */
 1422         { &vop_readdir_desc, (vop_t *) hpfs_readdir },  /* readdir */
 1423         { &vop_readlink_desc, genfs_eopnotsupp },       /* readlink */
 1424         { &vop_abortop_desc, genfs_abortop },           /* abortop */
 1425         { &vop_inactive_desc, (vop_t *) hpfs_inactive },        /* inactive */
 1426         { &vop_reclaim_desc, (vop_t *) hpfs_reclaim },  /* reclaim */
 1427         { &vop_lock_desc, genfs_lock },                 /* lock */
 1428         { &vop_unlock_desc, genfs_unlock },             /* unlock */
 1429         { &vop_bmap_desc, (vop_t *) hpfs_bmap },        /* bmap */
 1430         { &vop_strategy_desc, (vop_t *) hpfs_strategy },        /* strategy */
 1431         { &vop_print_desc, (vop_t *) hpfs_print },      /* print */
 1432         { &vop_islocked_desc, genfs_islocked },         /* islocked */
 1433         { &vop_pathconf_desc, hpfs_pathconf },          /* pathconf */
 1434         { &vop_advlock_desc, genfs_nullop },            /* advlock */
 1435         { &vop_blkatoff_desc, genfs_eopnotsupp },       /* blkatoff */
 1436         { &vop_valloc_desc, genfs_eopnotsupp },         /* valloc */
 1437         { &vop_reallocblks_desc, genfs_eopnotsupp },    /* reallocblks */
 1438         { &vop_vfree_desc, genfs_eopnotsupp },          /* vfree */
 1439         { &vop_truncate_desc, genfs_eopnotsupp },       /* truncate */
 1440         { &vop_update_desc, genfs_eopnotsupp },         /* update */
 1441         { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
 1442         { (struct vnodeop_desc *)NULL, (int (*) __P((void *)))NULL }
 1443 };
 1444 struct vnodeopv_desc ntfs_vnodeop_opv_desc =
 1445         { &ntfs_vnodeop_p, ntfs_vnodeop_entries };
 1446 
 1447 #endif

Cache object: b2d6cff47c13bf68bd61a521dd484bc5


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