From d9fc4acc572c6647a4f27b838d35d27d805d190e Mon Sep 17 00:00:00 2001 From: Jason Stubbs Date: Sun, 28 Aug 2005 08:37:44 +0000 Subject: Migration (without history) of the current stable line to subversion. svn path=/main/branches/2.0/; revision=1941 --- src/sandbox-1.1/getcwd.c | 511 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 511 insertions(+) create mode 100644 src/sandbox-1.1/getcwd.c (limited to 'src/sandbox-1.1/getcwd.c') diff --git a/src/sandbox-1.1/getcwd.c b/src/sandbox-1.1/getcwd.c new file mode 100644 index 000000000..552e41a0d --- /dev/null +++ b/src/sandbox-1.1/getcwd.c @@ -0,0 +1,511 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Wants: + AC_STDC_HEADERS + AC_DIR_HEADER + AC_UNISTD_H + AC_MEMORY_H + AC_CONST + AC_ALLOCA + */ + +/* + * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/getcwd.c,v 1.1.2.1 2004/10/22 16:53:30 carpaski Exp $ + */ + +/* Modified: 26 July 2003; Martin Schlemmer + * + * Cleaned up unneeded stuff. Add a wrapper to try and detect when + * we have a kernel whose getcwd system call do not handle directory + * names longer than PATH_MAX, and if so, use our generic version. + * To work truly with > PATH_MAX lengh CWDs, I had to increase the + * size of the dots[] array. Also prepended a 'e' to functions that + * I did not rip out. + * + */ + +/* AIX requires this to be the first thing in the file. */ +#if defined _AIX && !defined __GNUC__ +#pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#ifdef STDC_HEADERS +# include +#endif + +#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#ifndef NULL +# define NULL 0 +#endif + +#if defined USGr3 && !defined DIRENT +# define DIRENT +#endif /* USGr3 */ +#if defined Xenix && !defined SYSNDIR +# define SYSNDIR +#endif /* Xenix */ + +#if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__ +# include +# ifndef __GNU_LIBRARY__ +# define D_NAMLEN(d) strlen((d)->d_name) +# else +# define HAVE_D_NAMLEN +# define D_NAMLEN(d) ((d)->d_namlen) +# endif +#else /* not POSIX or DIRENT */ +# define dirent direct +# define D_NAMLEN(d) ((d)->d_namlen) +# define HAVE_D_NAMLEN +# if defined USG && !defined sgi +# if defined SYSNDIR +# include +# else /* Not SYSNDIR */ +# include "ndir.h" +# endif /* SYSNDIR */ +# else /* not USG */ +# include +# endif /* USG */ +#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */ + +#if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__ +# include +#endif + +#if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX +# include +# include +# define ANSI_STRING +#else /* No standard headers. */ + +# ifdef USG + +# include +# ifdef NEED_MEMORY_H +# include +# endif +# define ANSI_STRING + +# else /* Not USG. */ + +# ifdef NeXT + +# include + +# else /* Not NeXT. */ + +# include + +# ifndef bcmp +extern int bcmp(); +# endif +# ifndef bzero +extern void bzero(); +# endif +# ifndef bcopy +extern void bcopy(); +# endif + +# endif /* NeXT. */ + +# endif /* USG. */ + +extern char *malloc(), *realloc(); +extern void free(); + +#endif /* Standard headers. */ + +#ifndef ANSI_STRING +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memmove memcpy +#endif /* Not ANSI_STRING. */ + +#ifndef MAX +# define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif + +#ifdef _LIBC +# ifndef mempcpy +# define mempcpy __mempcpy +# endif +# define HAVE_MEMPCPY 1 +#endif + +#if !defined __alloca && !defined __GNU_LIBRARY__ + +# ifdef __GNUC__ +# undef alloca +# define alloca(n) __builtin_alloca (n) +# else /* Not GCC. */ +# if defined sparc || defined HAVE_ALLOCA_H +# include +# else /* Not sparc or HAVE_ALLOCA_H. */ +# ifndef _AIX +extern char *alloca(); +# endif /* Not _AIX. */ +# endif /* sparc or HAVE_ALLOCA_H. */ +# endif /* GCC. */ + +# define __alloca alloca + +#endif + +#if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__ +# include +#else +# include +#endif + +#ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 1024 +# endif +#endif + +#if !defined STDC_HEADERS && !defined __GNU_LIBRARY__ +# undef size_t +# define size_t unsigned int +#endif + +#if !__STDC__ && !defined const +# define const +#endif + +#ifndef __GNU_LIBRARY__ +# define __lstat stat +#endif + +#ifndef _LIBC +# define __getcwd getcwd +#endif + +#ifndef GETCWD_RETURN_TYPE +# define GETCWD_RETURN_TYPE char * +#endif + +#ifndef SB_PATH_MAX +# include "localdecls.h" +# define OUTSIDE_LIBSANDBOX +#endif + +#ifndef __LIBC +# define __lstat lstat +# define __readdir readdir +# define __closedir closedir +#endif + +/* Get the pathname of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE == 0, in which case it is as big as necessary. */ + +GETCWD_RETURN_TYPE +__egetcwd(buf, size) +char *buf; +size_t size; +{ + static const char dots[] + = "../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../../\ +../../../../../../../../../../../../../../../../../../../../../../../../../.."; + const char *dotp = &dots[sizeof (dots)]; + const char *dotlist = dots; + size_t dotsize = sizeof (dots) - 1; + dev_t rootdev, thisdev; + ino_t rootino, thisino; + char *path; + register char *pathp; + struct stat st; + int prev_errno = errno; + size_t allocated = size; + + if (size == 0) { + if (buf != NULL) { + __set_errno(EINVAL); + return NULL; + } + + allocated = SB_PATH_MAX + 1; + } + + if (buf != NULL) + path = buf; + else { + path = malloc(allocated); + if (path == NULL) + return NULL; + } + + pathp = path + allocated; + *--pathp = '\0'; + + if (__lstat(".", &st) < 0) + goto lose2; + thisdev = st.st_dev; + thisino = st.st_ino; + + if (__lstat("/", &st) < 0) + goto lose2; + rootdev = st.st_dev; + rootino = st.st_ino; + + while (!(thisdev == rootdev && thisino == rootino)) { + register DIR *dirstream; + struct dirent *d; + dev_t dotdev; + ino_t dotino; + char mount_point; + + /* Look at the parent directory. */ + if (dotp == dotlist) { + /* My, what a deep directory tree you have, Grandma. */ + char *new; + if (dotlist == dots) { + new = malloc(dotsize * 2 + 1); + if (new == NULL) + goto lose; +#ifdef HAVE_MEMPCPY + dotp = mempcpy(new, dots, dotsize); +#else + memcpy(new, dots, dotsize); + dotp = &new[dotsize]; +#endif + } else { + new = realloc((__ptr_t) dotlist, dotsize * 2 + 1); + if (new == NULL) + goto lose; + dotp = &new[dotsize]; + } +#ifdef HAVE_MEMPCPY + *((char *) mempcpy((char *) dotp, new, dotsize)) = '\0'; + dotsize *= 2; +#else + memcpy((char *) dotp, new, dotsize); + dotsize *= 2; + new[dotsize] = '\0'; +#endif + dotlist = new; + } + + dotp -= 3; + + /* Figure out if this directory is a mount point. */ + if (__lstat(dotp, &st) < 0) + goto lose; + dotdev = st.st_dev; + dotino = st.st_ino; + mount_point = dotdev != thisdev; + + /* Search for the last directory. */ +#ifdef OUTSIDE_LIBSANDBOX + dirstream = opendir(dotp); +#else + dirstream = true_opendir(dotp); +#endif + if (dirstream == NULL) + goto lose; + /* Clear errno to distinguish EOF from error if readdir returns + NULL. */ + __set_errno(0); + while ((d = __readdir(dirstream)) != NULL) { + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' + || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + if (mount_point || (ino_t) d->d_ino == thisino) { + char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN(d)]; +#ifdef HAVE_MEMPCPY + char *tmp = mempcpy(name, dotp, + dotlist + dotsize - dotp); + *tmp++ = '/'; + strcpy(tmp, d->d_name); +#else + memcpy(name, dotp, dotlist + dotsize - dotp); + name[dotlist + dotsize - dotp] = '/'; + strcpy(&name[dotlist + dotsize - dotp + 1], d->d_name); +#endif + /* We don't fail here if we cannot stat() a directory entry. + This can happen when (network) filesystems fail. If this + entry is in fact the one we are looking for we will find + out soon as we reach the end of the directory without + having found anything. */ + if (__lstat(name, &st) >= 0 && st.st_dev == thisdev + && st.st_ino == thisino) + break; + } + } + if (d == NULL) { + int save = errno; + (void) __closedir(dirstream); + if (save == 0) + /* EOF on dirstream, which means that the current directory + has been removed. */ + save = ENOENT; + __set_errno(save); + goto lose; + } else { + size_t namlen = _D_EXACT_NAMLEN(d); + + if ((size_t) (pathp - path) <= namlen) { + if (size != 0) { + (void) __closedir(dirstream); + __set_errno(ERANGE); + goto lose; + } else { + char *tmp; + size_t oldsize = allocated; + + allocated = 2 * MAX(allocated, namlen); + tmp = realloc(path, allocated); + if (tmp == NULL) { + (void) __closedir(dirstream); + __set_errno(ENOMEM); /* closedir might have changed it. */ + goto lose; + } + + /* Move current contents up to the end of the buffer. + This is guaranteed to be non-overlapping. */ + pathp = + memcpy(tmp + allocated - + (path + oldsize - pathp), + tmp + (pathp - path), path + oldsize - pathp); + path = tmp; + } + } + pathp -= namlen; + (void) memcpy(pathp, d->d_name, namlen); + *--pathp = '/'; + (void) __closedir(dirstream); + } + + thisdev = dotdev; + thisino = dotino; + } + + if (pathp == &path[allocated - 1]) + *--pathp = '/'; + + if (dotlist != dots) + free((__ptr_t) dotlist); + + memmove(path, pathp, path + allocated - pathp); + + /* Restore errno on successful return. */ + __set_errno(prev_errno); + + return path; + +lose: + if (dotlist != dots) + free((__ptr_t) dotlist); +lose2: + if (buf == NULL) + free(path); + return NULL; +} + +GETCWD_RETURN_TYPE +egetcwd(buf, size) +char *buf; +size_t size; +{ + struct stat st; + char *tmpbuf; + + __set_errno(0); + tmpbuf = getcwd(buf, size); + + if (tmpbuf) { + __lstat(buf, &st); + } else { + return tmpbuf; + } + + if (errno) { + /* If lstat() failed with eerror = ENOENT, then its + * possible that we are running on an older kernel, + * so use our generic version which *should* not fail. + */ + if (errno == ENOENT) { + return __egetcwd(buf, size); + } else { + return tmpbuf; + } + } + + return tmpbuf; +} + +// vim:expandtab noai:cindent ai -- cgit v1.2.3-1-g7c22