154371Ssemenu/*- 254371Ssemenu * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 354371Ssemenu * All rights reserved. 454371Ssemenu * 554371Ssemenu * Redistribution and use in source and binary forms, with or without 654371Ssemenu * modification, are permitted provided that the following conditions 754371Ssemenu * are met: 854371Ssemenu * 1. Redistributions of source code must retain the above copyright 954371Ssemenu * notice, this list of conditions and the following disclaimer. 1054371Ssemenu * 2. Redistributions in binary form must reproduce the above copyright 1154371Ssemenu * notice, this list of conditions and the following disclaimer in the 1254371Ssemenu * documentation and/or other materials provided with the distribution. 1354371Ssemenu * 1454371Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1554371Ssemenu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1654371Ssemenu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1754371Ssemenu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1854371Ssemenu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1954371Ssemenu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2054371Ssemenu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2154371Ssemenu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2254371Ssemenu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2354371Ssemenu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2454371Ssemenu * SUCH DAMAGE. 2554371Ssemenu * 2654371Ssemenu * $FreeBSD$ 2754371Ssemenu */ 2854371Ssemenu 2954371Ssemenu#include <sys/param.h> 3054371Ssemenu#include <sys/systm.h> 3154371Ssemenu#include <sys/kernel.h> 3254371Ssemenu#include <sys/proc.h> 33143588Sphk#include <sys/conf.h> 3454371Ssemenu#include <sys/time.h> 3554371Ssemenu#include <sys/types.h> 3654371Ssemenu#include <sys/stat.h> 3754371Ssemenu#include <sys/vnode.h> 3854371Ssemenu#include <sys/mount.h> 3954371Ssemenu#include <sys/namei.h> 4054371Ssemenu#include <sys/malloc.h> 4160041Sphk#include <sys/bio.h> 4254371Ssemenu#include <sys/buf.h> 4354371Ssemenu#include <sys/dirent.h> 4454371Ssemenu 4554371Ssemenu#include <vm/vm.h> 4654371Ssemenu#include <vm/vm_param.h> 4754371Ssemenu#include <vm/vm_page.h> 4854371Ssemenu#include <vm/vm_object.h> 4954371Ssemenu#include <vm/vm_pager.h> 5054371Ssemenu#include <vm/vnode_pager.h> 5154371Ssemenu#include <vm/vm_extern.h> 5254371Ssemenu 5354371Ssemenu#include <sys/unistd.h> /* for pathconf(2) constants */ 5454371Ssemenu 5554371Ssemenu#include <fs/hpfs/hpfs.h> 5654371Ssemenu#include <fs/hpfs/hpfsmount.h> 5754371Ssemenu#include <fs/hpfs/hpfs_subr.h> 5854371Ssemenu#include <fs/hpfs/hpfs_ioctl.h> 5954371Ssemenu 6092727Salfredstatic int hpfs_de_uiomove(struct hpfsmount *, struct hpfsdirent *, 6192727Salfred struct uio *); 62138270Sphkstatic vop_ioctl_t hpfs_ioctl; 63138270Sphkstatic vop_read_t hpfs_read; 64138270Sphkstatic vop_write_t hpfs_write; 65138270Sphkstatic vop_getattr_t hpfs_getattr; 66138270Sphkstatic vop_setattr_t hpfs_setattr; 67138270Sphkstatic vop_inactive_t hpfs_inactive; 68138270Sphkstatic vop_print_t hpfs_print; 69138270Sphkstatic vop_reclaim_t hpfs_reclaim; 70138270Sphkstatic vop_strategy_t hpfs_strategy; 71138270Sphkstatic vop_access_t hpfs_access; 72138270Sphkstatic vop_open_t hpfs_open; 73138270Sphkstatic vop_close_t hpfs_close; 74138270Sphkstatic vop_readdir_t hpfs_readdir; 75138279Sphkstatic vop_cachedlookup_t hpfs_lookup; 76138270Sphkstatic vop_create_t hpfs_create; 77138270Sphkstatic vop_remove_t hpfs_remove; 78138270Sphkstatic vop_bmap_t hpfs_bmap; 79138270Sphkstatic vop_fsync_t hpfs_fsync; 80138270Sphkstatic vop_pathconf_t hpfs_pathconf; 81166774Spjdstatic vop_vptofh_t hpfs_vptofh; 8254371Ssemenu 8354371Ssemenustatic int 8454371Ssemenuhpfs_fsync(ap) 8554371Ssemenu struct vop_fsync_args /* { 8654371Ssemenu struct vnode *a_vp; 8754371Ssemenu struct ucred *a_cred; 8854371Ssemenu int a_waitfor; 8983366Sjulian struct thread *a_td; 9054371Ssemenu } */ *ap; 9154371Ssemenu{ 9254371Ssemenu /* 93110584Sjeff * Flush our dirty buffers. 9454371Ssemenu */ 95110584Sjeff vop_stdfsync(ap); 9654371Ssemenu 9754371Ssemenu /* 9854371Ssemenu * Write out the on-disc version of the vnode. 9954371Ssemenu */ 100110584Sjeff return hpfs_update(VTOHP(ap->a_vp)); 10154371Ssemenu} 10254371Ssemenu 10354371Ssemenustatic int 10454371Ssemenuhpfs_ioctl ( 10554371Ssemenu struct vop_ioctl_args /* { 10654371Ssemenu struct vnode *a_vp; 10754371Ssemenu u_long a_command; 10854371Ssemenu caddr_t a_data; 10954371Ssemenu int a_fflag; 11054371Ssemenu struct ucred *a_cred; 11186928Sjhb struct thread *a_td; 11254371Ssemenu } */ *ap) 11354371Ssemenu{ 11454371Ssemenu register struct vnode *vp = ap->a_vp; 11554371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 11654371Ssemenu int error; 11754371Ssemenu 11854371Ssemenu printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ", 11954371Ssemenu hp->h_no, ap->a_command, ap->a_data, ap->a_fflag); 12054371Ssemenu 12154371Ssemenu switch (ap->a_command) { 12254371Ssemenu case HPFSIOCGEANUM: { 12354371Ssemenu u_long eanum; 12454371Ssemenu u_long passed; 12554371Ssemenu struct ea *eap; 12654371Ssemenu 12754371Ssemenu eanum = 0; 12854371Ssemenu 12954371Ssemenu if (hp->h_fn.fn_ealen > 0) { 13054371Ssemenu eap = (struct ea *)&(hp->h_fn.fn_int); 13154371Ssemenu passed = 0; 13254371Ssemenu 13354371Ssemenu while (passed < hp->h_fn.fn_ealen) { 13454371Ssemenu 13554371Ssemenu printf("EAname: %s\n", EA_NAME(eap)); 13654371Ssemenu 13754371Ssemenu eanum++; 13854371Ssemenu passed += sizeof(struct ea) + 13954371Ssemenu eap->ea_namelen + 1 + eap->ea_vallen; 14054371Ssemenu eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + 14154371Ssemenu passed); 14254371Ssemenu } 14354371Ssemenu error = 0; 14454371Ssemenu } else { 14554371Ssemenu error = ENOENT; 14654371Ssemenu } 14754371Ssemenu 14854371Ssemenu printf("%lu eas\n", eanum); 14954371Ssemenu 15054371Ssemenu *(u_long *)ap->a_data = eanum; 15154371Ssemenu 15254371Ssemenu break; 15354371Ssemenu } 15454371Ssemenu case HPFSIOCGEASZ: { 15554371Ssemenu u_long eanum; 15654371Ssemenu u_long passed; 15754371Ssemenu struct ea *eap; 15854371Ssemenu 15954371Ssemenu printf("EA%ld\n", *(u_long *)ap->a_data); 16054371Ssemenu 16154371Ssemenu eanum = 0; 16254371Ssemenu if (hp->h_fn.fn_ealen > 0) { 16354371Ssemenu eap = (struct ea *)&(hp->h_fn.fn_int); 16454371Ssemenu passed = 0; 16554371Ssemenu 16654371Ssemenu error = ENOENT; 16754371Ssemenu while (passed < hp->h_fn.fn_ealen) { 16854371Ssemenu printf("EAname: %s\n", EA_NAME(eap)); 16954371Ssemenu 17054371Ssemenu if (eanum == *(u_long *)ap->a_data) { 17154371Ssemenu *(u_long *)ap->a_data = 17254371Ssemenu eap->ea_namelen + 1 + 17354371Ssemenu eap->ea_vallen; 17454371Ssemenu 17554371Ssemenu error = 0; 17654371Ssemenu break; 17754371Ssemenu } 17854371Ssemenu 17954371Ssemenu eanum++; 18054371Ssemenu passed += sizeof(struct ea) + 18154371Ssemenu eap->ea_namelen + 1 + eap->ea_vallen; 18254371Ssemenu eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + 18354371Ssemenu passed); 18454371Ssemenu } 18554371Ssemenu } else { 18654371Ssemenu error = ENOENT; 18754371Ssemenu } 18854371Ssemenu 18954371Ssemenu break; 19054371Ssemenu } 19154371Ssemenu case HPFSIOCRDEA: { 19254371Ssemenu u_long eanum; 19354371Ssemenu u_long passed; 19454371Ssemenu struct hpfs_rdea *rdeap; 19554371Ssemenu struct ea *eap; 19654371Ssemenu 19754371Ssemenu rdeap = (struct hpfs_rdea *)ap->a_data; 19854371Ssemenu printf("EA%ld\n", rdeap->ea_no); 19954371Ssemenu 20054371Ssemenu eanum = 0; 20154371Ssemenu if (hp->h_fn.fn_ealen > 0) { 20254371Ssemenu eap = (struct ea *)&(hp->h_fn.fn_int); 20354371Ssemenu passed = 0; 20454371Ssemenu 20554371Ssemenu error = ENOENT; 20654371Ssemenu while (passed < hp->h_fn.fn_ealen) { 20754371Ssemenu printf("EAname: %s\n", EA_NAME(eap)); 20854371Ssemenu 20954371Ssemenu if (eanum == rdeap->ea_no) { 21054371Ssemenu rdeap->ea_sz = eap->ea_namelen + 1 + 21154371Ssemenu eap->ea_vallen; 21254371Ssemenu copyout(EA_NAME(eap),rdeap->ea_data, 21354371Ssemenu rdeap->ea_sz); 21454371Ssemenu error = 0; 21554371Ssemenu break; 21654371Ssemenu } 21754371Ssemenu 21854371Ssemenu eanum++; 21954371Ssemenu passed += sizeof(struct ea) + 22054371Ssemenu eap->ea_namelen + 1 + eap->ea_vallen; 22154371Ssemenu eap = (struct ea *)((caddr_t)hp->h_fn.fn_int + 22254371Ssemenu passed); 22354371Ssemenu } 22454371Ssemenu } else { 22554371Ssemenu error = ENOENT; 22654371Ssemenu } 22754371Ssemenu 22854371Ssemenu break; 22954371Ssemenu } 23054371Ssemenu default: 231104003Sphk error = ENOTTY; 23254371Ssemenu break; 23354371Ssemenu } 23454371Ssemenu return (error); 23554371Ssemenu} 23654371Ssemenu 23754371Ssemenu/* 23854371Ssemenu * Map file offset to disk offset. 23954371Ssemenu */ 24054371Ssemenuint 24154371Ssemenuhpfs_bmap(ap) 24254371Ssemenu struct vop_bmap_args /* { 24354371Ssemenu struct vnode *a_vp; 24454371Ssemenu daddr_t a_bn; 245137726Sphk struct bufobj **a_bop; 24654371Ssemenu daddr_t *a_bnp; 24754371Ssemenu int *a_runp; 24854371Ssemenu int *a_runb; 24954371Ssemenu } */ *ap; 25054371Ssemenu{ 25154371Ssemenu register struct hpfsnode *hp = VTOHP(ap->a_vp); 25292363Smckusick daddr_t blkno; 25354371Ssemenu int error; 25454371Ssemenu 255137726Sphk if (ap->a_bop != NULL) 256137726Sphk *ap->a_bop = &hp->h_devvp->v_bufobj; 25754371Ssemenu if (ap->a_runb != NULL) 25854371Ssemenu *ap->a_runb = 0; 25954371Ssemenu if (ap->a_bnp == NULL) 26054371Ssemenu return (0); 26154371Ssemenu 26254371Ssemenu dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn)); 26354371Ssemenu 26492363Smckusick error = hpfs_hpbmap (hp, ap->a_bn, &blkno, ap->a_runp); 26592363Smckusick *ap->a_bnp = blkno; 26654371Ssemenu 26754371Ssemenu return (error); 26854371Ssemenu} 26954371Ssemenu 27054371Ssemenustatic int 27154371Ssemenuhpfs_read(ap) 27254371Ssemenu struct vop_read_args /* { 27354371Ssemenu struct vnode *a_vp; 27454371Ssemenu struct uio *a_uio; 27554371Ssemenu int a_ioflag; 27654371Ssemenu struct ucred *a_cred; 27754371Ssemenu } */ *ap; 27854371Ssemenu{ 27954371Ssemenu register struct vnode *vp = ap->a_vp; 28054371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 28154371Ssemenu struct uio *uio = ap->a_uio; 28254371Ssemenu struct buf *bp; 28354371Ssemenu u_int xfersz, toread; 28454371Ssemenu u_int off; 28554371Ssemenu daddr_t lbn, bn; 28654371Ssemenu int resid; 28754371Ssemenu int runl; 28854371Ssemenu int error = 0; 28954371Ssemenu 29054371Ssemenu resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset); 29154371Ssemenu 29254371Ssemenu 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)); 29354371Ssemenu 29454371Ssemenu while (resid) { 29554371Ssemenu lbn = uio->uio_offset >> DEV_BSHIFT; 29654371Ssemenu off = uio->uio_offset & (DEV_BSIZE - 1); 29754371Ssemenu dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n", 29854371Ssemenu uio->uio_resid, lbn, off)); 29954371Ssemenu error = hpfs_hpbmap(hp, lbn, &bn, &runl); 30054371Ssemenu if (error) 30154371Ssemenu return (error); 30254371Ssemenu 30354371Ssemenu toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE)); 30454371Ssemenu xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 30554371Ssemenu dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n", 30654371Ssemenu bn, runl, toread, xfersz)); 30754371Ssemenu 30854371Ssemenu if (toread == 0) 30954371Ssemenu break; 31054371Ssemenu 31154371Ssemenu error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp); 31254371Ssemenu if (error) { 31354371Ssemenu brelse(bp); 31454371Ssemenu break; 31554371Ssemenu } 31654371Ssemenu 31754371Ssemenu error = uiomove(bp->b_data + off, toread - off, uio); 31854371Ssemenu if(error) { 31954371Ssemenu brelse(bp); 32054371Ssemenu break; 32154371Ssemenu } 32254371Ssemenu brelse(bp); 32354371Ssemenu resid -= toread; 32454371Ssemenu } 32554371Ssemenu dprintf(("hpfs_read: successful\n")); 32654371Ssemenu return (error); 32754371Ssemenu} 32854371Ssemenu 32954371Ssemenustatic int 33054371Ssemenuhpfs_write(ap) 33154371Ssemenu struct vop_write_args /* { 33254371Ssemenu struct vnode *a_vp; 33354371Ssemenu struct uio *a_uio; 33454371Ssemenu int a_ioflag; 33554371Ssemenu struct ucred *a_cred; 33654371Ssemenu } */ *ap; 33754371Ssemenu{ 33854371Ssemenu register struct vnode *vp = ap->a_vp; 33954371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 34054371Ssemenu struct uio *uio = ap->a_uio; 34154371Ssemenu struct buf *bp; 34254371Ssemenu u_int xfersz, towrite; 34354371Ssemenu u_int off; 34454371Ssemenu daddr_t lbn, bn; 34554371Ssemenu int runl; 34654371Ssemenu int error = 0; 34754371Ssemenu 34854371Ssemenu 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)); 34954371Ssemenu 35054371Ssemenu if (ap->a_ioflag & IO_APPEND) { 35154371Ssemenu dprintf(("hpfs_write: APPEND mode\n")); 35254371Ssemenu uio->uio_offset = hp->h_fn.fn_size; 35354371Ssemenu } 35454371Ssemenu if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) { 35554371Ssemenu error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid); 35654371Ssemenu if (error) { 35754371Ssemenu printf("hpfs_write: hpfs_extend FAILED %d\n", error); 35854371Ssemenu return (error); 35954371Ssemenu } 36054371Ssemenu } 36154371Ssemenu 36254371Ssemenu while (uio->uio_resid) { 36354371Ssemenu lbn = uio->uio_offset >> DEV_BSHIFT; 36454371Ssemenu off = uio->uio_offset & (DEV_BSIZE - 1); 36554371Ssemenu dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n", 36654371Ssemenu uio->uio_resid, lbn, off)); 36754371Ssemenu error = hpfs_hpbmap(hp, lbn, &bn, &runl); 36854371Ssemenu if (error) 36954371Ssemenu return (error); 37054371Ssemenu 37154371Ssemenu towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE)); 37254371Ssemenu xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 37354371Ssemenu dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n", 37454371Ssemenu bn, runl, towrite, xfersz)); 37554371Ssemenu 37654371Ssemenu if ((off == 0) && (towrite == xfersz)) { 377111856Sjeff bp = getblk(hp->h_devvp, bn, xfersz, 0, 0, 0); 37854371Ssemenu clrbuf(bp); 37954371Ssemenu } else { 38054371Ssemenu error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp); 38154371Ssemenu if (error) { 38254371Ssemenu brelse(bp); 38354371Ssemenu return (error); 38454371Ssemenu } 38554371Ssemenu } 38654371Ssemenu 38754371Ssemenu error = uiomove(bp->b_data + off, towrite - off, uio); 38854371Ssemenu if(error) { 38954371Ssemenu brelse(bp); 39054371Ssemenu return (error); 39154371Ssemenu } 39254371Ssemenu 39354371Ssemenu if (ap->a_ioflag & IO_SYNC) 39454371Ssemenu bwrite(bp); 39554371Ssemenu else 39654371Ssemenu bawrite(bp); 39754371Ssemenu } 39854371Ssemenu 39954371Ssemenu dprintf(("hpfs_write: successful\n")); 40054371Ssemenu return (0); 40154371Ssemenu} 40254371Ssemenu 40354371Ssemenu/* 40454371Ssemenu * XXXXX do we need hpfsnode locking inside? 40554371Ssemenu */ 40654371Ssemenustatic int 40754371Ssemenuhpfs_getattr(ap) 40854371Ssemenu struct vop_getattr_args /* { 40954371Ssemenu struct vnode *a_vp; 41054371Ssemenu struct vattr *a_vap; 41154371Ssemenu struct ucred *a_cred; 41254371Ssemenu } */ *ap; 41354371Ssemenu{ 41454371Ssemenu register struct vnode *vp = ap->a_vp; 41554371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 41654371Ssemenu register struct vattr *vap = ap->a_vap; 41754371Ssemenu int error; 41854371Ssemenu 41954371Ssemenu dprintf(("hpfs_getattr(0x%x):\n", hp->h_no)); 42054371Ssemenu 42154371Ssemenu vap->va_fsid = dev2udev(hp->h_dev); 42254371Ssemenu vap->va_fileid = hp->h_no; 42354371Ssemenu vap->va_mode = hp->h_mode; 42454371Ssemenu vap->va_nlink = 1; 42554371Ssemenu vap->va_uid = hp->h_uid; 42654371Ssemenu vap->va_gid = hp->h_gid; 427183214Skib vap->va_rdev = NODEV; 42854371Ssemenu vap->va_size = hp->h_fn.fn_size; 42954371Ssemenu vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) + 43054371Ssemenu DEV_BSIZE; 43154371Ssemenu 43254371Ssemenu if (!(hp->h_flag & H_PARVALID)) { 43354371Ssemenu error = hpfs_validateparent(hp); 43454371Ssemenu if (error) 43554371Ssemenu return (error); 43654371Ssemenu } 43754371Ssemenu vap->va_atime = hpfstimetounix(hp->h_atime); 43854371Ssemenu vap->va_mtime = hpfstimetounix(hp->h_mtime); 43954371Ssemenu vap->va_ctime = hpfstimetounix(hp->h_ctime); 44054371Ssemenu 44154371Ssemenu vap->va_flags = 0; 44254371Ssemenu vap->va_gen = 0; 44354371Ssemenu vap->va_blocksize = DEV_BSIZE; 44454371Ssemenu vap->va_type = vp->v_type; 44554371Ssemenu vap->va_filerev = 0; 44654371Ssemenu 44754371Ssemenu return (0); 44854371Ssemenu} 44954371Ssemenu 45054371Ssemenu/* 45154371Ssemenu * XXXXX do we need hpfsnode locking inside? 45254371Ssemenu */ 45354371Ssemenustatic int 45454371Ssemenuhpfs_setattr(ap) 45554371Ssemenu struct vop_setattr_args /* { 45654371Ssemenu struct vnode *a_vp; 45754371Ssemenu struct vattr *a_vap; 45854371Ssemenu struct ucred *a_cred; 45954371Ssemenu } */ *ap; 46054371Ssemenu{ 46154371Ssemenu struct vnode *vp = ap->a_vp; 46254371Ssemenu struct hpfsnode *hp = VTOHP(vp); 46354371Ssemenu struct vattr *vap = ap->a_vap; 46454371Ssemenu struct ucred *cred = ap->a_cred; 465182371Sattilio struct thread *td = curthread; 46654371Ssemenu int error; 46754371Ssemenu 46854371Ssemenu dprintf(("hpfs_setattr(0x%x):\n", hp->h_no)); 46954371Ssemenu 47054371Ssemenu /* 47154371Ssemenu * Check for unsettable attributes. 47254371Ssemenu */ 47354371Ssemenu if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 47454371Ssemenu (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 47554371Ssemenu (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 47654371Ssemenu (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 47754371Ssemenu dprintf(("hpfs_setattr: changing nonsettable attr\n")); 47854371Ssemenu return (EINVAL); 47954371Ssemenu } 48054371Ssemenu 48154371Ssemenu /* Can't change flags XXX Could be implemented */ 48254371Ssemenu if (vap->va_flags != VNOVAL) { 48354371Ssemenu printf("hpfs_setattr: FLAGS CANNOT BE SET\n"); 48454371Ssemenu return (EINVAL); 48554371Ssemenu } 48654371Ssemenu 48754371Ssemenu /* Can't change uid/gid XXX Could be implemented */ 48854371Ssemenu if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 48954371Ssemenu printf("hpfs_setattr: UID/GID CANNOT BE SET\n"); 49054371Ssemenu return (EINVAL); 49154371Ssemenu } 49254371Ssemenu 49354371Ssemenu /* Can't change mode XXX Could be implemented */ 49454371Ssemenu if (vap->va_mode != (mode_t)VNOVAL) { 49554371Ssemenu printf("hpfs_setattr: MODE CANNOT BE SET\n"); 49654371Ssemenu return (EINVAL); 49754371Ssemenu } 49854371Ssemenu 49954371Ssemenu /* Update times */ 50054371Ssemenu if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 50154371Ssemenu if (vp->v_mount->mnt_flag & MNT_RDONLY) 50254371Ssemenu return (EROFS); 503164033Srwatson if (vap->va_vaflags & VA_UTIMES_NULL) { 504164033Srwatson error = VOP_ACCESS(vp, VADMIN, cred, td); 505164033Srwatson if (error) 506164033Srwatson error = VOP_ACCESS(vp, VWRITE, cred, td); 507164033Srwatson } else 508164033Srwatson error = VOP_ACCESS(vp, VADMIN, cred, td); 50954371Ssemenu if (vap->va_atime.tv_sec != VNOVAL) 51054371Ssemenu hp->h_atime = vap->va_atime.tv_sec; 51154371Ssemenu if (vap->va_mtime.tv_sec != VNOVAL) 51254371Ssemenu hp->h_mtime = vap->va_mtime.tv_sec; 51354371Ssemenu 51454371Ssemenu hp->h_flag |= H_PARCHANGE; 51554371Ssemenu } 51654371Ssemenu 51754371Ssemenu if (vap->va_size != VNOVAL) { 51854371Ssemenu switch (vp->v_type) { 51954371Ssemenu case VDIR: 52054371Ssemenu return (EISDIR); 52154371Ssemenu case VREG: 52254371Ssemenu if (vp->v_mount->mnt_flag & MNT_RDONLY) 52354371Ssemenu return (EROFS); 52454371Ssemenu break; 52554371Ssemenu default: 52654371Ssemenu printf("hpfs_setattr: WRONG v_type\n"); 52754371Ssemenu return (EINVAL); 52854371Ssemenu } 52954371Ssemenu 53054371Ssemenu if (vap->va_size < hp->h_fn.fn_size) { 53186931Sjhb error = vtruncbuf(vp, cred, td, vap->va_size, DEV_BSIZE); 53254371Ssemenu if (error) 53354371Ssemenu return (error); 53454371Ssemenu error = hpfs_truncate(hp, vap->va_size); 53554371Ssemenu if (error) 53654371Ssemenu return (error); 53754371Ssemenu 53854371Ssemenu } else if (vap->va_size > hp->h_fn.fn_size) { 53954371Ssemenu vnode_pager_setsize(vp, vap->va_size); 54054371Ssemenu error = hpfs_extend(hp, vap->va_size); 54154371Ssemenu if (error) 54254371Ssemenu return (error); 54354371Ssemenu } 54454371Ssemenu } 54554371Ssemenu 54654371Ssemenu return (0); 54754371Ssemenu} 54854371Ssemenu 54954371Ssemenu/* 550108470Sschweikh * Last reference to a node. If necessary, write or delete it. 55154371Ssemenu */ 55254371Ssemenuint 55354371Ssemenuhpfs_inactive(ap) 55454371Ssemenu struct vop_inactive_args /* { 55554371Ssemenu struct vnode *a_vp; 55654371Ssemenu } */ *ap; 55754371Ssemenu{ 55854371Ssemenu register struct vnode *vp = ap->a_vp; 55954371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 56054371Ssemenu int error; 56154371Ssemenu 56254371Ssemenu dprintf(("hpfs_inactive(0x%x): \n", hp->h_no)); 56354371Ssemenu 56454371Ssemenu if (hp->h_flag & H_CHANGE) { 56554371Ssemenu dprintf(("hpfs_inactive: node changed, update\n")); 56654371Ssemenu error = hpfs_update (hp); 56754371Ssemenu if (error) 56854371Ssemenu return (error); 56954371Ssemenu } 57054371Ssemenu 57154371Ssemenu if (hp->h_flag & H_PARCHANGE) { 57254371Ssemenu dprintf(("hpfs_inactive: parent node changed, update\n")); 57354371Ssemenu error = hpfs_updateparent (hp); 57454371Ssemenu if (error) 57554371Ssemenu return (error); 57654371Ssemenu } 57754371Ssemenu 57854371Ssemenu if (hp->h_flag & H_INVAL) { 579140936Sphk vrecycle(vp, ap->a_td); 58054371Ssemenu return (0); 58154371Ssemenu } 58254371Ssemenu 58354371Ssemenu return (0); 58454371Ssemenu} 58554371Ssemenu 58654371Ssemenu/* 58754371Ssemenu * Reclaim an inode so that it can be used for other purposes. 58854371Ssemenu */ 58954371Ssemenuint 59054371Ssemenuhpfs_reclaim(ap) 59154371Ssemenu struct vop_reclaim_args /* { 59254371Ssemenu struct vnode *a_vp; 59354371Ssemenu } */ *ap; 59454371Ssemenu{ 59554371Ssemenu register struct vnode *vp = ap->a_vp; 59654371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 59754371Ssemenu 59854371Ssemenu dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no)); 59954371Ssemenu 600154487Salfred /* 601154487Salfred * Destroy the vm object and flush associated pages. 602154487Salfred */ 603154487Salfred vnode_destroy_vobject(vp); 604154487Salfred 605143588Sphk vfs_hash_remove(vp); 60654371Ssemenu 60771576Sjasone mtx_destroy(&hp->h_interlock); 60871509Sjhb 60954371Ssemenu vp->v_data = NULL; 61054371Ssemenu 611184205Sdes free(hp, M_HPFSNO); 61254371Ssemenu 61354371Ssemenu return (0); 61454371Ssemenu} 61554371Ssemenu 61654371Ssemenustatic int 61754371Ssemenuhpfs_print(ap) 61854371Ssemenu struct vop_print_args /* { 61954371Ssemenu struct vnode *a_vp; 62054371Ssemenu } */ *ap; 62154371Ssemenu{ 62254371Ssemenu register struct vnode *vp = ap->a_vp; 62354371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 62454371Ssemenu 625111841Snjl printf("\tino 0x%x\n", hp->h_no); 62654371Ssemenu return (0); 62754371Ssemenu} 62854371Ssemenu 62954371Ssemenu/* 63054371Ssemenu * Calculate the logical to physical mapping if not done already, 63154371Ssemenu * then call the device strategy routine. 63254371Ssemenu * 63376159Sphk * In order to be able to swap to a file, the hpfs_hpbmap operation may not 63454371Ssemenu * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl) 63554371Ssemenu */ 63654371Ssemenuint 63754371Ssemenuhpfs_strategy(ap) 63854371Ssemenu struct vop_strategy_args /* { 63954371Ssemenu struct buf *a_bp; 64054371Ssemenu } */ *ap; 64154371Ssemenu{ 64254371Ssemenu register struct buf *bp = ap->a_bp; 64354371Ssemenu register struct vnode *vp = ap->a_vp; 64476159Sphk register struct hpfsnode *hp = VTOHP(ap->a_vp); 64592363Smckusick daddr_t blkno; 646137040Sphk struct bufobj *bo; 64754371Ssemenu int error; 64854371Ssemenu 64954371Ssemenu dprintf(("hpfs_strategy(): \n")); 65054371Ssemenu 65154371Ssemenu if (vp->v_type == VBLK || vp->v_type == VCHR) 65254371Ssemenu panic("hpfs_strategy: spec"); 65354371Ssemenu if (bp->b_blkno == bp->b_lblkno) { 65492363Smckusick error = hpfs_hpbmap (hp, bp->b_lblkno, &blkno, NULL); 65592363Smckusick bp->b_blkno = blkno; 65654371Ssemenu if (error) { 65776159Sphk printf("hpfs_strategy: hpfs_bpbmap FAILED %d\n", error); 65854371Ssemenu bp->b_error = error; 65958934Sphk bp->b_ioflags |= BIO_ERROR; 660133326Sphk bufdone(bp); 661186194Strasz return (0); 66254371Ssemenu } 66354371Ssemenu if ((long)bp->b_blkno == -1) 66454371Ssemenu vfs_bio_clrbuf(bp); 66554371Ssemenu } 66654371Ssemenu if ((long)bp->b_blkno == -1) { 667133326Sphk bufdone(bp); 66854371Ssemenu return (0); 66954371Ssemenu } 670121205Sphk bp->b_iooffset = dbtob(bp->b_blkno); 671137040Sphk bo = hp->h_hpmp->hpm_bo; 672140051Sphk BO_STRATEGY(bo, bp); 67354371Ssemenu return (0); 67454371Ssemenu} 67554371Ssemenu 67654371Ssemenu/* 67754371Ssemenu * XXXXX do we need hpfsnode locking inside? 67854371Ssemenu */ 67954371Ssemenuint 68054371Ssemenuhpfs_access(ap) 68154371Ssemenu struct vop_access_args /* { 68254371Ssemenu struct vnode *a_vp; 683184413Strasz accmode_t a_accmode; 68454371Ssemenu struct ucred *a_cred; 68586928Sjhb struct thread *a_td; 68654371Ssemenu } */ *ap; 68754371Ssemenu{ 68854371Ssemenu struct vnode *vp = ap->a_vp; 68954371Ssemenu struct hpfsnode *hp = VTOHP(vp); 690184413Strasz accmode_t accmode = ap->a_accmode; 69154371Ssemenu 69254371Ssemenu dprintf(("hpfs_access(0x%x):\n", hp->h_no)); 69354371Ssemenu 69454371Ssemenu /* 69596755Strhodes * Disallow write attempts on read-only filesystems; 69654371Ssemenu * unless the file is a socket, fifo, or a block or 69796755Strhodes * character device resident on the filesystem. 69854371Ssemenu */ 699184413Strasz if (accmode & VWRITE) { 70054371Ssemenu switch ((int)vp->v_type) { 70154371Ssemenu case VDIR: 70254371Ssemenu case VLNK: 70354371Ssemenu case VREG: 70454371Ssemenu if (vp->v_mount->mnt_flag & MNT_RDONLY) 70554371Ssemenu return (EROFS); 70654371Ssemenu break; 70754371Ssemenu } 70854371Ssemenu } 70954371Ssemenu 71064865Sphk return (vaccess(vp->v_type, hp->h_mode, hp->h_uid, hp->h_gid, 711184413Strasz ap->a_accmode, ap->a_cred, NULL)); 71254371Ssemenu} 71354371Ssemenu 71454371Ssemenu/* 71554371Ssemenu * Open called. 71654371Ssemenu * 71754371Ssemenu * Nothing to do. 71854371Ssemenu */ 71954371Ssemenu/* ARGSUSED */ 72054371Ssemenustatic int 72154371Ssemenuhpfs_open(ap) 72254371Ssemenu struct vop_open_args /* { 72354371Ssemenu struct vnode *a_vp; 72454371Ssemenu int a_mode; 72554371Ssemenu struct ucred *a_cred; 72686928Sjhb struct thread *a_td; 72754371Ssemenu } */ *ap; 72854371Ssemenu{ 729153084Sru#ifdef HPFS_DEBUG 73054371Ssemenu register struct vnode *vp = ap->a_vp; 73154371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 73254371Ssemenu 73354371Ssemenu printf("hpfs_open(0x%x):\n",hp->h_no); 73454371Ssemenu#endif 73554371Ssemenu 73654371Ssemenu /* 73754371Ssemenu * Files marked append-only must be opened for appending. 73854371Ssemenu */ 73954371Ssemenu 74054371Ssemenu return (0); 74154371Ssemenu} 74254371Ssemenu 74354371Ssemenu/* 74454371Ssemenu * Close called. 74554371Ssemenu * 74654371Ssemenu * Update the times on the inode. 74754371Ssemenu */ 74854371Ssemenu/* ARGSUSED */ 74954371Ssemenustatic int 75054371Ssemenuhpfs_close(ap) 75154371Ssemenu struct vop_close_args /* { 75254371Ssemenu struct vnode *a_vp; 75354371Ssemenu int a_fflag; 75454371Ssemenu struct ucred *a_cred; 75586928Sjhb struct thread *a_td; 75654371Ssemenu } */ *ap; 75754371Ssemenu{ 758153084Sru#ifdef HPFS_DEBUG 75954371Ssemenu register struct vnode *vp = ap->a_vp; 76054371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 76154371Ssemenu 76254371Ssemenu printf("hpfs_close: %d\n",hp->h_no); 76354371Ssemenu#endif 76454371Ssemenu 76554371Ssemenu return (0); 76654371Ssemenu} 76754371Ssemenu 76854371Ssemenustatic int 76954371Ssemenuhpfs_de_uiomove ( 77054371Ssemenu struct hpfsmount *hpmp, 77154371Ssemenu struct hpfsdirent *dep, 77254371Ssemenu struct uio *uio) 77354371Ssemenu{ 77454371Ssemenu struct dirent cde; 77554371Ssemenu int i, error; 77654371Ssemenu 77754371Ssemenu dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ", 77854371Ssemenu dep->de_fnode, dep->de_size, dep->de_namelen, 77954371Ssemenu dep->de_namelen, dep->de_name, dep->de_flag)); 78054371Ssemenu 78154371Ssemenu /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/ 78254371Ssemenu for (i=0; i<dep->de_namelen; i++) 78354371Ssemenu cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]); 78454371Ssemenu 78554371Ssemenu cde.d_name[dep->de_namelen] = '\0'; 78654371Ssemenu cde.d_namlen = dep->de_namelen; 78754371Ssemenu cde.d_fileno = dep->de_fnode; 78854371Ssemenu cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG; 78954371Ssemenu cde.d_reclen = sizeof(struct dirent); 79054371Ssemenu 79154371Ssemenu error = uiomove((char *)&cde, sizeof(struct dirent), uio); 79254371Ssemenu if (error) 79354371Ssemenu return (error); 79454371Ssemenu 79554371Ssemenu dprintf(("[0x%x] ", uio->uio_resid)); 79654371Ssemenu return (error); 79754371Ssemenu} 79854371Ssemenu 79954371Ssemenu 80054371Ssemenustatic struct dirent hpfs_de_dot = 80154371Ssemenu { 0, sizeof(struct dirent), DT_DIR, 1, "." }; 80254371Ssemenustatic struct dirent hpfs_de_dotdot = 80354371Ssemenu { 0, sizeof(struct dirent), DT_DIR, 2, ".." }; 80454371Ssemenuint 80554371Ssemenuhpfs_readdir(ap) 80654371Ssemenu struct vop_readdir_args /* { 80754371Ssemenu struct vnode *a_vp; 80854371Ssemenu struct uio *a_uio; 80954371Ssemenu struct ucred *a_cred; 81054371Ssemenu int *a_ncookies; 81154371Ssemenu u_int **cookies; 81254371Ssemenu } */ *ap; 81354371Ssemenu{ 81454371Ssemenu register struct vnode *vp = ap->a_vp; 81554371Ssemenu register struct hpfsnode *hp = VTOHP(vp); 81654371Ssemenu struct hpfsmount *hpmp = hp->h_hpmp; 81754371Ssemenu struct uio *uio = ap->a_uio; 81854371Ssemenu int ncookies = 0, i, num, cnum; 81954371Ssemenu int error = 0; 82054371Ssemenu off_t off; 82154371Ssemenu struct buf *bp; 82254371Ssemenu struct dirblk *dp; 82354371Ssemenu struct hpfsdirent *dep; 82454371Ssemenu lsn_t olsn; 82554371Ssemenu lsn_t lsn; 82654371Ssemenu int level; 82754371Ssemenu 82854371Ssemenu dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid)); 82954371Ssemenu 83054371Ssemenu off = uio->uio_offset; 83154371Ssemenu 83254371Ssemenu if( uio->uio_offset < sizeof(struct dirent) ) { 83354371Ssemenu dprintf((". faked, ")); 83454371Ssemenu hpfs_de_dot.d_fileno = hp->h_no; 83554371Ssemenu error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio); 83654371Ssemenu if(error) { 83754371Ssemenu return (error); 83854371Ssemenu } 83954371Ssemenu 84054371Ssemenu ncookies ++; 84154371Ssemenu } 84254371Ssemenu 84354371Ssemenu if( uio->uio_offset < 2 * sizeof(struct dirent) ) { 84454371Ssemenu dprintf((".. faked, ")); 84554371Ssemenu hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent; 84654371Ssemenu 84754371Ssemenu error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent), 84854371Ssemenu uio); 84954371Ssemenu if(error) { 85054371Ssemenu return (error); 85154371Ssemenu } 85254371Ssemenu 85354371Ssemenu ncookies ++; 85454371Ssemenu } 85554371Ssemenu 85654371Ssemenu num = uio->uio_offset / sizeof(struct dirent) - 2; 85754371Ssemenu cnum = 0; 85854371Ssemenu 85954371Ssemenu lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn; 86054371Ssemenu 86154371Ssemenu olsn = 0; 86254371Ssemenu level = 1; 86354371Ssemenu 86454371Ssemenudive: 86554371Ssemenu dprintf(("[dive 0x%x] ", lsn)); 86654371Ssemenu error = bread(hp->h_devvp, lsn, D_BSIZE, NOCRED, &bp); 86754371Ssemenu if (error) { 86854371Ssemenu brelse(bp); 86954371Ssemenu return (error); 87054371Ssemenu } 87154371Ssemenu 87254371Ssemenu dp = (struct dirblk *) bp->b_data; 87354371Ssemenu if (dp->d_magic != D_MAGIC) { 87454371Ssemenu printf("hpfs_readdir: MAGIC DOESN'T MATCH\n"); 87554371Ssemenu brelse(bp); 87654371Ssemenu return (EINVAL); 87754371Ssemenu } 87854371Ssemenu 87954371Ssemenu dep = D_DIRENT(dp); 88054371Ssemenu 88154371Ssemenu if (olsn) { 88254371Ssemenu dprintf(("[restore 0x%x] ", olsn)); 88354371Ssemenu 88454371Ssemenu while(!(dep->de_flag & DE_END) ) { 88554371Ssemenu if((dep->de_flag & DE_DOWN) && 88654371Ssemenu (olsn == DE_DOWNLSN(dep))) 88754371Ssemenu break; 88854371Ssemenu dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 88954371Ssemenu } 89054371Ssemenu 89154371Ssemenu if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { 89254371Ssemenu if (dep->de_flag & DE_END) 89354371Ssemenu goto blockdone; 89454371Ssemenu 89554371Ssemenu if (!(dep->de_flag & DE_SPECIAL)) { 89654371Ssemenu if (num <= cnum) { 89754371Ssemenu if (uio->uio_resid < sizeof(struct dirent)) { 89854371Ssemenu brelse(bp); 89954371Ssemenu dprintf(("[resid] ")); 90054371Ssemenu goto readdone; 90154371Ssemenu } 90254371Ssemenu 90354371Ssemenu error = hpfs_de_uiomove(hpmp, dep, uio); 90454371Ssemenu if (error) { 90554371Ssemenu brelse (bp); 90654371Ssemenu return (error); 90754371Ssemenu } 90854371Ssemenu ncookies++; 90954371Ssemenu 91054371Ssemenu if (uio->uio_resid < sizeof(struct dirent)) { 91154371Ssemenu brelse(bp); 91254371Ssemenu dprintf(("[resid] ")); 91354371Ssemenu goto readdone; 91454371Ssemenu } 91554371Ssemenu } 91654371Ssemenu cnum++; 91754371Ssemenu } 91854371Ssemenu 91954371Ssemenu dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 92054371Ssemenu } else { 92154371Ssemenu printf("hpfs_readdir: ERROR! oLSN not found\n"); 92254371Ssemenu brelse(bp); 92354371Ssemenu return (EINVAL); 92454371Ssemenu } 92554371Ssemenu } 92654371Ssemenu 92754371Ssemenu olsn = 0; 92854371Ssemenu 92954371Ssemenu while(!(dep->de_flag & DE_END)) { 93054371Ssemenu if(dep->de_flag & DE_DOWN) { 93154371Ssemenu lsn = DE_DOWNLSN(dep); 93254371Ssemenu brelse(bp); 93354371Ssemenu level++; 93454371Ssemenu goto dive; 93554371Ssemenu } 93654371Ssemenu 93754371Ssemenu if (!(dep->de_flag & DE_SPECIAL)) { 93854371Ssemenu if (num <= cnum) { 93954371Ssemenu if (uio->uio_resid < sizeof(struct dirent)) { 94054371Ssemenu brelse(bp); 94154371Ssemenu dprintf(("[resid] ")); 94254371Ssemenu goto readdone; 94354371Ssemenu } 94454371Ssemenu 94554371Ssemenu error = hpfs_de_uiomove(hpmp, dep, uio); 94654371Ssemenu if (error) { 94754371Ssemenu brelse (bp); 94854371Ssemenu return (error); 94954371Ssemenu } 95054371Ssemenu ncookies++; 95154371Ssemenu 95254371Ssemenu if (uio->uio_resid < sizeof(struct dirent)) { 95354371Ssemenu brelse(bp); 95454371Ssemenu dprintf(("[resid] ")); 95554371Ssemenu goto readdone; 95654371Ssemenu } 95754371Ssemenu } 95854371Ssemenu cnum++; 95954371Ssemenu } 96054371Ssemenu 96154371Ssemenu dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 96254371Ssemenu } 96354371Ssemenu 96454371Ssemenu if(dep->de_flag & DE_DOWN) { 96554371Ssemenu dprintf(("[enddive] ")); 96654371Ssemenu lsn = DE_DOWNLSN(dep); 96754371Ssemenu brelse(bp); 96854371Ssemenu level++; 96954371Ssemenu goto dive; 97054371Ssemenu } 97154371Ssemenu 97254371Ssemenublockdone: 97354371Ssemenu dprintf(("[EOB] ")); 97454371Ssemenu olsn = lsn; 97554371Ssemenu lsn = dp->d_parent; 97654371Ssemenu brelse(bp); 97754371Ssemenu level--; 97854371Ssemenu 97954371Ssemenu dprintf(("[level %d] ", level)); 98054371Ssemenu 98154371Ssemenu if (level > 0) 98254371Ssemenu goto dive; /* undive really */ 98354371Ssemenu 98454371Ssemenu if (ap->a_eofflag) { 98554371Ssemenu dprintf(("[EOF] ")); 98654371Ssemenu *ap->a_eofflag = 1; 98754371Ssemenu } 98854371Ssemenu 98954371Ssemenureaddone: 99054371Ssemenu dprintf(("[readdone]\n")); 99154371Ssemenu if (!error && ap->a_ncookies != NULL) { 99254371Ssemenu struct dirent* dpStart; 99354371Ssemenu struct dirent* dp; 99454371Ssemenu u_long *cookies; 99554371Ssemenu u_long *cookiep; 99654371Ssemenu 99754371Ssemenu dprintf(("%d cookies, ",ncookies)); 99854371Ssemenu if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 99954371Ssemenu panic("hpfs_readdir: unexpected uio from NFS server"); 100054371Ssemenu dpStart = (struct dirent *) 100154371Ssemenu ((caddr_t)uio->uio_iov->iov_base - 100254371Ssemenu (uio->uio_offset - off)); 1003184205Sdes cookies = malloc(ncookies * sizeof(u_long), 1004111119Simp M_TEMP, M_WAITOK); 100554371Ssemenu for (dp = dpStart, cookiep = cookies, i=0; 100654371Ssemenu i < ncookies; 100754371Ssemenu dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) { 100854371Ssemenu off += dp->d_reclen; 100954371Ssemenu *cookiep++ = (u_int) off; 101054371Ssemenu } 101154371Ssemenu *ap->a_ncookies = ncookies; 101254371Ssemenu *ap->a_cookies = cookies; 101354371Ssemenu } 101454371Ssemenu 101554371Ssemenu return (0); 101654371Ssemenu} 101754371Ssemenu 101854371Ssemenuint 101954371Ssemenuhpfs_lookup(ap) 1020138279Sphk struct vop_cachedlookup_args /* { 102154371Ssemenu struct vnode *a_dvp; 102254371Ssemenu struct vnode **a_vpp; 102354371Ssemenu struct componentname *a_cnp; 102454371Ssemenu } */ *ap; 102554371Ssemenu{ 102654371Ssemenu register struct vnode *dvp = ap->a_dvp; 102754371Ssemenu register struct hpfsnode *dhp = VTOHP(dvp); 102854371Ssemenu struct hpfsmount *hpmp = dhp->h_hpmp; 102954371Ssemenu struct componentname *cnp = ap->a_cnp; 103054371Ssemenu struct ucred *cred = cnp->cn_cred; 103154371Ssemenu int error; 103254371Ssemenu int nameiop = cnp->cn_nameiop; 103354371Ssemenu int flags = cnp->cn_flags; 1034144230Sjeff dprintf(("hpfs_lookup(0x%x, %s, %ld):\n", 1035144228Sjeff dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen)); 103654371Ssemenu 103754371Ssemenu if (nameiop != CREATE && nameiop != DELETE && nameiop != LOOKUP) { 103854371Ssemenu printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n"); 103954371Ssemenu return (EOPNOTSUPP); 104054371Ssemenu } 104154371Ssemenu 104286928Sjhb error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread); 104354371Ssemenu if(error) 104454371Ssemenu return (error); 104554371Ssemenu 104654371Ssemenu if( (cnp->cn_namelen == 1) && 104754371Ssemenu !strncmp(cnp->cn_nameptr,".",1) ) { 104854371Ssemenu dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no)); 104954371Ssemenu 105054371Ssemenu VREF(dvp); 105154371Ssemenu *ap->a_vpp = dvp; 105254371Ssemenu 105354371Ssemenu return (0); 105454371Ssemenu } else if( (cnp->cn_namelen == 2) && 105554371Ssemenu !strncmp(cnp->cn_nameptr,"..",2) && (flags & ISDOTDOT) ) { 105654371Ssemenu dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n", 105754371Ssemenu dhp->h_no, dhp->h_fn.fn_parent)); 105854371Ssemenu 105992462Smckusick if (VFS_VGET(hpmp->hpm_mp, dhp->h_fn.fn_parent, 106092462Smckusick LK_NOWAIT | LK_EXCLUSIVE, ap->a_vpp)) { 1061175294Sattilio VOP_UNLOCK(dvp,0); 106292462Smckusick error = VFS_VGET(hpmp->hpm_mp, 106392462Smckusick dhp->h_fn.fn_parent, LK_EXCLUSIVE, ap->a_vpp); 1064175202Sattilio vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY); 1065145006Sjeff if (error) 106692462Smckusick return(error); 106754371Ssemenu } 106892462Smckusick return (0); 106954371Ssemenu } else { 107054371Ssemenu struct buf *bp; 107154371Ssemenu struct hpfsdirent *dep; 107254371Ssemenu struct hpfsnode *hp; 107354371Ssemenu 107454371Ssemenu error = hpfs_genlookupbyname(dhp, 107554371Ssemenu cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep); 107654371Ssemenu if (error) { 107754371Ssemenu if ((error == ENOENT) && (flags & ISLASTCN) && 107854371Ssemenu (nameiop == CREATE || nameiop == RENAME)) { 107954371Ssemenu cnp->cn_flags |= SAVENAME; 108054371Ssemenu return (EJUSTRETURN); 108154371Ssemenu } 108254371Ssemenu 108354371Ssemenu return (error); 108454371Ssemenu } 108554371Ssemenu 108654371Ssemenu dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n", 108754371Ssemenu dep->de_fnode, dep->de_cpid)); 108854371Ssemenu 108954371Ssemenu if (nameiop == DELETE && (flags & ISLASTCN)) { 109086928Sjhb error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread); 109154371Ssemenu if (error) { 109254371Ssemenu brelse(bp); 109354371Ssemenu return (error); 109454371Ssemenu } 109554371Ssemenu } 109654371Ssemenu 109754371Ssemenu if (dhp->h_no == dep->de_fnode) { 109854371Ssemenu brelse(bp); 109954371Ssemenu VREF(dvp); 110054371Ssemenu *ap->a_vpp = dvp; 110154371Ssemenu return (0); 110254371Ssemenu } 110354371Ssemenu 110492462Smckusick error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, LK_EXCLUSIVE, 110592462Smckusick ap->a_vpp); 110654371Ssemenu if (error) { 110754371Ssemenu printf("hpfs_lookup: VFS_VGET FAILED %d\n", error); 110854371Ssemenu brelse(bp); 110954371Ssemenu return(error); 111054371Ssemenu } 111154371Ssemenu 111254371Ssemenu hp = VTOHP(*ap->a_vpp); 111354371Ssemenu 111454371Ssemenu hp->h_mtime = dep->de_mtime; 111554371Ssemenu hp->h_ctime = dep->de_ctime; 111654371Ssemenu hp->h_atime = dep->de_atime; 111754371Ssemenu bcopy(dep->de_name, hp->h_name, dep->de_namelen); 111854371Ssemenu hp->h_name[dep->de_namelen] = '\0'; 111954371Ssemenu hp->h_namelen = dep->de_namelen; 112054371Ssemenu hp->h_flag |= H_PARVALID; 112154371Ssemenu 112254371Ssemenu brelse(bp); 112354371Ssemenu 112454371Ssemenu if ((flags & MAKEENTRY) && 112554371Ssemenu (!(flags & ISLASTCN) || 112654371Ssemenu (nameiop != DELETE && nameiop != CREATE))) 112754371Ssemenu cache_enter(dvp, *ap->a_vpp, cnp); 112854371Ssemenu } 112954371Ssemenu return (error); 113054371Ssemenu} 113154371Ssemenu 113254371Ssemenuint 113354371Ssemenuhpfs_remove(ap) 113454371Ssemenu struct vop_remove_args /* { 113554371Ssemenu struct vnode *a_dvp; 113654371Ssemenu struct vnode *a_vp; 113754371Ssemenu struct componentname *a_cnp; 113854371Ssemenu } */ *ap; 113954371Ssemenu{ 114054371Ssemenu int error; 114154371Ssemenu 114254371Ssemenu dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no, 114354371Ssemenu ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen)); 114454371Ssemenu 114554371Ssemenu if (ap->a_vp->v_type == VDIR) 114654371Ssemenu return (EPERM); 114754371Ssemenu 114854371Ssemenu error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp); 114954371Ssemenu return (error); 115054371Ssemenu} 115154371Ssemenu 115254371Ssemenuint 115354371Ssemenuhpfs_create(ap) 115454371Ssemenu struct vop_create_args /* { 115554371Ssemenu struct vnode *a_dvp; 115654371Ssemenu struct vnode **a_vpp; 115754371Ssemenu struct componentname *a_cnp; 115854371Ssemenu struct vattr *a_vap; 115954371Ssemenu } */ *ap; 116054371Ssemenu{ 116154371Ssemenu int error; 116254371Ssemenu 116354371Ssemenu dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no, 116454371Ssemenu ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen)); 116554371Ssemenu 116654371Ssemenu if (!(ap->a_cnp->cn_flags & HASBUF)) 116754371Ssemenu panic ("hpfs_create: no name\n"); 116854371Ssemenu 116954371Ssemenu error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap); 117054371Ssemenu 117154371Ssemenu return (error); 117254371Ssemenu} 117354371Ssemenu 117454371Ssemenu/* 117554371Ssemenu * Return POSIX pathconf information applicable to NTFS filesystem 117654371Ssemenu */ 117754371Ssemenuint 117854371Ssemenuhpfs_pathconf(ap) 117954371Ssemenu struct vop_pathconf_args /* { 118054371Ssemenu struct vnode *a_vp; 118154371Ssemenu int a_name; 118254371Ssemenu register_t *a_retval; 118354371Ssemenu } */ *ap; 118454371Ssemenu{ 118554371Ssemenu switch (ap->a_name) { 118654371Ssemenu case _PC_LINK_MAX: 118754371Ssemenu *ap->a_retval = 1; 118854371Ssemenu return (0); 118954371Ssemenu case _PC_NAME_MAX: 119054371Ssemenu *ap->a_retval = HPFS_MAXFILENAME; 119154371Ssemenu return (0); 119254371Ssemenu case _PC_PATH_MAX: 119354371Ssemenu *ap->a_retval = PATH_MAX; 119454371Ssemenu return (0); 119554371Ssemenu case _PC_CHOWN_RESTRICTED: 119654371Ssemenu *ap->a_retval = 1; 119754371Ssemenu return (0); 119854371Ssemenu case _PC_NO_TRUNC: 119954371Ssemenu *ap->a_retval = 0; 120054371Ssemenu return (0); 120154371Ssemenu default: 120254371Ssemenu return (EINVAL); 120354371Ssemenu } 120454371Ssemenu /* NOTREACHED */ 120554371Ssemenu} 120654371Ssemenu 1207166774Spjdint 1208166774Spjdhpfs_vptofh(ap) 1209166774Spjd struct vop_vptofh_args /* { 1210166774Spjd struct vnode *a_vp; 1211166774Spjd struct fid *a_fhp; 1212166774Spjd } */ *ap; 1213166774Spjd{ 1214166774Spjd register struct hpfsnode *hpp; 1215166774Spjd register struct hpfid *hpfhp; 121654371Ssemenu 1217166774Spjd hpp = VTOHP(ap->a_vp); 1218166774Spjd hpfhp = (struct hpfid *)ap->a_fhp; 1219166774Spjd hpfhp->hpfid_len = sizeof(struct hpfid); 1220166774Spjd hpfhp->hpfid_ino = hpp->h_no; 1221166774Spjd /* hpfhp->hpfid_gen = hpp->h_gen; */ 1222166774Spjd return (0); 1223166774Spjd} 1224166774Spjd 1225166774Spjd 122654371Ssemenu/* 122754371Ssemenu * Global vfs data structures 122854371Ssemenu */ 1229138290Sphkstruct vop_vector hpfs_vnodeops = { 1230140196Sphk .vop_default = &default_vnodeops, 123154371Ssemenu 1232140196Sphk .vop_access = hpfs_access, 1233140196Sphk .vop_bmap = hpfs_bmap, 1234140196Sphk .vop_cachedlookup = hpfs_lookup, 1235140196Sphk .vop_close = hpfs_close, 1236140196Sphk .vop_create = hpfs_create, 1237140196Sphk .vop_fsync = hpfs_fsync, 1238140196Sphk .vop_getattr = hpfs_getattr, 1239140196Sphk .vop_inactive = hpfs_inactive, 1240140196Sphk .vop_ioctl = hpfs_ioctl, 1241140196Sphk .vop_lookup = vfs_cache_lookup, 1242140196Sphk .vop_open = hpfs_open, 1243140196Sphk .vop_pathconf = hpfs_pathconf, 1244140196Sphk .vop_print = hpfs_print, 1245140196Sphk .vop_read = hpfs_read, 1246140196Sphk .vop_readdir = hpfs_readdir, 1247140196Sphk .vop_reclaim = hpfs_reclaim, 1248140196Sphk .vop_remove = hpfs_remove, 1249140196Sphk .vop_setattr = hpfs_setattr, 1250140196Sphk .vop_strategy = hpfs_strategy, 1251140196Sphk .vop_write = hpfs_write, 1252166774Spjd .vop_vptofh = hpfs_vptofh, 125354371Ssemenu}; 1254