[BACK]Return to vfs_lookup.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/vfs_lookup.c between version 1.133 and 1.134

version 1.133, 2011/04/11 01:33:04 version 1.134, 2011/04/11 01:35:00
Line 591  namei_ktrace(struct namei_state *state)
Line 591  namei_ktrace(struct namei_state *state)
  * appropriate.   * appropriate.
  */   */
 static int  static int
 namei_start(struct namei_state *state, int isnfsd, struct vnode *forcecwd)  namei_start(struct namei_state *state, struct vnode *forcecwd)
 {  {
         struct nameidata *ndp = state->ndp;          struct nameidata *ndp = state->ndp;
   
Line 609  namei_start(struct namei_state *state, i
Line 609  namei_start(struct namei_state *state, i
         ndp->ni_loopcnt = 0;          ndp->ni_loopcnt = 0;
   
         /* Get starting directory, set up root, and ktrace. */          /* Get starting directory, set up root, and ktrace. */
         if (isnfsd) {          if (forcecwd != NULL) {
                 state->namei_startdir = namei_getstartdir_for_nfsd(state,                  state->namei_startdir = namei_getstartdir_for_nfsd(state,
                                                                    forcecwd);                                                                     forcecwd);
                 /* no ktrace */                  /* no ktrace */
Line 645  namei_atsymlink(struct namei_state *stat
Line 645  namei_atsymlink(struct namei_state *stat
  * Follow a symlink.   * Follow a symlink.
  */   */
 static inline int  static inline int
 namei_follow(struct namei_state *state)  namei_follow(struct namei_state *state, int inhibitmagic)
 {  {
         struct nameidata *ndp = state->ndp;          struct nameidata *ndp = state->ndp;
         struct componentname *cnp = state->cnp;          struct componentname *cnp = state->cnp;
Line 690  namei_follow(struct namei_state *state)
Line 690  namei_follow(struct namei_state *state)
         /*          /*
          * Do symlink substitution, if appropriate, and           * Do symlink substitution, if appropriate, and
          * check length for potential overflow.           * check length for potential overflow.
            *
            * Inhibit symlink substitution for nfsd.
            * XXX: This is how it was before; is that a bug or a feature?
          */           */
         if ((vfs_magiclinks &&          if ((!inhibitmagic && vfs_magiclinks &&
              symlink_magic(self->l_proc, cp, &linklen)) ||               symlink_magic(self->l_proc, cp, &linklen)) ||
             (linklen + ndp->ni_pathlen >= MAXPATHLEN)) {              (linklen + ndp->ni_pathlen >= MAXPATHLEN)) {
                 PNBUF_PUT(cp);                  PNBUF_PUT(cp);
Line 1230  bad:
Line 1233  bad:
 //////////////////////////////  //////////////////////////////
   
 static int  static int
 do_namei(struct namei_state *state)  do_namei(struct namei_state *state, struct vnode *forcecwd,
            int neverfollow, int inhibitmagic)
 {  {
         int error;          int error;
   
Line 1253  do_namei(struct namei_state *state)
Line 1257  do_namei(struct namei_state *state)
                 savepath = NULL;                  savepath = NULL;
         }          }
   
         error = namei_start(state, 0/*not nfsd*/, NULL);          error = namei_start(state, forcecwd);
         if (error) {          if (error) {
                 if (savepath != NULL) {                  if (savepath != NULL) {
                         pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);                          pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
Line 1302  do_namei(struct namei_state *state)
Line 1306  do_namei(struct namei_state *state)
                  * aren't supposed to.                   * aren't supposed to.
                  */                   */
                 if (namei_atsymlink(state)) {                  if (namei_atsymlink(state)) {
                         error = namei_follow(state);                          if (neverfollow) {
                                   error = EINVAL;
                           } else {
                                   error = namei_follow(state, inhibitmagic);
                           }
                         if (error) {                          if (error) {
                                 KASSERT(ndp->ni_dvp != ndp->ni_vp);                                  KASSERT(ndp->ni_dvp != ndp->ni_vp);
                                 vput(ndp->ni_dvp);                                  vput(ndp->ni_dvp);
Line 1349  namei(struct nameidata *ndp)
Line 1357  namei(struct nameidata *ndp)
         int error;          int error;
   
         namei_init(&state, ndp);          namei_init(&state, ndp);
         error = do_namei(&state);          error = do_namei(&state, NULL, 0/*!neverfollow*/, 0/*!inhibitmagic*/);
         namei_cleanup(&state);          namei_cleanup(&state);
   
         return error;          return error;
Line 1366  namei(struct nameidata *ndp)
Line 1374  namei(struct nameidata *ndp)
  * affecting the other.   * affecting the other.
  */   */
   
 int  static int
 lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow)  do_lookup_for_nfsd(struct namei_state *state, struct vnode *forcecwd,
                      int neverfollow, int inhibitmagic)
 {  {
         struct namei_state state;  
         int error;          int error;
   
         struct iovec aiov;          struct nameidata *ndp = state->ndp;
         struct uio auio;          //struct componentname *cnp = state->cnp;
         int linklen;  
         char *cp;  
   
         namei_init(&state, ndp);  
   
         namei_start(&state, 1/*nfsd*/, dp);          error = namei_start(state, forcecwd);
           if (error) {
                   return error;
           }
   
     for (;;) {      for (;;) {
   
         error = do_lookup(&state, dp);          error = do_lookup(state, state->namei_startdir);
   
         if (error) {          if (error) {
                 /* BEGIN from nfsd */  
                 if (ndp->ni_dvp) {                  if (ndp->ni_dvp) {
                         vput(ndp->ni_dvp);                          vput(ndp->ni_dvp);
                 }                  }
                 /* END from nfsd */  
                 namei_cleanup(&state);  
                 return error;                  return error;
         }          }
   
         /*          /*
          * BEGIN wodge of code from nfsd  
          */  
   
         /*  
          * Check for encountering a symbolic link           * Check for encountering a symbolic link
          */           */
         if ((state.cnp->cn_flags & ISSYMLINK) == 0) {          if (namei_atsymlink(state)) {
                 if ((state.cnp->cn_flags & LOCKPARENT) == 0 && state.ndp->ni_dvp) {  
                         if (state.ndp->ni_dvp == state.ndp->ni_vp) {  
                                 vrele(state.ndp->ni_dvp);  
                         } else {  
                                 vput(state.ndp->ni_dvp);  
                         }  
                 }  
                 return (0);  
         } else {  
                 if (neverfollow) {                  if (neverfollow) {
                         error = EINVAL;                          error = EINVAL;
                         goto out;  
                 }  
                 if (state.ndp->ni_loopcnt++ >= MAXSYMLINKS) {  
                         error = ELOOP;  
                         goto out;  
                 }  
                 if (state.ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) {  
                         error = VOP_ACCESS(ndp->ni_vp, VEXEC, state.cnp->cn_cred);  
                         if (error != 0)  
                                 goto out;  
                 }  
                 cp = PNBUF_GET();  
                 aiov.iov_base = cp;  
                 aiov.iov_len = MAXPATHLEN;  
                 auio.uio_iov = &aiov;  
                 auio.uio_iovcnt = 1;  
                 auio.uio_offset = 0;  
                 auio.uio_rw = UIO_READ;  
                 auio.uio_resid = MAXPATHLEN;  
                 UIO_SETUP_SYSSPACE(&auio);  
                 error = VOP_READLINK(ndp->ni_vp, &auio, state.cnp->cn_cred);  
                 if (error) {  
                         PNBUF_PUT(cp);  
                         goto out;  
                 }  
                 linklen = MAXPATHLEN - auio.uio_resid;  
                 if (linklen == 0) {  
                         PNBUF_PUT(cp);  
                         error = ENOENT;  
                         goto out;  
                 }  
                 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {  
                         PNBUF_PUT(cp);  
                         error = ENAMETOOLONG;  
                         goto out;  
                 }  
                 if (ndp->ni_pathlen > 1) {  
                         /* includes a null-terminator */  
                         memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);  
                 } else {                  } else {
                         cp[linklen] = '\0';                          error = namei_follow(state, inhibitmagic);
                 }                  }
                 state.ndp->ni_pathlen += linklen;                  if (error) {
                 memcpy(state.ndp->ni_pnbuf, cp, state.ndp->ni_pathlen);                          KASSERT(ndp->ni_dvp != ndp->ni_vp);
                 PNBUF_PUT(cp);                          vput(state->ndp->ni_vp);
                 vput(state.ndp->ni_vp);                          vput(state->ndp->ni_dvp);
                 dp = state.ndp->ni_dvp;                          state->ndp->ni_vp = NULL;
                           return error;
                 /*  
                  * Check if root directory should replace current directory.  
                  */  
                 if (state.ndp->ni_pnbuf[0] == '/') {  
                         vput(dp);  
                         dp = ndp->ni_rootdir;  
                         vref(dp);  
                         vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);  
                 }                  }
           } else {
                   break;
         }          }
       }
   
       if ((state->cnp->cn_flags & LOCKPARENT) == 0 && state->ndp->ni_dvp) {
               if (state->ndp->ni_dvp == state->ndp->ni_vp) {
                       vrele(state->ndp->ni_dvp);
               } else {
                       vput(state->ndp->ni_dvp);
               }
     }      }
  out:      return (0);
         vput(state.ndp->ni_vp);  }
         vput(state.ndp->ni_dvp);  
         state.ndp->ni_vp = NULL;  
   
         /*  int
          * END wodge of code from nfsd  lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow)
          */  {
           struct namei_state state;
           int error;
   
           namei_init(&state, ndp);
           error = do_lookup_for_nfsd(&state, dp, neverfollow, 1/*inhibitmagic*/);
         namei_cleanup(&state);          namei_cleanup(&state);
   
         return error;          return error;

Legend:
Removed from v.1.133  
changed lines
  Added in v.1.134

CVSweb <webmaster@jp.NetBSD.org>