BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / nfs / nfs_subs.c
index bcc32ef..f015f74 100644 (file)
@@ -5,9 +5,35 @@
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)nfs_subs.c  7.39 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nfs_subs.c  7.41 (Berkeley) 5/15/91
  */
 
 /*
  */
 
 /*
@@ -660,9 +686,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
        vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
        if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
                np->n_size = vap->va_size;
        vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
        if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
                np->n_size = vap->va_size;
-#ifdef NVM
                vnode_pager_setsize(vp, np->n_size);
                vnode_pager_setsize(vp, np->n_size);
-#endif
        }
        vap->va_size_rsv = 0;
        vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
        }
        vap->va_size_rsv = 0;
        vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
@@ -706,9 +730,7 @@ nfs_getattrcache(vp, vap)
                bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
                if ((np->n_flag & NMODIFIED) == 0) {
                        np->n_size = vap->va_size;
                bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
                if ((np->n_flag & NMODIFIED) == 0) {
                        np->n_size = vap->va_size;
-#ifdef NVM
                        vnode_pager_setsize(vp, np->n_size);
                        vnode_pager_setsize(vp, np->n_size);
-#endif
                } else if (np->n_size > vap->va_size)
                        vap->va_size = np->n_size;
                return (0);
                } else if (np->n_size > vap->va_size)
                        vap->va_size = np->n_size;
                return (0);
@@ -721,84 +743,106 @@ nfs_getattrcache(vp, vap)
 /*
  * Set up nameidata for a namei() call and do it
  */
 /*
  * Set up nameidata for a namei() call and do it
  */
-nfs_namei(ndp, fhp, len, mdp, dposp)
+nfs_namei(ndp, fhp, len, mdp, dposp, p)
        register struct nameidata *ndp;
        fhandle_t *fhp;
        int len;
        struct mbuf **mdp;
        caddr_t *dposp;
        register struct nameidata *ndp;
        fhandle_t *fhp;
        int len;
        struct mbuf **mdp;
        caddr_t *dposp;
+       struct proc *p;
 {
        register int i, rem;
        register struct mbuf *md;
 {
        register int i, rem;
        register struct mbuf *md;
-       register char *cp;
+       register char *fromcp, *tocp;
        struct vnode *dp;
        int flag;
        int error;
 
        struct vnode *dp;
        int flag;
        int error;
 
-       if ((ndp->ni_nameiop & HASBUF) == 0) {
-               flag = ndp->ni_nameiop & OPMASK;
-               /*
-                * Copy the name from the mbuf list to the d_name field of ndp
-                * and set the various ndp fields appropriately.
-                */
-               cp = *dposp;
-               md = *mdp;
-               rem = mtod(md, caddr_t)+md->m_len-cp;
-               ndp->ni_hash = 0;
-               for (i = 0; i < len;) {
-                       while (rem == 0) {
-                               md = md->m_next;
-                               if (md == NULL)
-                                       return (EBADRPC);
-                               cp = mtod(md, caddr_t);
-                               rem = md->m_len;
+       flag = ndp->ni_nameiop & OPMASK;
+       MALLOC(ndp->ni_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
+       /*
+        * Copy the name from the mbuf list to ndp->ni_pnbuf
+        * and set the various ndp fields appropriately.
+        */
+       fromcp = *dposp;
+       tocp = ndp->ni_pnbuf;
+       md = *mdp;
+       rem = mtod(md, caddr_t) + md->m_len - fromcp;
+       ndp->ni_hash = 0;
+       for (i = 0; i < len; i++) {
+               while (rem == 0) {
+                       md = md->m_next;
+                       if (md == NULL) {
+                               error = EBADRPC;
+                               goto out;
                        }
                        }
-                       if (*cp == '\0' || *cp == '/')
-                               return (EINVAL);
-                       if (*cp & 0200)
-                               if ((*cp&0377) == ('/'|0200) || flag != DELETE)
-                                       return (EINVAL);
-                       ndp->ni_dent.d_name[i++] = *cp;
-                       ndp->ni_hash += (unsigned char)*cp * i;
-                       cp++;
-                       rem--;
+                       fromcp = mtod(md, caddr_t);
+                       rem = md->m_len;
                }
                }
-               *mdp = md;
-               *dposp = cp;
-               len = nfsm_rndup(len)-len;
-               if (len > 0) {
-                       if (rem < len) {
-                               if (error = nfs_adv(mdp, dposp, len, rem))
-                                       return (error);
-                       } else
-                               *dposp += len;
+               if (*fromcp == '\0' || *fromcp == '/') {
+                       error = EINVAL;
+                       goto out;
                }
                }
-       } else
-               i = len;
-       ndp->ni_namelen = i;
-       ndp->ni_dent.d_namlen = i;
-       ndp->ni_dent.d_name[i] = '\0';
-       ndp->ni_segflg = UIO_SYSSPACE;
-       ndp->ni_pathlen = 1;
-       ndp->ni_pnbuf = ndp->ni_dirp = ndp->ni_ptr = &ndp->ni_dent.d_name[0];
-       ndp->ni_next = &ndp->ni_dent.d_name[i];
-       ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE | HASBUF | STARTDIR);
+               if (*fromcp & 0200)
+                       if ((*fromcp&0377) == ('/'|0200) || flag != DELETE) {
+                               error = EINVAL;
+                               goto out;
+                       }
+               ndp->ni_hash += (unsigned char)*fromcp;
+               *tocp++ = *fromcp++;
+               rem--;
+       }
+       *tocp = '\0';
+       *mdp = md;
+       *dposp = fromcp;
+       len = nfsm_rndup(len)-len;
+       if (len > 0) {
+               if (rem >= len)
+                       *dposp += len;
+               else if (error = nfs_adv(mdp, dposp, len, rem))
+                       goto out;
+       }
+       ndp->ni_pathlen = tocp - ndp->ni_pnbuf;
+       ndp->ni_ptr = ndp->ni_pnbuf;
        /*
         * Extract and set starting directory.
         */
        if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
        /*
         * Extract and set starting directory.
         */
        if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
-               return (error);
+               goto out;
        if (dp->v_type != VDIR) {
                vrele(dp);
        if (dp->v_type != VDIR) {
                vrele(dp);
-               return (ENOTDIR);
+               error = ENOTDIR;
+               goto out;
        }
        ndp->ni_startdir = dp;
        }
        ndp->ni_startdir = dp;
+       ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE);
        /*
        /*
-        * And call namei() to do the real work
+        * And call lookup() to do the real work
         */
         */
-       error = namei(ndp, curproc);            /* XXX XXX XXX */
-       if (error || (ndp->ni_nameiop & SAVESTARTDIR) == 0)
-               vrele(dp);
+       if (error = lookup(ndp, p))
+               goto out;
+       /*
+        * Check for encountering a symbolic link
+        */
+       if (ndp->ni_more) {
+               if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
+                       vput(ndp->ni_dvp);
+               else
+                       vrele(ndp->ni_dvp);
+               vput(ndp->ni_vp);
+               ndp->ni_vp = NULL;
+               error = EINVAL;
+               goto out;
+       }
+       /*
+        * Check for saved name request
+        */
+       if (ndp->ni_nameiop & (SAVENAME | SAVESTART)) {
+               ndp->ni_nameiop |= HASBUF;
+               return (0);
+       }
+out:
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        return (error);
 }
 
        return (error);
 }