You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Robert S. Thau" <rs...@ai.mit.edu> on 1995/08/21 02:48:33 UTC

More fun with symlinks...

Roy and I just tracked down yet another problem with symlinks --- it seems
that on some systems, if you do an lstat() on "/path/to/some/symlink/", with
a trailing slash on the pathname, then it follows the symlink --- even in
lstat().  (Why his SunOS system exhibits this behavior, and mine doesn't, is
still a bit of a mystery, but his system does reliably exhibit this behavior.
Candidate explanations include SunOS 4.1.2 vs. 4.1.4, and direct-mounted vs.
NFS-mounted test directories).  The easiest fix (albeit not a pretty one)
is to strip slashes off of pathnames in check_symlinks --- Roy has verified
that this works on his box...

Now also on hyperreal as patch10.symlinks-again...

*** http_request.c	Sun Aug 20 19:58:00 1995
--- ../http_request.c	Sun Aug 20 20:24:40 1995
***************
*** 96,109 ****
  int check_symlinks (char *d, char opts)
  {
      struct stat lfi, fi;
    
      if (opts & OPT_SYM_LINKS) return OK;
  
      /* Note that we don't reject accesses to nonexistent files (multiviews
       * or the like may cons up a way to run the transaction anyway)...
       */
  		    
!     if (!(lstat (d, &lfi) >= 0) || !S_ISLNK(lfi.st_mode)) return OK;
  
      /* OK, it's a symlink.  May still be OK with OPT_SYM_OWNER */
      
--- 96,130 ----
  int check_symlinks (char *d, char opts)
  {
      struct stat lfi, fi;
+     char *lastp;
+     int res;
    
      if (opts & OPT_SYM_LINKS) return OK;
  
+     /* Strip trailing '/', if any, off what we're checking; trailing
+      * slashes make some systems follow symlinks to directories even in
+      * lstat().  After we've done the lstat, put it back.  Also, don't
+      * bother checking '/' at all...
+      *
+      * Note that we don't have to worry about multiple slashes here
+      * because of no2slash() below...
+      */
+ 
+     lastp = d + strlen(d) - 1;
+     if (lastp == d) return OK;	/* Root directory, '/' */
+     
+     if (*lastp == '/') *lastp = '\0';
+     else lastp = NULL;
+ 	
+     res = lstat (d, &lfi);
+ 
+     if (lastp) *lastp = '/';
+     
      /* Note that we don't reject accesses to nonexistent files (multiviews
       * or the like may cons up a way to run the transaction anyway)...
       */
  		    
!     if (!(res >= 0) || !S_ISLNK(lfi.st_mode)) return OK;
  
      /* OK, it's a symlink.  May still be OK with OPT_SYM_OWNER */