2 * Copyright (c) 1999, 2000 Boris Popov
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.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/sys/nwfs/nwfs_vnops.c,v 1.6.2.3 2001/03/14 11:26:59 bp Exp $
33 * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.38 2007/11/20 21:03:50 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
40 #include <sys/namei.h>
41 #include <sys/fcntl.h>
42 #include <sys/mount.h>
43 #include <sys/unistd.h>
44 #include <sys/vnode.h>
47 #include <vm/vm_extern.h>
48 #include <vm/vm_zone.h>
50 #include <netproto/ncp/ncp.h>
51 #include <netproto/ncp/ncp_conn.h>
52 #include <netproto/ncp/ncp_subr.h>
53 #include <netproto/ncp/nwerror.h>
54 #include <netproto/ncp/ncp_nls.h>
57 #include "nwfs_node.h"
58 #include "nwfs_subr.h"
61 * Prototypes for NWFS vnode operations
63 static int nwfs_create(struct vop_old_create_args
*);
64 static int nwfs_mknod(struct vop_old_mknod_args
*);
65 static int nwfs_open(struct vop_open_args
*);
66 static int nwfs_close(struct vop_close_args
*);
67 static int nwfs_access(struct vop_access_args
*);
68 static int nwfs_getattr(struct vop_getattr_args
*);
69 static int nwfs_setattr(struct vop_setattr_args
*);
70 static int nwfs_read(struct vop_read_args
*);
71 static int nwfs_write(struct vop_write_args
*);
72 static int nwfs_fsync(struct vop_fsync_args
*);
73 static int nwfs_remove(struct vop_old_remove_args
*);
74 static int nwfs_link(struct vop_old_link_args
*);
75 static int nwfs_lookup(struct vop_old_lookup_args
*);
76 static int nwfs_rename(struct vop_old_rename_args
*);
77 static int nwfs_mkdir(struct vop_old_mkdir_args
*);
78 static int nwfs_rmdir(struct vop_old_rmdir_args
*);
79 static int nwfs_symlink(struct vop_old_symlink_args
*);
80 static int nwfs_readdir(struct vop_readdir_args
*);
81 static int nwfs_bmap(struct vop_bmap_args
*);
82 static int nwfs_strategy(struct vop_strategy_args
*);
83 static int nwfs_print(struct vop_print_args
*);
84 static int nwfs_pathconf(struct vop_pathconf_args
*ap
);
86 /* Global vfs data structures for nwfs */
87 struct vop_ops nwfs_vnode_vops
= {
88 .vop_default
= vop_defaultop
,
89 .vop_access
= nwfs_access
,
90 .vop_bmap
= nwfs_bmap
,
91 .vop_open
= nwfs_open
,
92 .vop_close
= nwfs_close
,
93 .vop_old_create
= nwfs_create
,
94 .vop_fsync
= nwfs_fsync
,
95 .vop_getattr
= nwfs_getattr
,
96 .vop_getpages
= nwfs_getpages
,
97 .vop_putpages
= nwfs_putpages
,
98 .vop_ioctl
= nwfs_ioctl
,
99 .vop_inactive
= nwfs_inactive
,
100 .vop_old_link
= nwfs_link
,
101 .vop_old_lookup
= nwfs_lookup
,
102 .vop_old_mkdir
= nwfs_mkdir
,
103 .vop_old_mknod
= nwfs_mknod
,
104 .vop_pathconf
= nwfs_pathconf
,
105 .vop_print
= nwfs_print
,
106 .vop_read
= nwfs_read
,
107 .vop_readdir
= nwfs_readdir
,
108 .vop_reclaim
= nwfs_reclaim
,
109 .vop_old_remove
= nwfs_remove
,
110 .vop_old_rename
= nwfs_rename
,
111 .vop_old_rmdir
= nwfs_rmdir
,
112 .vop_setattr
= nwfs_setattr
,
113 .vop_strategy
= nwfs_strategy
,
114 .vop_old_symlink
= nwfs_symlink
,
115 .vop_write
= nwfs_write
119 * nwfs_access vnode op
120 * for now just return ok
122 * nwfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
125 nwfs_access(struct vop_access_args
*ap
)
127 struct vnode
*vp
= ap
->a_vp
;
128 struct ucred
*cred
= ap
->a_cred
;
129 u_int mode
= ap
->a_mode
;
130 struct nwmount
*nmp
= VTONWFS(vp
);
134 if ((ap
->a_mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
135 switch (vp
->v_type
) {
136 case VREG
: case VDIR
: case VLNK
:
142 if (cred
->cr_uid
== 0)
144 if (cred
->cr_uid
!= nmp
->m
.uid
) {
146 if (!groupmember(nmp
->m
.gid
, cred
))
149 error
= (((vp
->v_type
== VREG
) ? nmp
->m
.file_mode
: nmp
->m
.dir_mode
) & mode
) == mode
? 0 : EACCES
;
155 * nwfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
160 nwfs_open(struct vop_open_args
*ap
)
162 thread_t td
= curthread
; /* XXX */
163 struct vnode
*vp
= ap
->a_vp
;
164 int mode
= ap
->a_mode
;
165 struct nwnode
*np
= VTONW(vp
);
166 struct ncp_open_info no
;
167 struct nwmount
*nmp
= VTONWFS(vp
);
171 NCPVNDEBUG("%s,%d\n",np
->n_name
, np
->opened
);
172 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
) {
173 NCPFATAL("open vtype = %d\n", vp
->v_type
);
176 if (vp
->v_type
== VDIR
) return 0; /* nothing to do now */
177 if (np
->n_flag
& NMODIFIED
) {
178 if ((error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1)) == EINTR
)
181 error
= VOP_GETATTR(vp
, &vattr
);
184 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
186 error
= VOP_GETATTR(vp
, &vattr
);
189 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
190 if ((error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1)) == EINTR
)
192 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
197 return (vop_stdopen(ap
));
200 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0)
202 error
= ncp_open_create_file_or_subdir(nmp
, vp
, 0, NULL
, OC_MODE_OPEN
,
203 0, nwm
, &no
, td
, ap
->a_cred
);
208 error
= ncp_open_create_file_or_subdir(nmp
, vp
, 0, NULL
, OC_MODE_OPEN
, 0,
209 nwm
, &no
, td
, ap
->a_cred
);
215 np
->n_origfh
= no
.origfh
;
216 error
= vop_stdopen(ap
);
222 * nwfs_close(struct vnode *a_vp, int a_fflag)
225 nwfs_close(struct vop_close_args
*ap
)
227 thread_t td
= curthread
; /* XXX */
228 struct vnode
*vp
= ap
->a_vp
;
229 struct nwnode
*np
= VTONW(vp
);
232 NCPVNDEBUG("name=%s,td=%p,c=%d\n",np
->n_name
,ap
->a_td
,np
->opened
);
235 if (vp
->v_type
== VDIR
)
239 error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1);
240 if (np
->opened
== 0) {
241 error
= 0; /* huh? */
244 if (--np
->opened
== 0) {
245 error
= ncp_close_file(NWFSTOCONN(VTONWFS(vp
)), &np
->n_fh
,
255 * nwfs_getattr call from vfs.
257 * nwfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
260 nwfs_getattr(struct vop_getattr_args
*ap
)
262 thread_t td
= curthread
; /* XXX */
263 struct vnode
*vp
= ap
->a_vp
;
264 struct nwnode
*np
= VTONW(vp
);
265 struct vattr
*va
=ap
->a_vap
;
266 struct nwmount
*nmp
= VTONWFS(vp
);
267 struct nw_entry_info fattr
;
271 NCPVNDEBUG("%lx:%d: '%s' %d\n", (long)vp
, nmp
->n_volume
, np
->n_name
, (vp
->v_flag
& VROOT
) != 0);
272 error
= nwfs_attr_cachelookup(vp
,va
);
273 if (!error
) return 0;
274 NCPVNDEBUG("not in cache\n");
275 oldsize
= np
->n_size
;
276 if (np
->n_flag
& NVOLUME
) {
277 error
= ncp_obtain_info(nmp
, np
->n_fid
.f_id
, 0, NULL
, &fattr
,
280 error
= ncp_obtain_info(nmp
, np
->n_fid
.f_parent
, np
->n_nmlen
,
281 np
->n_name
, &fattr
, td
, proc0
.p_ucred
);
284 NCPVNDEBUG("error %d\n", error
);
287 nwfs_attr_cacheenter(vp
, &fattr
);
290 np
->n_size
= oldsize
;
294 * nwfs_setattr call from vfs.
296 * nwfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
299 nwfs_setattr(struct vop_setattr_args
*ap
)
301 thread_t td
= curthread
; /* XXX */
302 struct vnode
*vp
= ap
->a_vp
;
303 struct nwnode
*np
= VTONW(vp
);
304 struct vattr
*vap
= ap
->a_vap
;
309 if (vap
->va_flags
!= VNOVAL
)
312 * Disallow write attempts if the filesystem is mounted read-only.
314 if ((vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
||
315 vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
||
316 vap
->va_mode
!= (mode_t
)VNOVAL
) &&(vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
318 if (vap
->va_size
!= VNOVAL
) {
319 switch (vp
->v_type
) {
324 * Disallow write attempts if the filesystem is
327 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
329 vnode_pager_setsize(vp
, (u_long
)vap
->va_size
);
331 np
->n_size
= vap
->va_size
;
337 error
= ncp_setattr(vp
, vap
, ap
->a_cred
, td
);
338 if (error
&& vap
->va_size
!= VNOVAL
) {
340 vnode_pager_setsize(vp
, (u_long
)tsize
);
342 np
->n_atime
= 0; /* invalidate cache */
343 VOP_GETATTR(vp
, vap
);
344 np
->n_mtime
= vap
->va_mtime
.tv_sec
;
351 * nwfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
352 * struct ucred *a_cred)
355 nwfs_read(struct vop_read_args
*ap
)
357 struct vnode
*vp
= ap
->a_vp
;
358 struct uio
*uio
=ap
->a_uio
;
360 NCPVNDEBUG("nwfs_read:\n");
362 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
)
364 error
= nwfs_readvnode(vp
, uio
, ap
->a_cred
);
369 * nwfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
370 * struct ucred *a_cred)
373 nwfs_write(struct vop_write_args
*ap
)
375 struct vnode
*vp
= ap
->a_vp
;
376 struct uio
*uio
= ap
->a_uio
;
379 NCPVNDEBUG("%d,ofs=%d,sz=%d\n",vp
->v_type
, (int)uio
->uio_offset
, uio
->uio_resid
);
381 if (vp
->v_type
!= VREG
)
383 error
= nwfs_writevnode(vp
, uio
, ap
->a_cred
,ap
->a_ioflag
);
388 * Create a regular file. On entry the directory to contain the file being
389 * created is locked. We must release before we return.
391 * nwfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
392 * struct componentname *a_cnpl, struct vattr *a_vap)
395 nwfs_create(struct vop_old_create_args
*ap
)
397 struct vnode
*dvp
= ap
->a_dvp
;
398 struct vattr
*vap
= ap
->a_vap
;
399 struct vnode
**vpp
=ap
->a_vpp
;
400 struct componentname
*cnp
= ap
->a_cnp
;
401 struct vnode
*vp
= (struct vnode
*)0;
402 int error
= 0, fmode
;
405 struct ncp_open_info no
;
406 struct nwmount
*nmp
=VTONWFS(dvp
);
412 if (vap
->va_type
== VSOCK
)
414 if ((error
= VOP_GETATTR(dvp
, &vattr
))) {
417 fmode
= AR_READ
| AR_WRITE
;
418 /* if (vap->va_vaflags & VA_EXCLUSIVE)
419 fmode |= AR_DENY_READ | AR_DENY_WRITE;*/
421 error
= ncp_open_create_file_or_subdir(nmp
,dvp
,cnp
->cn_namelen
,cnp
->cn_nameptr
,
422 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
423 0, fmode
, &no
, cnp
->cn_td
, cnp
->cn_cred
);
425 error
= ncp_close_file(NWFSTOCONN(nmp
), &no
.fh
, cnp
->cn_td
,cnp
->cn_cred
);
426 fid
.f_parent
= VTONW(dvp
)->n_fid
.f_id
;
427 fid
.f_id
= no
.fattr
.dirEntNum
;
428 error
= nwfs_nget(VTOVFS(dvp
), fid
, &no
.fattr
, dvp
, &vp
);
439 * nwfs_remove call. It isn't possible to emulate UFS behaivour because
440 * NetWare doesn't allow delete/rename operations on an opened file.
442 * nwfs_remove(struct vnode *a_dvp,
443 * struct vnode *a_vp, struct componentname *a_cnp)
446 nwfs_remove(struct vop_old_remove_args
*ap
)
448 struct vnode
*vp
= ap
->a_vp
;
449 struct vnode
*dvp
= ap
->a_dvp
;
450 struct componentname
*cnp
= ap
->a_cnp
;
451 struct nwnode
*np
= VTONW(vp
);
452 struct nwmount
*nmp
= VTONWFS(vp
);
455 if (vp
->v_type
== VDIR
|| np
->opened
|| vp
->v_sysref
.refcnt
> 1) {
457 } else if (!ncp_conn_valid(NWFSTOCONN(nmp
))) {
460 error
= ncp_DeleteNSEntry(nmp
, VTONW(dvp
)->n_fid
.f_id
,
461 cnp
->cn_namelen
,cnp
->cn_nameptr
,cnp
->cn_td
,cnp
->cn_cred
);
463 np
->n_flag
|= NSHOULDFREE
;
464 else if (error
== 0x899c)
471 * nwfs_file rename call
473 * nwfs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
474 * struct componentname *a_fcnp, struct vnode *a_tdvp,
475 * struct vnode *a_tvp, struct componentname *a_tcnp)
478 nwfs_rename(struct vop_old_rename_args
*ap
)
480 struct vnode
*fvp
= ap
->a_fvp
;
481 struct vnode
*tvp
= ap
->a_tvp
;
482 struct vnode
*fdvp
= ap
->a_fdvp
;
483 struct vnode
*tdvp
= ap
->a_tdvp
;
484 struct componentname
*tcnp
= ap
->a_tcnp
;
485 struct componentname
*fcnp
= ap
->a_fcnp
;
486 struct nwmount
*nmp
=VTONWFS(fvp
);
487 u_int16_t oldtype
= 6;
490 /* Check for cross-device rename */
491 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
492 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
497 if (tvp
&& tvp
->v_sysref
.refcnt
> 1) {
501 if (tvp
&& tvp
!= fvp
) {
502 error
= ncp_DeleteNSEntry(nmp
, VTONW(tdvp
)->n_fid
.f_id
,
503 tcnp
->cn_namelen
, tcnp
->cn_nameptr
,
504 tcnp
->cn_td
, tcnp
->cn_cred
);
505 if (error
== 0x899c) error
= EACCES
;
509 if (fvp
->v_type
== VDIR
) {
510 oldtype
|= NW_TYPE_SUBDIR
;
511 } else if (fvp
->v_type
== VREG
) {
512 oldtype
|= NW_TYPE_FILE
;
515 error
= ncp_nsrename(NWFSTOCONN(nmp
), nmp
->n_volume
, nmp
->name_space
,
516 oldtype
, &nmp
->m
.nls
,
517 VTONW(fdvp
)->n_fid
.f_id
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
518 VTONW(tdvp
)->n_fid
.f_id
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
,
519 tcnp
->cn_td
,tcnp
->cn_cred
);
532 nwfs_attr_cacheremove(fdvp
);
533 nwfs_attr_cacheremove(tdvp
);
535 * Need to get rid of old vnodes, because netware will change
542 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
550 * nwfs hard link create call
551 * Netware filesystems don't know what links are.
553 * nwfs_link(struct vnode *a_tdvp, struct vnode *a_vp,
554 * struct componentname *a_cnp)
557 nwfs_link(struct vop_old_link_args
*ap
)
563 * nwfs_symlink link create call
564 * Netware filesystems don't know what symlinks are.
566 * nwfs_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
567 * struct componentname *a_cnp, struct vattr *a_vap,
571 nwfs_symlink(struct vop_old_symlink_args
*ap
)
576 static int nwfs_mknod(struct vop_old_mknod_args
*ap
)
584 * nwfs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
585 * struct componentname *a_cnp, struct vattr *a_vap)
588 nwfs_mkdir(struct vop_old_mkdir_args
*ap
)
590 struct vnode
*dvp
= ap
->a_dvp
;
591 /* struct vattr *vap = ap->a_vap;*/
592 struct componentname
*cnp
= ap
->a_cnp
;
593 int len
=cnp
->cn_namelen
;
594 struct ncp_open_info no
;
596 struct vnode
*newvp
= (struct vnode
*)0;
600 char *name
=cnp
->cn_nameptr
;
602 if ((error
= VOP_GETATTR(dvp
, &vattr
))) {
605 if ((name
[0] == '.') && ((len
== 1) || ((len
== 2) && (name
[1] == '.')))) {
608 if (ncp_open_create_file_or_subdir(VTONWFS(dvp
),dvp
, cnp
->cn_namelen
,
609 cnp
->cn_nameptr
,OC_MODE_CREATE
, aDIR
, 0xffff,
610 &no
, cnp
->cn_td
, cnp
->cn_cred
) != 0) {
616 fid
.f_parent
= VTONW(dvp
)->n_fid
.f_id
;
617 fid
.f_id
= no
.fattr
.dirEntNum
;
618 error
= nwfs_nget(VTOVFS(dvp
), fid
, &no
.fattr
, dvp
, &newvp
);
621 newvp
->v_type
= VDIR
;
629 * nwfs_remove directory call
631 * nwfs_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
632 * struct componentname *a_cnp)
635 nwfs_rmdir(struct vop_old_rmdir_args
*ap
)
637 struct vnode
*vp
= ap
->a_vp
;
638 struct vnode
*dvp
= ap
->a_dvp
;
639 struct componentname
*cnp
= ap
->a_cnp
;
640 struct nwnode
*np
= VTONW(vp
);
641 struct nwmount
*nmp
= VTONWFS(vp
);
642 struct nwnode
*dnp
= VTONW(dvp
);
648 error
= ncp_DeleteNSEntry(nmp
, dnp
->n_fid
.f_id
,
649 cnp
->cn_namelen
, cnp
->cn_nameptr
,cnp
->cn_td
,cnp
->cn_cred
);
651 np
->n_flag
|= NSHOULDFREE
;
652 else if (error
== NWE_DIR_NOT_EMPTY
)
654 dnp
->n_flag
|= NMODIFIED
;
655 nwfs_attr_cacheremove(dvp
);
662 * nwfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
663 * int *a_eofflag, off_t *a_cookies, int a_ncookies)
666 nwfs_readdir(struct vop_readdir_args
*ap
)
668 struct vnode
*vp
= ap
->a_vp
;
669 struct uio
*uio
= ap
->a_uio
;
672 if (vp
->v_type
!= VDIR
)
674 if (ap
->a_ncookies
) {
675 kprintf("nwfs_readdir: no support for cookies now...");
678 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
680 error
= nwfs_readvnode(vp
, uio
, ap
->a_cred
);
686 * nwfs_fsync(struct vnode *a_vp, int a_waitfor)
690 nwfs_fsync(struct vop_fsync_args
*ap
)
692 /* return (nfs_flush(ap->a_vp, ap->a_waitfor, curthread, 1));*/
697 * nwfs_print(struct vnode *a_vp)
701 nwfs_print(struct vop_print_args
*ap
)
703 struct vnode
*vp
= ap
->a_vp
;
704 struct nwnode
*np
= VTONW(vp
);
706 kprintf("nwfs node: name = '%s', fid = %d, pfid = %d\n",
707 np
->n_name
, np
->n_fid
.f_id
, np
->n_fid
.f_parent
);
712 * nwfs_pathconf(struct vnode *vp, int name, register_t *retval)
715 nwfs_pathconf(struct vop_pathconf_args
*ap
)
717 int name
=ap
->a_name
, error
=0;
718 register_t
*retval
=ap
->a_retval
;
725 *retval
=NCP_MAX_FILENAME
; /* XXX from nwfsnode */
728 *retval
=NCP_MAXPATHLEN
; /* XXX from nwfsnode */
737 * nwfs_strategy(struct vnode *a_vp, struct bio *a_bio)
740 nwfs_strategy(struct vop_strategy_args
*ap
)
742 struct bio
*bio
= ap
->a_bio
;
743 struct buf
*bp
= bio
->bio_buf
;
745 struct thread
*td
= NULL
;
748 if ((bp
->b_flags
& B_ASYNC
) == 0)
749 td
= curthread
; /* YYY dunno if this is legal */
751 * If the op is asynchronous and an i/o daemon is waiting
752 * queue the request, wake it up and wait for completion
753 * otherwise just do it ourselves.
755 if ((bp
->b_flags
& B_ASYNC
) == 0 )
756 error
= nwfs_doio(ap
->a_vp
, bio
, proc0
.p_ucred
, td
);
761 * nwfs_bmap(struct vnode *a_vp, off_t a_loffset,
762 * off_t *a_doffsetp, int *a_runp, int *a_runb)
765 nwfs_bmap(struct vop_bmap_args
*ap
)
767 if (ap
->a_doffsetp
!= NULL
)
768 *ap
->a_doffsetp
= ap
->a_loffset
;
769 if (ap
->a_runp
!= NULL
)
771 if (ap
->a_runb
!= NULL
)
777 nwfs_nget(struct mount
*mp
, ncpfid fid
, const struct nw_entry_info
*fap
,
778 struct vnode
*dvp
, struct vnode
**vpp
)
781 struct nwnode
*newnp
;
785 error
= nwfs_allocvp(mp
, fid
, &vp
);
790 newnp
->n_attr
= fap
->attributes
;
791 vp
->v_type
= newnp
->n_attr
& aDIR
? VDIR
: VREG
;
792 nwfs_attr_cacheenter(vp
, fap
);
795 newnp
->n_parent
= VTONW(dvp
)->n_fid
;
796 if ((newnp
->n_flag
& NNEW
) && vp
->v_type
== VDIR
) {
797 if ((dvp
->v_flag
& VROOT
) == 0) {
798 newnp
->n_refparent
= 1;
799 vref(dvp
); /* vhold */
803 if ((newnp
->n_flag
& NNEW
) && vp
->v_type
== VREG
)
804 kprintf("new vnode '%s' borned without parent ?\n",newnp
->n_name
);
806 newnp
->n_flag
&= ~NNEW
;
812 * How to keep the brain busy ...
813 * Currently lookup routine can make two lookup for vnode. This can be
814 * avoided by reorg the code.
816 * nwfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
817 * struct componentname *a_cnp)
820 nwfs_lookup(struct vop_old_lookup_args
*ap
)
822 struct componentname
*cnp
= ap
->a_cnp
;
823 struct vnode
*dvp
= ap
->a_dvp
;
824 struct vnode
**vpp
= ap
->a_vpp
;
825 int flags
= cnp
->cn_flags
;
828 struct mount
*mp
= dvp
->v_mount
;
829 struct nwnode
*dnp
, *npp
;
830 struct nw_entry_info fattr
, *fap
;
832 int nameiop
=cnp
->cn_nameiop
;
833 int lockparent
, wantparent
, error
= 0, notfound
;
834 struct thread
*td
= cnp
->cn_td
;
835 char _name
[cnp
->cn_namelen
+1];
836 bcopy(cnp
->cn_nameptr
,_name
,cnp
->cn_namelen
);
837 _name
[cnp
->cn_namelen
]=0;
839 if (dvp
->v_type
!= VDIR
)
841 if ((flags
& CNP_ISDOTDOT
) && (dvp
->v_flag
& VROOT
)) {
842 kprintf("nwfs_lookup: invalid '..'\n");
846 NCPVNDEBUG("%d '%s' in '%s' id=d\n", nameiop
, _name
,
847 VTONW(dvp
)->n_name
/*, VTONW(dvp)->n_name*/);
849 if ((mp
->mnt_flag
& MNT_RDONLY
) && nameiop
!= NAMEI_LOOKUP
)
851 if ((error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
)))
853 lockparent
= flags
& CNP_LOCKPARENT
;
854 wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
858 kprintf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISDOTDOT);
860 error
= ncp_pathcheck(cnp
->cn_nameptr
, cnp
->cn_namelen
, &nmp
->m
.nls
,
861 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) && (nmp
->m
.nls
.opt
& NWHP_NOSTRICT
) == 0);
868 if (flags
& CNP_ISDOTDOT
) {
869 if (NWCMPF(&dnp
->n_parent
, &nmp
->n_rootent
)) {
870 fid
= nmp
->n_rootent
;
874 error
= nwfs_lookupnp(nmp
, dnp
->n_parent
, td
, &npp
);
881 notfound
= ncp_obtain_info(nmp
, npp
->n_dosfid
,
882 0, NULL
, fap
, td
, cnp
->cn_cred
);
886 notfound
= ncp_lookup(dvp
, cnp
->cn_namelen
, cnp
->cn_nameptr
,
887 fap
, td
, cnp
->cn_cred
);
888 fid
.f_id
= fap
->dirEntNum
;
889 if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
890 fid
.f_parent
= dnp
->n_fid
.f_parent
;
892 fid
.f_parent
= dnp
->n_fid
.f_id
;
893 NCPVNDEBUG("call to ncp_lookup returned=%d\n",notfound
);
895 if (notfound
&& notfound
< 0x80 )
896 return (notfound
); /* hard error */
897 if (notfound
) { /* entry not found */
898 /* Handle RENAME or CREATE case... */
899 if ((nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) && wantparent
) {
902 return (EJUSTRETURN
);
906 NCPVNDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
908 /* handle DELETE case ... */
909 if (nameiop
== NAMEI_DELETE
) { /* delete last component */
910 error
= VOP_ACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
911 if (error
) return (error
);
912 if (NWCMPF(&dnp
->n_fid
, &fid
)) { /* we found ourselfs */
917 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
918 if (error
) return (error
);
920 if (!lockparent
) vn_unlock(dvp
);
923 if (nameiop
== NAMEI_RENAME
&& wantparent
) {
924 error
= VOP_ACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
925 if (error
) return (error
);
926 if (NWCMPF(&dnp
->n_fid
, &fid
)) return EISDIR
;
927 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
928 if (error
) return (error
);
934 if (flags
& CNP_ISDOTDOT
) {
935 vn_unlock(dvp
); /* race to get the inode */
936 error
= nwfs_nget(mp
, fid
, NULL
, NULL
, &vp
);
938 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
941 if (lockparent
&& (error
= vn_lock(dvp
, LK_EXCLUSIVE
))) {
946 } else if (NWCMPF(&dnp
->n_fid
, &fid
)) {
950 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
951 if (error
) return (error
);
953 NCPVNDEBUG("lookup: getnewvp!\n");
958 /* XXX MOVE TO NREMOVE */
959 if ((cnp
->cn_flags
& CNP_MAKEENTRY
)) {
960 VTONW(*vpp
)->n_ctime
= VTONW(*vpp
)->n_vattr
.va_ctime
.tv_sec
;