diff options
Diffstat (limited to 'posix/tst-chmod.c')
-rw-r--r-- | posix/tst-chmod.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/posix/tst-chmod.c b/posix/tst-chmod.c new file mode 100644 index 0000000..f7a37fa --- /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" |