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
121 * nwfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred)
124 nwfs_access(struct vop_access_args
*ap
)
126 struct vnode
*vp
= ap
->a_vp
;
127 struct nwmount
*nmp
= VTONWFS(vp
);
132 mode
= ((vp
->v_type
== VREG
) ? nmp
->m
.file_mode
: nmp
->m
.dir_mode
);
133 error
= vop_helper_access(ap
, nmp
->m
.uid
, nmp
->m
.gid
, mode
, 0);
140 * nwfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
145 nwfs_open(struct vop_open_args
*ap
)
147 thread_t td
= curthread
; /* XXX */
148 struct vnode
*vp
= ap
->a_vp
;
149 int mode
= ap
->a_mode
;
150 struct nwnode
*np
= VTONW(vp
);
151 struct ncp_open_info no
;
152 struct nwmount
*nmp
= VTONWFS(vp
);
156 NCPVNDEBUG("%s,%d\n",np
->n_name
, np
->opened
);
157 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
) {
158 NCPFATAL("open vtype = %d\n", vp
->v_type
);
161 if (vp
->v_type
== VDIR
) return 0; /* nothing to do now */
162 if (np
->n_flag
& NMODIFIED
) {
163 if ((error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1)) == EINTR
)
166 error
= VOP_GETATTR(vp
, &vattr
);
169 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
171 error
= VOP_GETATTR(vp
, &vattr
);
174 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
175 if ((error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1)) == EINTR
)
177 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
182 return (vop_stdopen(ap
));
185 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0)
187 error
= ncp_open_create_file_or_subdir(nmp
, vp
, 0, NULL
, OC_MODE_OPEN
,
188 0, nwm
, &no
, td
, ap
->a_cred
);
193 error
= ncp_open_create_file_or_subdir(nmp
, vp
, 0, NULL
, OC_MODE_OPEN
, 0,
194 nwm
, &no
, td
, ap
->a_cred
);
200 np
->n_origfh
= no
.origfh
;
201 error
= vop_stdopen(ap
);
207 * nwfs_close(struct vnode *a_vp, int a_fflag)
210 nwfs_close(struct vop_close_args
*ap
)
212 thread_t td
= curthread
; /* XXX */
213 struct vnode
*vp
= ap
->a_vp
;
214 struct nwnode
*np
= VTONW(vp
);
217 NCPVNDEBUG("name=%s,td=%p,c=%d\n",np
->n_name
,ap
->a_td
,np
->opened
);
220 if (vp
->v_type
== VDIR
)
224 error
= nwfs_vinvalbuf(vp
, V_SAVE
, 1);
225 if (np
->opened
== 0) {
226 error
= 0; /* huh? */
229 if (--np
->opened
== 0) {
230 error
= ncp_close_file(NWFSTOCONN(VTONWFS(vp
)), &np
->n_fh
,
240 * nwfs_getattr call from vfs.
242 * nwfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
245 nwfs_getattr(struct vop_getattr_args
*ap
)
247 thread_t td
= curthread
; /* XXX */
248 struct vnode
*vp
= ap
->a_vp
;
249 struct nwnode
*np
= VTONW(vp
);
250 struct vattr
*va
=ap
->a_vap
;
251 struct nwmount
*nmp
= VTONWFS(vp
);
252 struct nw_entry_info fattr
;
256 NCPVNDEBUG("%lx:%d: '%s' %d\n", (long)vp
, nmp
->n_volume
, np
->n_name
, (vp
->v_flag
& VROOT
) != 0);
257 error
= nwfs_attr_cachelookup(vp
,va
);
258 if (!error
) return 0;
259 NCPVNDEBUG("not in cache\n");
260 oldsize
= np
->n_size
;
261 if (np
->n_flag
& NVOLUME
) {
262 error
= ncp_obtain_info(nmp
, np
->n_fid
.f_id
, 0, NULL
, &fattr
,
265 error
= ncp_obtain_info(nmp
, np
->n_fid
.f_parent
, np
->n_nmlen
,
266 np
->n_name
, &fattr
, td
, proc0
.p_ucred
);
269 NCPVNDEBUG("error %d\n", error
);
272 nwfs_attr_cacheenter(vp
, &fattr
);
275 np
->n_size
= oldsize
;
279 * nwfs_setattr call from vfs.
281 * nwfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred)
284 nwfs_setattr(struct vop_setattr_args
*ap
)
286 thread_t td
= curthread
; /* XXX */
287 struct vnode
*vp
= ap
->a_vp
;
288 struct nwnode
*np
= VTONW(vp
);
289 struct vattr
*vap
= ap
->a_vap
;
294 if (vap
->va_flags
!= VNOVAL
)
297 * Disallow write attempts if the filesystem is mounted read-only.
299 if ((vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
||
300 vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
||
301 vap
->va_mode
!= (mode_t
)VNOVAL
) &&(vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
303 if (vap
->va_size
!= VNOVAL
) {
304 switch (vp
->v_type
) {
309 * Disallow write attempts if the filesystem is
312 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
314 vnode_pager_setsize(vp
, (u_long
)vap
->va_size
);
316 np
->n_size
= vap
->va_size
;
322 error
= ncp_setattr(vp
, vap
, ap
->a_cred
, td
);
323 if (error
&& vap
->va_size
!= VNOVAL
) {
325 vnode_pager_setsize(vp
, (u_long
)tsize
);
327 np
->n_atime
= 0; /* invalidate cache */
328 VOP_GETATTR(vp
, vap
);
329 np
->n_mtime
= vap
->va_mtime
.tv_sec
;
336 * nwfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
337 * struct ucred *a_cred)
340 nwfs_read(struct vop_read_args
*ap
)
342 struct vnode
*vp
= ap
->a_vp
;
343 struct uio
*uio
=ap
->a_uio
;
345 NCPVNDEBUG("nwfs_read:\n");
347 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
)
349 error
= nwfs_readvnode(vp
, uio
, ap
->a_cred
);
354 * nwfs_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
355 * struct ucred *a_cred)
358 nwfs_write(struct vop_write_args
*ap
)
360 struct vnode
*vp
= ap
->a_vp
;
361 struct uio
*uio
= ap
->a_uio
;
364 NCPVNDEBUG("%d,ofs=%d,sz=%d\n",vp
->v_type
, (int)uio
->uio_offset
, uio
->uio_resid
);
366 if (vp
->v_type
!= VREG
)
368 error
= nwfs_writevnode(vp
, uio
, ap
->a_cred
,ap
->a_ioflag
);
373 * Create a regular file. On entry the directory to contain the file being
374 * created is locked. We must release before we return.
376 * nwfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
377 * struct componentname *a_cnpl, struct vattr *a_vap)
380 nwfs_create(struct vop_old_create_args
*ap
)
382 struct vnode
*dvp
= ap
->a_dvp
;
383 struct vattr
*vap
= ap
->a_vap
;
384 struct vnode
**vpp
=ap
->a_vpp
;
385 struct componentname
*cnp
= ap
->a_cnp
;
386 struct vnode
*vp
= NULL
;
387 int error
= 0, fmode
;
390 struct ncp_open_info no
;
391 struct nwmount
*nmp
=VTONWFS(dvp
);
397 if (vap
->va_type
== VSOCK
)
399 if ((error
= VOP_GETATTR(dvp
, &vattr
))) {
402 fmode
= AR_READ
| AR_WRITE
;
403 /* if (vap->va_vaflags & VA_EXCLUSIVE)
404 fmode |= AR_DENY_READ | AR_DENY_WRITE;*/
406 error
= ncp_open_create_file_or_subdir(nmp
,dvp
,cnp
->cn_namelen
,cnp
->cn_nameptr
,
407 OC_MODE_CREATE
| OC_MODE_OPEN
| OC_MODE_REPLACE
,
408 0, fmode
, &no
, cnp
->cn_td
, cnp
->cn_cred
);
410 error
= ncp_close_file(NWFSTOCONN(nmp
), &no
.fh
, cnp
->cn_td
,cnp
->cn_cred
);
411 fid
.f_parent
= VTONW(dvp
)->n_fid
.f_id
;
412 fid
.f_id
= no
.fattr
.dirEntNum
;
413 error
= nwfs_nget(VTOVFS(dvp
), fid
, &no
.fattr
, dvp
, &vp
);
424 * nwfs_remove call. It isn't possible to emulate UFS behaivour because
425 * NetWare doesn't allow delete/rename operations on an opened file.
427 * nwfs_remove(struct vnode *a_dvp,
428 * struct vnode *a_vp, struct componentname *a_cnp)
431 nwfs_remove(struct vop_old_remove_args
*ap
)
433 struct vnode
*vp
= ap
->a_vp
;
434 struct vnode
*dvp
= ap
->a_dvp
;
435 struct componentname
*cnp
= ap
->a_cnp
;
436 struct nwnode
*np
= VTONW(vp
);
437 struct nwmount
*nmp
= VTONWFS(vp
);
440 if (vp
->v_type
== VDIR
|| np
->opened
|| vp
->v_sysref
.refcnt
> 1) {
442 } else if (!ncp_conn_valid(NWFSTOCONN(nmp
))) {
445 error
= ncp_DeleteNSEntry(nmp
, VTONW(dvp
)->n_fid
.f_id
,
446 cnp
->cn_namelen
,cnp
->cn_nameptr
,cnp
->cn_td
,cnp
->cn_cred
);
448 np
->n_flag
|= NSHOULDFREE
;
449 else if (error
== 0x899c)
456 * nwfs_file rename call
458 * nwfs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
459 * struct componentname *a_fcnp, struct vnode *a_tdvp,
460 * struct vnode *a_tvp, struct componentname *a_tcnp)
463 nwfs_rename(struct vop_old_rename_args
*ap
)
465 struct vnode
*fvp
= ap
->a_fvp
;
466 struct vnode
*tvp
= ap
->a_tvp
;
467 struct vnode
*fdvp
= ap
->a_fdvp
;
468 struct vnode
*tdvp
= ap
->a_tdvp
;
469 struct componentname
*tcnp
= ap
->a_tcnp
;
470 struct componentname
*fcnp
= ap
->a_fcnp
;
471 struct nwmount
*nmp
=VTONWFS(fvp
);
472 u_int16_t oldtype
= 6;
475 /* Check for cross-device rename */
476 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
477 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
482 if (tvp
&& tvp
->v_sysref
.refcnt
> 1) {
486 if (tvp
&& tvp
!= fvp
) {
487 error
= ncp_DeleteNSEntry(nmp
, VTONW(tdvp
)->n_fid
.f_id
,
488 tcnp
->cn_namelen
, tcnp
->cn_nameptr
,
489 tcnp
->cn_td
, tcnp
->cn_cred
);
490 if (error
== 0x899c) error
= EACCES
;
494 if (fvp
->v_type
== VDIR
) {
495 oldtype
|= NW_TYPE_SUBDIR
;
496 } else if (fvp
->v_type
== VREG
) {
497 oldtype
|= NW_TYPE_FILE
;
500 error
= ncp_nsrename(NWFSTOCONN(nmp
), nmp
->n_volume
, nmp
->name_space
,
501 oldtype
, &nmp
->m
.nls
,
502 VTONW(fdvp
)->n_fid
.f_id
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
503 VTONW(tdvp
)->n_fid
.f_id
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
,
504 tcnp
->cn_td
,tcnp
->cn_cred
);
517 nwfs_attr_cacheremove(fdvp
);
518 nwfs_attr_cacheremove(tdvp
);
520 * Need to get rid of old vnodes, because netware will change
527 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
535 * nwfs hard link create call
536 * Netware filesystems don't know what links are.
538 * nwfs_link(struct vnode *a_tdvp, struct vnode *a_vp,
539 * struct componentname *a_cnp)
542 nwfs_link(struct vop_old_link_args
*ap
)
548 * nwfs_symlink link create call
549 * Netware filesystems don't know what symlinks are.
551 * nwfs_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
552 * struct componentname *a_cnp, struct vattr *a_vap,
556 nwfs_symlink(struct vop_old_symlink_args
*ap
)
561 static int nwfs_mknod(struct vop_old_mknod_args
*ap
)
569 * nwfs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
570 * struct componentname *a_cnp, struct vattr *a_vap)
573 nwfs_mkdir(struct vop_old_mkdir_args
*ap
)
575 struct vnode
*dvp
= ap
->a_dvp
;
576 /* struct vattr *vap = ap->a_vap;*/
577 struct componentname
*cnp
= ap
->a_cnp
;
578 int len
=cnp
->cn_namelen
;
579 struct ncp_open_info no
;
581 struct vnode
*newvp
= NULL
;
585 char *name
=cnp
->cn_nameptr
;
587 if ((error
= VOP_GETATTR(dvp
, &vattr
))) {
590 if ((name
[0] == '.') && ((len
== 1) || ((len
== 2) && (name
[1] == '.')))) {
593 if (ncp_open_create_file_or_subdir(VTONWFS(dvp
),dvp
, cnp
->cn_namelen
,
594 cnp
->cn_nameptr
,OC_MODE_CREATE
, aDIR
, 0xffff,
595 &no
, cnp
->cn_td
, cnp
->cn_cred
) != 0) {
601 fid
.f_parent
= VTONW(dvp
)->n_fid
.f_id
;
602 fid
.f_id
= no
.fattr
.dirEntNum
;
603 error
= nwfs_nget(VTOVFS(dvp
), fid
, &no
.fattr
, dvp
, &newvp
);
606 newvp
->v_type
= VDIR
;
614 * nwfs_remove directory call
616 * nwfs_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
617 * struct componentname *a_cnp)
620 nwfs_rmdir(struct vop_old_rmdir_args
*ap
)
622 struct vnode
*vp
= ap
->a_vp
;
623 struct vnode
*dvp
= ap
->a_dvp
;
624 struct componentname
*cnp
= ap
->a_cnp
;
625 struct nwnode
*np
= VTONW(vp
);
626 struct nwmount
*nmp
= VTONWFS(vp
);
627 struct nwnode
*dnp
= VTONW(dvp
);
633 error
= ncp_DeleteNSEntry(nmp
, dnp
->n_fid
.f_id
,
634 cnp
->cn_namelen
, cnp
->cn_nameptr
,cnp
->cn_td
,cnp
->cn_cred
);
636 np
->n_flag
|= NSHOULDFREE
;
637 else if (error
== NWE_DIR_NOT_EMPTY
)
639 dnp
->n_flag
|= NMODIFIED
;
640 nwfs_attr_cacheremove(dvp
);
647 * nwfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred,
648 * int *a_eofflag, off_t *a_cookies, int a_ncookies)
651 nwfs_readdir(struct vop_readdir_args
*ap
)
653 struct vnode
*vp
= ap
->a_vp
;
654 struct uio
*uio
= ap
->a_uio
;
657 if (vp
->v_type
!= VDIR
)
659 if (ap
->a_ncookies
) {
660 kprintf("nwfs_readdir: no support for cookies now...");
663 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
665 error
= nwfs_readvnode(vp
, uio
, ap
->a_cred
);
671 * nwfs_fsync(struct vnode *a_vp, int a_waitfor)
675 nwfs_fsync(struct vop_fsync_args
*ap
)
677 /* return (nfs_flush(ap->a_vp, ap->a_waitfor, curthread, 1));*/
682 * nwfs_print(struct vnode *a_vp)
686 nwfs_print(struct vop_print_args
*ap
)
688 struct vnode
*vp
= ap
->a_vp
;
689 struct nwnode
*np
= VTONW(vp
);
691 kprintf("nwfs node: name = '%s', fid = %d, pfid = %d\n",
692 np
->n_name
, np
->n_fid
.f_id
, np
->n_fid
.f_parent
);
697 * nwfs_pathconf(struct vnode *vp, int name, register_t *retval)
700 nwfs_pathconf(struct vop_pathconf_args
*ap
)
702 int name
=ap
->a_name
, error
=0;
703 register_t
*retval
=ap
->a_retval
;
710 *retval
=NCP_MAX_FILENAME
; /* XXX from nwfsnode */
713 *retval
=NCP_MAXPATHLEN
; /* XXX from nwfsnode */
722 * nwfs_strategy(struct vnode *a_vp, struct bio *a_bio)
725 nwfs_strategy(struct vop_strategy_args
*ap
)
727 struct bio
*bio
= ap
->a_bio
;
729 struct thread
*td
= NULL
;
732 if ((bio
->bio_flags
& BIO_SYNC
))
733 td
= curthread
; /* YYY dunno if this is legal */
735 * If the op is asynchronous and an i/o daemon is waiting
736 * queue the request, wake it up and wait for completion
737 * otherwise just do it ourselves.
739 if (bio
->bio_flags
& BIO_SYNC
)
740 error
= nwfs_doio(ap
->a_vp
, bio
, proc0
.p_ucred
, td
);
745 * nwfs_bmap(struct vnode *a_vp, off_t a_loffset,
746 * off_t *a_doffsetp, int *a_runp, int *a_runb)
749 nwfs_bmap(struct vop_bmap_args
*ap
)
751 if (ap
->a_doffsetp
!= NULL
)
752 *ap
->a_doffsetp
= ap
->a_loffset
;
753 if (ap
->a_runp
!= NULL
)
755 if (ap
->a_runb
!= NULL
)
761 nwfs_nget(struct mount
*mp
, ncpfid fid
, const struct nw_entry_info
*fap
,
762 struct vnode
*dvp
, struct vnode
**vpp
)
765 struct nwnode
*newnp
;
769 error
= nwfs_allocvp(mp
, fid
, &vp
);
774 newnp
->n_attr
= fap
->attributes
;
775 vp
->v_type
= newnp
->n_attr
& aDIR
? VDIR
: VREG
;
776 nwfs_attr_cacheenter(vp
, fap
);
779 newnp
->n_parent
= VTONW(dvp
)->n_fid
;
780 if ((newnp
->n_flag
& NNEW
) && vp
->v_type
== VDIR
) {
781 if ((dvp
->v_flag
& VROOT
) == 0) {
782 newnp
->n_refparent
= 1;
783 vref(dvp
); /* vhold */
787 if ((newnp
->n_flag
& NNEW
) && vp
->v_type
== VREG
)
788 kprintf("new vnode '%s' borned without parent ?\n",newnp
->n_name
);
790 newnp
->n_flag
&= ~NNEW
;
796 * How to keep the brain busy ...
797 * Currently lookup routine can make two lookup for vnode. This can be
798 * avoided by reorg the code.
800 * nwfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
801 * struct componentname *a_cnp)
804 nwfs_lookup(struct vop_old_lookup_args
*ap
)
806 struct componentname
*cnp
= ap
->a_cnp
;
807 struct vnode
*dvp
= ap
->a_dvp
;
808 struct vnode
**vpp
= ap
->a_vpp
;
809 int flags
= cnp
->cn_flags
;
812 struct mount
*mp
= dvp
->v_mount
;
813 struct nwnode
*dnp
, *npp
;
814 struct nw_entry_info fattr
, *fap
;
816 int nameiop
=cnp
->cn_nameiop
;
817 int lockparent
, wantparent
, error
= 0, notfound
;
818 struct thread
*td
= cnp
->cn_td
;
819 char _name
[cnp
->cn_namelen
+1];
820 bcopy(cnp
->cn_nameptr
,_name
,cnp
->cn_namelen
);
821 _name
[cnp
->cn_namelen
]=0;
823 if (dvp
->v_type
!= VDIR
)
825 if ((flags
& CNP_ISDOTDOT
) && (dvp
->v_flag
& VROOT
)) {
826 kprintf("nwfs_lookup: invalid '..'\n");
830 NCPVNDEBUG("%d '%s' in '%s' id=d\n", nameiop
, _name
,
831 VTONW(dvp
)->n_name
/*, VTONW(dvp)->n_name*/);
833 if ((mp
->mnt_flag
& MNT_RDONLY
) && nameiop
!= NAMEI_LOOKUP
)
835 if ((error
= VOP_EACCESS(dvp
, VEXEC
, cnp
->cn_cred
)))
837 lockparent
= flags
& CNP_LOCKPARENT
;
838 wantparent
= flags
& (CNP_LOCKPARENT
| CNP_WANTPARENT
);
842 kprintf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & CNP_ISDOTDOT);
844 error
= ncp_pathcheck(cnp
->cn_nameptr
, cnp
->cn_namelen
, &nmp
->m
.nls
,
845 (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) && (nmp
->m
.nls
.opt
& NWHP_NOSTRICT
) == 0);
852 if (flags
& CNP_ISDOTDOT
) {
853 if (NWCMPF(&dnp
->n_parent
, &nmp
->n_rootent
)) {
854 fid
= nmp
->n_rootent
;
858 error
= nwfs_lookupnp(nmp
, dnp
->n_parent
, td
, &npp
);
865 notfound
= ncp_obtain_info(nmp
, npp
->n_dosfid
,
866 0, NULL
, fap
, td
, cnp
->cn_cred
);
870 notfound
= ncp_lookup(dvp
, cnp
->cn_namelen
, cnp
->cn_nameptr
,
871 fap
, td
, cnp
->cn_cred
);
872 fid
.f_id
= fap
->dirEntNum
;
873 if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
874 fid
.f_parent
= dnp
->n_fid
.f_parent
;
876 fid
.f_parent
= dnp
->n_fid
.f_id
;
877 NCPVNDEBUG("call to ncp_lookup returned=%d\n",notfound
);
879 if (notfound
&& notfound
< 0x80 )
880 return (notfound
); /* hard error */
881 if (notfound
) { /* entry not found */
882 /* Handle RENAME or CREATE case... */
883 if ((nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) && wantparent
) {
886 return (EJUSTRETURN
);
890 NCPVNDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
892 /* handle DELETE case ... */
893 if (nameiop
== NAMEI_DELETE
) { /* delete last component */
894 error
= VOP_EACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
895 if (error
) return (error
);
896 if (NWCMPF(&dnp
->n_fid
, &fid
)) { /* we found ourselfs */
901 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
902 if (error
) return (error
);
904 if (!lockparent
) vn_unlock(dvp
);
907 if (nameiop
== NAMEI_RENAME
&& wantparent
) {
908 error
= VOP_EACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
909 if (error
) return (error
);
910 if (NWCMPF(&dnp
->n_fid
, &fid
)) return EISDIR
;
911 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
912 if (error
) return (error
);
918 if (flags
& CNP_ISDOTDOT
) {
919 vn_unlock(dvp
); /* race to get the inode */
920 error
= nwfs_nget(mp
, fid
, NULL
, NULL
, &vp
);
922 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
925 if (lockparent
&& (error
= vn_lock(dvp
, LK_EXCLUSIVE
))) {
930 } else if (NWCMPF(&dnp
->n_fid
, &fid
)) {
934 error
= nwfs_nget(mp
, fid
, fap
, dvp
, &vp
);
935 if (error
) return (error
);
937 NCPVNDEBUG("lookup: getnewvp!\n");
942 /* XXX MOVE TO NREMOVE */
943 if ((cnp
->cn_flags
& CNP_MAKEENTRY
)) {
944 VTONW(*vpp
)->n_ctime
= VTONW(*vpp
)->n_vattr
.va_ctime
.tv_sec
;