[3128] in Athena Bugs
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);
}