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.44 2007/08/21 17:26:48 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_getpages (struct vop_getpages_args
*ap
);
92 static int hpfs_putpages (struct vop_putpages_args
*);
93 static int hpfs_fsync (struct vop_fsync_args
*ap
);
95 static int hpfs_pathconf (struct vop_pathconf_args
*ap
);
97 #if defined(__DragonFly__)
99 hpfs_getpages(struct vop_getpages_args
*ap
)
101 return vnode_pager_generic_getpages(ap
->a_vp
, ap
->a_m
, ap
->a_count
,
106 hpfs_putpages(struct vop_putpages_args
*ap
)
108 return vnode_pager_generic_putpages(ap
->a_vp
, ap
->a_m
, ap
->a_count
,
109 ap
->a_sync
, ap
->a_rtvals
);
113 * hpfs_fsync(struct vnode *a_vp, int a_waitfor)
116 hpfs_fsync(struct vop_fsync_args
*ap
)
118 struct vnode
*vp
= ap
->a_vp
;
121 * Flush all dirty buffers associated with a vnode.
126 vfsync(vp
, ap
->a_waitfor
, 0, NULL
, NULL
);
128 if (ap
->a_waitfor
== MNT_WAIT
&& !RB_EMPTY(&vp
->v_rbdirty_tree
)) {
129 vprint("hpfs_fsync: dirty", vp
);
135 * Write out the on-disc version of the vnode.
137 return hpfs_update(VTOHP(vp
));
143 * hpfs_ioctl(struct vnode *a_vp, u_long a_command, caddr_t a_data,
144 * int a_fflag, struct ucred *a_cred)
147 hpfs_ioctl(struct vop_ioctl_args
*ap
)
149 struct vnode
*vp
= ap
->a_vp
;
150 struct hpfsnode
*hp
= VTOHP(vp
);
153 kprintf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
154 hp
->h_no
, ap
->a_command
, ap
->a_data
, ap
->a_fflag
);
156 switch (ap
->a_command
) {
157 case HPFSIOCGEANUM
: {
164 if (hp
->h_fn
.fn_ealen
> 0) {
165 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
168 while (passed
< hp
->h_fn
.fn_ealen
) {
170 kprintf("EAname: %s\n", EA_NAME(eap
));
173 passed
+= sizeof(struct ea
) +
174 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
175 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
183 kprintf("%lu eas\n", eanum
);
185 *(u_long
*)ap
->a_data
= eanum
;
194 kprintf("EA%ld\n", *(u_long
*)ap
->a_data
);
197 if (hp
->h_fn
.fn_ealen
> 0) {
198 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
202 while (passed
< hp
->h_fn
.fn_ealen
) {
203 kprintf("EAname: %s\n", EA_NAME(eap
));
205 if (eanum
== *(u_long
*)ap
->a_data
) {
206 *(u_long
*)ap
->a_data
=
207 eap
->ea_namelen
+ 1 +
215 passed
+= sizeof(struct ea
) +
216 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
217 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
229 struct hpfs_rdea
*rdeap
;
232 rdeap
= (struct hpfs_rdea
*)ap
->a_data
;
233 kprintf("EA%ld\n", rdeap
->ea_no
);
236 if (hp
->h_fn
.fn_ealen
> 0) {
237 eap
= (struct ea
*)&(hp
->h_fn
.fn_int
);
241 while (passed
< hp
->h_fn
.fn_ealen
) {
242 kprintf("EAname: %s\n", EA_NAME(eap
));
244 if (eanum
== rdeap
->ea_no
) {
245 rdeap
->ea_sz
= eap
->ea_namelen
+ 1 +
247 copyout(EA_NAME(eap
),rdeap
->ea_data
,
254 passed
+= sizeof(struct ea
) +
255 eap
->ea_namelen
+ 1 + eap
->ea_vallen
;
256 eap
= (struct ea
*)((caddr_t
)hp
->h_fn
.fn_int
+
273 * Map file offset to disk offset.
275 * hpfs_bmap(struct vnode *a_vp, off_t a_loffset,
276 * off_t *a_doffsetp, int *a_runp, int *a_runb)
279 hpfs_bmap(struct vop_bmap_args
*ap
)
281 struct hpfsnode
*hp
= VTOHP(ap
->a_vp
);
286 if (ap
->a_runb
!= NULL
)
288 if (ap
->a_doffsetp
== NULL
)
291 dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp
->h_no
, ap
->a_bn
));
293 lbn
= ap
->a_loffset
>> DEV_BSHIFT
;
294 KKASSERT(((int)ap
->a_loffset
& DEV_BMASK
) == 0);
296 error
= hpfs_hpbmap (hp
, lbn
, &dbn
, ap
->a_runp
);
297 if (error
|| dbn
== (daddr_t
)-1) {
298 *ap
->a_doffsetp
= NOOFFSET
;
300 *ap
->a_doffsetp
= (off_t
)dbn
<< DEV_BSHIFT
;
306 * hpfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
307 * struct ucred *a_cred)
310 hpfs_read(struct vop_read_args
*ap
)
312 struct vnode
*vp
= ap
->a_vp
;
313 struct hpfsnode
*hp
= VTOHP(vp
);
314 struct uio
*uio
= ap
->a_uio
;
316 u_int xfersz
, toread
;
323 resid
= min (uio
->uio_resid
, hp
->h_fn
.fn_size
- uio
->uio_offset
);
325 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
));
328 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
329 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
330 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
331 uio
->uio_resid
, lbn
, off
));
332 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
336 toread
= min(off
+ resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
337 xfersz
= (toread
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
338 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
339 bn
, runl
, toread
, xfersz
));
344 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
350 error
= uiomove(bp
->b_data
+ off
, toread
- off
, uio
);
358 dprintf(("hpfs_read: successful\n"));
363 * hpfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
364 * struct ucred *a_cred)
367 hpfs_write(struct vop_write_args
*ap
)
369 struct vnode
*vp
= ap
->a_vp
;
370 struct hpfsnode
*hp
= VTOHP(vp
);
371 struct uio
*uio
= ap
->a_uio
;
373 u_int xfersz
, towrite
;
379 dprintf(("hpfs_write(0x%x, off: %d resid: %d, segflg: %d):\n",hp
->h_no
,(u_int32_t
)uio
->uio_offset
,uio
->uio_resid
,uio
->uio_segflg
));
381 if (ap
->a_ioflag
& IO_APPEND
) {
382 dprintf(("hpfs_write: APPEND mode\n"));
383 uio
->uio_offset
= hp
->h_fn
.fn_size
;
385 if (uio
->uio_offset
+ uio
->uio_resid
> hp
->h_fn
.fn_size
) {
386 error
= hpfs_extend (hp
, uio
->uio_offset
+ uio
->uio_resid
);
388 kprintf("hpfs_write: hpfs_extend FAILED %d\n", error
);
393 while (uio
->uio_resid
) {
394 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
395 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
396 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
397 uio
->uio_resid
, lbn
, off
));
398 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
402 towrite
= min(off
+ uio
->uio_resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
403 xfersz
= (towrite
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
404 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
405 bn
, runl
, towrite
, xfersz
));
408 * We do not have to issue a read-before-write if the xfer
409 * size does not cover the whole block.
411 * In the UIO_NOCOPY case, however, we are not overwriting
412 * anything and must do a read-before-write to fill in
413 * any missing pieces.
415 if (off
== 0 && towrite
== xfersz
&&
416 uio
->uio_segflg
!= UIO_NOCOPY
) {
417 bp
= getblk(hp
->h_devvp
, dbtodoff(bn
), xfersz
, 0, 0);
420 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
427 error
= uiomove(bp
->b_data
+ off
, towrite
- off
, uio
);
433 if (ap
->a_ioflag
& IO_SYNC
)
439 dprintf(("hpfs_write: successful\n"));
444 * XXXXX do we need hpfsnode locking inside?
446 * hpfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
449 hpfs_getattr(struct vop_getattr_args
*ap
)
451 struct vnode
*vp
= ap
->a_vp
;
452 struct hpfsnode
*hp
= VTOHP(vp
);
453 struct vattr
*vap
= ap
->a_vap
;
456 dprintf(("hpfs_getattr(0x%x):\n", hp
->h_no
));
458 #if defined(__DragonFly__)
459 vap
->va_fsid
= dev2udev(hp
->h_dev
);
460 #else /* defined(__NetBSD__) */
461 vap
->va_fsid
= ip
->i_dev
;
463 vap
->va_fileid
= hp
->h_no
;
464 vap
->va_mode
= hp
->h_mode
;
466 vap
->va_uid
= hp
->h_uid
;
467 vap
->va_gid
= hp
->h_gid
;
468 vap
->va_rmajor
= VNOVAL
;
469 vap
->va_rminor
= VNOVAL
;
470 vap
->va_size
= hp
->h_fn
.fn_size
;
471 vap
->va_bytes
= ((hp
->h_fn
.fn_size
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)) +
474 if (!(hp
->h_flag
& H_PARVALID
)) {
475 error
= hpfs_validateparent(hp
);
479 vap
->va_atime
= hpfstimetounix(hp
->h_atime
);
480 vap
->va_mtime
= hpfstimetounix(hp
->h_mtime
);
481 vap
->va_ctime
= hpfstimetounix(hp
->h_ctime
);
485 vap
->va_blocksize
= DEV_BSIZE
;
486 vap
->va_type
= vp
->v_type
;
493 * XXXXX do we need hpfsnode locking inside?
495 * hpfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
498 hpfs_setattr(struct vop_setattr_args
*ap
)
500 struct vnode
*vp
= ap
->a_vp
;
501 struct hpfsnode
*hp
= VTOHP(vp
);
502 struct vattr
*vap
= ap
->a_vap
;
503 struct ucred
*cred
= ap
->a_cred
;
506 dprintf(("hpfs_setattr(0x%x):\n", hp
->h_no
));
509 * Check for unsettable attributes.
511 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
512 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
513 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rmajor
!= VNOVAL
) ||
514 (vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
515 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
519 /* Can't change flags XXX Could be implemented */
520 if (vap
->va_flags
!= VNOVAL
) {
521 kprintf("hpfs_setattr: FLAGS CANNOT BE SET\n");
525 /* Can't change uid/gid XXX Could be implemented */
526 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
527 kprintf("hpfs_setattr: UID/GID CANNOT BE SET\n");
531 /* Can't change mode XXX Could be implemented */
532 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
533 kprintf("hpfs_setattr: MODE CANNOT BE SET\n");
538 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
539 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
541 if (cred
->cr_uid
!= hp
->h_uid
&&
542 (error
= suser_cred(cred
, PRISON_ROOT
)) &&
543 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
544 (error
= VOP_ACCESS(vp
, VWRITE
, cred
))))
546 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
547 hp
->h_atime
= vap
->va_atime
.tv_sec
;
548 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
549 hp
->h_mtime
= vap
->va_mtime
.tv_sec
;
551 hp
->h_flag
|= H_PARCHANGE
;
554 if (vap
->va_size
!= VNOVAL
) {
555 switch (vp
->v_type
) {
559 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
563 kprintf("hpfs_setattr: WRONG v_type\n");
567 if (vap
->va_size
< hp
->h_fn
.fn_size
) {
568 #if defined(__DragonFly__)
569 error
= vtruncbuf(vp
, vap
->va_size
, DEV_BSIZE
);
572 #else /* defined(__NetBSD__) */
573 #error Need alternation for vtruncbuf()
575 error
= hpfs_truncate(hp
, vap
->va_size
);
579 } else if (vap
->va_size
> hp
->h_fn
.fn_size
) {
580 #if defined(__DragonFly__)
581 vnode_pager_setsize(vp
, vap
->va_size
);
583 error
= hpfs_extend(hp
, vap
->va_size
);
593 * Last reference to an node. If necessary, write or delete it.
595 * hpfs_inactive(struct vnode *a_vp)
598 hpfs_inactive(struct vop_inactive_args
*ap
)
600 struct vnode
*vp
= ap
->a_vp
;
601 struct hpfsnode
*hp
= VTOHP(vp
);
604 dprintf(("hpfs_inactive(0x%x): \n", hp
->h_no
));
606 if (hp
->h_flag
& H_CHANGE
) {
607 dprintf(("hpfs_inactive: node changed, update\n"));
608 error
= hpfs_update (hp
);
613 if (hp
->h_flag
& H_PARCHANGE
) {
614 dprintf(("hpfs_inactive: parent node changed, update\n"));
615 error
= hpfs_updateparent (hp
);
620 if (prtactive
&& vp
->v_sysref
.refcnt
> 1)
621 vprint("hpfs_inactive: pushing active", vp
);
623 if (hp
->h_flag
& H_INVAL
) {
624 #if defined(__DragonFly__)
626 #else /* defined(__NetBSD__) */
635 * Reclaim an inode so that it can be used for other purposes.
637 * hpfs_reclaim(struct vnode *a_vp)
640 hpfs_reclaim(struct vop_reclaim_args
*ap
)
642 struct vnode
*vp
= ap
->a_vp
;
643 struct hpfsnode
*hp
= VTOHP(vp
);
645 dprintf(("hpfs_reclaim(0x%x0): \n", hp
->h_no
));
649 /* Purge old data structures associated with the inode. */
663 * hpfs_print(struct vnode *a_vp)
666 hpfs_print(struct vop_print_args
*ap
)
668 struct vnode
*vp
= ap
->a_vp
;
669 struct hpfsnode
*hp
= VTOHP(vp
);
671 kprintf("tag VT_HPFS, ino 0x%x",hp
->h_no
);
672 lockmgr_printinfo(&vp
->v_lock
);
678 * Calculate the logical to physical mapping if not done already,
679 * then call the device strategy routine.
681 * In order to be able to swap to a file, the VOP_BMAP operation may not
682 * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl)
684 * hpfs_strategy(struct vnode *a_vp, struct bio *a_bio)
687 hpfs_strategy(struct vop_strategy_args
*ap
)
689 struct bio
*bio
= ap
->a_bio
;
691 struct buf
*bp
= bio
->bio_buf
;
692 struct vnode
*vp
= ap
->a_vp
;
696 dprintf(("hpfs_strategy(): \n"));
698 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
699 panic("hpfs_strategy: spec");
701 nbio
= push_bio(bio
);
702 if (nbio
->bio_offset
== NOOFFSET
) {
703 error
= VOP_BMAP(vp
, bio
->bio_offset
, &nbio
->bio_offset
,
706 kprintf("hpfs_strategy: VOP_BMAP FAILED %d\n", error
);
708 bp
->b_flags
|= B_ERROR
;
709 /* I/O was never started on nbio, must biodone(bio) */
713 if (nbio
->bio_offset
== NOOFFSET
)
716 if (nbio
->bio_offset
== NOOFFSET
) {
717 /* I/O was never started on nbio, must biodone(bio) */
721 hp
= VTOHP(ap
->a_vp
);
722 vn_strategy(hp
->h_devvp
, nbio
);
727 * XXXXX do we need hpfsnode locking inside?
729 * hpfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
732 hpfs_access(struct vop_access_args
*ap
)
734 struct vnode
*vp
= ap
->a_vp
;
735 struct hpfsnode
*hp
= VTOHP(vp
);
736 struct ucred
*cred
= ap
->a_cred
;
737 mode_t mask
, mode
= ap
->a_mode
;
741 dprintf(("hpfs_access(0x%x):\n", hp
->h_no
));
744 * Disallow write attempts on read-only file systems;
745 * unless the file is a socket, fifo, or a block or
746 * character device resident on the file system.
749 switch ((int)vp
->v_type
) {
753 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
759 /* Otherwise, user id 0 always gets access. */
760 if (cred
->cr_uid
== 0)
765 /* Otherwise, check the owner. */
766 if (cred
->cr_uid
== hp
->h_uid
) {
773 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
776 /* Otherwise, check the groups. */
777 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
778 if (hp
->h_gid
== *gp
) {
785 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
788 /* Otherwise, check everyone else. */
795 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
799 hpfs_de_uiomove(int *error
, struct hpfsmount
*hpmp
, struct hpfsdirent
*dep
,
802 char convname
[HPFS_MAXFILENAME
+ 1];
805 dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
806 dep
->de_fnode
, dep
->de_size
, dep
->de_namelen
,
807 dep
->de_namelen
, dep
->de_name
, dep
->de_flag
));
809 /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
810 for (i
=0; i
<dep
->de_namelen
; i
++)
811 convname
[i
] = hpfs_d2u(hpmp
, dep
->de_name
[i
]);
812 convname
[dep
->de_namelen
] = '\0';
814 success
= vop_write_dirent(error
, uio
, dep
->de_fnode
,
815 (dep
->de_flag
& DE_DIR
) ? DT_DIR
: DT_REG
,
816 dep
->de_namelen
, convname
);
818 dprintf(("[0x%x] ", uio
->uio_resid
));
824 * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
825 * int *a_ncookies, u_int **cookies)
828 hpfs_readdir(struct vop_readdir_args
*ap
)
830 struct vnode
*vp
= ap
->a_vp
;
831 struct hpfsnode
*hp
= VTOHP(vp
);
832 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
833 struct uio
*uio
= ap
->a_uio
;
834 int ncookies
= 0, i
, num
, cnum
;
838 struct hpfsdirent
*dep
;
843 dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp
->h_no
,(u_int32_t
)uio
->uio_offset
,uio
->uio_resid
));
846 * As we need to fake up . and .., and the remaining directory structure
847 * can't be expressed in one off_t as well, we just increment uio_offset
848 * by 1 for each entry.
850 * num is the entry we need to start reporting
851 * cnum is the current entry
853 if (uio
->uio_offset
< 0 || uio
->uio_offset
> INT_MAX
)
855 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
858 num
= uio
->uio_offset
;
862 dprintf((". faked, "));
863 if (vop_write_dirent(&error
, uio
, hp
->h_no
, DT_DIR
, 1, "."))
872 dprintf((".. faked, "));
873 if (vop_write_dirent(&error
, uio
, hp
->h_fn
.fn_parent
, DT_DIR
, 2, ".."))
881 lsn
= ((alleaf_t
*)hp
->h_fn
.fn_abd
)->al_lsn
;
887 dprintf(("[dive 0x%x] ", lsn
));
888 error
= bread(hp
->h_devvp
, dbtodoff(lsn
), D_BSIZE
, &bp
);
894 dp
= (struct dirblk
*) bp
->b_data
;
895 if (dp
->d_magic
!= D_MAGIC
) {
896 kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
905 dprintf(("[restore 0x%x] ", olsn
));
907 while(!(dep
->de_flag
& DE_END
) ) {
908 if((dep
->de_flag
& DE_DOWN
) &&
909 (olsn
== DE_DOWNLSN(dep
)))
911 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
914 if((dep
->de_flag
& DE_DOWN
) && (olsn
== DE_DOWNLSN(dep
))) {
915 if (dep
->de_flag
& DE_END
)
918 if (!(dep
->de_flag
& DE_SPECIAL
)) {
920 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
922 dprintf(("[resid] "));
934 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
936 kprintf("hpfs_readdir: ERROR! oLSN not found\n");
945 while(!(dep
->de_flag
& DE_END
)) {
946 if(dep
->de_flag
& DE_DOWN
) {
947 lsn
= DE_DOWNLSN(dep
);
953 if (!(dep
->de_flag
& DE_SPECIAL
)) {
955 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
957 dprintf(("[resid] "));
969 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
972 if(dep
->de_flag
& DE_DOWN
) {
973 dprintf(("[enddive] "));
974 lsn
= DE_DOWNLSN(dep
);
987 dprintf(("[level %d] ", level
));
990 goto dive
; /* undive really */
998 uio
->uio_offset
= cnum
;
999 dprintf(("[readdone]\n"));
1000 if (!error
&& ap
->a_ncookies
!= NULL
) {
1001 #if defined(__DragonFly__)
1004 #else /* defined(__NetBSD__) */
1009 dprintf(("%d cookies, ",ncookies
));
1010 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
1011 panic("hpfs_readdir: unexpected uio from NFS server");
1012 #if defined(__DragonFly__)
1013 MALLOC(cookies
, u_long
*, ncookies
* sizeof(u_long
),
1015 #else /* defined(__NetBSD__) */
1016 MALLOC(cookies
, off_t
*, ncookies
* sizeof(off_t
),
1019 for (cookiep
= cookies
, i
=0; i
< ncookies
; i
++)
1020 *cookiep
++ = (u_int
)++num
;
1022 *ap
->a_ncookies
= ncookies
;
1023 *ap
->a_cookies
= cookies
;
1027 vn_unlock(ap
->a_vp
);
1032 * hpfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
1033 * struct componentname *a_cnp)
1036 hpfs_lookup(struct vop_old_lookup_args
*ap
)
1038 struct vnode
*dvp
= ap
->a_dvp
;
1039 struct hpfsnode
*dhp
= VTOHP(dvp
);
1040 struct hpfsmount
*hpmp
= dhp
->h_hpmp
;
1041 struct componentname
*cnp
= ap
->a_cnp
;
1042 struct ucred
*cred
= cnp
->cn_cred
;
1044 int nameiop
= cnp
->cn_nameiop
;
1045 int flags
= cnp
->cn_flags
;
1046 int lockparent
= flags
& CNP_LOCKPARENT
;
1048 int wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
1050 dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
1051 dhp
->h_no
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
1052 lockparent
, wantparent
));
1054 if (nameiop
!= NAMEI_CREATE
&& nameiop
!= NAMEI_DELETE
&& nameiop
!= NAMEI_LOOKUP
) {
1055 kprintf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
1056 return (EOPNOTSUPP
);
1059 error
= VOP_ACCESS(dvp
, VEXEC
, cred
);
1063 if( (cnp
->cn_namelen
== 1) &&
1064 !strncmp(cnp
->cn_nameptr
,".",1) ) {
1065 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp
->h_no
));
1071 } else if( (cnp
->cn_namelen
== 2) &&
1072 !strncmp(cnp
->cn_nameptr
,"..",2) && (flags
& CNP_ISDOTDOT
) ) {
1073 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
1074 dhp
->h_no
, dhp
->h_fn
.fn_parent
));
1076 VOP__UNLOCK(dvp
, 0);
1078 error
= VFS_VGET(hpmp
->hpm_mp
,
1079 dhp
->h_fn
.fn_parent
, ap
->a_vpp
);
1085 if (lockparent
&& (error
= VOP__LOCK(dvp
, 0))) {
1086 vput( *(ap
->a_vpp
) );
1092 struct hpfsdirent
*dep
;
1093 struct hpfsnode
*hp
;
1095 error
= hpfs_genlookupbyname(dhp
,
1096 cnp
->cn_nameptr
, cnp
->cn_namelen
, &bp
, &dep
);
1098 if (error
== ENOENT
&&
1099 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
)) {
1101 VOP__UNLOCK(dvp
, 0);
1102 return (EJUSTRETURN
);
1108 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
1109 dep
->de_fnode
, dep
->de_cpid
));
1111 if (nameiop
== NAMEI_DELETE
) {
1112 error
= VOP_ACCESS(dvp
, VWRITE
, cred
);
1119 if (dhp
->h_no
== dep
->de_fnode
) {
1126 error
= VFS_VGET(hpmp
->hpm_mp
, dep
->de_fnode
, ap
->a_vpp
);
1128 kprintf("hpfs_lookup: VFS_VGET FAILED %d\n", error
);
1133 hp
= VTOHP(*ap
->a_vpp
);
1135 hp
->h_mtime
= dep
->de_mtime
;
1136 hp
->h_ctime
= dep
->de_ctime
;
1137 hp
->h_atime
= dep
->de_atime
;
1138 bcopy(dep
->de_name
, hp
->h_name
, dep
->de_namelen
);
1139 hp
->h_name
[dep
->de_namelen
] = '\0';
1140 hp
->h_namelen
= dep
->de_namelen
;
1141 hp
->h_flag
|= H_PARVALID
;
1146 VOP__UNLOCK(dvp
, 0);
1152 * hpfs_remove(struct vnode *a_dvp, struct vnode *a_vp,
1153 * struct componentname *a_cnp)
1156 hpfs_remove(struct vop_old_remove_args
*ap
)
1160 dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap
->a_vp
)->h_no
,
1161 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1163 if (ap
->a_vp
->v_type
== VDIR
)
1166 error
= hpfs_removefnode (ap
->a_dvp
, ap
->a_vp
, ap
->a_cnp
);
1171 * hpfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
1172 * struct componentname *a_cnp, struct vattr *a_vap)
1175 hpfs_create(struct vop_old_create_args
*ap
)
1179 dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap
->a_dvp
)->h_no
,
1180 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1182 error
= hpfs_makefnode (ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
);
1188 * Return POSIX pathconf information applicable to NTFS filesystem
1190 * hpfs_pathconf(struct vnode *a_vp, int a_name, t *a_retval)
1193 hpfs_pathconf(struct vop_pathconf_args
*ap
)
1195 switch (ap
->a_name
) {
1200 *ap
->a_retval
= HPFS_MAXFILENAME
;
1203 *ap
->a_retval
= PATH_MAX
;
1205 case _PC_CHOWN_RESTRICTED
:
1211 #if defined(__NetBSD__)
1215 case _PC_FILESIZEBITS
:
1227 * Global vfs data structures
1230 struct vop_ops hpfs_vnode_vops
= {
1231 .vop_default
= vop_defaultop
,
1232 .vop_getattr
= hpfs_getattr
,
1233 .vop_setattr
= hpfs_setattr
,
1234 .vop_inactive
= hpfs_inactive
,
1235 .vop_reclaim
= hpfs_reclaim
,
1236 .vop_print
= hpfs_print
,
1237 .vop_old_create
= hpfs_create
,
1238 .vop_old_remove
= hpfs_remove
,
1239 .vop_old_lookup
= hpfs_lookup
,
1240 .vop_access
= hpfs_access
,
1241 .vop_readdir
= hpfs_readdir
,
1242 .vop_fsync
= hpfs_fsync
,
1243 .vop_bmap
= hpfs_bmap
,
1244 .vop_getpages
= hpfs_getpages
,
1245 .vop_putpages
= hpfs_putpages
,
1246 .vop_strategy
= hpfs_strategy
,
1247 .vop_read
= hpfs_read
,
1248 .vop_write
= hpfs_write
,
1249 .vop_ioctl
= hpfs_ioctl
,
1250 .vop_pathconf
= hpfs_pathconf