The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/nwfs/nwfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1999, 2000 Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    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.
   19  *
   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
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD$
   33  */
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/namei.h>
   37 #include <sys/kernel.h>
   38 #include <sys/buf.h>
   39 #include <sys/proc.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/mount.h>
   42 #include <sys/unistd.h>
   43 #include <sys/vnode.h>
   44 
   45 #include <vm/vm.h>
   46 #include <vm/vm_extern.h>
   47 #include <vm/vm_zone.h>
   48 
   49 #include <netncp/ncp.h>
   50 #include <netncp/ncp_conn.h>
   51 #include <netncp/ncp_subr.h>
   52 #include <netncp/nwerror.h>
   53 #include <netncp/ncp_nls.h>
   54 
   55 #include <nwfs/nwfs.h>
   56 #include <nwfs/nwfs_node.h>
   57 #include <nwfs/nwfs_subr.h>
   58 
   59 /*
   60  * Prototypes for NWFS vnode operations
   61  */
   62 static int nwfs_create(struct vop_create_args *);
   63 static int nwfs_mknod(struct vop_mknod_args *);
   64 static int nwfs_open(struct vop_open_args *);
   65 static int nwfs_close(struct vop_close_args *);
   66 static int nwfs_access(struct vop_access_args *);
   67 static int nwfs_getattr(struct vop_getattr_args *);
   68 static int nwfs_setattr(struct vop_setattr_args *);
   69 static int nwfs_read(struct vop_read_args *);
   70 static int nwfs_write(struct vop_write_args *);
   71 static int nwfs_fsync(struct vop_fsync_args *);
   72 static int nwfs_remove(struct vop_remove_args *);
   73 static int nwfs_link(struct vop_link_args *);
   74 static int nwfs_lookup(struct vop_lookup_args *);
   75 static int nwfs_rename(struct vop_rename_args *);
   76 static int nwfs_mkdir(struct vop_mkdir_args *);
   77 static int nwfs_rmdir(struct vop_rmdir_args *);
   78 static int nwfs_symlink(struct vop_symlink_args *);
   79 static int nwfs_readdir(struct vop_readdir_args *);
   80 static int nwfs_bmap(struct vop_bmap_args *);
   81 static int nwfs_strategy(struct vop_strategy_args *);
   82 static int nwfs_print(struct vop_print_args *);
   83 static int nwfs_pathconf(struct vop_pathconf_args *ap);
   84 
   85 /* Global vfs data structures for nwfs */
   86 vop_t **nwfs_vnodeop_p;
   87 static struct vnodeopv_entry_desc nwfs_vnodeop_entries[] = {
   88         { &vop_default_desc,            (vop_t *) vop_defaultop },
   89         { &vop_access_desc,             (vop_t *) nwfs_access },
   90         { &vop_bmap_desc,               (vop_t *) nwfs_bmap },
   91         { &vop_open_desc,               (vop_t *) nwfs_open },
   92         { &vop_close_desc,              (vop_t *) nwfs_close },
   93         { &vop_create_desc,             (vop_t *) nwfs_create },
   94         { &vop_fsync_desc,              (vop_t *) nwfs_fsync },
   95         { &vop_getattr_desc,            (vop_t *) nwfs_getattr },
   96         { &vop_getpages_desc,           (vop_t *) nwfs_getpages },
   97         { &vop_putpages_desc,           (vop_t *) nwfs_putpages },
   98         { &vop_ioctl_desc,              (vop_t *) nwfs_ioctl },
   99         { &vop_inactive_desc,           (vop_t *) nwfs_inactive },
  100         { &vop_islocked_desc,           (vop_t *) vop_stdislocked },
  101         { &vop_link_desc,               (vop_t *) nwfs_link },
  102         { &vop_lock_desc,               (vop_t *) vop_stdlock },
  103         { &vop_lookup_desc,             (vop_t *) nwfs_lookup },
  104         { &vop_mkdir_desc,              (vop_t *) nwfs_mkdir },
  105         { &vop_mknod_desc,              (vop_t *) nwfs_mknod },
  106         { &vop_pathconf_desc,           (vop_t *) nwfs_pathconf },
  107         { &vop_print_desc,              (vop_t *) nwfs_print },
  108         { &vop_read_desc,               (vop_t *) nwfs_read },
  109         { &vop_readdir_desc,            (vop_t *) nwfs_readdir },
  110         { &vop_reclaim_desc,            (vop_t *) nwfs_reclaim },
  111         { &vop_remove_desc,             (vop_t *) nwfs_remove },
  112         { &vop_rename_desc,             (vop_t *) nwfs_rename },
  113         { &vop_rmdir_desc,              (vop_t *) nwfs_rmdir },
  114         { &vop_setattr_desc,            (vop_t *) nwfs_setattr },
  115         { &vop_strategy_desc,           (vop_t *) nwfs_strategy },
  116         { &vop_symlink_desc,            (vop_t *) nwfs_symlink },
  117         { &vop_unlock_desc,             (vop_t *) vop_stdunlock },
  118         { &vop_write_desc,              (vop_t *) nwfs_write },
  119         { NULL, NULL }
  120 };
  121 static struct vnodeopv_desc nwfs_vnodeop_opv_desc =
  122         { &nwfs_vnodeop_p, nwfs_vnodeop_entries };
  123 
  124 VNODEOP_SET(nwfs_vnodeop_opv_desc);
  125 
  126 /*
  127  * nwfs_access vnode op
  128  * for now just return ok
  129  */
  130 static int
  131 nwfs_access(ap)
  132         struct vop_access_args /* {
  133                 struct vnode *a_vp;
  134                 int  a_mode;
  135                 struct ucred *a_cred;
  136                 struct proc *a_p;
  137         } */ *ap;
  138 {
  139         struct vnode *vp = ap->a_vp;
  140         struct ucred *cred = ap->a_cred;
  141         u_int mode = ap->a_mode;
  142         struct nwmount *nmp = VTONWFS(vp);
  143         int error = 0;
  144 
  145         NCPVNDEBUG("\n");
  146         if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
  147                 switch (vp->v_type) {
  148                     case VREG: case VDIR: case VLNK:
  149                         return (EROFS);
  150                     default:
  151                         break;
  152                 }
  153         }
  154         if (cred->cr_uid == 0)
  155                 return 0;
  156         if (cred->cr_uid != nmp->m.uid) {
  157                 mode >>= 3;
  158                 if (!groupmember(nmp->m.gid, cred))
  159                         mode >>= 3;
  160         }
  161         error = (((vp->v_type == VREG) ? nmp->m.file_mode : nmp->m.dir_mode) & mode) == mode ? 0 : EACCES;
  162         return error;
  163 }
  164 /*
  165  * nwfs_open vnode op
  166  */
  167 /* ARGSUSED */
  168 static int
  169 nwfs_open(ap)
  170         struct vop_open_args /* {
  171                 struct vnode *a_vp;
  172                 int  a_mode;
  173                 struct ucred *a_cred;
  174                 struct proc *a_p;
  175         } */ *ap;
  176 {
  177         struct vnode *vp = ap->a_vp;
  178         int mode = ap->a_mode;
  179         struct nwnode *np = VTONW(vp);
  180         struct ncp_open_info no;
  181         struct nwmount *nmp = VTONWFS(vp);
  182         struct vattr vattr;
  183         int error, nwm;
  184 
  185         NCPVNDEBUG("%s,%d\n",np->n_name, np->opened);
  186         if (vp->v_type != VREG && vp->v_type != VDIR) { 
  187                 NCPFATAL("open vtype = %d\n", vp->v_type);
  188                 return (EACCES);
  189         }
  190         if (vp->v_type == VDIR) return 0;       /* nothing to do now */
  191         if (np->n_flag & NMODIFIED) {
  192                 if ((error = nwfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR)
  193                         return (error);
  194                 np->n_atime = 0;
  195                 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
  196                 if (error) return (error);
  197                 np->n_mtime = vattr.va_mtime.tv_sec;
  198         } else {
  199                 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
  200                 if (error) return (error);
  201                 if (np->n_mtime != vattr.va_mtime.tv_sec) {
  202                         if ((error = nwfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR)
  203                                 return (error);
  204                         np->n_mtime = vattr.va_mtime.tv_sec;
  205                 }
  206         }
  207         if (np->opened) {
  208                 np->opened++;
  209                 return 0;
  210         }
  211         nwm = AR_READ;
  212         if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
  213                 nwm |= AR_WRITE;
  214         error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN,
  215                                                0, nwm, &no, ap->a_p, ap->a_cred);
  216         if (error) {
  217                 if (mode & FWRITE)
  218                         return EACCES;
  219                 nwm = AR_READ;
  220                 error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0,
  221                                                    nwm, &no, ap->a_p,ap->a_cred);
  222         }
  223         if (!error) {
  224                 np->opened++;
  225                 np->n_fh = no.fh;
  226                 np->n_origfh = no.origfh;
  227         }
  228         np->n_atime = 0;
  229         return (error);
  230 }
  231 
  232 static int
  233 nwfs_close(ap)
  234         struct vop_close_args /* {
  235                 struct vnodeop_desc *a_desc;
  236                 struct vnode *a_vp;
  237                 int  a_fflag;
  238                 struct ucred *a_cred;
  239                 struct proc *a_p;
  240         } */ *ap;
  241 {
  242         struct vnode *vp = ap->a_vp;
  243         struct nwnode *np = VTONW(vp);
  244         int error;
  245 
  246         NCPVNDEBUG("name=%s,pid=%d,c=%d\n",np->n_name,ap->a_p->p_pid,np->opened);
  247 
  248         if (vp->v_type == VDIR) return 0;       /* nothing to do now */
  249         error = 0;
  250         simple_lock(&vp->v_interlock);
  251         if (np->opened == 0) {
  252                 simple_unlock(&vp->v_interlock);
  253                 return 0;
  254         }
  255         simple_unlock(&vp->v_interlock);
  256         error = nwfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
  257         simple_lock(&vp->v_interlock);
  258         if (np->opened == 0) {
  259                 simple_unlock(&vp->v_interlock);
  260                 return 0;
  261         }
  262         if (--np->opened == 0) {
  263                 simple_unlock(&vp->v_interlock);
  264                 error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, 
  265                    ap->a_p, ap->a_cred);
  266         } else
  267                 simple_unlock(&vp->v_interlock);
  268         np->n_atime = 0;
  269         return (error);
  270 }
  271 
  272 /*
  273  * nwfs_getattr call from vfs.
  274  */
  275 static int
  276 nwfs_getattr(ap)
  277         struct vop_getattr_args /* {
  278                 struct vnode *a_vp;
  279                 struct vattr *a_vap;
  280                 struct ucred *a_cred;
  281                 struct proc *a_p;
  282         } */ *ap;
  283 {
  284         struct vnode *vp = ap->a_vp;
  285         struct nwnode *np = VTONW(vp);
  286         struct vattr *va=ap->a_vap;
  287         struct nwmount *nmp = VTONWFS(vp);
  288         struct nw_entry_info fattr;
  289         int error;
  290         u_int32_t oldsize;
  291 
  292         NCPVNDEBUG("%lx:%d: '%s' %d\n", (long)vp, nmp->n_volume, np->n_name, (vp->v_flag & VROOT) != 0);
  293         error = nwfs_attr_cachelookup(vp,va);
  294         if (!error) return 0;
  295         NCPVNDEBUG("not in cache\n");
  296         oldsize = np->n_size;
  297         if (np->n_flag & NVOLUME) {
  298                 error = ncp_obtain_info(nmp, np->n_fid.f_id, 0, NULL, &fattr,
  299                     ap->a_p,ap->a_cred);
  300         } else {
  301                 error = ncp_obtain_info(nmp, np->n_fid.f_parent, np->n_nmlen, 
  302                     np->n_name, &fattr, ap->a_p, ap->a_cred);
  303         }
  304         if (error) {
  305                 NCPVNDEBUG("error %d\n", error);
  306                 return error;
  307         }
  308         nwfs_attr_cacheenter(vp, &fattr);
  309         *va = np->n_vattr;
  310         if (np->opened)
  311                 np->n_size = oldsize;
  312         return (0);
  313 }
  314 /*
  315  * nwfs_setattr call from vfs.
  316  */
  317 static int
  318 nwfs_setattr(ap)
  319         struct vop_setattr_args /* {
  320                 struct vnode *a_vp;
  321                 struct vattr *a_vap;
  322                 struct ucred *a_cred;
  323                 struct proc *a_p;
  324         } */ *ap;
  325 {
  326         struct vnode *vp = ap->a_vp;
  327         struct nwnode *np = VTONW(vp);
  328         struct vattr *vap = ap->a_vap;
  329         u_quad_t tsize=0;
  330         int error = 0;
  331 
  332         NCPVNDEBUG("\n");
  333         if (vap->va_flags != VNOVAL)
  334                 return (EOPNOTSUPP);
  335         /*
  336          * Disallow write attempts if the filesystem is mounted read-only.
  337          */
  338         if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || 
  339              vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
  340              vap->va_mode != (mode_t)VNOVAL) &&(vp->v_mount->mnt_flag & MNT_RDONLY))
  341                 return (EROFS);
  342         if (vap->va_size != VNOVAL) {
  343                 switch (vp->v_type) {
  344                 case VDIR:
  345                         return (EISDIR);
  346                 case VREG:
  347                         /*
  348                          * Disallow write attempts if the filesystem is
  349                          * mounted read-only.
  350                          */
  351                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  352                                 return (EROFS);
  353                         vnode_pager_setsize(vp, (u_long)vap->va_size);
  354                         tsize = np->n_size;
  355                         np->n_size = vap->va_size;
  356                         break;
  357                 default:
  358                         return EINVAL;
  359                 };
  360         }
  361         error = ncp_setattr(vp, vap, ap->a_cred, ap->a_p);
  362         if (error && vap->va_size != VNOVAL) {
  363                 np->n_size = tsize;
  364                 vnode_pager_setsize(vp, (u_long)tsize);
  365         }
  366         np->n_atime = 0;        /* invalidate cache */
  367         VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
  368         np->n_mtime = vap->va_mtime.tv_sec;
  369         return (0);
  370 }
  371 /*
  372  * nwfs_read call.
  373  */
  374 static int
  375 nwfs_read(ap)
  376         struct vop_read_args /* {
  377                 struct vnode *a_vp;
  378                 struct uio *a_uio;
  379                 int  a_ioflag;
  380                 struct ucred *a_cred;
  381         } */ *ap;
  382 {
  383         struct vnode *vp = ap->a_vp;
  384         struct uio *uio=ap->a_uio;
  385         int error;
  386         NCPVNDEBUG("nwfs_read:\n");
  387 
  388         if (vp->v_type != VREG && vp->v_type != VDIR)
  389                 return (EPERM);
  390         error = nwfs_readvnode(vp, uio, ap->a_cred);
  391         return error;
  392 }
  393 
  394 static int
  395 nwfs_write(ap)
  396         struct vop_write_args /* {
  397                 struct vnode *a_vp;
  398                 struct uio *a_uio;
  399                 int  a_ioflag;
  400                 struct ucred *a_cred;
  401         } */ *ap;
  402 {
  403         struct vnode *vp = ap->a_vp;
  404         struct uio *uio = ap->a_uio;
  405         int error;
  406 
  407         NCPVNDEBUG("%d,ofs=%d,sz=%d\n",vp->v_type, (int)uio->uio_offset, uio->uio_resid);
  408 
  409         if (vp->v_type != VREG)
  410                 return (EPERM);
  411         error = nwfs_writevnode(vp, uio, ap->a_cred,ap->a_ioflag);
  412         return(error);
  413 }
  414 /*
  415  * nwfs_create call
  416  * Create a regular file. On entry the directory to contain the file being
  417  * created is locked.  We must release before we return. We must also free
  418  * the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or
  419  * only if the SAVESTART bit in cn_flags is clear on success.
  420  */
  421 static int
  422 nwfs_create(ap)
  423         struct vop_create_args /* {
  424                 struct vnode *a_dvp;
  425                 struct vnode **a_vpp;
  426                 struct componentname *a_cnp;
  427                 struct vattr *a_vap;
  428         } */ *ap;
  429 {
  430         struct vnode *dvp = ap->a_dvp;
  431         struct vattr *vap = ap->a_vap;
  432         struct vnode **vpp=ap->a_vpp;
  433         struct componentname *cnp = ap->a_cnp;
  434         struct vnode *vp = (struct vnode *)0;
  435         int error = 0, fmode;
  436         struct vattr vattr;
  437         struct nwnode *np;
  438         struct ncp_open_info no;
  439         struct nwmount *nmp=VTONWFS(dvp);
  440         ncpfid fid;
  441         
  442 
  443         NCPVNDEBUG("\n");
  444         *vpp = NULL;
  445         if (vap->va_type == VSOCK)
  446                 return (EOPNOTSUPP);
  447         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc))) {
  448                 return (error);
  449         }
  450         fmode = AR_READ | AR_WRITE;
  451 /*      if (vap->va_vaflags & VA_EXCLUSIVE)
  452                 fmode |= AR_DENY_READ | AR_DENY_WRITE;*/
  453         
  454         error = ncp_open_create_file_or_subdir(nmp,dvp,cnp->cn_namelen,cnp->cn_nameptr, 
  455                            OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
  456                            0, fmode, &no, cnp->cn_proc, cnp->cn_cred);
  457         if (!error) {
  458                 error = ncp_close_file(NWFSTOCONN(nmp), &no.fh, cnp->cn_proc,cnp->cn_cred);
  459                 fid.f_parent = VTONW(dvp)->n_fid.f_id;
  460                 fid.f_id = no.fattr.dirEntNum;
  461                 error = nwfs_nget(VTOVFS(dvp), fid, &no.fattr, dvp, &vp);
  462                 if (!error) {
  463                         np = VTONW(vp);
  464                         np->opened = 0;
  465                         *vpp = vp;
  466                 }
  467                 if (cnp->cn_flags & MAKEENTRY)
  468                         cache_enter(dvp, vp, cnp);
  469         }
  470         return (error);
  471 }
  472 
  473 /*
  474  * nwfs_remove call. It isn't possible to emulate UFS behaivour because
  475  * NetWare doesn't allow delete/rename operations on an opened file.
  476  */
  477 static int
  478 nwfs_remove(ap)
  479         struct vop_remove_args /* {
  480                 struct vnodeop_desc *a_desc;
  481                 struct vnode * a_dvp;
  482                 struct vnode * a_vp;
  483                 struct componentname * a_cnp;
  484         } */ *ap;
  485 {
  486         struct vnode *vp = ap->a_vp;
  487         struct vnode *dvp = ap->a_dvp;
  488         struct componentname *cnp = ap->a_cnp;
  489         struct nwnode *np = VTONW(vp);
  490         struct nwmount *nmp = VTONWFS(vp);
  491         int error;
  492 
  493         if (vp->v_type == VDIR || np->opened || vp->v_usecount != 1) {
  494                 error = EPERM;
  495         } else if (!ncp_conn_valid(NWFSTOCONN(nmp))) {
  496                 error = EIO;
  497         } else {
  498                 cache_purge(vp);
  499                 error = ncp_DeleteNSEntry(nmp, VTONW(dvp)->n_fid.f_id,
  500                     cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred);
  501                 if (error == 0)
  502                         np->n_flag |= NSHOULDFREE;
  503                 else if (error == 0x899c)
  504                         error = EACCES;
  505         }
  506         return (error);
  507 }
  508 
  509 /*
  510  * nwfs_file rename call
  511  */
  512 static int
  513 nwfs_rename(ap)
  514         struct vop_rename_args  /* {
  515                 struct vnode *a_fdvp;
  516                 struct vnode *a_fvp;
  517                 struct componentname *a_fcnp;
  518                 struct vnode *a_tdvp;
  519                 struct vnode *a_tvp;
  520                 struct componentname *a_tcnp;
  521         } */ *ap;
  522 {
  523         struct vnode *fvp = ap->a_fvp;
  524         struct vnode *tvp = ap->a_tvp;
  525         struct vnode *fdvp = ap->a_fdvp;
  526         struct vnode *tdvp = ap->a_tdvp;
  527         struct componentname *tcnp = ap->a_tcnp;
  528         struct componentname *fcnp = ap->a_fcnp;
  529         struct nwmount *nmp=VTONWFS(fvp);
  530         u_int16_t oldtype = 6;
  531         int error=0;
  532 
  533         /* Check for cross-device rename */
  534         if ((fvp->v_mount != tdvp->v_mount) ||
  535             (tvp && (fvp->v_mount != tvp->v_mount))) {
  536                 error = EXDEV;
  537                 goto out;
  538         }
  539 
  540         if (tvp && tvp->v_usecount > 1) {
  541                 error = EBUSY;
  542                 goto out;
  543         }
  544         if (tvp && tvp != fvp) {
  545                 error = ncp_DeleteNSEntry(nmp, VTONW(tdvp)->n_fid.f_id,
  546                     tcnp->cn_namelen, tcnp->cn_nameptr, 
  547                     tcnp->cn_proc, tcnp->cn_cred);
  548                 if (error == 0x899c) error = EACCES;
  549                 if (error)
  550                         goto out;
  551         }
  552         if (fvp->v_type == VDIR) {
  553                 oldtype |= NW_TYPE_SUBDIR;
  554         } else if (fvp->v_type == VREG) {
  555                 oldtype |= NW_TYPE_FILE;
  556         } else
  557                 return EINVAL;
  558         error = ncp_nsrename(NWFSTOCONN(nmp), nmp->n_volume, nmp->name_space, 
  559                 oldtype, &nmp->m.nls,
  560                 VTONW(fdvp)->n_fid.f_id, fcnp->cn_nameptr, fcnp->cn_namelen,
  561                 VTONW(tdvp)->n_fid.f_id, tcnp->cn_nameptr, tcnp->cn_namelen,
  562                 tcnp->cn_proc,tcnp->cn_cred);
  563 
  564         if (error == 0x8992)
  565                 error = EEXIST;
  566         if (fvp->v_type == VDIR) {
  567                 if (tvp != NULL && tvp->v_type == VDIR)
  568                         cache_purge(tdvp);
  569                 cache_purge(fdvp);
  570         }
  571 out:
  572         if (tdvp == tvp)
  573                 vrele(tdvp);
  574         else
  575                 vput(tdvp);
  576         if (tvp)
  577                 vput(tvp);
  578         vrele(fdvp);
  579         vrele(fvp);
  580         nwfs_attr_cacheremove(fdvp);
  581         nwfs_attr_cacheremove(tdvp);
  582         /*
  583          * Need to get rid of old vnodes, because netware will change
  584          * file id on rename
  585          */
  586         vgone(fvp);
  587         if (tvp)
  588                 vgone(tvp);
  589         /*
  590          * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
  591          */
  592         if (error == ENOENT)
  593                 error = 0;
  594         return (error);
  595 }
  596 
  597 /*
  598  * nwfs hard link create call
  599  * Netware filesystems don't know what links are.
  600  */
  601 static int
  602 nwfs_link(ap)
  603         struct vop_link_args /* {
  604                 struct vnode *a_tdvp;
  605                 struct vnode *a_vp;
  606                 struct componentname *a_cnp;
  607         } */ *ap;
  608 {
  609         return EOPNOTSUPP;
  610 }
  611 
  612 /*
  613  * nwfs_symlink link create call
  614  * Netware filesystems don't know what symlinks are.
  615  */
  616 static int
  617 nwfs_symlink(ap)
  618         struct vop_symlink_args /* {
  619                 struct vnode *a_dvp;
  620                 struct vnode **a_vpp;
  621                 struct componentname *a_cnp;
  622                 struct vattr *a_vap;
  623                 char *a_target;
  624         } */ *ap;
  625 {
  626         return (EOPNOTSUPP);
  627 }
  628 
  629 static int nwfs_mknod(ap) 
  630         struct vop_mknod_args /* {
  631         } */ *ap;
  632 {
  633         return (EOPNOTSUPP);
  634 }
  635 
  636 /*
  637  * nwfs_mkdir call
  638  */
  639 static int
  640 nwfs_mkdir(ap)
  641         struct vop_mkdir_args /* {
  642                 struct vnode *a_dvp;
  643                 struct vnode **a_vpp;
  644                 struct componentname *a_cnp;
  645                 struct vattr *a_vap;
  646         } */ *ap;
  647 {
  648         struct vnode *dvp = ap->a_dvp;
  649 /*      struct vattr *vap = ap->a_vap;*/
  650         struct componentname *cnp = ap->a_cnp;
  651         int len=cnp->cn_namelen;
  652         struct ncp_open_info no;
  653         struct nwnode *np;
  654         struct vnode *newvp = (struct vnode *)0;
  655         ncpfid fid;
  656         int error = 0;
  657         struct vattr vattr;
  658         char *name=cnp->cn_nameptr;
  659 
  660         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc))) {
  661                 return (error);
  662         }       
  663         if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.')))) {
  664                 return EEXIST;
  665         }
  666         if (ncp_open_create_file_or_subdir(VTONWFS(dvp),dvp, cnp->cn_namelen,
  667                         cnp->cn_nameptr,OC_MODE_CREATE, aDIR, 0xffff,
  668                         &no, cnp->cn_proc, cnp->cn_cred) != 0) {
  669                 error = EACCES;
  670         } else {
  671                 error = 0;
  672         }
  673         if (!error) {
  674                 fid.f_parent = VTONW(dvp)->n_fid.f_id;
  675                 fid.f_id = no.fattr.dirEntNum;
  676                 error = nwfs_nget(VTOVFS(dvp), fid, &no.fattr, dvp, &newvp);
  677                 if (!error) {
  678                         np = VTONW(newvp);
  679                         newvp->v_type = VDIR;
  680                         *ap->a_vpp = newvp;
  681                 }
  682         }
  683         return (error);
  684 }
  685 
  686 /*
  687  * nwfs_remove directory call
  688  */
  689 static int
  690 nwfs_rmdir(ap)
  691         struct vop_rmdir_args /* {
  692                 struct vnode *a_dvp;
  693                 struct vnode *a_vp;
  694                 struct componentname *a_cnp;
  695         } */ *ap;
  696 {
  697         struct vnode *vp = ap->a_vp;
  698         struct vnode *dvp = ap->a_dvp;
  699         struct componentname *cnp = ap->a_cnp;
  700         struct nwnode *np = VTONW(vp);
  701         struct nwmount *nmp = VTONWFS(vp);
  702         struct nwnode *dnp = VTONW(dvp);
  703         int error = EIO;
  704 
  705         if (dvp == vp)
  706                 return EINVAL;
  707 
  708         error = ncp_DeleteNSEntry(nmp, dnp->n_fid.f_id, 
  709                 cnp->cn_namelen, cnp->cn_nameptr,cnp->cn_proc,cnp->cn_cred);
  710         if (error == 0)
  711                 np->n_flag |= NSHOULDFREE;
  712         else if (error == NWE_DIR_NOT_EMPTY)
  713                 error = ENOTEMPTY;
  714         dnp->n_flag |= NMODIFIED;
  715         nwfs_attr_cacheremove(dvp);
  716         cache_purge(dvp);
  717         cache_purge(vp);
  718         return (error);
  719 }
  720 
  721 /*
  722  * nwfs_readdir call
  723  */
  724 static int
  725 nwfs_readdir(ap)
  726         struct vop_readdir_args /* {
  727                 struct vnode *a_vp;
  728                 struct uio *a_uio;
  729                 struct ucred *a_cred;
  730                 int *a_eofflag;
  731                 u_long *a_cookies;
  732                 int a_ncookies;
  733         } */ *ap;
  734 {
  735         struct vnode *vp = ap->a_vp;
  736         struct uio *uio = ap->a_uio;
  737         int error;
  738 
  739         if (vp->v_type != VDIR)
  740                 return (EPERM);
  741         if (ap->a_ncookies) {
  742                 printf("nwfs_readdir: no support for cookies now...");
  743                 return (EOPNOTSUPP);
  744         }
  745 
  746         error = nwfs_readvnode(vp, uio, ap->a_cred);
  747         return error;
  748 }
  749 /* ARGSUSED */
  750 static int
  751 nwfs_fsync(ap)
  752         struct vop_fsync_args /* {
  753                 struct vnodeop_desc *a_desc;
  754                 struct vnode * a_vp;
  755                 struct ucred * a_cred;
  756                 int  a_waitfor;
  757                 struct proc * a_p;
  758         } */ *ap;
  759 {
  760 /*      return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));*/
  761     return (0);
  762 }
  763 
  764 /* ARGSUSED */
  765 static 
  766 int nwfs_print (ap) 
  767         struct vop_print_args /* {
  768                 struct vnode *a_vp;
  769         } */ *ap;
  770 {
  771         struct vnode *vp = ap->a_vp;
  772         struct nwnode *np = VTONW(vp);
  773 
  774         printf("nwfs node: name = '%s', fid = %d, pfid = %d\n",
  775             np->n_name, np->n_fid.f_id, np->n_fid.f_parent);
  776         return (0);
  777 }
  778 
  779 static int nwfs_pathconf (ap)
  780         struct vop_pathconf_args  /* {
  781         struct vnode *vp;
  782         int name;
  783         register_t *retval;
  784         } */ *ap;
  785 {
  786         int name=ap->a_name, error=0;
  787         register_t *retval=ap->a_retval;
  788         
  789         switch(name){
  790                 case _PC_LINK_MAX:
  791                         *retval=0;
  792                         break;
  793                 case _PC_NAME_MAX:
  794                         *retval=NCP_MAX_FILENAME; /* XXX from nwfsnode */
  795                         break;
  796                 case _PC_PATH_MAX:
  797                         *retval=NCP_MAXPATHLEN; /* XXX from nwfsnode */
  798                         break;
  799                 default:
  800                         error=EINVAL;
  801         }
  802         return(error);
  803 }
  804 
  805 static int nwfs_strategy (ap) 
  806         struct vop_strategy_args /* {
  807         struct buf *a_bp
  808         } */ *ap;
  809 {
  810         struct buf *bp=ap->a_bp;
  811         struct ucred *cr;
  812         struct proc *p;
  813         int error = 0;
  814 
  815         NCPVNDEBUG("\n");
  816         if (bp->b_flags & B_PHYS)
  817                 panic("nwfs physio");
  818         if (bp->b_flags & B_ASYNC)
  819                 p = (struct proc *)0;
  820         else
  821                 p = curproc;    /* XXX */
  822         if (bp->b_flags & B_READ)
  823                 cr = bp->b_rcred;
  824         else
  825                 cr = bp->b_wcred;
  826         /*
  827          * If the op is asynchronous and an i/o daemon is waiting
  828          * queue the request, wake it up and wait for completion
  829          * otherwise just do it ourselves.
  830          */
  831         if ((bp->b_flags & B_ASYNC) == 0 )
  832                 error = nwfs_doio(bp, cr, p);
  833         return (error);
  834 }
  835 
  836 static int
  837 nwfs_bmap(ap)
  838         struct vop_bmap_args /* {
  839                 struct vnode *a_vp;
  840                 daddr_t  a_bn;
  841                 struct vnode **a_vpp;
  842                 daddr_t *a_bnp;
  843                 int *a_runp;
  844                 int *a_runb;
  845         } */ *ap;
  846 {
  847         struct vnode *vp = ap->a_vp;
  848 
  849         if (ap->a_vpp != NULL)
  850                 *ap->a_vpp = vp;
  851         if (ap->a_bnp != NULL)
  852                 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
  853         if (ap->a_runp != NULL)
  854                 *ap->a_runp = 0;
  855         if (ap->a_runb != NULL)
  856                 *ap->a_runb = 0;
  857         return (0);
  858 }
  859 
  860 int
  861 nwfs_nget(struct mount *mp, ncpfid fid, struct nw_entry_info *fap,
  862           struct vnode *dvp, struct vnode **vpp)
  863 {
  864         int error;
  865         struct nwnode *newnp;
  866         struct vnode *vp;
  867 
  868         *vpp = NULL;
  869         error = nwfs_allocvp(mp, fid, &vp);
  870         if (error)
  871                 return error;
  872         newnp = VTONW(vp);
  873         if (fap) {
  874                 newnp->n_attr = fap->attributes;
  875                 vp->v_type = newnp->n_attr & aDIR ? VDIR : VREG;
  876                 nwfs_attr_cacheenter(vp, fap);
  877         }
  878         if (dvp) {
  879                 newnp->n_parent = VTONW(dvp)->n_fid;
  880                 if ((newnp->n_flag & NNEW) && vp->v_type == VDIR) {
  881                         if ((dvp->v_flag & VROOT) == 0) {
  882                                 newnp->n_refparent = 1;
  883                                 vref(dvp);      /* vhold */
  884                         }
  885                 }
  886         } else {
  887                 if ((newnp->n_flag & NNEW) && vp->v_type == VREG)
  888                         printf("new vnode '%s' borned without parent ?\n",newnp->n_name);
  889         }
  890         newnp->n_flag &= ~NNEW;
  891         *vpp = vp;
  892         return 0;
  893 }
  894 
  895 /*
  896  * How to keep the brain busy ...
  897  * Currently lookup routine can make two lookup for vnode. This can be
  898  * avoided by reorg the code.
  899  */
  900 int
  901 nwfs_lookup(ap)
  902         struct vop_lookup_args /* {
  903                 struct vnodeop_desc *a_desc;
  904                 struct vnode *a_dvp;
  905                 struct vnode **a_vpp;
  906                 struct componentname *a_cnp;
  907         } */ *ap;
  908 {
  909         struct componentname *cnp = ap->a_cnp;
  910         struct vnode *dvp = ap->a_dvp;
  911         struct vnode **vpp = ap->a_vpp;
  912         int flags = cnp->cn_flags;
  913         struct vnode *vp;
  914         struct nwmount *nmp;
  915         struct mount *mp = dvp->v_mount;
  916         struct nwnode *dnp, *npp;
  917         struct nw_entry_info fattr, *fap;
  918         ncpfid fid;
  919         int nameiop=cnp->cn_nameiop, islastcn;
  920         int lockparent, wantparent, error = 0, notfound;
  921         struct proc *p = cnp->cn_proc;
  922         char _name[cnp->cn_namelen+1];
  923         bcopy(cnp->cn_nameptr,_name,cnp->cn_namelen);
  924         _name[cnp->cn_namelen]=0;
  925         
  926         if (dvp->v_type != VDIR)
  927                 return (ENOTDIR);
  928         if ((flags & ISDOTDOT) && (dvp->v_flag & VROOT)) {
  929                 printf("nwfs_lookup: invalid '..'\n");
  930                 return EIO;
  931         }
  932 
  933         NCPVNDEBUG("%d '%s' in '%s' id=d\n", nameiop, _name, 
  934                 VTONW(dvp)->n_name/*, VTONW(dvp)->n_name*/);
  935 
  936         islastcn = flags & ISLASTCN;
  937         if (islastcn && (mp->mnt_flag & MNT_RDONLY) && (nameiop != LOOKUP))
  938                 return (EROFS);
  939         if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)))
  940                 return (error);
  941         lockparent = flags & LOCKPARENT;
  942         wantparent = flags & (LOCKPARENT|WANTPARENT);
  943         nmp = VFSTONWFS(mp);
  944         dnp = VTONW(dvp);
  945 /*
  946 printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_flag & VROOT, (int)flags & ISDOTDOT);
  947 */
  948         error = ncp_pathcheck(cnp->cn_nameptr, cnp->cn_namelen, &nmp->m.nls, 
  949             (nameiop == CREATE || nameiop == RENAME) && (nmp->m.nls.opt & NWHP_NOSTRICT) == 0);
  950         if (error) 
  951             return ENOENT;
  952 
  953         error = cache_lookup(dvp, vpp, cnp);
  954         NCPVNDEBUG("cache_lookup returned %d\n",error);
  955         if (error > 0)
  956                 return error;
  957         if (error) {            /* name was found */
  958                 struct vattr vattr;
  959                 int vpid;
  960 
  961                 vp = *vpp;
  962                 vpid = vp->v_id;
  963                 if (dvp == vp) {        /* lookup on current */
  964                         vref(vp);
  965                         error = 0;
  966                         NCPVNDEBUG("cached '.'");
  967                 } else if (flags & ISDOTDOT) {
  968                         VOP_UNLOCK(dvp, 0, p);  /* unlock parent */
  969                         error = vget(vp, LK_EXCLUSIVE, p);
  970                         if (!error && lockparent && islastcn)
  971                                 error = vn_lock(dvp, LK_EXCLUSIVE, p);
  972                 } else {
  973                         error = vget(vp, LK_EXCLUSIVE, p);
  974                         if (!lockparent || error || !islastcn)
  975                                 VOP_UNLOCK(dvp, 0, p);
  976                 }
  977                 if (!error) {
  978                         if (vpid == vp->v_id) {
  979                            if (!VOP_GETATTR(vp, &vattr, cnp->cn_cred, p)
  980                             && vattr.va_ctime.tv_sec == VTONW(vp)->n_ctime) {
  981                                 if (nameiop != LOOKUP && islastcn)
  982                                         cnp->cn_flags |= SAVENAME;
  983                                 NCPVNDEBUG("use cached vnode");
  984                                 return (0);
  985                            }
  986                            cache_purge(vp);
  987                         }
  988                         vput(vp);
  989                         if (lockparent && dvp != vp && islastcn)
  990                                 VOP_UNLOCK(dvp, 0, p);
  991                 }
  992                 error = vn_lock(dvp, LK_EXCLUSIVE, p);
  993                 *vpp = NULLVP;
  994                 if (error)
  995                         return (error);
  996         }
  997         /* not in cache, so ...  */
  998         error = 0;
  999         *vpp = NULLVP;
 1000         fap = NULL;
 1001         if (flags & ISDOTDOT) {
 1002                 if (NWCMPF(&dnp->n_parent, &nmp->n_rootent)) {
 1003                         fid = nmp->n_rootent;
 1004                         fap = NULL;
 1005                         notfound = 0;
 1006                 } else {
 1007                         error = nwfs_lookupnp(nmp, dnp->n_parent, p, &npp);
 1008                         if (error) {
 1009                                 return error;
 1010                         }
 1011                         fid = dnp->n_parent;
 1012                         fap = &fattr;
 1013                         /*np = *npp;*/
 1014                         notfound = ncp_obtain_info(nmp, npp->n_dosfid,
 1015                             0, NULL, fap, p, cnp->cn_cred);
 1016                 }
 1017         } else {
 1018                 fap = &fattr;
 1019                 notfound = ncp_lookup(dvp, cnp->cn_namelen, cnp->cn_nameptr,
 1020                         fap, p, cnp->cn_cred);
 1021                 fid.f_id = fap->dirEntNum;
 1022                 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
 1023                         fid.f_parent = dnp->n_fid.f_parent;
 1024                 } else
 1025                         fid.f_parent = dnp->n_fid.f_id;
 1026                 NCPVNDEBUG("call to ncp_lookup returned=%d\n",notfound);
 1027         }
 1028         if (notfound && notfound < 0x80 )
 1029                 return (notfound);      /* hard error */
 1030         if (notfound) { /* entry not found */
 1031                 /* Handle RENAME or CREATE case... */
 1032                 if ((nameiop == CREATE || nameiop == RENAME) && wantparent && islastcn) {
 1033                         cnp->cn_flags |= SAVENAME;
 1034                         if (!lockparent)
 1035                                 VOP_UNLOCK(dvp, 0, p);
 1036                         return (EJUSTRETURN);
 1037                 }
 1038                 return ENOENT;
 1039         }/* else {
 1040                 NCPVNDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
 1041         }*/
 1042         /* handle DELETE case ... */
 1043         if (nameiop == DELETE && islastcn) {    /* delete last component */
 1044                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, cnp->cn_proc);
 1045                 if (error) return (error);
 1046                 if (NWCMPF(&dnp->n_fid, &fid)) {        /* we found ourselfs */
 1047                         VREF(dvp);
 1048                         *vpp = dvp;
 1049                         return 0;
 1050                 }
 1051                 error = nwfs_nget(mp, fid, fap, dvp, &vp);
 1052                 if (error) return (error);
 1053                 *vpp = vp;
 1054                 cnp->cn_flags |= SAVENAME;      /* I free it later */
 1055                 if (!lockparent) VOP_UNLOCK(dvp,0,p);
 1056                 return (0);
 1057         }
 1058         if (nameiop == RENAME && islastcn && wantparent) {
 1059                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, cnp->cn_proc);
 1060                 if (error) return (error);
 1061                 if (NWCMPF(&dnp->n_fid, &fid)) return EISDIR;
 1062                 error = nwfs_nget(mp, fid, fap, dvp, &vp);
 1063                 if (error) return (error);
 1064                 *vpp = vp;
 1065                 cnp->cn_flags |= SAVENAME;
 1066                 if (!lockparent)
 1067                         VOP_UNLOCK(dvp,0,p);
 1068                 return (0);
 1069         }
 1070         if (flags & ISDOTDOT) {
 1071                 VOP_UNLOCK(dvp, 0, p);          /* race to get the inode */
 1072                 error = nwfs_nget(mp, fid, NULL, NULL, &vp);
 1073                 if (error) {
 1074                         vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
 1075                         return (error);
 1076                 }
 1077                 if (lockparent && islastcn &&
 1078                     (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
 1079                         vput(vp);
 1080                         return (error);
 1081                 }
 1082                 *vpp = vp;
 1083         } else if (NWCMPF(&dnp->n_fid, &fid)) {
 1084                 vref(dvp);
 1085                 *vpp = dvp;
 1086         } else {
 1087                 error = nwfs_nget(mp, fid, fap, dvp, &vp);
 1088                 if (error) return (error);
 1089                 *vpp = vp;
 1090                 NCPVNDEBUG("lookup: getnewvp!\n");
 1091                 if (!lockparent || !islastcn)
 1092                         VOP_UNLOCK(dvp, 0, p);
 1093         }
 1094         if ((cnp->cn_flags & MAKEENTRY)/* && !islastcn*/) {
 1095                 VTONW(*vpp)->n_ctime = VTONW(*vpp)->n_vattr.va_ctime.tv_sec;
 1096                 cache_enter(dvp, *vpp, cnp);
 1097         }
 1098         return (0);
 1099 }

Cache object: b8fb96571d5157192549c6652c33858c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.