mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-04 09:12:27 +02:00
Imported from ../bash-3.2.tar.gz.
This commit is contained in:
@@ -101,14 +101,7 @@ static int test_error_return;
|
||||
#define test_exit(val) \
|
||||
do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0)
|
||||
|
||||
/* We have to use access(2) for machines running AFS, because it's
|
||||
not a Unix file system. This may produce incorrect answers for
|
||||
non-AFS files. I hate AFS. */
|
||||
#if defined (AFS)
|
||||
# define EACCESS(path, mode) access(path, mode)
|
||||
#else
|
||||
# define EACCESS(path, mode) test_eaccess(path, mode)
|
||||
#endif /* AFS */
|
||||
extern int sh_stat __P((const char *, struct stat *));
|
||||
|
||||
static int pos; /* The offset of the current argument in ARGV. */
|
||||
static int argc; /* The number of arguments present in ARGV. */
|
||||
@@ -119,8 +112,6 @@ static void test_syntax_error __P((char *, char *)) __attribute__((__noreturn__)
|
||||
static void beyond __P((void)) __attribute__((__noreturn__));
|
||||
static void integer_expected_error __P((char *)) __attribute__((__noreturn__));
|
||||
|
||||
static int test_stat __P((char *, struct stat *));
|
||||
|
||||
static int unary_operator __P((void));
|
||||
static int binary_operator __P((void));
|
||||
static int two_arguments __P((void));
|
||||
@@ -163,96 +154,6 @@ integer_expected_error (pch)
|
||||
test_syntax_error (_("%s: integer expression expected"), pch);
|
||||
}
|
||||
|
||||
/* A wrapper for stat () which disallows pathnames that are empty strings
|
||||
and handles /dev/fd emulation on systems that don't have it. */
|
||||
static int
|
||||
test_stat (path, finfo)
|
||||
char *path;
|
||||
struct stat *finfo;
|
||||
{
|
||||
if (*path == '\0')
|
||||
{
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
|
||||
{
|
||||
#if !defined (HAVE_DEV_FD)
|
||||
intmax_t fd;
|
||||
int r;
|
||||
|
||||
if (legal_number (path + 8, &fd) && fd == (int)fd)
|
||||
{
|
||||
r = fstat ((int)fd, finfo);
|
||||
if (r == 0 || errno != EBADF)
|
||||
return (r);
|
||||
}
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
#else
|
||||
/* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
|
||||
trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
|
||||
On most systems, with the notable exception of linux, this is
|
||||
effectively a no-op. */
|
||||
char pbuf[32];
|
||||
strcpy (pbuf, DEV_FD_PREFIX);
|
||||
strcat (pbuf, path + 8);
|
||||
return (stat (pbuf, finfo));
|
||||
#endif /* !HAVE_DEV_FD */
|
||||
}
|
||||
#if !defined (HAVE_DEV_STDIN)
|
||||
else if (STREQN (path, "/dev/std", 8))
|
||||
{
|
||||
if (STREQ (path+8, "in"))
|
||||
return (fstat (0, finfo));
|
||||
else if (STREQ (path+8, "out"))
|
||||
return (fstat (1, finfo));
|
||||
else if (STREQ (path+8, "err"))
|
||||
return (fstat (2, finfo));
|
||||
else
|
||||
return (stat (path, finfo));
|
||||
}
|
||||
#endif /* !HAVE_DEV_STDIN */
|
||||
return (stat (path, finfo));
|
||||
}
|
||||
|
||||
/* Do the same thing access(2) does, but use the effective uid and gid,
|
||||
and don't make the mistake of telling root that any file is
|
||||
executable. */
|
||||
int
|
||||
test_eaccess (path, mode)
|
||||
char *path;
|
||||
int mode;
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (test_stat (path, &st) < 0)
|
||||
return (-1);
|
||||
|
||||
if (current_user.euid == 0)
|
||||
{
|
||||
/* Root can read or write any file. */
|
||||
if (mode != X_OK)
|
||||
return (0);
|
||||
|
||||
/* Root can execute any file that has any one of the execute
|
||||
bits set. */
|
||||
if (st.st_mode & S_IXUGO)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (st.st_uid == current_user.euid) /* owner */
|
||||
mode <<= 6;
|
||||
else if (group_member (st.st_gid))
|
||||
mode <<= 3;
|
||||
|
||||
if (st.st_mode & mode)
|
||||
return (0);
|
||||
|
||||
errno = EACCES;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Increment our position in the argument list. Check that we're not
|
||||
past the end of the argument list. This check is supressed if the
|
||||
argument is FALSE. Made a macro for efficiency. */
|
||||
@@ -394,12 +295,12 @@ filecomp (s, t, op)
|
||||
struct stat st1, st2;
|
||||
int r1, r2;
|
||||
|
||||
if ((r1 = test_stat (s, &st1)) < 0)
|
||||
if ((r1 = sh_stat (s, &st1)) < 0)
|
||||
{
|
||||
if (op == EF)
|
||||
return (FALSE);
|
||||
}
|
||||
if ((r2 = test_stat (t, &st2)) < 0)
|
||||
if ((r2 = sh_stat (t, &st2)) < 0)
|
||||
{
|
||||
if (op == EF)
|
||||
return (FALSE);
|
||||
@@ -597,31 +498,31 @@ unary_test (op, arg)
|
||||
{
|
||||
case 'a': /* file exists in the file system? */
|
||||
case 'e':
|
||||
return (test_stat (arg, &stat_buf) == 0);
|
||||
return (sh_stat (arg, &stat_buf) == 0);
|
||||
|
||||
case 'r': /* file is readable? */
|
||||
return (EACCESS (arg, R_OK) == 0);
|
||||
return (sh_eaccess (arg, R_OK) == 0);
|
||||
|
||||
case 'w': /* File is writeable? */
|
||||
return (EACCESS (arg, W_OK) == 0);
|
||||
return (sh_eaccess (arg, W_OK) == 0);
|
||||
|
||||
case 'x': /* File is executable? */
|
||||
return (EACCESS (arg, X_OK) == 0);
|
||||
return (sh_eaccess (arg, X_OK) == 0);
|
||||
|
||||
case 'O': /* File is owned by you? */
|
||||
return (test_stat (arg, &stat_buf) == 0 &&
|
||||
return (sh_stat (arg, &stat_buf) == 0 &&
|
||||
(uid_t) current_user.euid == (uid_t) stat_buf.st_uid);
|
||||
|
||||
case 'G': /* File is owned by your group? */
|
||||
return (test_stat (arg, &stat_buf) == 0 &&
|
||||
return (sh_stat (arg, &stat_buf) == 0 &&
|
||||
(gid_t) current_user.egid == (gid_t) stat_buf.st_gid);
|
||||
|
||||
case 'N':
|
||||
return (test_stat (arg, &stat_buf) == 0 &&
|
||||
return (sh_stat (arg, &stat_buf) == 0 &&
|
||||
stat_buf.st_atime <= stat_buf.st_mtime);
|
||||
|
||||
case 'f': /* File is a file? */
|
||||
if (test_stat (arg, &stat_buf) < 0)
|
||||
if (sh_stat (arg, &stat_buf) < 0)
|
||||
return (FALSE);
|
||||
|
||||
/* -f is true if the given file exists and is a regular file. */
|
||||
@@ -632,29 +533,29 @@ unary_test (op, arg)
|
||||
#endif /* !S_IFMT */
|
||||
|
||||
case 'd': /* File is a directory? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode)));
|
||||
return (sh_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode)));
|
||||
|
||||
case 's': /* File has something in it? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0);
|
||||
return (sh_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0);
|
||||
|
||||
case 'S': /* File is a socket? */
|
||||
#if !defined (S_ISSOCK)
|
||||
return (FALSE);
|
||||
#else
|
||||
return (test_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));
|
||||
return (sh_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));
|
||||
#endif /* S_ISSOCK */
|
||||
|
||||
case 'c': /* File is character special? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode));
|
||||
return (sh_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode));
|
||||
|
||||
case 'b': /* File is block special? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode));
|
||||
return (sh_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode));
|
||||
|
||||
case 'p': /* File is a named pipe? */
|
||||
#ifndef S_ISFIFO
|
||||
return (FALSE);
|
||||
#else
|
||||
return (test_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));
|
||||
return (sh_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));
|
||||
#endif /* S_ISFIFO */
|
||||
|
||||
case 'L': /* Same as -h */
|
||||
@@ -667,17 +568,17 @@ unary_test (op, arg)
|
||||
#endif /* S_IFLNK && HAVE_LSTAT */
|
||||
|
||||
case 'u': /* File is setuid? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0);
|
||||
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0);
|
||||
|
||||
case 'g': /* File is setgid? */
|
||||
return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0);
|
||||
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0);
|
||||
|
||||
case 'k': /* File has sticky bit set? */
|
||||
#if !defined (S_ISVTX)
|
||||
/* This is not Posix, and is not defined on some Posix systems. */
|
||||
return (FALSE);
|
||||
#else
|
||||
return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);
|
||||
return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);
|
||||
#endif
|
||||
|
||||
case 't': /* File fd is a terminal? */
|
||||
|
||||
Reference in New Issue
Block a user