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 $
27 * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.47 2008/06/19 23:27:39 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #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>
61 #if !defined(__DragonFly__)
62 #include <miscfs/specfs/specdev.h>
63 #include <miscfs/genfs/genfs.h>
66 #include <sys/unistd.h> /* for pathconf(2) constants */
69 #include "hpfsmount.h"
70 #include "hpfs_subr.h"
71 #include "hpfs_ioctl.h"
73 static int hpfs_de_uiomove (int *, struct hpfsmount
*,
74 struct hpfsdirent
*, struct uio
*);
75 static int hpfs_ioctl (struct vop_ioctl_args
*ap
);
76 static int hpfs_read (struct vop_read_args
*);
77 static int hpfs_write (struct vop_write_args
*ap
);
78 static int hpfs_getattr (struct vop_getattr_args
*ap
);
79 static int hpfs_setattr (struct vop_setattr_args
*ap
);
80 static int hpfs_inactive (struct vop_inactive_args
*ap
);
81 static int hpfs_print (struct vop_print_args
*ap
);
82 static int hpfs_reclaim (struct vop_reclaim_args
*ap
);
83 static int hpfs_strategy (struct vop_strategy_args
*ap
);
84 static int hpfs_access (struct vop_access_args
*ap
);
85 static int hpfs_readdir (struct vop_readdir_args
*ap
);
86 static int hpfs_lookup (struct vop_old_lookup_args
*ap
);
87 static int hpfs_create (struct vop_old_create_args
*);
88 static int hpfs_remove (struct vop_old_remove_args
*);
89 static int hpfs_bmap (struct vop_bmap_args
*ap
);
90 #if defined(__DragonFly__)
91 static int hpfs_fsync (struct vop_fsync_args
*ap
);
93 static int hpfs_pathconf (struct vop_pathconf_args
*ap
);
95 #if defined(__DragonFly__)
98 * hpfs_fsync(struct vnode *a_vp, int a_waitfor)
101 hpfs_fsync(struct vop_fsync_args
*ap
)
103 struct vnode
*vp
= ap
->a_vp
;
106 * Flush all dirty buffers associated with a vnode.
111 vfsync(vp
, ap
->a_waitfor
, 0, NULL
, NULL
);
113 if (ap
->a_waitfor
== MNT_WAIT
&& !RB_EMPTY(&vp
->v_rbdirty_tree
)) {
114 vprint("hpfs_fsync: dirty", vp
);
120 * Write out the on-disc version of the vnode.
122 return hpfs_update(VTOHP(vp
));
128 * hpfs_ioctl(struct vnode *a_vp, u_long a_command, caddr_t a_data,
129 * int a_fflag, struct ucred *a_cred)
132 hpfs_ioctl(struct vop_ioctl_args
*ap
)
134 struct vnode
*vp
= ap
->a_vp
;
135 struct hpfsnode
*hp
= VTOHP(vp
);
138 kprintf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
139 hp
->h_no
, ap
->a_command
, ap
->a_data
, ap
->a_fflag
);
141 switch (ap
->a_command
) {
142 case HPFSIOCGEANUM
: {
149 if (hp
->h_fn
.fn_ealen
> 0) {
150 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
153 while (passed
< hp
->h_fn
.fn_ealen
) {
155 kprintf("EAname: %s\n", EA_NAME(eap
));
158 passed
+= sizeof(struct ea
) +
159 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
160 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
168 kprintf("%lu eas\n", eanum
);
170 *(u_long
*)ap
->a_data
= eanum
;
179 kprintf("EA%ld\n", *(u_long
*)ap
->a_data
);
182 if (hp
->h_fn
.fn_ealen
> 0) {
183 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
187 while (passed
< hp
->h_fn
.fn_ealen
) {
188 kprintf("EAname: %s\n", EA_NAME(eap
));
190 if (eanum
== *(u_long
*)ap
->a_data
) {
191 *(u_long
*)ap
->a_data
=
192 eap
->ea_namelen
+ 1 +
200 passed
+= sizeof(struct ea
) +
201 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
202 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
214 struct hpfs_rdea
*rdeap
;
217 rdeap
= (struct hpfs_rdea
*)ap
->a_data
;
218 kprintf("EA%ld\n", rdeap
->ea_no
);
221 if (hp
->h_fn
.fn_ealen
> 0) {
222 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
226 while (passed
< hp
->h_fn
.fn_ealen
) {
227 kprintf("EAname: %s\n", EA_NAME(eap
));
229 if (eanum
== rdeap
->ea_no
) {
230 rdeap
->ea_sz
= eap
->ea_namelen
+ 1 +
232 copyout(EA_NAME(eap
),rdeap
->ea_data
,
239 passed
+= sizeof(struct ea
) +
240 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
241 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
258 * Map file offset to disk offset.
260 * hpfs_bmap(struct vnode *a_vp, off_t a_loffset,
261 * off_t *a_doffsetp, int *a_runp, int *a_runb)
264 hpfs_bmap(struct vop_bmap_args
*ap
)
266 struct hpfsnode
*hp
= VTOHP(ap
->a_vp
);
271 if (ap
->a_runb
!= NULL
)
273 if (ap
->a_doffsetp
== NULL
)
276 dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp
->h_no
, ap
->a_bn
));
278 lbn
= ap
->a_loffset
>> DEV_BSHIFT
;
279 KKASSERT(((int)ap
->a_loffset
& DEV_BMASK
) == 0);
281 error
= hpfs_hpbmap (hp
, lbn
, &dbn
, ap
->a_runp
);
282 if (error
|| dbn
== (daddr_t
)-1) {
283 *ap
->a_doffsetp
= NOOFFSET
;
285 *ap
->a_doffsetp
= (off_t
)dbn
<< DEV_BSHIFT
;
291 * hpfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
292 * struct ucred *a_cred)
295 hpfs_read(struct vop_read_args
*ap
)
297 struct vnode
*vp
= ap
->a_vp
;
298 struct hpfsnode
*hp
= VTOHP(vp
);
299 struct uio
*uio
= ap
->a_uio
;
301 u_int xfersz
, toread
;
308 resid
= min (uio
->uio_resid
, hp
->h_fn
.fn_size
- uio
->uio_offset
);
310 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
));
313 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
314 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
315 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
316 uio
->uio_resid
, lbn
, off
));
317 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
321 toread
= min(off
+ resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
322 xfersz
= (toread
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
323 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
324 bn
, runl
, toread
, xfersz
));
329 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
335 error
= uiomove(bp
->b_data
+ off
, toread
- off
, uio
);
343 dprintf(("hpfs_read: successful\n"));
348 * hpfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
349 * struct ucred *a_cred)
352 hpfs_write(struct vop_write_args
*ap
)
354 struct vnode
*vp
= ap
->a_vp
;
355 struct hpfsnode
*hp
= VTOHP(vp
);
356 struct uio
*uio
= ap
->a_uio
;
358 u_int xfersz
, towrite
;
364 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
));
366 if (ap
->a_ioflag
& IO_APPEND
) {
367 dprintf(("hpfs_write: APPEND mode\n"));
368 uio
->uio_offset
= hp
->h_fn
.fn_size
;
370 if (uio
->uio_offset
+ uio
->uio_resid
> hp
->h_fn
.fn_size
) {
371 error
= hpfs_extend (hp
, uio
->uio_offset
+ uio
->uio_resid
);
373 kprintf("hpfs_write: hpfs_extend FAILED %d\n", error
);
378 while (uio
->uio_resid
) {
379 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
380 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
381 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
382 uio
->uio_resid
, lbn
, off
));
383 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
387 towrite
= min(off
+ uio
->uio_resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
388 xfersz
= (towrite
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
389 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
390 bn
, runl
, towrite
, xfersz
));
393 * We do not have to issue a read-before-write if the xfer
394 * size does not cover the whole block.
396 * In the UIO_NOCOPY case, however, we are not overwriting
397 * anything and must do a read-before-write to fill in
398 * any missing pieces.
400 if (off
== 0 && towrite
== xfersz
&&
401 uio
->uio_segflg
!= UIO_NOCOPY
) {
402 bp
= getblk(hp
->h_devvp
, dbtodoff(bn
), xfersz
, 0, 0);
405 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
412 error
= uiomove(bp
->b_data
+ off
, towrite
- off
, uio
);
418 if (ap
->a_ioflag
& IO_SYNC
)
424 dprintf(("hpfs_write: successful\n"));
429 * XXXXX do we need hpfsnode locking inside?
431 * hpfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
434 hpfs_getattr(struct vop_getattr_args
*ap
)
436 struct vnode
*vp
= ap
->a_vp
;
437 struct hpfsnode
*hp
= VTOHP(vp
);
438 struct vattr
*vap
= ap
->a_vap
;
441 dprintf(("hpfs_getattr(0x%x):\n", hp
->h_no
));
443 #if defined(__DragonFly__)
444 vap
->va_fsid
= dev2udev(hp
->h_dev
);
445 #else /* defined(__NetBSD__) */
446 vap
->va_fsid
= ip
->i_dev
;
448 vap
->va_fileid
= hp
->h_no
;
449 vap
->va_mode
= hp
->h_mode
;
451 vap
->va_uid
= hp
->h_uid
;
452 vap
->va_gid
= hp
->h_gid
;
453 vap
->va_rmajor
= VNOVAL
;
454 vap
->va_rminor
= VNOVAL
;
455 vap
->va_size
= hp
->h_fn
.fn_size
;
456 vap
->va_bytes
= ((hp
->h_fn
.fn_size
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)) +
459 if (!(hp
->h_flag
& H_PARVALID
)) {
460 error
= hpfs_validateparent(hp
);
464 vap
->va_atime
= hpfstimetounix(hp
->h_atime
);
465 vap
->va_mtime
= hpfstimetounix(hp
->h_mtime
);
466 vap
->va_ctime
= hpfstimetounix(hp
->h_ctime
);
470 vap
->va_blocksize
= DEV_BSIZE
;
471 vap
->va_type
= vp
->v_type
;
478 * XXXXX do we need hpfsnode locking inside?
480 * hpfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
483 hpfs_setattr(struct vop_setattr_args
*ap
)
485 struct vnode
*vp
= ap
->a_vp
;
486 struct hpfsnode
*hp
= VTOHP(vp
);
487 struct vattr
*vap
= ap
->a_vap
;
488 struct ucred
*cred
= ap
->a_cred
;
491 dprintf(("hpfs_setattr(0x%x):\n", hp
->h_no
));
494 * Check for unsettable attributes.
496 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
497 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
498 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rmajor
!= VNOVAL
) ||
499 (vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
500 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
504 /* Can't change flags XXX Could be implemented */
505 if (vap
->va_flags
!= VNOVAL
) {
506 kprintf("hpfs_setattr: FLAGS CANNOT BE SET\n");
510 /* Can't change uid/gid XXX Could be implemented */
511 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
512 kprintf("hpfs_setattr: UID/GID CANNOT BE SET\n");
516 /* Can't change mode XXX Could be implemented */
517 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
518 kprintf("hpfs_setattr: MODE CANNOT BE SET\n");
523 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
524 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
526 if (cred
->cr_uid
!= hp
->h_uid
&&
527 (error
= suser_cred(cred
, PRISON_ROOT
)) &&
528 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
529 (error
= VOP_ACCESS(vp
, VWRITE
, cred
))))
531 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
532 hp
->h_atime
= vap
->va_atime
.tv_sec
;
533 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
534 hp
->h_mtime
= vap
->va_mtime
.tv_sec
;
536 hp
->h_flag
|= H_PARCHANGE
;
539 if (vap
->va_size
!= VNOVAL
) {
540 switch (vp
->v_type
) {
544 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
548 kprintf("hpfs_setattr: WRONG v_type\n");
552 if (vap
->va_size
< hp
->h_fn
.fn_size
) {
553 #if defined(__DragonFly__)
554 error
= vtruncbuf(vp
, vap
->va_size
, DEV_BSIZE
);
557 #else /* defined(__NetBSD__) */
558 #error Need alternation for vtruncbuf()
560 error
= hpfs_truncate(hp
, vap
->va_size
);
564 } else if (vap
->va_size
> hp
->h_fn
.fn_size
) {
565 #if defined(__DragonFly__)
566 vnode_pager_setsize(vp
, vap
->va_size
);
568 error
= hpfs_extend(hp
, vap
->va_size
);
578 * Last reference to an node. If necessary, write or delete it.
580 * hpfs_inactive(struct vnode *a_vp)
583 hpfs_inactive(struct vop_inactive_args
*ap
)
585 struct vnode
*vp
= ap
->a_vp
;
586 struct hpfsnode
*hp
= VTOHP(vp
);
589 dprintf(("hpfs_inactive(0x%x): \n", hp
->h_no
));
591 if (hp
->h_flag
& H_CHANGE
) {
592 dprintf(("hpfs_inactive: node changed, update\n"));
593 error
= hpfs_update (hp
);
598 if (hp
->h_flag
& H_PARCHANGE
) {
599 dprintf(("hpfs_inactive: parent node changed, update\n"));
600 error
= hpfs_updateparent (hp
);
605 if (prtactive
&& vp
->v_sysref
.refcnt
> 1)
606 vprint("hpfs_inactive: pushing active", vp
);
608 if (hp
->h_flag
& H_INVAL
) {
609 #if defined(__DragonFly__)
611 #else /* defined(__NetBSD__) */
620 * Reclaim an inode so that it can be used for other purposes.
622 * hpfs_reclaim(struct vnode *a_vp)
625 hpfs_reclaim(struct vop_reclaim_args
*ap
)
627 struct vnode
*vp
= ap
->a_vp
;
628 struct hpfsnode
*hp
= VTOHP(vp
);
630 dprintf(("hpfs_reclaim(0x%x0): \n", hp
->h_no
));
634 /* Purge old data structures associated with the inode. */
648 * hpfs_print(struct vnode *a_vp)
651 hpfs_print(struct vop_print_args
*ap
)
653 struct vnode
*vp
= ap
->a_vp
;
654 struct hpfsnode
*hp
= VTOHP(vp
);
656 kprintf("tag VT_HPFS, ino 0x%x",hp
->h_no
);
657 lockmgr_printinfo(&vp
->v_lock
);
663 * Calculate the logical to physical mapping if not done already,
664 * then call the device strategy routine.
666 * In order to be able to swap to a file, the VOP_BMAP operation may not
667 * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl)
669 * hpfs_strategy(struct vnode *a_vp, struct bio *a_bio)
672 hpfs_strategy(struct vop_strategy_args
*ap
)
674 struct bio
*bio
= ap
->a_bio
;
676 struct buf
*bp
= bio
->bio_buf
;
677 struct vnode
*vp
= ap
->a_vp
;
681 dprintf(("hpfs_strategy(): \n"));
683 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
684 panic("hpfs_strategy: spec");
686 nbio
= push_bio(bio
);
687 if (nbio
->bio_offset
== NOOFFSET
) {
688 error
= VOP_BMAP(vp
, bio
->bio_offset
, &nbio
->bio_offset
,
689 NULL
, NULL
, bp
->b_cmd
);
691 kprintf("hpfs_strategy: VOP_BMAP FAILED %d\n", error
);
693 bp
->b_flags
|= B_ERROR
;
694 /* I/O was never started on nbio, must biodone(bio) */
698 if (nbio
->bio_offset
== NOOFFSET
)
701 if (nbio
->bio_offset
== NOOFFSET
) {
702 /* I/O was never started on nbio, must biodone(bio) */
706 hp
= VTOHP(ap
->a_vp
);
707 vn_strategy(hp
->h_devvp
, nbio
);
712 * XXXXX do we need hpfsnode locking inside?
714 * hpfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
717 hpfs_access(struct vop_access_args
*ap
)
719 struct vnode
*vp
= ap
->a_vp
;
720 struct hpfsnode
*hp
= VTOHP(vp
);
721 struct ucred
*cred
= ap
->a_cred
;
722 mode_t mask
, mode
= ap
->a_mode
;
726 dprintf(("hpfs_access(0x%x):\n", hp
->h_no
));
729 * Disallow write attempts on read-only file systems;
730 * unless the file is a socket, fifo, or a block or
731 * character device resident on the file system.
734 switch ((int)vp
->v_type
) {
738 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
744 /* Otherwise, user id 0 always gets access. */
745 if (cred
->cr_uid
== 0)
750 /* Otherwise, check the owner. */
751 if (cred
->cr_uid
== hp
->h_uid
) {
758 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
761 /* Otherwise, check the groups. */
762 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
763 if (hp
->h_gid
== *gp
) {
770 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
773 /* Otherwise, check everyone else. */
780 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
784 hpfs_de_uiomove(int *error
, struct hpfsmount
*hpmp
, struct hpfsdirent
*dep
,
787 char convname
[HPFS_MAXFILENAME
+ 1];
790 dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
791 dep
->de_fnode
, dep
->de_size
, dep
->de_namelen
,
792 dep
->de_namelen
, dep
->de_name
, dep
->de_flag
));
794 /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
795 for (i
=0; i
<dep
->de_namelen
; i
++)
796 convname
[i
] = hpfs_d2u(hpmp
, dep
->de_name
[i
]);
797 convname
[dep
->de_namelen
] = '\0';
799 success
= vop_write_dirent(error
, uio
, dep
->de_fnode
,
800 (dep
->de_flag
& DE_DIR
) ? DT_DIR
: DT_REG
,
801 dep
->de_namelen
, convname
);
803 dprintf(("[0x%x] ", uio
->uio_resid
));
809 * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
810 * int *a_ncookies, off_t **cookies)
813 hpfs_readdir(struct vop_readdir_args
*ap
)
815 struct vnode
*vp
= ap
->a_vp
;
816 struct hpfsnode
*hp
= VTOHP(vp
);
817 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
818 struct uio
*uio
= ap
->a_uio
;
819 int ncookies
= 0, i
, num
, cnum
;
823 struct hpfsdirent
*dep
;
828 dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp
->h_no
,(u_int32_t
)uio
->uio_offset
,uio
->uio_resid
));
831 * As we need to fake up . and .., and the remaining directory structure
832 * can't be expressed in one off_t as well, we just increment uio_offset
833 * by 1 for each entry.
835 * num is the entry we need to start reporting
836 * cnum is the current entry
838 if (uio
->uio_offset
< 0 || uio
->uio_offset
> INT_MAX
)
840 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
843 num
= uio
->uio_offset
;
847 dprintf((". faked, "));
848 if (vop_write_dirent(&error
, uio
, hp
->h_no
, DT_DIR
, 1, "."))
857 dprintf((".. faked, "));
858 if (vop_write_dirent(&error
, uio
, hp
->h_fn
.fn_parent
, DT_DIR
, 2, ".."))
866 lsn
= ((alleaf_t
*)hp
->h_fn
.fn_abd
)->al_lsn
;
872 dprintf(("[dive 0x%x] ", lsn
));
873 error
= bread(hp
->h_devvp
, dbtodoff(lsn
), D_BSIZE
, &bp
);
879 dp
= (struct dirblk
*) bp
->b_data
;
880 if (dp
->d_magic
!= D_MAGIC
) {
881 kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
890 dprintf(("[restore 0x%x] ", olsn
));
892 while(!(dep
->de_flag
& DE_END
) ) {
893 if((dep
->de_flag
& DE_DOWN
) &&
894 (olsn
== DE_DOWNLSN(dep
)))
896 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
899 if((dep
->de_flag
& DE_DOWN
) && (olsn
== DE_DOWNLSN(dep
))) {
900 if (dep
->de_flag
& DE_END
)
903 if (!(dep
->de_flag
& DE_SPECIAL
)) {
905 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
907 dprintf(("[resid] "));
919 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
921 kprintf("hpfs_readdir: ERROR! oLSN not found\n");
930 while(!(dep
->de_flag
& DE_END
)) {
931 if(dep
->de_flag
& DE_DOWN
) {
932 lsn
= DE_DOWNLSN(dep
);
938 if (!(dep
->de_flag
& DE_SPECIAL
)) {
940 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
942 dprintf(("[resid] "));
954 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
957 if(dep
->de_flag
& DE_DOWN
) {
958 dprintf(("[enddive] "));
959 lsn
= DE_DOWNLSN(dep
);
972 dprintf(("[level %d] ", level
));
975 goto dive
; /* undive really */
983 uio
->uio_offset
= cnum
;
984 dprintf(("[readdone]\n"));
985 if (!error
&& ap
->a_ncookies
!= NULL
) {
989 dprintf(("%d cookies, ",ncookies
));
990 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
991 panic("hpfs_readdir: unexpected uio from NFS server");
992 MALLOC(cookies
, off_t
*, ncookies
* sizeof(off_t
),
994 for (cookiep
= cookies
, i
=0; i
< ncookies
; i
++)
997 *ap
->a_ncookies
= ncookies
;
998 *ap
->a_cookies
= cookies
;
1002 vn_unlock(ap
->a_vp
);
1007 * hpfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
1008 * struct componentname *a_cnp)
1011 hpfs_lookup(struct vop_old_lookup_args
*ap
)
1013 struct vnode
*dvp
= ap
->a_dvp
;
1014 struct hpfsnode
*dhp
= VTOHP(dvp
);
1015 struct hpfsmount
*hpmp
= dhp
->h_hpmp
;
1016 struct componentname
*cnp
= ap
->a_cnp
;
1017 struct ucred
*cred
= cnp
->cn_cred
;
1019 int nameiop
= cnp
->cn_nameiop
;
1020 int flags
= cnp
->cn_flags
;
1021 int lockparent
= flags
& CNP_LOCKPARENT
;
1023 int wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
1025 dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
1026 dhp
->h_no
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
1027 lockparent
, wantparent
));
1029 if (nameiop
!= NAMEI_CREATE
&& nameiop
!= NAMEI_DELETE
&& nameiop
!= NAMEI_LOOKUP
) {
1030 kprintf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
1031 return (EOPNOTSUPP
);
1034 error
= VOP_ACCESS(dvp
, VEXEC
, cred
);
1038 if( (cnp
->cn_namelen
== 1) &&
1039 !strncmp(cnp
->cn_nameptr
,".",1) ) {
1040 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp
->h_no
));
1046 } else if( (cnp
->cn_namelen
== 2) &&
1047 !strncmp(cnp
->cn_nameptr
,"..",2) && (flags
& CNP_ISDOTDOT
) ) {
1048 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
1049 dhp
->h_no
, dhp
->h_fn
.fn_parent
));
1051 VOP__UNLOCK(dvp
, 0);
1053 error
= VFS_VGET(hpmp
->hpm_mp
,
1054 dhp
->h_fn
.fn_parent
, ap
->a_vpp
);
1060 if (lockparent
&& (error
= VOP__LOCK(dvp
, 0))) {
1061 vput( *(ap
->a_vpp
) );
1067 struct hpfsdirent
*dep
;
1068 struct hpfsnode
*hp
;
1070 error
= hpfs_genlookupbyname(dhp
,
1071 cnp
->cn_nameptr
, cnp
->cn_namelen
, &bp
, &dep
);
1073 if (error
== ENOENT
&&
1074 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
)) {
1076 VOP__UNLOCK(dvp
, 0);
1077 return (EJUSTRETURN
);
1083 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
1084 dep
->de_fnode
, dep
->de_cpid
));
1086 if (nameiop
== NAMEI_DELETE
) {
1087 error
= VOP_ACCESS(dvp
, VWRITE
, cred
);
1094 if (dhp
->h_no
== dep
->de_fnode
) {
1101 error
= VFS_VGET(hpmp
->hpm_mp
, dep
->de_fnode
, ap
->a_vpp
);
1103 kprintf("hpfs_lookup: VFS_VGET FAILED %d\n", error
);
1108 hp
= VTOHP(*ap
->a_vpp
);
1110 hp
->h_mtime
= dep
->de_mtime
;
1111 hp
->h_ctime
= dep
->de_ctime
;
1112 hp
->h_atime
= dep
->de_atime
;
1113 bcopy(dep
->de_name
, hp
->h_name
, dep
->de_namelen
);
1114 hp
->h_name
[dep
->de_namelen
] = '\0';
1115 hp
->h_namelen
= dep
->de_namelen
;
1116 hp
->h_flag
|= H_PARVALID
;
1121 VOP__UNLOCK(dvp
, 0);
1127 * hpfs_remove(struct vnode *a_dvp, struct vnode *a_vp,
1128 * struct componentname *a_cnp)
1131 hpfs_remove(struct vop_old_remove_args
*ap
)
1135 dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap
->a_vp
)->h_no
,
1136 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1138 if (ap
->a_vp
->v_type
== VDIR
)
1141 error
= hpfs_removefnode (ap
->a_dvp
, ap
->a_vp
, ap
->a_cnp
);
1146 * hpfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
1147 * struct componentname *a_cnp, struct vattr *a_vap)
1150 hpfs_create(struct vop_old_create_args
*ap
)
1154 dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap
->a_dvp
)->h_no
,
1155 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1157 error
= hpfs_makefnode (ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
);
1163 * Return POSIX pathconf information applicable to NTFS filesystem
1165 * hpfs_pathconf(struct vnode *a_vp, int a_name, t *a_retval)
1168 hpfs_pathconf(struct vop_pathconf_args
*ap
)
1170 switch (ap
->a_name
) {
1175 *ap
->a_retval
= HPFS_MAXFILENAME
;
1178 *ap
->a_retval
= PATH_MAX
;
1180 case _PC_CHOWN_RESTRICTED
:
1186 #if defined(__NetBSD__)
1190 case _PC_FILESIZEBITS
:
1202 * Global vfs data structures
1205 struct vop_ops hpfs_vnode_vops
= {
1206 .vop_default
= vop_defaultop
,
1207 .vop_getattr
= hpfs_getattr
,
1208 .vop_setattr
= hpfs_setattr
,
1209 .vop_inactive
= hpfs_inactive
,
1210 .vop_reclaim
= hpfs_reclaim
,
1211 .vop_print
= hpfs_print
,
1212 .vop_old_create
= hpfs_create
,
1213 .vop_old_remove
= hpfs_remove
,
1214 .vop_old_lookup
= hpfs_lookup
,
1215 .vop_access
= hpfs_access
,
1216 .vop_readdir
= hpfs_readdir
,
1217 .vop_fsync
= hpfs_fsync
,
1218 .vop_bmap
= hpfs_bmap
,
1219 .vop_getpages
= vop_stdgetpages
,
1220 .vop_putpages
= vop_stdputpages
,
1221 .vop_strategy
= hpfs_strategy
,
1222 .vop_read
= hpfs_read
,
1223 .vop_write
= hpfs_write
,
1224 .vop_ioctl
= hpfs_ioctl
,
1225 .vop_pathconf
= hpfs_pathconf