[3128] in Athena Bugs

home help back first fref pref prev next nref lref last post

discuss blowing away symbolic links (patch)

daemon@ATHENA.MIT.EDU (Jonathan I. Kamens)
Thu Sep 7 20:10:22 1989

Date: Thu, 7 Sep 89 20:09:50 -0400
From: Jonathan I. Kamens <jik@ATHENA.MIT.EDU>
To: bugs@ATHENA.MIT.EDU

  The following patch fixes the previously reported problem of discuss
blowing away symlinks pointing to .meetings.

  It is #ifdef'd with the symbol FOLLOW_LINKS, so either remove the
#ifdef's or compile with -DFOLLOW_LINKS if you intend to use the
patch.

  It isn't portable to sites that don't have symbolic links or that
don't have readlink(), so you might want to put some other #ifdef
around the code to make sure that it compiles on machines that don't
have links (if you care about the code in our source tree compiling
anywhere besides Athena).

  jik

		      *************************

*** /minos/source/4.3/usr.athena/discuss/source/libds/dsname.c	Thu Feb 18 07:36:16 1988
--- dsname.c	Thu Sep  7 18:04:03 1989
***************
*** 21,26 ****
--- 21,30 ----
  #include <pwd.h>
  #include <sys/file.h>
  #include <sys/param.h>
+ #ifdef FOLLOW_LINKS
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #endif
  #include <errno.h>
  #include <assert.h>
  #include "config.h"
***************
*** 67,73 ****
  {
  	struct passwd *pw = NULL;
  	register char *cp;
! 
  	if (disrcfile)
  		return 0;
  
--- 71,81 ----
  {
  	struct passwd *pw = NULL;
  	register char *cp;
! #ifdef FOLLOW_LINKS
! 	int stat_val;
! 	struct stat stat_buf;
! #endif
! 	
  	if (disrcfile)
  		return 0;
  
***************
*** 94,99 ****
--- 102,136 ----
  		strcpy(disrcbuf, pw->pw_dir);
  		strcat(disrcbuf, mtgs);
  	}
+ #ifdef FOLLOW_LINKS
+ 	do {
+ 	     stat_val = lstat(disrcbuf, &stat_buf);
+ 	     if (stat_val)
+ 		  return errno;
+ 	     if ((stat_buf.st_mode & S_IFMT) == S_IFLNK) {
+ 		  int cc;
+ 		  char link_buf[MAXPATHLEN+1];
+ 		  char *last_slash;
+ 
+ 		  stat_val = 1;
+ 		  cc = readlink(disrcbuf, link_buf, MAXPATHLEN);
+ 		  if (cc == -1)
+ 		       break;
+ 		  link_buf[cc] = '\0'; /* readlink doesn't null-terminate strings */
+ 		  if (*link_buf == '/')
+ 		       strcpy(disrcbuf, link_buf); /* replace old path */
+ 		  /* with symlink path */
+ 		  else {	/* append symlink to old path sans filename */
+ 		       last_slash = rindex(disrcbuf, '/');
+ 		       *(last_slash + 1) = '\0';
+ 		       strncat(disrcbuf, link_buf,
+ 			       (cc < MAXPATHLEN - strlen(disrcbuf)) ? cc :
+ 			       MAXPATHLEN - strlen(disrcbuf));
+ 		  }
+ 	     }
+ 	} while (! stat_val);
+ #endif
+      
  	if (!access(disrcbuf, R_OK|W_OK)) {
  		disrcfile = disrcbuf;
  		return 0;
***************
*** 107,113 ****
  {
  	struct passwd *pw = NULL;
  	register char *cp = NULL;
! 
  	if ((auser_id == NULL) || 
  	    (auser_id[0] == '\0') ||
  	    (me && !strcmp(auser_id, me))) {
--- 144,154 ----
  {
  	struct passwd *pw = NULL;
  	register char *cp = NULL;
! #ifdef FOLLOW_LINKS
! 	int stat_val;
! 	struct stat stat_buf;
! #endif
! 	
  	if ((auser_id == NULL) || 
  	    (auser_id[0] == '\0') ||
  	    (me && !strcmp(auser_id, me))) {
***************
*** 130,135 ****
--- 171,205 ----
  	}
  	strncpy(buf, pw->pw_dir, len);
  	strncat(buf, mtgs, len - strlen(buf));
+ 
+ #ifdef FOLLOW_LINKS
+ 	do {
+ 	     stat_val = lstat(buf, &stat_buf);
+ 	     if (stat_val)
+ 		  return ((errno == ENOENT) ? NO_MTGS_FILE : errno);
+ 	     if ((stat_buf.st_mode & S_IFMT) == S_IFLNK) {
+ 		  int cc;
+ 		  char link_buf[MAXPATHLEN+1];
+ 		  char *last_slash;
+ 
+ 		  stat_val = 1;
+ 		  cc = readlink(buf, link_buf, MAXPATHLEN);
+ 		  if (cc == -1)
+ 		       break;
+ 		  link_buf[cc] = '\0'; /* readlink doesn't null-terminate strings */
+ 		  if (*link_buf == '/')
+ 		       strcpy(buf, link_buf); /* replace old path with symlink path */
+ 		  else {	/* append symlink to old path sans filename */
+ 		       last_slash = rindex(buf, '/');
+ 		       *(last_slash + 1) = '\0';
+ 		       strncat(buf, link_buf,
+ 			       (cc < MAXPATHLEN - strlen(buf)) ? cc :
+ 			       MAXPATHLEN - strlen(buf));
+ 		  }
+ 	     }
+ 	} while (! stat_val);
+ #endif
+ 
  	return (access(buf, R_OK)? NO_MTGS_FILE : 0);
  }
  

home help back first fref pref prev next nref lref last post