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

Cache object: c362469d6d82be5435803255f5a700d6


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