Jim Meyering <jim <at> meyering.net> writes: > > Meanwhile, the rmdir-errno module, in use by coreutils until today, guessed > > wrong for cross-compilation to Solaris (where rmdir fails with EEXIST, not > > ENOTEMPTY, on a populated directory); now that coreutils no longer uses the > > module [1], I see no reason to keep the module alive. > > I was thinking of marking it as obsolete, > (AFAIK, there's been no actual problem report) > but if coreutils was the only user, deleting should be ok.
OK, I'll be nice, as obsoletion gives a bit longer transition phase if anyone else was using rmdir-errno. Also, I added a test of unlinkat, to make sure that rmdir bugs don't reappear. Path [1/2] of the previous mail is unchanged, but here's what replaces [2/2] and a new [3/2]: From: Eric Blake <e...@byu.net> Date: Wed, 16 Sep 2009 13:31:05 -0600 Subject: [PATCH 2/2] rmdir-errno: mark obsolete, it is unsafe for cross- compilation * modules/rmdir-errno (Status, Notice): Now obsolete. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 3 +++ modules/rmdir-errno | 6 ++++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index c6b3e25..e7f3669 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2009-09-16 Eric Blake <e...@byu.net> + rmdir-errno: mark obsolete, it is unsafe for cross-compilation + * modules/rmdir-errno (Status, Notice): Now obsolete. + rmdir: work around cygwin 1.5.x and mingw bugs * m4/rmdir.m4 (gl_FUNC_RMDIR): Detect the bugs. * lib/rmdir.c (rmdir): Work around it. diff --git a/modules/rmdir-errno b/modules/rmdir-errno index d0b81b6..ef02a95 100644 --- a/modules/rmdir-errno +++ b/modules/rmdir-errno @@ -1,6 +1,12 @@ Description: rmdir errno for nonempty directories +Status: +obsolete + +Notice: +This module is obsolete. + Files: m4/rmdir-errno.m4 -- 1.6.4.2 >From c433306b7db7440e27df2150decba6b89ecfc625 Mon Sep 17 00:00:00 2001 From: Eric Blake <e...@byu.net> Date: Wed, 16 Sep 2009 13:21:46 -0600 Subject: [PATCH 3/2] openat-tests: ensure unlinkat behaves like rmdir * tests/test-rmdir.c (main): Factor guts... * tests/test-rmdir.h (test_rmdir_func): ...into new file. * modules/rmdir-tests (Files): Ship new file. * modules/openat-tests: New test. * tests/test-unlinkat.c: Likewise. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 7 +++ modules/openat-tests | 13 ++++++ modules/rmdir-tests | 1 + tests/test-rmdir.c | 78 +-------------------------------- tests/{test-rmdir.c => test-rmdir.h} | 63 +++++++++------------------- tests/test-unlinkat.c | 61 ++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 118 deletions(-) create mode 100644 modules/openat-tests copy tests/{test-rmdir.c => test-rmdir.h} (63%) create mode 100644 tests/test-unlinkat.c diff --git a/ChangeLog b/ChangeLog index e7f3669..94e07e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-09-16 Eric Blake <e...@byu.net> + openat-tests: ensure unlinkat behaves like rmdir + * tests/test-rmdir.c (main): Factor guts... + * tests/test-rmdir.h (test_rmdir_func): ...into new file. + * modules/rmdir-tests (Files): Ship new file. + * modules/openat-tests: New test. + * tests/test-unlinkat.c: Likewise. + rmdir-errno: mark obsolete, it is unsafe for cross-compilation * modules/rmdir-errno (Status, Notice): Now obsolete. diff --git a/modules/openat-tests b/modules/openat-tests new file mode 100644 index 0000000..a82a4f3 --- /dev/null +++ b/modules/openat-tests @@ -0,0 +1,13 @@ +Files: +tests/test-rmdir.h +tests/test-unlinkat.c + +Depends-on: + +configure.ac: +AC_CHECK_FUNCS_ONCE([symlink]) + +Makefile.am: +TESTS += test-unlinkat +check_PROGRAMS += test-unlinkat +test_unlinkat_LDADD = $(LDADD) @LIBINTL@ diff --git a/modules/rmdir-tests b/modules/rmdir-tests index f5b69f8..2a68120 100644 --- a/modules/rmdir-tests +++ b/modules/rmdir-tests @@ -1,4 +1,5 @@ Files: +tests/test-rmdir.h tests/test-rmdir.c Depends-on: diff --git a/tests/test-rmdir.c b/tests/test-rmdir.c index 17fb0ff..6d55ea9 100644 --- a/tests/test-rmdir.c +++ b/tests/test-rmdir.c @@ -44,82 +44,10 @@ #define BASE "test-rmdir.t" +#include "test-rmdir.h" + int main () { - /* Remove any leftovers from a previous partial run. */ - ASSERT (system ("rm -rf " BASE "*") == 0); - - /* Setup. */ - ASSERT (mkdir (BASE "dir", 0700) == 0); - ASSERT (close (creat (BASE "dir/file", 0600)) == 0); - - /* Basic error conditions. */ - errno = 0; - ASSERT (rmdir ("") == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (rmdir (BASE "nosuch") == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (rmdir (BASE "nosuch/") == -1); - ASSERT (errno == ENOENT); - errno = 0; - ASSERT (rmdir (".") == -1); - ASSERT (errno == EINVAL || errno == EBUSY); - /* Resulting errno after ".." or "/" is too varied to test; it is - reasonable to see any of EINVAL, EBUSY, EEXIST, ENOTEMPTY, - EACCES, EPERM. */ - ASSERT (rmdir ("..") == -1); - ASSERT (rmdir ("/") == -1); - ASSERT (rmdir ("///") == -1); - errno = 0; - ASSERT (rmdir (BASE "dir/file/") == -1); - ASSERT (errno == ENOTDIR); - - /* Non-empty directory. */ - errno = 0; - ASSERT (rmdir (BASE "dir") == -1); - ASSERT (errno == EEXIST || errno == ENOTEMPTY); - - /* Non-directory. */ - errno = 0; - ASSERT (rmdir (BASE "dir/file") == -1); - ASSERT (errno == ENOTDIR); - - /* Empty directory. */ - ASSERT (unlink (BASE "dir/file") == 0); - errno = 0; - ASSERT (rmdir (BASE "dir/./") == -1); - ASSERT (errno == EINVAL); - ASSERT (rmdir (BASE "dir") == 0); - - /* Test symlink behavior. Specifying trailing slash should remove - referent directory (POSIX), or cause ENOTDIR failure (Linux), but - not touch symlink. We prefer the Linux behavior for its - intuitiveness (especially compared to rmdir("symlink-to-file/")), - but not enough to penalize POSIX systems with an rpl_rmdir. */ - if (symlink (BASE "dir", BASE "link") != 0) - { - fputs ("skipping test: symlinks not supported on this filesystem\n", - stderr); - return 77; - } - ASSERT (mkdir (BASE "dir", 0700) == 0); - errno = 0; - if (rmdir (BASE "link/") == 0) - { - struct stat st; - errno = 0; - ASSERT (stat (BASE "link", &st) == -1); - ASSERT (errno == ENOENT); - } - else - { - ASSERT (errno == ENOTDIR); - ASSERT (rmdir (BASE "dir") == 0); - } - ASSERT (unlink (BASE "link") == 0); - - return 0; + return test_rmdir_func (rmdir); } diff --git a/tests/test-rmdir.c b/tests/test-rmdir.h similarity index 63% copy from tests/test-rmdir.c copy to tests/test-rmdir.h index 17fb0ff..bf8cbb4 100644 --- a/tests/test-rmdir.c +++ b/tests/test-rmdir.h @@ -16,36 +16,13 @@ /* Written by Eric Blake <e...@byu.net>, 2009. */ -#include <config.h> +/* This file is designed to test both rmdir(n) and + unlinkat(AT_FDCWD,n,AT_REMOVEDIR). FUNC is the function to test. + Assumes that BASE and ASSERT are already defined, and that + appropriate headers are already included. */ -#include <unistd.h> - -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> - -#if !HAVE_SYMLINK -# define symlink(a,b) (-1) -#endif - -#define ASSERT(expr) \ - do \ - { \ - if (!(expr)) \ - { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ - abort (); \ - } \ - } \ - while (0) - -#define BASE "test-rmdir.t" - -int -main () +static int +test_rmdir_func (int (*func) (char const *name)) { /* Remove any leftovers from a previous partial run. */ ASSERT (system ("rm -rf " BASE "*") == 0); @@ -56,43 +33,43 @@ main () /* Basic error conditions. */ errno = 0; - ASSERT (rmdir ("") == -1); + ASSERT (func ("") == -1); ASSERT (errno == ENOENT); errno = 0; - ASSERT (rmdir (BASE "nosuch") == -1); + ASSERT (func (BASE "nosuch") == -1); ASSERT (errno == ENOENT); errno = 0; - ASSERT (rmdir (BASE "nosuch/") == -1); + ASSERT (func (BASE "nosuch/") == -1); ASSERT (errno == ENOENT); errno = 0; - ASSERT (rmdir (".") == -1); + ASSERT (func (".") == -1); ASSERT (errno == EINVAL || errno == EBUSY); /* Resulting errno after ".." or "/" is too varied to test; it is reasonable to see any of EINVAL, EBUSY, EEXIST, ENOTEMPTY, EACCES, EPERM. */ - ASSERT (rmdir ("..") == -1); - ASSERT (rmdir ("/") == -1); - ASSERT (rmdir ("///") == -1); + ASSERT (func ("..") == -1); + ASSERT (func ("/") == -1); + ASSERT (func ("///") == -1); errno = 0; - ASSERT (rmdir (BASE "dir/file/") == -1); + ASSERT (func (BASE "dir/file/") == -1); ASSERT (errno == ENOTDIR); /* Non-empty directory. */ errno = 0; - ASSERT (rmdir (BASE "dir") == -1); + ASSERT (func (BASE "dir") == -1); ASSERT (errno == EEXIST || errno == ENOTEMPTY); /* Non-directory. */ errno = 0; - ASSERT (rmdir (BASE "dir/file") == -1); + ASSERT (func (BASE "dir/file") == -1); ASSERT (errno == ENOTDIR); /* Empty directory. */ ASSERT (unlink (BASE "dir/file") == 0); errno = 0; - ASSERT (rmdir (BASE "dir/./") == -1); + ASSERT (func (BASE "dir/./") == -1); ASSERT (errno == EINVAL); - ASSERT (rmdir (BASE "dir") == 0); + ASSERT (func (BASE "dir") == 0); /* Test symlink behavior. Specifying trailing slash should remove referent directory (POSIX), or cause ENOTDIR failure (Linux), but @@ -107,7 +84,7 @@ main () } ASSERT (mkdir (BASE "dir", 0700) == 0); errno = 0; - if (rmdir (BASE "link/") == 0) + if (func (BASE "link/") == 0) { struct stat st; errno = 0; @@ -117,7 +94,7 @@ main () else { ASSERT (errno == ENOTDIR); - ASSERT (rmdir (BASE "dir") == 0); + ASSERT (func (BASE "dir") == 0); } ASSERT (unlink (BASE "link") == 0); diff --git a/tests/test-unlinkat.c b/tests/test-unlinkat.c new file mode 100644 index 0000000..fb87a19 --- /dev/null +++ b/tests/test-unlinkat.c @@ -0,0 +1,61 @@ +/* Tests of unlinkat. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program 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. + + This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake <e...@byu.net>, 2009. */ + +#include <config.h> + +#include <unistd.h> + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> + +#if !HAVE_SYMLINK +# define symlink(a,b) (-1) +#endif + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +#define BASE "test-unlinkat.t" + +#include "test-rmdir.h" + +/* Wrapper around unlinkat to test rmdir behavior. */ +static int +rmdirat (char const *name) +{ + return unlinkat (AT_FDCWD, name, AT_REMOVEDIR); +} + +int +main () +{ + /* FIXME: Add tests of unlinkat(,0), and of fd instead of AT_FDCWD. */ + return test_rmdir_func (rmdirat); +} -- 1.6.4.2