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>
36 #include <sys/types.h>
38 #include <sys/vnode.h>
39 #include <sys/mount.h>
40 #include <sys/namei.h>
41 #include <sys/malloc.h>
43 #include <sys/dirent.h>
45 #include <machine/limits.h>
48 #include <vm/vm_param.h>
49 #if !defined(__DragonFly__)
50 #include <vm/vm_prot.h>
52 #include <vm/vm_page.h>
53 #include <vm/vm_object.h>
54 #include <vm/vm_pager.h>
55 #include <vm/vm_zone.h>
56 #if defined(__DragonFly__)
57 #include <vm/vnode_pager.h>
59 #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, 0x%x): ",hp
->h_no
, ap
->a_bn
));
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
= min (uio
->uio_resid
, hp
->h_fn
.fn_size
- uio
->uio_offset
);
311 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
));
314 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
315 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
316 dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
317 uio
->uio_resid
, lbn
, off
));
318 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
322 toread
= min(off
+ resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
323 xfersz
= (toread
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
324 dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
325 bn
, runl
, toread
, xfersz
));
330 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
336 error
= uiomove(bp
->b_data
+ off
, toread
- off
, uio
);
344 dprintf(("hpfs_read: successful\n"));
349 * hpfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
350 * struct ucred *a_cred)
353 hpfs_write(struct vop_write_args
*ap
)
355 struct vnode
*vp
= ap
->a_vp
;
356 struct hpfsnode
*hp
= VTOHP(vp
);
357 struct uio
*uio
= ap
->a_uio
;
359 u_int xfersz
, towrite
;
365 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
));
367 if (ap
->a_ioflag
& IO_APPEND
) {
368 dprintf(("hpfs_write: APPEND mode\n"));
369 uio
->uio_offset
= hp
->h_fn
.fn_size
;
371 if (uio
->uio_offset
+ uio
->uio_resid
> hp
->h_fn
.fn_size
) {
372 error
= hpfs_extend (hp
, uio
->uio_offset
+ uio
->uio_resid
);
374 kprintf("hpfs_write: hpfs_extend FAILED %d\n", error
);
379 while (uio
->uio_resid
) {
380 lbn
= uio
->uio_offset
>> DEV_BSHIFT
;
381 off
= uio
->uio_offset
& (DEV_BSIZE
- 1);
382 dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
383 uio
->uio_resid
, lbn
, off
));
384 error
= hpfs_hpbmap(hp
, lbn
, &bn
, &runl
);
388 towrite
= min(off
+ uio
->uio_resid
, min(DFLTPHYS
, (runl
+1)*DEV_BSIZE
));
389 xfersz
= (towrite
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
390 dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
391 bn
, runl
, towrite
, xfersz
));
394 * We do not have to issue a read-before-write if the xfer
395 * size does not cover the whole block.
397 * In the UIO_NOCOPY case, however, we are not overwriting
398 * anything and must do a read-before-write to fill in
399 * any missing pieces.
401 if (off
== 0 && towrite
== xfersz
&&
402 uio
->uio_segflg
!= UIO_NOCOPY
) {
403 bp
= getblk(hp
->h_devvp
, dbtodoff(bn
), xfersz
, 0, 0);
406 error
= bread(hp
->h_devvp
, dbtodoff(bn
), xfersz
, &bp
);
413 error
= uiomove(bp
->b_data
+ off
, towrite
- off
, uio
);
419 if (ap
->a_ioflag
& IO_SYNC
)
425 dprintf(("hpfs_write: successful\n"));
430 * XXXXX do we need hpfsnode locking inside?
432 * hpfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
435 hpfs_getattr(struct vop_getattr_args
*ap
)
437 struct vnode
*vp
= ap
->a_vp
;
438 struct hpfsnode
*hp
= VTOHP(vp
);
439 struct vattr
*vap
= ap
->a_vap
;
442 dprintf(("hpfs_getattr(0x%x):\n", hp
->h_no
));
444 #if defined(__DragonFly__)
445 vap
->va_fsid
= dev2udev(hp
->h_dev
);
446 #else /* defined(__NetBSD__) */
447 vap
->va_fsid
= ip
->i_dev
;
449 vap
->va_fileid
= hp
->h_no
;
450 vap
->va_mode
= hp
->h_mode
;
452 vap
->va_uid
= hp
->h_uid
;
453 vap
->va_gid
= hp
->h_gid
;
454 vap
->va_rmajor
= VNOVAL
;
455 vap
->va_rminor
= VNOVAL
;
456 vap
->va_size
= hp
->h_fn
.fn_size
;
457 vap
->va_bytes
= ((hp
->h_fn
.fn_size
+ DEV_BSIZE
-1) & ~(DEV_BSIZE
-1)) +
460 if (!(hp
->h_flag
& H_PARVALID
)) {
461 error
= hpfs_validateparent(hp
);
465 vap
->va_atime
= hpfstimetounix(hp
->h_atime
);
466 vap
->va_mtime
= hpfstimetounix(hp
->h_mtime
);
467 vap
->va_ctime
= hpfstimetounix(hp
->h_ctime
);
471 vap
->va_blocksize
= DEV_BSIZE
;
472 vap
->va_type
= vp
->v_type
;
479 * XXXXX do we need hpfsnode locking inside?
481 * hpfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
484 hpfs_setattr(struct vop_setattr_args
*ap
)
486 struct vnode
*vp
= ap
->a_vp
;
487 struct hpfsnode
*hp
= VTOHP(vp
);
488 struct vattr
*vap
= ap
->a_vap
;
489 struct ucred
*cred
= ap
->a_cred
;
492 dprintf(("hpfs_setattr(0x%x):\n", hp
->h_no
));
495 * Check for unsettable attributes.
497 if ((vap
->va_type
!= VNON
) || (vap
->va_nlink
!= VNOVAL
) ||
498 (vap
->va_fsid
!= VNOVAL
) || (vap
->va_fileid
!= VNOVAL
) ||
499 (vap
->va_blocksize
!= VNOVAL
) || (vap
->va_rmajor
!= VNOVAL
) ||
500 (vap
->va_bytes
!= VNOVAL
) || (vap
->va_gen
!= VNOVAL
)) {
501 dprintf(("hpfs_setattr: changing nonsettable attr\n"));
505 /* Can't change flags XXX Could be implemented */
506 if (vap
->va_flags
!= VNOVAL
) {
507 kprintf("hpfs_setattr: FLAGS CANNOT BE SET\n");
511 /* Can't change uid/gid XXX Could be implemented */
512 if (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
) {
513 kprintf("hpfs_setattr: UID/GID CANNOT BE SET\n");
517 /* Can't change mode XXX Could be implemented */
518 if (vap
->va_mode
!= (mode_t
)VNOVAL
) {
519 kprintf("hpfs_setattr: MODE CANNOT BE SET\n");
524 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
525 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
527 if (cred
->cr_uid
!= hp
->h_uid
&&
528 (error
= priv_check_cred(cred
, PRIV_ROOT
, PRISON_ROOT
)) &&
529 ((vap
->va_vaflags
& VA_UTIMES_NULL
) == 0 ||
530 (error
= VOP_ACCESS(vp
, VWRITE
, cred
))))
532 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
533 hp
->h_atime
= vap
->va_atime
.tv_sec
;
534 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
535 hp
->h_mtime
= vap
->va_mtime
.tv_sec
;
537 hp
->h_flag
|= H_PARCHANGE
;
540 if (vap
->va_size
!= VNOVAL
) {
541 switch (vp
->v_type
) {
545 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
549 kprintf("hpfs_setattr: WRONG v_type\n");
553 if (vap
->va_size
< hp
->h_fn
.fn_size
) {
554 #if defined(__DragonFly__)
555 error
= vtruncbuf(vp
, vap
->va_size
, DEV_BSIZE
);
558 #else /* defined(__NetBSD__) */
559 #error Need alternation for vtruncbuf()
561 error
= hpfs_truncate(hp
, vap
->va_size
);
565 } else if (vap
->va_size
> hp
->h_fn
.fn_size
) {
566 #if defined(__DragonFly__)
567 vnode_pager_setsize(vp
, vap
->va_size
);
569 error
= hpfs_extend(hp
, vap
->va_size
);
579 * Last reference to an node. If necessary, write or delete it.
581 * hpfs_inactive(struct vnode *a_vp)
584 hpfs_inactive(struct vop_inactive_args
*ap
)
586 struct vnode
*vp
= ap
->a_vp
;
587 struct hpfsnode
*hp
= VTOHP(vp
);
590 dprintf(("hpfs_inactive(0x%x): \n", hp
->h_no
));
592 if (hp
->h_flag
& H_CHANGE
) {
593 dprintf(("hpfs_inactive: node changed, update\n"));
594 error
= hpfs_update (hp
);
599 if (hp
->h_flag
& H_PARCHANGE
) {
600 dprintf(("hpfs_inactive: parent node changed, update\n"));
601 error
= hpfs_updateparent (hp
);
606 if (prtactive
&& vp
->v_sysref
.refcnt
> 1)
607 vprint("hpfs_inactive: pushing active", vp
);
609 if (hp
->h_flag
& H_INVAL
) {
610 #if defined(__DragonFly__)
612 #else /* defined(__NetBSD__) */
621 * Reclaim an inode so that it can be used for other purposes.
623 * hpfs_reclaim(struct vnode *a_vp)
626 hpfs_reclaim(struct vop_reclaim_args
*ap
)
628 struct vnode
*vp
= ap
->a_vp
;
629 struct hpfsnode
*hp
= VTOHP(vp
);
631 dprintf(("hpfs_reclaim(0x%x0): \n", hp
->h_no
));
635 /* Purge old data structures associated with the inode. */
649 * hpfs_print(struct vnode *a_vp)
652 hpfs_print(struct vop_print_args
*ap
)
654 struct vnode
*vp
= ap
->a_vp
;
655 struct hpfsnode
*hp
= VTOHP(vp
);
657 kprintf("tag VT_HPFS, ino 0x%x",hp
->h_no
);
658 lockmgr_printinfo(&vp
->v_lock
);
664 * Calculate the logical to physical mapping if not done already,
665 * then call the device strategy routine.
667 * In order to be able to swap to a file, the VOP_BMAP operation may not
668 * deadlock on memory. See hpfs_bmap() for details. XXXXXXX (not impl)
670 * hpfs_strategy(struct vnode *a_vp, struct bio *a_bio)
673 hpfs_strategy(struct vop_strategy_args
*ap
)
675 struct bio
*bio
= ap
->a_bio
;
677 struct buf
*bp
= bio
->bio_buf
;
678 struct vnode
*vp
= ap
->a_vp
;
682 dprintf(("hpfs_strategy(): \n"));
684 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
685 panic("hpfs_strategy: spec");
687 nbio
= push_bio(bio
);
688 if (nbio
->bio_offset
== NOOFFSET
) {
689 error
= VOP_BMAP(vp
, bio
->bio_offset
, &nbio
->bio_offset
,
690 NULL
, NULL
, bp
->b_cmd
);
692 kprintf("hpfs_strategy: VOP_BMAP FAILED %d\n", error
);
694 bp
->b_flags
|= B_ERROR
;
695 /* I/O was never started on nbio, must biodone(bio) */
699 if (nbio
->bio_offset
== NOOFFSET
)
702 if (nbio
->bio_offset
== NOOFFSET
) {
703 /* I/O was never started on nbio, must biodone(bio) */
707 hp
= VTOHP(ap
->a_vp
);
708 vn_strategy(hp
->h_devvp
, nbio
);
713 * XXXXX do we need hpfsnode locking inside?
715 * hpfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
718 hpfs_access(struct vop_access_args
*ap
)
720 struct vnode
*vp
= ap
->a_vp
;
721 struct hpfsnode
*hp
= VTOHP(vp
);
722 struct ucred
*cred
= ap
->a_cred
;
723 mode_t mask
, mode
= ap
->a_mode
;
727 dprintf(("hpfs_access(0x%x):\n", hp
->h_no
));
730 * Disallow write attempts on read-only file systems;
731 * unless the file is a socket, fifo, or a block or
732 * character device resident on the file system.
735 switch ((int)vp
->v_type
) {
739 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
745 /* Otherwise, user id 0 always gets access. */
746 if (cred
->cr_uid
== 0)
751 /* Otherwise, check the owner. */
752 if (cred
->cr_uid
== hp
->h_uid
) {
761 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
764 /* Otherwise, check the groups. */
765 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
766 if (hp
->h_gid
== *gp
) {
773 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
776 /* Otherwise, check everyone else. */
783 return ((hp
->h_mode
& mask
) == mask
? 0 : EACCES
);
787 hpfs_de_uiomove(int *error
, struct hpfsmount
*hpmp
, struct hpfsdirent
*dep
,
790 char convname
[HPFS_MAXFILENAME
+ 1];
793 dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
794 dep
->de_fnode
, dep
->de_size
, dep
->de_namelen
,
795 dep
->de_namelen
, dep
->de_name
, dep
->de_flag
));
797 /*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
798 for (i
=0; i
<dep
->de_namelen
; i
++)
799 convname
[i
] = hpfs_d2u(hpmp
, dep
->de_name
[i
]);
800 convname
[dep
->de_namelen
] = '\0';
802 success
= vop_write_dirent(error
, uio
, dep
->de_fnode
,
803 (dep
->de_flag
& DE_DIR
) ? DT_DIR
: DT_REG
,
804 dep
->de_namelen
, convname
);
806 dprintf(("[0x%x] ", uio
->uio_resid
));
812 * hpfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
813 * int *a_ncookies, off_t **cookies)
816 hpfs_readdir(struct vop_readdir_args
*ap
)
818 struct vnode
*vp
= ap
->a_vp
;
819 struct hpfsnode
*hp
= VTOHP(vp
);
820 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
821 struct uio
*uio
= ap
->a_uio
;
822 int ncookies
= 0, i
, num
, cnum
;
826 struct hpfsdirent
*dep
;
831 dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp
->h_no
,(u_int32_t
)uio
->uio_offset
,uio
->uio_resid
));
834 * As we need to fake up . and .., and the remaining directory structure
835 * can't be expressed in one off_t as well, we just increment uio_offset
836 * by 1 for each entry.
838 * num is the entry we need to start reporting
839 * cnum is the current entry
841 if (uio
->uio_offset
< 0 || uio
->uio_offset
> INT_MAX
)
843 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
846 num
= uio
->uio_offset
;
850 dprintf((". faked, "));
851 if (vop_write_dirent(&error
, uio
, hp
->h_no
, DT_DIR
, 1, "."))
860 dprintf((".. faked, "));
861 if (vop_write_dirent(&error
, uio
, hp
->h_fn
.fn_parent
, DT_DIR
, 2, ".."))
869 lsn
= ((alleaf_t
*)hp
->h_fn
.fn_abd
)->al_lsn
;
875 dprintf(("[dive 0x%x] ", lsn
));
876 error
= bread(hp
->h_devvp
, dbtodoff(lsn
), D_BSIZE
, &bp
);
882 dp
= (struct dirblk
*) bp
->b_data
;
883 if (dp
->d_magic
!= D_MAGIC
) {
884 kprintf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
893 dprintf(("[restore 0x%x] ", olsn
));
895 while(!(dep
->de_flag
& DE_END
) ) {
896 if((dep
->de_flag
& DE_DOWN
) &&
897 (olsn
== DE_DOWNLSN(dep
)))
899 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
902 if((dep
->de_flag
& DE_DOWN
) && (olsn
== DE_DOWNLSN(dep
))) {
903 if (dep
->de_flag
& DE_END
)
906 if (!(dep
->de_flag
& DE_SPECIAL
)) {
908 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
910 dprintf(("[resid] "));
922 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
924 kprintf("hpfs_readdir: ERROR! oLSN not found\n");
933 while(!(dep
->de_flag
& DE_END
)) {
934 if(dep
->de_flag
& DE_DOWN
) {
935 lsn
= DE_DOWNLSN(dep
);
941 if (!(dep
->de_flag
& DE_SPECIAL
)) {
943 if (hpfs_de_uiomove(&error
, hpmp
, dep
, uio
)) {
945 dprintf(("[resid] "));
957 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
960 if(dep
->de_flag
& DE_DOWN
) {
961 dprintf(("[enddive] "));
962 lsn
= DE_DOWNLSN(dep
);
975 dprintf(("[level %d] ", level
));
978 goto dive
; /* undive really */
986 uio
->uio_offset
= cnum
;
987 dprintf(("[readdone]\n"));
988 if (!error
&& ap
->a_ncookies
!= NULL
) {
992 dprintf(("%d cookies, ",ncookies
));
993 if (uio
->uio_segflg
!= UIO_SYSSPACE
|| uio
->uio_iovcnt
!= 1)
994 panic("hpfs_readdir: unexpected uio from NFS server");
995 MALLOC(cookies
, off_t
*, ncookies
* sizeof(off_t
),
997 for (cookiep
= cookies
, i
=0; i
< ncookies
; i
++)
1000 *ap
->a_ncookies
= ncookies
;
1001 *ap
->a_cookies
= cookies
;
1005 vn_unlock(ap
->a_vp
);
1010 * hpfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
1011 * struct componentname *a_cnp)
1014 hpfs_lookup(struct vop_old_lookup_args
*ap
)
1016 struct vnode
*dvp
= ap
->a_dvp
;
1017 struct hpfsnode
*dhp
= VTOHP(dvp
);
1018 struct hpfsmount
*hpmp
= dhp
->h_hpmp
;
1019 struct componentname
*cnp
= ap
->a_cnp
;
1020 struct ucred
*cred
= cnp
->cn_cred
;
1022 int nameiop
= cnp
->cn_nameiop
;
1023 int flags
= cnp
->cn_flags
;
1024 int lockparent
= flags
& CNP_LOCKPARENT
;
1026 int wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
1028 dprintf(("hpfs_lookup(0x%x, %s, %ld, %d, %d): \n",
1029 dhp
->h_no
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
1030 lockparent
, wantparent
));
1032 if (nameiop
!= NAMEI_CREATE
&& nameiop
!= NAMEI_DELETE
&& nameiop
!= NAMEI_LOOKUP
) {
1033 kprintf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
1034 return (EOPNOTSUPP
);
1037 error
= VOP_ACCESS(dvp
, VEXEC
, cred
);
1041 if( (cnp
->cn_namelen
== 1) &&
1042 !strncmp(cnp
->cn_nameptr
,".",1) ) {
1043 dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp
->h_no
));
1049 } else if( (cnp
->cn_namelen
== 2) &&
1050 !strncmp(cnp
->cn_nameptr
,"..",2) && (flags
& CNP_ISDOTDOT
) ) {
1051 dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
1052 dhp
->h_no
, dhp
->h_fn
.fn_parent
));
1054 VOP__UNLOCK(dvp
, 0);
1056 error
= VFS_VGET(hpmp
->hpm_mp
,
1057 dhp
->h_fn
.fn_parent
, ap
->a_vpp
);
1063 if (lockparent
&& (error
= VOP__LOCK(dvp
, 0))) {
1064 vput( *(ap
->a_vpp
) );
1070 struct hpfsdirent
*dep
;
1071 struct hpfsnode
*hp
;
1073 error
= hpfs_genlookupbyname(dhp
,
1074 cnp
->cn_nameptr
, cnp
->cn_namelen
, &bp
, &dep
);
1076 if (error
== ENOENT
&&
1077 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
)) {
1079 VOP__UNLOCK(dvp
, 0);
1080 return (EJUSTRETURN
);
1086 dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
1087 dep
->de_fnode
, dep
->de_cpid
));
1089 if (nameiop
== NAMEI_DELETE
) {
1090 error
= VOP_ACCESS(dvp
, VWRITE
, cred
);
1097 if (dhp
->h_no
== dep
->de_fnode
) {
1104 error
= VFS_VGET(hpmp
->hpm_mp
, dep
->de_fnode
, ap
->a_vpp
);
1106 kprintf("hpfs_lookup: VFS_VGET FAILED %d\n", error
);
1111 hp
= VTOHP(*ap
->a_vpp
);
1113 hp
->h_mtime
= dep
->de_mtime
;
1114 hp
->h_ctime
= dep
->de_ctime
;
1115 hp
->h_atime
= dep
->de_atime
;
1116 bcopy(dep
->de_name
, hp
->h_name
, dep
->de_namelen
);
1117 hp
->h_name
[dep
->de_namelen
] = '\0';
1118 hp
->h_namelen
= dep
->de_namelen
;
1119 hp
->h_flag
|= H_PARVALID
;
1124 VOP__UNLOCK(dvp
, 0);
1130 * hpfs_remove(struct vnode *a_dvp, struct vnode *a_vp,
1131 * struct componentname *a_cnp)
1134 hpfs_remove(struct vop_old_remove_args
*ap
)
1138 dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap
->a_vp
)->h_no
,
1139 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1141 if (ap
->a_vp
->v_type
== VDIR
)
1144 error
= hpfs_removefnode (ap
->a_dvp
, ap
->a_vp
, ap
->a_cnp
);
1149 * hpfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
1150 * struct componentname *a_cnp, struct vattr *a_vap)
1153 hpfs_create(struct vop_old_create_args
*ap
)
1157 dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap
->a_dvp
)->h_no
,
1158 ap
->a_cnp
->cn_nameptr
, ap
->a_cnp
->cn_namelen
));
1160 error
= hpfs_makefnode (ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
);
1166 * Return POSIX pathconf information applicable to NTFS filesystem
1168 * hpfs_pathconf(struct vnode *a_vp, int a_name, t *a_retval)
1171 hpfs_pathconf(struct vop_pathconf_args
*ap
)
1173 switch (ap
->a_name
) {
1178 *ap
->a_retval
= HPFS_MAXFILENAME
;
1181 *ap
->a_retval
= PATH_MAX
;
1183 case _PC_CHOWN_RESTRICTED
:
1189 #if defined(__NetBSD__)
1193 case _PC_FILESIZEBITS
:
1205 * Global vfs data structures
1208 struct vop_ops hpfs_vnode_vops
= {
1209 .vop_default
= vop_defaultop
,
1210 .vop_getattr
= hpfs_getattr
,
1211 .vop_setattr
= hpfs_setattr
,
1212 .vop_inactive
= hpfs_inactive
,
1213 .vop_reclaim
= hpfs_reclaim
,
1214 .vop_print
= hpfs_print
,
1215 .vop_old_create
= hpfs_create
,
1216 .vop_old_remove
= hpfs_remove
,
1217 .vop_old_lookup
= hpfs_lookup
,
1218 .vop_access
= hpfs_access
,
1219 .vop_readdir
= hpfs_readdir
,
1220 .vop_fsync
= hpfs_fsync
,
1221 .vop_bmap
= hpfs_bmap
,
1222 .vop_getpages
= vop_stdgetpages
,
1223 .vop_putpages
= vop_stdputpages
,
1224 .vop_strategy
= hpfs_strategy
,
1225 .vop_read
= hpfs_read
,
1226 .vop_write
= hpfs_write
,
1227 .vop_ioctl
= hpfs_ioctl
,
1228 .vop_pathconf
= hpfs_pathconf