2 * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
35 #include <sys/types.h>
37 #include <sys/vnode.h>
38 #include <sys/mount.h>
39 #include <sys/namei.h>
40 #include <sys/malloc.h>
42 #include <sys/dirent.h>
44 #include <machine/limits.h>
47 #include <vm/vm_param.h>
48 #if !defined(__DragonFly__)
49 #include <vm/vm_prot.h>
51 #include <vm/vm_page.h>
52 #include <vm/vm_object.h>
53 #include <vm/vm_pager.h>
54 #include <vm/vm_zone.h>
55 #if defined(__DragonFly__)
56 #include <vm/vnode_pager.h>
58 #include <vm/vm_extern.h>
62 #if !defined(__DragonFly__)
63 #include <miscfs/specfs/specdev.h>
64 #include <miscfs/genfs/genfs.h>
67 #include <sys/unistd.h> /* for pathconf(2) constants */
70 #include "hpfsmount.h"
71 #include "hpfs_subr.h"
72 #include "hpfs_ioctl.h"
74 static int hpfs_de_uiomove (int *, struct hpfsmount
*,
75 struct hpfsdirent
*, struct uio
*);
76 static int hpfs_ioctl (struct vop_ioctl_args
*ap
);
77 static int hpfs_read (struct vop_read_args
*);
78 static int hpfs_write (struct vop_write_args
*ap
);
79 static int hpfs_getattr (struct vop_getattr_args
*ap
);
80 static int hpfs_setattr (struct vop_setattr_args
*ap
);
81 static int hpfs_inactive (struct vop_inactive_args
*ap
);
82 static int hpfs_print (struct vop_print_args
*ap
);
83 static int hpfs_reclaim (struct vop_reclaim_args
*ap
);
84 static int hpfs_strategy (struct vop_strategy_args
*ap
);
85 static int hpfs_access (struct vop_access_args
*ap
);
86 static int hpfs_readdir (struct vop_readdir_args
*ap
);
87 static int hpfs_lookup (struct vop_old_lookup_args
*ap
);
88 static int hpfs_create (struct vop_old_create_args
*);
89 static int hpfs_remove (struct vop_old_remove_args
*);
90 static int hpfs_bmap (struct vop_bmap_args
*ap
);
91 #if defined(__DragonFly__)
92 static int hpfs_fsync (struct vop_fsync_args
*ap
);
94 static int hpfs_pathconf (struct vop_pathconf_args
*ap
);
96 #if defined(__DragonFly__)
99 * hpfs_fsync(struct vnode *a_vp, int a_waitfor)
102 hpfs_fsync(struct vop_fsync_args
*ap
)
104 struct vnode
*vp
= ap
->a_vp
;
107 * Flush all dirty buffers associated with a vnode.
112 vfsync(vp
, ap
->a_waitfor
, 0, NULL
, NULL
);
114 if (ap
->a_waitfor
== MNT_WAIT
&& !RB_EMPTY(&vp
->v_rbdirty_tree
)) {
115 vprint("hpfs_fsync: dirty", vp
);
121 * Write out the on-disc version of the vnode.
123 return hpfs_update(VTOHP(vp
));
129 * hpfs_ioctl(struct vnode *a_vp, u_long a_command, caddr_t a_data,
130 * int a_fflag, struct ucred *a_cred)
133 hpfs_ioctl(struct vop_ioctl_args
*ap
)
135 struct vnode
*vp
= ap
->a_vp
;
136 struct hpfsnode
*hp
= VTOHP(vp
);
139 kprintf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
140 hp
->h_no
, ap
->a_command
, ap
->a_data
, ap
->a_fflag
);
142 switch (ap
->a_command
) {
143 case HPFSIOCGEANUM
: {
150 if (hp
->h_fn
.fn_ealen
> 0) {
151 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
154 while (passed
< hp
->h_fn
.fn_ealen
) {
156 kprintf("EAname: %s\n", EA_NAME(eap
));
159 passed
+= sizeof(struct ea
) +
160 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
161 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
169 kprintf("%lu eas\n", eanum
);
171 *(u_long
*)ap
->a_data
= eanum
;
180 kprintf("EA%ld\n", *(u_long
*)ap
->a_data
);
183 if (hp
->h_fn
.fn_ealen
> 0) {
184 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
188 while (passed
< hp
->h_fn
.fn_ealen
) {
189 kprintf("EAname: %s\n", EA_NAME(eap
));
191 if (eanum
== *(u_long
*)ap
->a_data
) {
192 *(u_long
*)ap
->a_data
=
193 eap
->ea_namelen
+ 1 +
201 passed
+= sizeof(struct ea
) +
202 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
203 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
215 struct hpfs_rdea
*rdeap
;
218 rdeap
= (struct hpfs_rdea
*)ap
->a_data
;
219 kprintf("EA%ld\n", rdeap
->ea_no
);
222 if (hp
->h_fn
.fn_ealen
> 0) {
223 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
227 while (passed
< hp
->h_fn
.fn_ealen
) {
228 kprintf("EAname: %s\n", EA_NAME(eap
));
230 if (eanum
== rdeap
->ea_no
) {
231 rdeap
->ea_sz
= eap
->ea_namelen
+ 1 +
233 copyout(EA_NAME(eap
),rdeap
->ea_data
,
240 passed
+= sizeof(struct ea
) +
241 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
242 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
259 * Map file offset to disk offset.
261 * hpfs_bmap(struct vnode *a_vp, off_t a_loffset,
262 * off_t *a_doffsetp, int *a_runp, int *a_runb)
265 hpfs_bmap(struct vop_bmap_args
*ap
)
267 struct hpfsnode
*hp
= VTOHP(ap
->a_vp
);
272 if (ap
->a_runb
!= NULL
)
274 if (ap
->a_doffsetp
== NULL
)
277 dprintf(("hpfs_bmap(0x%x): ", hp
->h_no
));
279 lbn
= ap
->a_loffset
>> DEV_BSHIFT
;
280 KKASSERT(((int)ap
->a_loffset
& DEV_BMASK
) == 0);
282 error
= hpfs_hpbmap (hp
, lbn
, &dbn
, ap
->a_runp
);
283 if (error
|| dbn
== (daddr_t
)-1) {
284 *ap
->a_doffsetp
= NOOFFSET
;
286 *ap
->a_doffsetp
= (off_t
)dbn
<< DEV_BSHIFT
;
292 * hpfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
293 * struct ucred *a_cred)
296 hpfs_read(struct vop_read_args
*ap
)
298 struct vnode
*vp
= ap
->a_vp
;
299 struct hpfsnode
*hp
= VTOHP(vp
);
300 struct uio
*uio
= ap
->a_uio
;
302 u_int xfersz
, toread
;
309 resid
= (int)szmin(uio
->uio_resid
, hp
->h_fn
.fn_size
- uio
->uio_offset
);
311 dprintf(("hpfs_read(0x%x, off: %d resid: %zx, segflg: %d): "
313 hp
->h_no
, (u_int32_t
)uio
->uio_offset
,
314 uio
->uio_resid
, uio
->uio_segflg
, resid
));
317 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
318 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
319 dprintf(("hpfs_read: resid: 0x%zx lbn: 0x%x off: 0x%x\n",
320 uio
->uio_resid
, lbn
, off
));
321 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
325 toread
= min(off
+ resid
, min(64*1024, (runl
+1)*DEV_BSIZE
));
326 xfersz
= roundup2(toread
, DEV_BSIZE
);
327 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
328 bn
, runl
, toread
, xfersz
));
333 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
339 error
= uiomove(bp
->b_data
+ off
, (size_t)(toread
- off
), uio
);
347 dprintf(("hpfs_read: successful\n"));
352 * hpfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
353 * struct ucred *a_cred)
356 hpfs_write(struct vop_write_args
*ap
)
358 struct vnode
*vp
= ap
->a_vp
;
359 struct hpfsnode
*hp
= VTOHP(vp
);
360 struct uio
*uio
= ap
->a_uio
;
362 u_int xfersz
, towrite
;
368 dprintf(("hpfs_write(0x%x, off: %d resid: %zd, segflg: %d):\n",
369 hp
->h_no
, (u_int32_t
)uio
->uio_offset
,
370 uio
->uio_resid
, uio
->uio_segflg
));
372 if (ap
->a_ioflag
& IO_APPEND
) {
373 dprintf(("hpfs_write: APPEND mode\n"));
374 uio
->uio_offset
= hp
->h_fn
.fn_size
;
376 if (uio
->uio_offset
+ uio
->uio_resid
> hp
->h_fn
.fn_size
) {
377 error
= hpfs_extend (hp
, uio
->uio_offset
+ uio
->uio_resid
);
379 kprintf("hpfs_write: hpfs_extend FAILED %d\n", error
);
384 while (uio
->uio_resid
) {
385 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
386 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
387 dprintf(("hpfs_write: resid: 0x%zx lbn: 0x%x off: 0x%x\n",
388 uio
->uio_resid
, lbn
, off
));
389 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
393 towrite
= szmin(off
+ uio
->uio_resid
,
394 min(64*1024, (runl
+1)*DEV_BSIZE
));
395 xfersz
= roundup2(towrite
, DEV_BSIZE
);
396 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
397 bn
, runl
, towrite
, xfersz
));
400 * We do not have to issue a read-before-write if the xfer
401 * size does not cover the whole block.
403 * In the UIO_NOCOPY case, however, we are not overwriting
404 * anything and must do a read-before-write to fill in
405 * any missing pieces.
407 if (off
== 0 && towrite
== xfersz
&&
408 uio
->uio_segflg
!= UIO_NOCOPY
) {
409 bp
= getblk(hp
->h_devvp
, dbtodoff(bn
), xfersz
, 0, 0);
412 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
419 error
= uiomove(bp
->b_data
+ off
, (size_t)(towrite
- off
), uio
);
425 if (ap
->a_ioflag
& IO_SYNC
)
431 dprintf(("hpfs_write: successful\n"));
436 * XXXXX do we need hpfsnode locking inside?
438 * hpfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
441 hpfs_getattr(struct vop_getattr_args
*ap
)
443 struct vnode
*vp
= ap
->a_vp
;
444 struct hpfsnode
*hp
= VTOHP(vp
);
445 struct vattr
*vap
= ap
->a_vap
;
448 dprintf(("hpfs_getattr(0x%x):\n", hp
->h_no
));
450 #if defined(__DragonFly__)
451 vap
->va_fsid
= dev2udev(hp
->h_dev
);
452 #else /* defined(__NetBSD__) */
453 vap
->va_fsid
= ip
->i_dev
;
455 vap
->va_fileid
= hp
->h_no
;
456 vap
->va_mode
= hp
->h_mode
;
458 vap
->va_uid
= hp
->h_uid
;
459 vap
->va_gid
= hp
->h_gid
;
460 vap
->va_rmajor
= VNOVAL
;
461 vap
->va_rminor
= VNOVAL
;
462 vap
->va_size
= hp
->h_fn
.fn_size
;
463 vap
->va_bytes
= roundup2(hp
->h_fn
.fn_size
, DEV_BSIZE
) + DEV_BSIZE
;
465 if (!(hp
->h_flag
& H_PARVALID
)) {
466 error
= hpfs_validateparent(hp
);
470 vap
->va_atime
= hpfstimetounix(hp
->h_atime
);
471 vap
->va_mtime
= hpfstimetounix(hp
->h_mtime
);
472 vap
->va_ctime
= hpfstimetounix(hp
->h_ctime
);
476 vap
->va_blocksize
= DEV_BSIZE
;
477 vap
->va_type
= vp
->v_type
;
484 * XXXXX do we need hpfsnode locking inside?
486 * hpfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
489 hpfs_setattr(struct vop_setattr_args
*ap
)
491 struct vnode
*vp
= ap
->a_vp
;
492 struct hpfsnode
*hp
= VTOHP(vp
);
493 struct vattr
*vap
= ap
->a_vap
;
494 struct ucred
*cred
= ap
->a_cred
;
497 dprintf(("hpfs_setattr(0x%x):\n", hp
->h_no
));
500 * Check for unsettable attributes.
502 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
503 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
504 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rmajor
!= VNOVAL
) ||
505 (vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
506 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
510 /* Can't change flags XXX Could be implemented */
511 if (vap
->va_flags
!= VNOVAL
) {
512 kprintf("hpfs_setattr: FLAGS CANNOT BE SET\n");
516 /* Can't change uid/gid XXX Could be implemented */
517 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
518 kprintf("hpfs_setattr: UID/GID CANNOT BE SET\n");
522 /* Can't change mode XXX Could be implemented */
523 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
524 kprintf("hpfs_setattr: MODE CANNOT BE SET\n");
529 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
530 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
532 if (cred
->cr_uid
!= hp
->h_uid
&&
533 (error
= priv_check_cred(cred
, PRIV_VFS_SETATTR
, 0)) &&
534 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
535 (error
= VOP_EACCESS(vp
, VWRITE
, cred
))))
537 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
538 hp
->h_atime
= vap
->va_atime
.tv_sec
;
539 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
540 hp
->h_mtime
= vap
->va_mtime
.tv_sec
;
542 hp
->h_flag
|= H_PARCHANGE
;
545 if (vap
->va_size
!= VNOVAL
) {
546 switch (vp
->v_type
) {
550 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
554 kprintf("hpfs_setattr: WRONG v_type\n");
558 if (vap
->va_size
< hp
->h_fn
.fn_size
) {
559 #if defined(__DragonFly__)
560 error
= vtruncbuf(vp
, vap
->va_size
, DEV_BSIZE
);
563 #else /* defined(__NetBSD__) */
564 #error Need alternation for vtruncbuf()
566 error
= hpfs_truncate(hp
, vap
->va_size
);
570 } else if (vap
->va_size
> hp
->h_fn
.fn_size
) {
571 #if defined(__DragonFly__)
572 vnode_pager_setsize(vp
, vap
->va_size
);
574 error
= hpfs_extend(hp
, vap
->va_size
);
584 * Last reference to an node. If necessary, write or delete it.
586 * hpfs_inactive(struct vnode *a_vp)
589 hpfs_inactive(struct vop_inactive_args
*ap
)
591 struct vnode
*vp
= ap
->a_vp
;
592 struct hpfsnode
*hp
= VTOHP(vp
);
595 dprintf(("hpfs_inactive(0x%x): \n", hp
->h_no
));
597 if (hp
->h_flag
& H_CHANGE
) {
598 dprintf(("hpfs_inactive: node changed, update\n"));
599 error
= hpfs_update (hp
);
604 if (hp
->h_flag
& H_PARCHANGE
) {
605 dprintf(("hpfs_inactive: parent node changed, update\n"));
606 error
= hpfs_updateparent (hp
);
611 if (prtactive
&& VREFCNT(vp
) > 1)
612 vprint("hpfs_inactive: pushing active", vp
);
614 if (hp
->h_flag
& H_INVAL
) {
615 #if defined(__DragonFly__)
617 #else /* defined(__NetBSD__) */
626 * Reclaim an inode so that it can be used for other purposes.
628 * hpfs_reclaim(struct vnode *a_vp)
631 hpfs_reclaim(struct vop_reclaim_args
*ap
)
633 struct vnode
*vp
= ap
->a_vp
;
634 struct hpfsnode
*hp
= VTOHP(vp
);
636 dprintf(("hpfs_reclaim(0x%x0): \n", hp
->h_no
));
640 /* Purge old data structures associated with the inode. */
654 * hpfs_print(struct vnode *a_vp)
657 hpfs_print(struct vop_print_args
*ap
)
659 struct vnode
*vp
= ap
->a_vp
;
660 struct hpfsnode
*hp
= VTOHP(vp
);
662 kprintf("tag VT_HPFS, ino 0x%x",hp
->h_no
);
663 lockmgr_printinfo(&vp
->v_lock
);
669 * Calculate the logical to physical mapping if not done already,
670 * then call the device strategy routine.
672 * In order to be able to swap to a file, the VOP_BMAP operation may not
673 * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl)
675 * hpfs_strategy(struct vnode *a_vp, struct bio *a_bio)
678 hpfs_strategy(struct vop_strategy_args
*ap
)
680 struct bio
*bio
= ap
->a_bio
;
682 struct buf
*bp
= bio
->bio_buf
;
683 struct vnode
*vp
= ap
->a_vp
;
687 dprintf(("hpfs_strategy(): \n"));
689 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
690 panic("hpfs_strategy: spec");
692 nbio
= push_bio(bio
);
693 if (nbio
->bio_offset
== NOOFFSET
) {
694 error
= VOP_BMAP(vp
, bio
->bio_offset
, &nbio
->bio_offset
,
695 NULL
, NULL
, bp
->b_cmd
);
697 kprintf("hpfs_strategy: VOP_BMAP FAILED %d\n", error
);
699 bp
->b_flags
|= B_ERROR
;
700 /* I/O was never started on nbio, must biodone(bio) */
704 if (nbio
->bio_offset
== NOOFFSET
)
707 if (nbio
->bio_offset
== NOOFFSET
) {
708 /* I/O was never started on nbio, must biodone(bio) */
712 hp
= VTOHP(ap
->a_vp
);
713 vn_strategy(hp
->h_devvp
, nbio
);
718 * XXXXX do we need hpfsnode locking inside?
720 * hpfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
723 hpfs_access(struct vop_access_args
*ap
)
725 struct vnode
*vp
= ap
->a_vp
;
726 struct hpfsnode
*hp
= VTOHP(vp
);
728 dprintf(("hpfs_access(0x%x):\n", hp
->h_no
));
729 return (vop_helper_access(ap
, hp
->h_uid
, hp
->h_gid
, hp
->h_mode
, 0));
733 hpfs_de_uiomove(int *error
, struct hpfsmount
*hpmp
, struct hpfsdirent
*dep
,
736 char convname
[HPFS_MAXFILENAME
+ 1];
739 dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
740 dep
->de_fnode
, dep
->de_size
, dep
->de_namelen
,
741 dep
->de_namelen
, dep
->de_name
, dep
->de_flag
));
743 /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
744 for (i
=0; i
<dep
->de_namelen
; i
++)
745 convname
[i
] = hpfs_d2u(hpmp
, dep
->de_name
[i
]);
746 convname
[dep
->de_namelen
] = '\0';
748 success
= vop_write_dirent(error
, uio
, dep
->de_fnode
,
749 (dep
->de_flag
& DE_DIR
) ? DT_DIR
: DT_REG
,
750 dep
->de_namelen
, convname
);
752 dprintf(("[0x%zx] ", uio
->uio_resid
));
758 * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
759 * int *a_ncookies, off_t **cookies)
762 hpfs_readdir(struct vop_readdir_args
*ap
)
764 struct vnode
*vp
= ap
->a_vp
;
765 struct hpfsnode
*hp
= VTOHP(vp
);
766 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
767 struct uio
*uio
= ap
->a_uio
;
768 int ncookies
= 0, i
, num
, cnum
;
772 struct hpfsdirent
*dep
;
777 dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%zx): ",
778 hp
->h_no
, (u_int32_t
)uio
->uio_offset
, uio
->uio_resid
));
781 * As we need to fake up . and .., and the remaining directory structure
782 * can't be expressed in one off_t as well, we just increment uio_offset
783 * by 1 for each entry.
785 * num is the entry we need to start reporting
786 * cnum is the current entry
788 if (uio
->uio_offset
< 0 || uio
->uio_offset
> INT_MAX
)
790 error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
| LK_FAILRECLAIM
);
794 num
= uio
->uio_offset
;
798 dprintf((". faked, "));
799 if (vop_write_dirent(&error
, uio
, hp
->h_no
, DT_DIR
, 1, "."))
808 dprintf((".. faked, "));
809 if (vop_write_dirent(&error
, uio
, hp
->h_fn
.fn_parent
, DT_DIR
, 2, ".."))
817 lsn
= ((alleaf_t
*)hp
->h_fn
.fn_abd
)->al_lsn
;
823 dprintf(("[dive 0x%x] ", lsn
));
824 error
= bread(hp
->h_devvp
, dbtodoff(lsn
), D_BSIZE
, &bp
);
830 dp
= (struct dirblk
*) bp
->b_data
;
831 if (dp
->d_magic
!= D_MAGIC
) {
832 kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
841 dprintf(("[restore 0x%x] ", olsn
));
843 while(!(dep
->de_flag
& DE_END
) ) {
844 if((dep
->de_flag
& DE_DOWN
) &&
845 (olsn
== DE_DOWNLSN(dep
)))
847 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
850 if((dep
->de_flag
& DE_DOWN
) && (olsn
== DE_DOWNLSN(dep
))) {
851 if (dep
->de_flag
& DE_END
)
854 if (!(dep
->de_flag
& DE_SPECIAL
)) {
856 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
858 dprintf(("[resid] "));
870 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
872 kprintf("hpfs_readdir: ERROR! oLSN not found\n");
881 while(!(dep
->de_flag
& DE_END
)) {
882 if(dep
->de_flag
& DE_DOWN
) {
883 lsn
= DE_DOWNLSN(dep
);
889 if (!(dep
->de_flag
& DE_SPECIAL
)) {
891 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
893 dprintf(("[resid] "));
905 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
908 if(dep
->de_flag
& DE_DOWN
) {
909 dprintf(("[enddive] "));
910 lsn
= DE_DOWNLSN(dep
);
923 dprintf(("[level %d] ", level
));
926 goto dive
; /* undive really */
934 uio
->uio_offset
= cnum
;
935 dprintf(("[readdone]\n"));
936 if (!error
&& ap
->a_ncookies
!= NULL
) {
940 dprintf(("%d cookies, ",ncookies
));
941 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
942 panic("hpfs_readdir: unexpected uio from NFS server");
943 cookies
= kmalloc(ncookies
* sizeof(off_t
), M_TEMP
, M_WAITOK
);
944 for (cookiep
= cookies
, i
=0; i
< ncookies
; i
++)
947 *ap
->a_ncookies
= ncookies
;
948 *ap
->a_cookies
= cookies
;
957 * hpfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
958 * struct componentname *a_cnp)
961 hpfs_lookup(struct vop_old_lookup_args
*ap
)
963 struct vnode
*dvp
= ap
->a_dvp
;
964 struct hpfsnode
*dhp
= VTOHP(dvp
);
965 struct hpfsmount
*hpmp
= dhp
->h_hpmp
;
966 struct componentname
*cnp
= ap
->a_cnp
;
967 struct ucred
*cred
= cnp
->cn_cred
;
968 struct vnode
**vpp
= ap
->a_vpp
;
970 int nameiop
= cnp
->cn_nameiop
;
971 int flags
= cnp
->cn_flags
;
972 int lockparent
= flags
& CNP_LOCKPARENT
;
974 int wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
977 dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
978 dhp
->h_no
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
979 lockparent
, wantparent
));
981 if (nameiop
!= NAMEI_CREATE
&& nameiop
!= NAMEI_DELETE
&& nameiop
!= NAMEI_LOOKUP
) {
982 kprintf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
986 error
= VOP_EACCESS(dvp
, VEXEC
, cred
);
990 if( (cnp
->cn_namelen
== 1) &&
991 !strncmp(cnp
->cn_nameptr
,".",1) ) {
992 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp
->h_no
));
998 } else if( (cnp
->cn_namelen
== 2) &&
999 !strncmp(cnp
->cn_nameptr
,"..",2) && (flags
& CNP_ISDOTDOT
) ) {
1000 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
1001 dhp
->h_no
, dhp
->h_fn
.fn_parent
));
1003 VOP__UNLOCK(dvp
, 0);
1005 error
= VFS_VGET(hpmp
->hpm_mp
, NULL
,
1006 dhp
->h_fn
.fn_parent
, vpp
);
1012 if (lockparent
&& (error
= VOP__LOCK(dvp
, 0))) {
1019 struct hpfsdirent
*dep
;
1020 struct hpfsnode
*hp
;
1022 error
= hpfs_genlookupbyname(dhp
,
1023 cnp
->cn_nameptr
, cnp
->cn_namelen
, &bp
, &dep
);
1025 if (error
== ENOENT
&&
1026 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
)) {
1028 cnp
->cn_flags
|= CNP_PDIRUNLOCK
;
1029 VOP__UNLOCK(dvp
, 0);
1031 return (EJUSTRETURN
);
1037 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
1038 dep
->de_fnode
, dep
->de_cpid
));
1040 if (nameiop
== NAMEI_DELETE
) {
1041 error
= VOP_EACCESS(dvp
, VWRITE
, cred
);
1048 if (dhp
->h_no
== dep
->de_fnode
) {
1055 error
= VFS_VGET(hpmp
->hpm_mp
, NULL
, dep
->de_fnode
, vpp
);
1057 kprintf("hpfs_lookup: VFS_VGET FAILED %d\n", error
);
1064 hp
->h_mtime
= dep
->de_mtime
;
1065 hp
->h_ctime
= dep
->de_ctime
;
1066 hp
->h_atime
= dep
->de_atime
;
1067 bcopy(dep
->de_name
, hp
->h_name
, dep
->de_namelen
);
1068 hp
->h_name
[dep
->de_namelen
] = '\0';
1069 hp
->h_namelen
= dep
->de_namelen
;
1070 hp
->h_flag
|= H_PARVALID
;
1075 cnp
->cn_flags
|= CNP_PDIRUNLOCK
;
1076 VOP__UNLOCK(dvp
, 0);
1083 * hpfs_remove(struct vnode *a_dvp, struct vnode *a_vp,
1084 * struct componentname *a_cnp)
1087 hpfs_remove(struct vop_old_remove_args
*ap
)
1091 dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap
->a_vp
)->h_no
,
1092 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1094 if (ap
->a_vp
->v_type
== VDIR
)
1097 error
= hpfs_removefnode (ap
->a_dvp
, ap
->a_vp
, ap
->a_cnp
);
1102 * hpfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
1103 * struct componentname *a_cnp, struct vattr *a_vap)
1106 hpfs_create(struct vop_old_create_args
*ap
)
1110 dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap
->a_dvp
)->h_no
,
1111 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1113 error
= hpfs_makefnode (ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
);
1119 * Return POSIX pathconf information applicable to NTFS filesystem
1121 * hpfs_pathconf(struct vnode *a_vp, int a_name, t *a_retval)
1124 hpfs_pathconf(struct vop_pathconf_args
*ap
)
1126 switch (ap
->a_name
) {
1131 *ap
->a_retval
= HPFS_MAXFILENAME
;
1134 *ap
->a_retval
= PATH_MAX
;
1136 case _PC_CHOWN_RESTRICTED
:
1142 #if defined(__NetBSD__)
1146 case _PC_FILESIZEBITS
:
1158 * Global vfs data structures
1161 struct vop_ops hpfs_vnode_vops
= {
1162 .vop_default
= vop_defaultop
,
1163 .vop_getattr
= hpfs_getattr
,
1164 .vop_setattr
= hpfs_setattr
,
1165 .vop_inactive
= hpfs_inactive
,
1166 .vop_reclaim
= hpfs_reclaim
,
1167 .vop_print
= hpfs_print
,
1168 .vop_old_create
= hpfs_create
,
1169 .vop_old_remove
= hpfs_remove
,
1170 .vop_old_lookup
= hpfs_lookup
,
1171 .vop_access
= hpfs_access
,
1172 .vop_readdir
= hpfs_readdir
,
1173 .vop_fsync
= hpfs_fsync
,
1174 .vop_bmap
= hpfs_bmap
,
1175 .vop_getpages
= vop_stdgetpages
,
1176 .vop_putpages
= vop_stdputpages
,
1177 .vop_strategy
= hpfs_strategy
,
1178 .vop_read
= hpfs_read
,
1179 .vop_write
= hpfs_write
,
1180 .vop_ioctl
= hpfs_ioctl
,
1181 .vop_pathconf
= hpfs_pathconf