[PATCH] realpath fix for NeXT (Re: Snapshot)

Ben Lindstrom mouring at pconline.com
Sun Oct 1 11:20:51 EST 2000


<sigh> Stupid NeXT platform!  I swear somedays I want to slap the orignal
programmers around...  (realpath does not exist, yet somewhere in NeXT's
libc there is a lightly bound realpath() function that has nothing to do
with what we want.)

So here is the realpath() implemenation for those that lack it.  (I assume
NeXT only since no one else has yelled. =)

I used the realpath() from OpenBSD.. since NeXT lacks fchdir() I worked
around it.  

This brings NeXT inline with everyone else. 

- Ben



diff -ruN openssh/Makefile.in openssh-mine/Makefile.in
--- openssh/Makefile.in	Fri Sep 29 07:01:36 2000
+++ openssh-mine/Makefile.in	Sat Sep 30 18:42:53 2000
@@ -37,7 +37,7 @@
 
 LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readp
ass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o 
 
-LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o bsd-strtok.o
 fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
+LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-realpath.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep
.o bsd-strtok.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
 
 SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
 
diff -ruN openssh/bsd-realpath.c openssh-mine/bsd-realpath.c
--- openssh/bsd-realpath.c	Wed Dec 31 18:00:00 1969
+++ openssh-mine/bsd-realpath.c	Sat Sep 30 18:54:30 2000
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#if !defined(HAVE_REALPATH)
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: realpath..c,v 1.4 1998/05/18 09:55:19 deraadt Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Mimic getcwd() by using getwd() for those OS that don't support
+ * getcwd().
+ */
+#ifndef HAVE_GETCWD
+#define getcwd(buf,size) getwd(buf)
+#endif
+
+/*
+ * S_ISLNK compatibility
+ */
+#ifndef S_ISLNK
+#define S_ISLNK(m) ((m & 0170000) == 0120000)
+#endif
+
+/*
+ * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
+ *
+ * Find the real name of path, by removing all ".", ".." and symlink
+ * components.  Returns (resolved) on success, or (NULL) on failure,
+ * in which case the path which caused trouble is left in (resolved).
+ */
+char *
+realpath(const char *path, char *resolved)
+{
+	struct stat sb;
+	int fd, n, rootd, serrno = 0;
+	char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN];
+	int symlinks = 0;
+
+	/* Save the starting point. */
+	getcwd(start,MAXPATHLEN);	
+	if ((fd = open(".", O_RDONLY)) < 0) {
+		(void)strcpy(resolved, ".");
+		return (NULL);
+	}
+	close(fd);
+
+	/*
+	 * Find the dirname and basename from the path to be resolved.
+	 * Change directory to the dirname component.
+	 * lstat the basename part.
+	 *     if it is a symlink, read in the value and loop.
+	 *     if it is a directory, then change to that directory.
+	 * get the current directory name and append the basename.
+	 */
+	(void)strncpy(resolved, path, MAXPATHLEN - 1);
+	resolved[MAXPATHLEN - 1] = '\0';
+loop:
+	q = strrchr(resolved, '/');
+	if (q != NULL) {
+		p = q + 1;
+		if (q == resolved)
+			q = "/";
+		else {
+			do {
+				--q;
+			} while (q > resolved && *q == '/');
+			q[1] = '\0';
+			q = resolved;
+		}
+		if (chdir(q) < 0)
+			goto err1;
+	} else
+		p = resolved;
+
+	/* Deal with the last component. */
+	if (lstat(p, &sb) == 0) {
+		if (S_ISLNK(sb.st_mode)) {
+			if (++symlinks > MAXSYMLINKS) {
+				serrno = ELOOP;
+				goto err1;
+			}
+			n = readlink(p, resolved, MAXPATHLEN-1);
+			if (n < 0)
+				goto err1;
+			resolved[n] = '\0';
+			goto loop;
+		}
+		if (S_ISDIR(sb.st_mode)) {
+			if (chdir(p) < 0)
+				goto err1;
+			p = "";
+		}
+	}
+
+	/*
+	 * Save the last component name and get the full pathname of
+	 * the current directory.
+	 */
+	(void)strcpy(wbuf, p);
+	if (getcwd(resolved, MAXPATHLEN) == 0)
+		goto err1;
+
+	/*
+	 * Join the two strings together, ensuring that the right thing
+	 * happens if the last component is empty, or the dirname is root.
+	 */
+	if (resolved[0] == '/' && resolved[1] == '\0')
+		rootd = 1;
+	else
+		rootd = 0;
+
+	if (*wbuf) {
+		if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
+			serrno = ENAMETOOLONG;
+			goto err1;
+		}
+		if (rootd == 0)
+			(void)strcat(resolved, "/");
+		(void)strcat(resolved, wbuf);
+	}
+
+	/* Go back to where we came from. */
+	if (chdir(start) < 0) {
+		serrno = errno;
+		goto err2;
+	}
+	return (resolved);
+
+err1:	chdir(start);
+err2:	errno = serrno;
+	return (NULL);
+}
+#endif
diff -ruN openssh/config.h.in openssh-mine/config.h.in
--- openssh/config.h.in	Fri Sep 29 22:30:02 2000
+++ openssh-mine/config.h.in	Sat Sep 30 18:56:24 2000
@@ -5,6 +5,11 @@
 /* Generated automatically from acconfig.h by autoheader. */
 /* Please make your changes there */
 
+/* Define if you have realpath() */
+#undef HAVE_REALPATH
+
+/* Define if you have getcwd() */
+#undef HAVE_GETCWD
 
 /* Define if the `getpgrp' function takes no argument.  */
 #undef GETPGRP_VOID
diff -ruN openssh/configure.in openssh-mine/configure.in
--- openssh/configure.in	Fri Sep 29 17:43:20 2000
+++ openssh-mine/configure.in	Sat Sep 30 18:41:12 2000
@@ -268,7 +268,7 @@
 AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h getopt.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/s
elect.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h sys/un.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h)
 
 dnl    Checks for library functions.
-AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock fchmod freeaddrinfo futimes gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af
 setenv seteuid setlogin setproctitle setreuid setrlimit sigaction sigvec snprintf strerror strlcat strlcpy strsep strtok_r vsnprintf vhangup _getpty __b64_ntop)
+AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock fchmod freeaddrinfo futimes gai_strerror getaddrinfo getcwd getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty realp
ath rresvport_af setenv seteuid setlogin setproctitle setreuid setrlimit sigaction sigvec snprintf strerror strlcat strlcpy strsep strtok_r vsnprintf vhangup _getpty __b64_ntop)
 dnl    Checks for time functions
 AC_CHECK_FUNCS(gettimeofday time)
 dnl    Checks for libutil functions







More information about the openssh-unix-dev mailing list