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

Cache object: 87d42686eae2f9eb5df7e5dda63f45d7


[ 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.