- (dtucker) [LICENCE configure.ac defines.h openbsd-compat/realpath.c]

Sync current (thread-safe) version of realpath.c from OpenBSD (which is
   in turn based on FreeBSD's).  ok djm@
This commit is contained in:
Darren Tucker 2005-08-10 21:52:36 +10:00
Родитель c7572b2661
Коммит 73f671a090
5 изменённых файлов: 141 добавлений и 142 удалений

Просмотреть файл

@ -1,6 +1,9 @@
20050810
- (dtucker) [configure.ac] Test libedit library and headers for compatibility.
Report from skeleten AT shillest.net, ok djm@
- (dtucker) [LICENCE configure.ac defines.h openbsd-compat/realpath.c]
Sync current (thread-safe) version of realpath.c from OpenBSD (which is
in turn based on FreeBSD's). ok djm@
20050809
- (tim) [configure.ac] Allow --with-audit=no. OK dtucker@
@ -2904,4 +2907,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.3864 2005/08/10 10:34:15 dtucker Exp $
$Id: ChangeLog,v 1.3865 2005/08/10 11:52:36 dtucker Exp $

Просмотреть файл

@ -255,6 +255,7 @@ OpenSSH contains no GPL code.
Damien Miller
Eric P. Allman
The Regents of the University of California
Constantin S. Svintsoff
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions

Просмотреть файл

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.284 2005/08/10 10:34:15 dtucker Exp $
# $Id: configure.ac,v 1.285 2005/08/10 11:52:36 dtucker Exp $
#
# Copyright (c) 1999-2004 Damien Miller
#
@ -1085,7 +1085,6 @@ AC_CHECK_FUNCS( \
clock \
closefrom \
dirfd \
fchdir \
fchmod \
fchown \
freeaddrinfo \

Просмотреть файл

@ -25,7 +25,7 @@
#ifndef _DEFINES_H
#define _DEFINES_H
/* $Id: defines.h,v 1.122 2005/07/14 07:22:11 dtucker Exp $ */
/* $Id: defines.h,v 1.123 2005/08/10 11:52:36 dtucker Exp $ */
/* Constants */
@ -62,6 +62,10 @@ enum
# endif /* PATH_MAX */
#endif /* MAXPATHLEN */
#ifndef MAXSYMLINKS
# define MAXSYMLINKS 5
#endif
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif

Просмотреть файл

@ -1,11 +1,7 @@
/* OPENBSD ORIGINAL: lib/libc/stdlib/realpath.c */
/*
* 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.
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -15,14 +11,14 @@
* 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. 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.
* 3. The names of the authors may not 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
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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)
@ -36,169 +32,165 @@
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
#if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: realpath.c,v 1.11 2004/11/30 15:12:59 millert 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>
/*
* MAXSYMLINKS
*/
#ifndef MAXSYMLINKS
#define MAXSYMLINKS 5
#endif
/*
* char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
* char *realpath(const char *path, char resolved[PATH_MAX]);
*
* 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)
realpath(const char *path, char resolved[PATH_MAX])
{
struct stat sb;
int fd, n, needslash, serrno;
char *p, *q, wbuf[MAXPATHLEN];
int symlinks = 0;
char *p, *q, *s;
size_t left_len, resolved_len;
unsigned symlinks;
int serrno, slen;
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
/* Save the starting point. */
#ifndef HAVE_FCHDIR
char start[MAXPATHLEN];
/* this is potentially racy but without fchdir we have no option */
if (getcwd(start, sizeof(start)) == NULL) {
resolved[0] = '.';
serrno = errno;
symlinks = 0;
if (path[0] == '/') {
resolved[0] = '/';
resolved[1] = '\0';
return (NULL);
}
#endif
if ((fd = open(".", O_RDONLY)) < 0) {
resolved[0] = '.';
resolved[1] = '\0';
return (NULL);
}
/* Convert "." -> "" to optimize away a needless lstat() and chdir() */
if (path[0] == '.' && path[1] == '\0')
path = "";
/*
* 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.
*/
if (strlcpy(resolved, path, MAXPATHLEN) >= MAXPATHLEN) {
serrno = ENAMETOOLONG;
goto err2;
}
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 (*p != '\0' && lstat(p, &sb) == 0) {
if (S_ISLNK(sb.st_mode)) {
if (++symlinks > MAXSYMLINKS) {
errno = ELOOP;
goto err1;
}
if ((n = readlink(p, resolved, MAXPATHLEN-1)) < 0)
goto err1;
resolved[n] = '\0';
goto loop;
}
if (S_ISDIR(sb.st_mode)) {
if (chdir(p) < 0)
goto err1;
p = "";
if (path[1] == '\0')
return (resolved);
resolved_len = 1;
left_len = strlcpy(left, path + 1, sizeof(left));
} else {
if (getcwd(resolved, PATH_MAX) == NULL) {
strlcpy(resolved, ".", PATH_MAX);
return (NULL);
}
resolved_len = strlen(resolved);
left_len = strlcpy(left, path, sizeof(left));
}
/*
* Save the last component name and get the full pathname of
* the current directory.
*/
if (strlcpy(wbuf, p, sizeof(wbuf)) >= sizeof(wbuf)) {
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
goto err1;
return (NULL);
}
if (getcwd(resolved, MAXPATHLEN) == NULL)
goto err1;
/*
* Join the two strings together, ensuring that the right thing
* happens if the last component is empty, or the dirname is root.
* Iterate over path components in `left'.
*/
if (resolved[0] == '/' && resolved[1] == '\0')
needslash = 0;
else
needslash = 1;
if (*wbuf) {
if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) {
while (left_len != 0) {
/*
* Extract the next path component and adjust `left'
* and its length.
*/
p = strchr(left, '/');
s = p ? p : left + left_len;
if (s - left >= sizeof(next_token)) {
errno = ENAMETOOLONG;
goto err1;
return (NULL);
}
if (needslash) {
if (strlcat(resolved, "/", MAXPATHLEN) >= MAXPATHLEN) {
memcpy(next_token, left, s - left);
next_token[s - left] = '\0';
left_len -= s - left;
if (p != NULL)
memmove(left, s + 1, left_len + 1);
if (resolved[resolved_len - 1] != '/') {
if (resolved_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
goto err1;
return (NULL);
}
resolved[resolved_len++] = '/';
resolved[resolved_len] = '\0';
}
if (strlcat(resolved, wbuf, MAXPATHLEN) >= MAXPATHLEN) {
if (next_token[0] == '\0')
continue;
else if (strcmp(next_token, ".") == 0)
continue;
else if (strcmp(next_token, "..") == 0) {
/*
* Strip the last path component except when we have
* single "/"
*/
if (resolved_len > 1) {
resolved[resolved_len - 1] = '\0';
q = strrchr(resolved, '/') + 1;
*q = '\0';
resolved_len = q - resolved;
}
continue;
}
/*
* Append the next path component and lstat() it. If
* lstat() fails we still can return successfully if
* there are no more path components left.
*/
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
errno = ENAMETOOLONG;
goto err1;
return (NULL);
}
if (lstat(resolved, &sb) != 0) {
if (errno == ENOENT && p == NULL) {
errno = serrno;
return (resolved);
}
return (NULL);
}
if (S_ISLNK(sb.st_mode)) {
if (symlinks++ > MAXSYMLINKS) {
errno = ELOOP;
return (NULL);
}
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
if (slen < 0)
return (NULL);
symlink[slen] = '\0';
if (symlink[0] == '/') {
resolved[1] = 0;
resolved_len = 1;
} else if (resolved_len > 1) {
/* Strip the last path component. */
resolved[resolved_len - 1] = '\0';
q = strrchr(resolved, '/') + 1;
*q = '\0';
resolved_len = q - resolved;
}
/*
* If there are any path components left, then
* append them to symlink. The result is placed
* in `left'.
*/
if (p != NULL) {
if (symlink[slen - 1] != '/') {
if (slen + 1 >= sizeof(symlink)) {
errno = ENAMETOOLONG;
return (NULL);
}
symlink[slen] = '/';
symlink[slen + 1] = 0;
}
left_len = strlcat(symlink, left, sizeof(left));
if (left_len >= sizeof(left)) {
errno = ENAMETOOLONG;
return (NULL);
}
}
left_len = strlcpy(left, symlink, sizeof(left));
}
}
/* Go back to where we came from. */
#ifdef HAVE_FCHDIR
if (fchdir(fd) < 0) {
#else
if (chdir(start) < 0) {
#endif
serrno = errno;
goto err2;
}
/* It's okay if the close fails, what's an fd more or less? */
(void)close(fd);
/*
* Remove trailing slash except when the resolved pathname
* is a single "/".
*/
if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
resolved[resolved_len - 1] = '\0';
return (resolved);
err1: serrno = errno;
#ifdef HAVE_FCHDIR
(void)fchdir(fd);
#else
chdir(start);
#endif
err2: (void)close(fd);
errno = serrno;
return (NULL);
}
#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */