diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | posix/Makefile | 4 | ||||
-rw-r--r-- | posix/tst-chmod.c | 368 | ||||
-rw-r--r-- | posix/tst-exec.c | 21 | ||||
-rw-r--r-- | posix/tst-spawn.c | 21 | ||||
-rw-r--r-- | sysdeps/unix/opendir.c | 21 | ||||
-rw-r--r-- | test-skeleton.c | 4 |
7 files changed, 422 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog index 1156695fef..5ff289c43d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2000-10-26 Ulrich Drepper <drepper@redhat.com> + + * posix/Makefile (tests): Add tst-chmod. + (tst-chmod-ARGS): Define. + * posix/tst-chmod.c: New file. + + * test-skeleton.c: Before calling user-defined function remove + parameters from argument list. + * posix/tst-exec.c: Adjust to this change. + * posix/tst-spawn.c: Likewise. + + * sysdeps/unix/opendir.c (__opendir): Optimize a bit. Add + __builtin_expect. + 2000-10-25 Ulrich Drepper <drepper@redhat.com> * intl/Makefile (tests): Add tst-ngettext. diff --git a/posix/Makefile b/posix/Makefile index 3430d3c0c5..4329566c0b 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -68,7 +68,8 @@ aux := init-posix environ tests := tstgetopt testfnm runtests runptests \ tst-preadwrite tst-preadwrite64 test-vfork regexbug1 \ tst-getlogin tst-mmap tst-getaddrinfo tst-truncate \ - tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir + tst-truncate64 tst-fork tst-fnmatch tst-regexloc tst-dir \ + tst-chmod ifeq (yes,$(build-shared)) test-srcs := globtest tests += wordexp-test tst-exec tst-spawn @@ -114,6 +115,7 @@ tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \ tst-exec-ARGS = -- $(built-program-cmd) tst-spawn-ARGS = -- $(built-program-cmd) tst-dir-ARGS = `pwd` "$(objdir)/$(subdir)" "$(common-objdir)" $(objpfx)tst-dir +tst-chmod-ARGS = $(objpfx) tst-fnmatch-ENV = LOCPATH=$(common-objpfx)localedata tst-regexloc-ENV = LOCPATH=$(common-objpfx)localedata diff --git a/posix/tst-chmod.c b/posix/tst-chmod.c new file mode 100644 index 0000000000..f7a37fa3a3 --- /dev/null +++ b/posix/tst-chmod.c @@ -0,0 +1,368 @@ +/* Test for chmod functions. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <dirent.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <mcheck.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + + +#define OUT_OF_MEMORY \ + do { \ + puts ("cannot allocate memory"); \ + result = 1; \ + goto fail; \ + } while (0) + +int +do_test (int argc, char *argv[]) +{ + const char *builddir; + struct stat64 st1; + struct stat64 st2; + char *buf; + char *testdir; + char *testfile = NULL; + char *startdir; + size_t buflen; + int fd; + int result = 0; + DIR *dir; + + mtrace (); + + if (argc <= 1) + error (EXIT_FAILURE, 0, "no parameters"); + + /* This is where we will create the test files. */ + builddir = argv[1]; + buflen = strlen (builddir) + 50; + + startdir = getcwd (NULL, 0); + if (startdir == NULL) + { + printf ("cannot get current directory: %m\n"); + exit (EXIT_FAILURE); + } + + /* A buffer large enough for everything we need. */ + buf = (char *) alloca (buflen); + + /* Create the directory name. */ + snprintf (buf, buflen, "%schmoddirXXXXXX", builddir); + + if (mkdtemp (buf) == NULL) + { + printf ("cannot create test directory: %m\n"); + exit (EXIT_FAILURE); + } + + if (chmod ("", 0600) == 0) + { + puts ("chmod(\"\", 0600 didn't fail"); + result = 1; + } + else if (errno != ENOENT) + { + puts ("chmod(\"\",0600) does not set errno to ENOENT"); + result = 1; + } + + /* Create a duplicate. */ + testdir = strdup (buf); + if (testdir == NULL) + OUT_OF_MEMORY; + + if (stat64 (testdir, &st1) != 0) + { + printf ("cannot stat test directory: %m\n"); + exit (1); + } + if (!S_ISDIR (st1.st_mode)) + { + printf ("file not created as directory: %m\n"); + exit (1); + } + + /* We have to wait for a second to make sure the ctime changes. */ + sleep (1); + + /* Remove all access rights from the directory. */ + if (chmod (testdir, 0) != 0) + { + printf ("cannot change mode of test directory: %m\n"); + result = 1; + goto fail; + } + + if (stat64 (testdir, &st2) != 0) + { + printf ("cannot stat test directory: %m\n"); + result = 1; + goto fail; + } + + /* Compare result. */ + if ((st2.st_mode & ALLPERMS) != 0) + { + printf ("chmod(...,0) on directory left bits nonzero: %o\n", + st2.st_mode & ALLPERMS); + result = 1; + } + if (st1.st_ctime >= st2.st_ctime) + { + puts ("chmod(...,0) did not set ctime correctly"); + result = 1; + } + + /* Name of a file in the directory. */ + snprintf (buf, buflen, "%s/file", testdir); + testfile = strdup (buf); + if (testfile == NULL) + OUT_OF_MEMORY; + + fd = creat (testfile, 0); + if (fd != -1) + { + puts ("managed to create test file in protected directory"); + result = 1; + close (fd); + } + if (errno != EACCES) + { + puts ("creat didn't generate correct errno value"); + result = 1; + } + + /* With this mode it still shouldn't be possible to create a file. */ + if (chmod (testdir, 0600) != 0) + { + printf ("cannot change mode of test directory to 0600: %m\n"); + result = 1; + goto fail; + } + + fd = creat (testfile, 0); + if (fd != -1) + { + puts ("managed to create test file in no-x protected directory"); + result = 1; + close (fd); + } + if (errno != EACCES) + { + puts ("creat didn't generate correct errno value"); + result = 1; + } + + /* Change the directory mode back to allow creating a file. This + time with fchmod. */ + dir = opendir (testdir); + if (dir != NULL) + { + if (fchmod (dirfd (dir), 0700) != 0) + { + printf ("cannot change mode of test directory to 0700: %m\n"); + result = 1; + closedir (dir); + goto fail; + } + + closedir (dir); + } + else + { + printf ("cannot open directory: %m\n"); + result = 1; + + if (chmod (testdir, 0700) != 0) + { + printf ("cannot change mode of test directory to 0700: %m\n"); + goto fail; + } + } + + fd = creat (testfile, 0); + if (fd == -1) + { + puts ("still didn't manage to create test file in protected directory"); + result = 1; + goto fail; + } + if (fstat64 (fd, &st1) != 0) + { + printf ("cannot stat new file: %m\n"); + result = 1; + } + else if ((st1.st_mode & ALLPERMS) != 0) + { + puts ("file not created with access mode 0"); + result = 1; + } + close (fd); + + snprintf (buf, buflen, "%s/..", testdir); + chdir (buf); + /* We are now in the directory above the one we create the test + directory in. */ + + sleep (1); + snprintf (buf, buflen, "./%s/../%s/file", + basename (testdir), basename (testdir)); + if (chmod (buf, 0600) != 0) + { + printf ("cannot change mode of file to 0600: %m\n"); + result = 1; + goto fail; + } + snprintf (buf, buflen, "./%s//file", basename (testdir)); + if (stat64 (buf, &st2) != 0) + { + printf ("cannot stat new file: %m\n"); + result = 1; + } + else if ((st2.st_mode & ALLPERMS) != 0600) + { + puts ("file mode not changed to 0600"); + result = 1; + } + else if (st1.st_ctime >= st2.st_ctime) + { + puts ("chmod(\".../file\",0600) did not set ctime correctly"); + result = 1; + } + + if (chmod (buf, 0777 | S_ISUID | S_ISGID) != 0) + { + printf ("cannot change mode of file to %o: %m\n", + 0777 | S_ISUID | S_ISGID); + result = 1; + } + if (stat64 (buf, &st2) != 0) + { + printf ("cannot stat test file: %m\n"); + result = 1; + } + else if ((st2.st_mode & ALLPERMS) != (0777 | S_ISUID | S_ISGID)) + { + puts ("file mode not changed to 0777 | S_ISUID | S_ISGID"); + result = 1; + } + + if (chmod (basename (testdir), 0777 | S_ISUID | S_ISGID | S_ISVTX) != 0) + { + printf ("cannot change mode of test directory to %o: %m\n", + 0777 | S_ISUID | S_ISGID | S_ISVTX); + result = 1; + } + if (stat64 (basename (testdir), &st2) != 0) + { + printf ("cannot stat test directory: %m\n"); + result = 1; + } + else if ((st2.st_mode & ALLPERMS) != (0777 | S_ISUID | S_ISGID | S_ISVTX)) + { + puts ("directory mode not changed to 0777 | S_ISUID | S_ISGID | S_ISGID"); + result = 1; + } + + snprintf (buf, buflen, "./%s/no-such-file", basename (testdir)); + if (chmod (buf, 0600) != -1) + { + puts ("chmod(\".../no-such-file\",0600) did not fail"); + result = 1; + } + else if (errno != ENOENT) + { + puts ("chmod(\".../no-such-file\",0600) does not set errno to ENOENT"); + result = 1; + } + + snprintf (buf, buflen, "%s/", basename (testdir)); + if (chmod (basename (testdir), 0677) != 0) + { + printf ("cannot change mode of test directory to 0677: %m\n"); + result = 1; + } + else + { + snprintf (buf, buflen, "./%s/file", basename (testdir)); + if (chmod (buf, 0600) == 0) + { + puts ("chmod(\".../file\") with no-exec directory succeeded"); + result = 1; + } + else if (errno != EACCES) + { + puts ("chmod(\".../file\") with no-exec directory didn't set EACCES"); + result = 1; + } + } + + if (chmod (basename (testdir), 0777) != 0) + { + printf ("cannot change mode of test directory to 0777: %m\n"); + result = 1; + goto fail; + } + + snprintf (buf, buflen, "%s/file/cannot-be", basename (testdir)); + if (chmod (buf, 0600) == 0) + { + puts ("chmod(\".../file/cannot-be\",0600) did not fail"); + result = 1; + } + else if (errno != ENOTDIR) + { + puts ("chmod(\".../file/cannot-be\",0600) does not set errno to ENOTDIR"); + result = 1; + } + + fail: + chdir (startdir); + + /* Remove all the files. */ + chmod (testdir, 0700); + if (testfile != NULL) + { + chmod (testfile, 0700); + unlink (testfile); + } + rmdir (testdir); + + /* Free the resources. */ + free (testfile); + free (testdir); + free (startdir); + + return result; +} + + +/* We need a few seconds since we have a few sleeps in the code. */ +#define TIMEOUT 20 + + +#include "../test-skeleton.c" diff --git a/posix/tst-exec.c b/posix/tst-exec.c index 0cb988d1de..2c541fcd04 100644 --- a/posix/tst-exec.c +++ b/posix/tst-exec.c @@ -126,24 +126,27 @@ do_test (int argc, char *argv[]) int status; /* We must have - - five parameters left of called initially - + -- + - four parameters left of called initially + path for ld.so + "--library-path" + the library path + the application name - - five parameters left if called through re-execution - + --direct - + --restart + - three parameters left if called through re-execution + file descriptor number which is supposed to be closed + the open file descriptor + the name of the closed desriptor */ - if (argc != 6) - error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); if (restart) - return handle_restart (argv[3], argv[4], argv[5]); + { + if (argc != 4) + error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); + + return handle_restart (argv[1], argv[2], argv[3]); + } + + if (argc != 5) + error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); /* Prepare the test. We are creating two files: one which file descriptor will be marked with FD_CLOEXEC, another which is not. */ @@ -182,7 +185,7 @@ do_test (int argc, char *argv[]) snprintf (fd2name, sizeof fd2name, "%d", fd2); /* This is the child. Construct the command line. */ - execl (argv[2], argv[2], argv[3], argv[4], argv[5], "--direct", + execl (argv[1], argv[1], argv[2], argv[3], argv[4], "--direct", "--restart", fd1name, fd2name, name1, NULL); error (EXIT_FAILURE, errno, "cannot exec"); diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c index 4bc94e0544..663320c2a5 100644 --- a/posix/tst-spawn.c +++ b/posix/tst-spawn.c @@ -171,26 +171,23 @@ do_test (int argc, char *argv[]) char *spargv[12]; /* We must have - - five parameters left of called initially - + -- + - four parameters left of called initially + path for ld.so + "--library-path" + the library path + the application name - - seven parameters left if called through re-execution - + --direct - + --restart + - five parameters left if called through re-execution + file descriptor number which is supposed to be closed + the open file descriptor + the newly opened file descriptor + thhe duped second descriptor + the name of the closed descriptor */ - if (argc != (restart ? 8 : 6)) + if (argc != (restart ? 6 : 5)) error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); if (restart) - return handle_restart (argv[3], argv[4], argv[5], argv[6], argv[7]); + return handle_restart (argv[1], argv[2], argv[3], argv[4], argv[5]); /* Prepare the test. We are creating two files: one which file descriptor will be marked with FD_CLOEXEC, another which is not. */ @@ -238,10 +235,10 @@ do_test (int argc, char *argv[]) snprintf (fd3name, sizeof fd3name, "%d", fd3); snprintf (fd4name, sizeof fd4name, "%d", fd4); - spargv[0] = argv[2]; - spargv[1] = argv[3]; - spargv[2] = argv[4]; - spargv[3] = argv[5]; + spargv[0] = argv[1]; + spargv[1] = argv[2]; + spargv[2] = argv[3]; + spargv[3] = argv[4]; spargv[4] = (char *) "--direct"; spargv[5] = (char *) "--restart"; spargv[6] = fd1name; @@ -251,7 +248,7 @@ do_test (int argc, char *argv[]) spargv[10] = name1; spargv[11] = NULL; - if (posix_spawn (&pid, argv[2], &actions, NULL, spargv, environ) != 0) + if (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ) != 0) error (EXIT_FAILURE, errno, "posix_spawn"); /* Cleanup. */ diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c index ad91931de4..cf83847847 100644 --- a/sysdeps/unix/opendir.c +++ b/sysdeps/unix/opendir.c @@ -81,7 +81,7 @@ __opendir (const char *name) size_t allocation; int save_errno; - if (name[0] == '\0') + if (__builtin_expect (name[0], '\1') == '\0') { /* POSIX.1-1990 says an empty name gets ENOENT; but `open' might like it fine. */ @@ -101,9 +101,9 @@ __opendir (const char *name) /* We first have to check whether the name is for a directory. We cannot do this after the open() call since the open/close operation performed on, say, a tape device might have undesirable effects. */ - if (__xstat64 (_STAT_VER, name, &statbuf) < 0) + if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0) return NULL; - if (! S_ISDIR (statbuf.st_mode)) + if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); return NULL; @@ -111,24 +111,27 @@ __opendir (const char *name) } fd = __open (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS); - if (fd < 0) + if (__builtin_expect (fd, 0) < 0) return NULL; /* Now make sure this really is a directory and nothing changed since - the `stat' call. */ - if (__fxstat64 (_STAT_VER, fd, &statbuf) < 0) + the `stat' call. We do not have to perform the test for the + descriptor being associated with a directory if we know the + O_DIRECTORY flag is honored by the kernel. */ + if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) goto lose; - if (! S_ISDIR (statbuf.st_mode)) + if (o_directory_works <= 0 + && __builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { save_errno = ENOTDIR; goto lose; } - if (__fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) + if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) goto lose; #ifdef _STATBUF_ST_BLKSIZE - if (statbuf.st_blksize < sizeof (struct dirent)) + if (__builtin_expect (statbuf.st_blksize < sizeof (struct dirent), 0)) allocation = sizeof (struct dirent); else allocation = statbuf.st_blksize; diff --git a/test-skeleton.c b/test-skeleton.c index db04b11e63..e4cd95702d 100644 --- a/test-skeleton.c +++ b/test-skeleton.c @@ -166,6 +166,10 @@ main (int argc, char *argv[]) /* make sure temporary files are deleted. */ atexit (delete_temp_files); + /* Correct for the possible parameters. */ + argv += optind - 1; + argc -= optind - 1; + /* Call the initializing function, if one is available. */ #ifdef PREPARE PREPARE (argc, argv); |