Adding upstream version 5.2.37.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
cf91100bce
commit
fa1b3d3922
1435 changed files with 757174 additions and 0 deletions
356
lib/sh/getcwd.c
Normal file
356
lib/sh/getcwd.c
Normal file
|
@ -0,0 +1,356 @@
|
|||
/* getcwd.c -- get pathname of current directory */
|
||||
|
||||
/* Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if !defined (HAVE_GETCWD)
|
||||
|
||||
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
|
||||
#pragma alloca
|
||||
#endif /* _AIX && RISC6000 && !__GNUC__ */
|
||||
|
||||
#if defined (__QNX__)
|
||||
# undef HAVE_LSTAT
|
||||
#endif
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#include <maxpath.h>
|
||||
#include <memalloc.h>
|
||||
|
||||
#include <bashansi.h>
|
||||
|
||||
#if !defined (D_FILENO_AVAILABLE)
|
||||
# include "command.h"
|
||||
# include "general.h"
|
||||
# include "externs.h"
|
||||
#endif
|
||||
|
||||
#include <xmalloc.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
#if !defined (HAVE_LSTAT)
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if !defined (NULL)
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/* If the d_fileno member of a struct dirent doesn't return anything useful,
|
||||
we need to check inode number equivalence the hard way. Return 1 if
|
||||
the inode corresponding to PATH/DIR is identical to THISINO. */
|
||||
#if !defined (D_FILENO_AVAILABLE)
|
||||
static int
|
||||
_path_checkino (dotp, name, thisino)
|
||||
char *dotp;
|
||||
char *name;
|
||||
ino_t thisino;
|
||||
{
|
||||
char *fullpath;
|
||||
int r, e;
|
||||
struct stat st;
|
||||
|
||||
e = errno;
|
||||
fullpath = sh_makepath (dotp, name, MP_RMDOT);
|
||||
if (stat (fullpath, &st) < 0)
|
||||
{
|
||||
errno = e;
|
||||
return 0;
|
||||
}
|
||||
free (fullpath);
|
||||
errno = e;
|
||||
return (st.st_ino == thisino);
|
||||
}
|
||||
#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. */
|
||||
#if defined (__STDC__)
|
||||
char *
|
||||
getcwd (char *buf, size_t size)
|
||||
#else /* !__STDC__ */
|
||||
char *
|
||||
getcwd (buf, size)
|
||||
char *buf;
|
||||
size_t size;
|
||||
#endif /* !__STDC__ */
|
||||
{
|
||||
static const char dots[]
|
||||
= "../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../..";
|
||||
const char *dotp, *dotlist;
|
||||
size_t dotsize;
|
||||
dev_t rootdev, thisdev;
|
||||
ino_t rootino, thisino;
|
||||
char path[PATH_MAX + 1];
|
||||
register char *pathp;
|
||||
char *pathbuf;
|
||||
size_t pathsize;
|
||||
struct stat st;
|
||||
int saved_errno;
|
||||
|
||||
if (buf != NULL && size == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
pathsize = sizeof (path);
|
||||
pathp = &path[pathsize];
|
||||
*--pathp = '\0';
|
||||
pathbuf = path;
|
||||
|
||||
if (stat (".", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
thisdev = st.st_dev;
|
||||
thisino = st.st_ino;
|
||||
|
||||
if (stat ("/", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
rootdev = st.st_dev;
|
||||
rootino = st.st_ino;
|
||||
|
||||
saved_errno = 0;
|
||||
|
||||
dotsize = sizeof (dots) - 1;
|
||||
dotp = &dots[sizeof (dots)];
|
||||
dotlist = dots;
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
{
|
||||
register DIR *dirstream;
|
||||
register struct dirent *d;
|
||||
dev_t dotdev;
|
||||
ino_t dotino;
|
||||
char mount_point;
|
||||
int namlen;
|
||||
|
||||
/* Look at the parent directory. */
|
||||
if (dotp == dotlist)
|
||||
{
|
||||
/* My, what a deep directory tree you have, Grandma. */
|
||||
char *new;
|
||||
if (dotlist == dots)
|
||||
{
|
||||
new = (char *)malloc (dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
memcpy (new, dots, dotsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
}
|
||||
memcpy (&new[dotsize], new, dotsize);
|
||||
dotp = &new[dotsize];
|
||||
dotsize *= 2;
|
||||
new[dotsize] = '\0';
|
||||
dotlist = new;
|
||||
}
|
||||
|
||||
dotp -= 3;
|
||||
|
||||
/* Figure out if this directory is a mount point. */
|
||||
if (stat (dotp, &st) < 0)
|
||||
goto lose;
|
||||
dotdev = st.st_dev;
|
||||
dotino = st.st_ino;
|
||||
mount_point = dotdev != thisdev;
|
||||
|
||||
/* Search for the last directory. */
|
||||
dirstream = opendir (dotp);
|
||||
if (dirstream == NULL)
|
||||
goto lose;
|
||||
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 defined (D_FILENO_AVAILABLE)
|
||||
if (mount_point || d->d_fileno == thisino)
|
||||
#else
|
||||
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
|
||||
#endif
|
||||
{
|
||||
char *name;
|
||||
|
||||
namlen = D_NAMLEN(d);
|
||||
name = (char *)
|
||||
alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
|
||||
memcpy (name, dotp, dotlist + dotsize - dotp);
|
||||
name[dotlist + dotsize - dotp] = '/';
|
||||
memcpy (&name[dotlist + dotsize - dotp + 1],
|
||||
d->d_name, namlen + 1);
|
||||
if (lstat (name, &st) < 0)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
#else
|
||||
saved_errno = errno;
|
||||
#endif
|
||||
}
|
||||
if (st.st_dev == thisdev && st.st_ino == thisino)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d == NULL)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
#else
|
||||
int save = errno ? errno : saved_errno;
|
||||
#endif
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t space;
|
||||
|
||||
while ((space = pathp - pathbuf) <= namlen)
|
||||
{
|
||||
char *new;
|
||||
|
||||
if (pathbuf == path)
|
||||
{
|
||||
new = (char *)malloc (pathsize * 2);
|
||||
if (!new)
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
|
||||
if (!new)
|
||||
goto lose;
|
||||
pathp = new + space;
|
||||
}
|
||||
(void) memcpy (new + pathsize + space, pathp, pathsize - space);
|
||||
pathp = new + pathsize + space;
|
||||
pathbuf = new;
|
||||
pathsize *= 2;
|
||||
}
|
||||
|
||||
pathp -= namlen;
|
||||
(void) memcpy (pathp, d->d_name, namlen);
|
||||
*--pathp = '/';
|
||||
(void) closedir (dirstream);
|
||||
}
|
||||
|
||||
thisdev = dotdev;
|
||||
thisino = dotino;
|
||||
}
|
||||
|
||||
if (pathp == &path[sizeof(path) - 1])
|
||||
*--pathp = '/';
|
||||
|
||||
if (dotlist != dots)
|
||||
free ((PTR_T) dotlist);
|
||||
|
||||
{
|
||||
size_t len = pathbuf + pathsize - pathp;
|
||||
if (buf == NULL && size <= 0)
|
||||
size = len;
|
||||
|
||||
if ((size_t) size < len)
|
||||
{
|
||||
errno = ERANGE;
|
||||
goto lose2;
|
||||
}
|
||||
if (buf == NULL)
|
||||
{
|
||||
buf = (char *) malloc (size);
|
||||
if (buf == NULL)
|
||||
goto lose2;
|
||||
}
|
||||
|
||||
(void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
|
||||
}
|
||||
|
||||
if (pathbuf != path)
|
||||
free (pathbuf);
|
||||
|
||||
return (buf);
|
||||
|
||||
lose:
|
||||
if ((dotlist != dots) && dotlist)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR_T) dotlist);
|
||||
errno = e;
|
||||
}
|
||||
|
||||
lose2:
|
||||
if ((pathbuf != path) && pathbuf)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR_T) pathbuf);
|
||||
errno = e;
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
# include <stdio.h>
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char b[PATH_MAX];
|
||||
|
||||
if (getcwd(b, sizeof(b)))
|
||||
{
|
||||
printf ("%s\n", b);
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
perror ("cwd: getcwd");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#endif /* TEST */
|
||||
#endif /* !HAVE_GETCWD */
|
Loading…
Add table
Add a link
Reference in a new issue