From: Eric Blake Date: Mon, 9 Aug 2010 17:16:07 +0000 (-0600) Subject: readlinkat: split into its own module X-Git-Tag: v0.1~3948 X-Git-Url: http://erislabs.net/gitweb/?p=gnulib.git;a=commitdiff_plain;h=be5bb85c5cbfe813efb92e7de9c8d29860de8f09 readlinkat: split into its own module * modules/symlinkat: Split readlinkat... * modules/readlinkat: ...into separate module. * m4/symlinkat.m4 (gl_FUNC_SYMLINKAT): Move readlinkat check... * m4/readlinkat.m4 (gl_FUNC_READLINAT): ...to new file. * lib/symlinkat.c (readlinkat): Move... * lib/readlinkat.c: ...into new file. * modules/symlinkat-tests: Split readlinkat test... * modules/readlinkat-tests: ...into separate module. * tests/test-symlinkat.c: Split... * tests/test-readlinkat.c: ...into new file. * NEWS: Document the split. * doc/posix-functions/readlinkat.texi (readlinkat): Likewise. * lib/unistd.in.h (readlinkat): Likewise. Suggested by Bruno Haible. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 3c7a86eb4..2e7143829 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2010-08-09 Eric Blake + + readlinkat: split into its own module + * modules/symlinkat: Split readlinkat... + * modules/readlinkat: ...into separate module. + * m4/symlinkat.m4 (gl_FUNC_SYMLINKAT): Move readlinkat check... + * m4/readlinkat.m4 (gl_FUNC_READLINAT): ...to new file. + * lib/symlinkat.c (readlinkat): Move... + * lib/readlinkat.c: ...into new file. + * modules/symlinkat-tests: Split readlinkat test... + * modules/readlinkat-tests: ...into separate module. + * tests/test-symlinkat.c: Split... + * tests/test-readlinkat.c: ...into new file. + * NEWS: Document the split. + * doc/posix-functions/readlinkat.texi (readlinkat): Likewise. + * lib/unistd.in.h (readlinkat): Likewise. + Suggested by Bruno Haible. + 2010-08-08 Bruno Haible memxfrm: Speed up. diff --git a/NEWS b/NEWS index f8b125a36..ff3bfb6c2 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ User visible incompatible changes Date Modules Changes +2010-08-09 symlinkat This module now only provides symlinkat; use the + new module 'readlinkat' if needed. + 2010-07-31 ansi-c++-opt If Autoconf >= 2.66 is used, the 'configure' option is now called --disable-c++ rather than --disable-cxx. diff --git a/doc/posix-functions/readlinkat.texi b/doc/posix-functions/readlinkat.texi index 2cbaf624a..4cef74368 100644 --- a/doc/posix-functions/readlinkat.texi +++ b/doc/posix-functions/readlinkat.texi @@ -4,7 +4,7 @@ POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/readlinkat.html} -Gnulib module: symlinkat +Gnulib module: readlinkat Portability problems fixed by Gnulib: @itemize diff --git a/lib/readlinkat.c b/lib/readlinkat.c new file mode 100644 index 000000000..de80ba307 --- /dev/null +++ b/lib/readlinkat.c @@ -0,0 +1,47 @@ +/* Read a symlink relative to an open directory. + Copyright (C) 2009-2010 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 . */ + +/* written by Eric Blake */ + +#include + +#include + +/* Gnulib provides a readlink stub for mingw; use it for distinction + between EINVAL and ENOENT, rather than always failing with ENOSYS. */ + +/* POSIX 2008 says that unlike readlink, readlinkat returns 0 for + success instead of the buffer length. But this would render + readlinkat worthless since readlink does not guarantee a + NUL-terminated buffer. Assume this was a bug in POSIX. */ + +/* Read the contents of symlink FILE into buffer BUF of size LEN, in the + directory open on descriptor FD. If possible, do it without changing + the working directory. Otherwise, resort to using save_cwd/fchdir, + then readlink/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ + +#define AT_FUNC_NAME readlinkat +#define AT_FUNC_F1 readlink +#define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len +#define AT_FUNC_POST_FILE_ARGS , buf, len +#define AT_FUNC_RESULT ssize_t +#include "at-func.c" +#undef AT_FUNC_NAME +#undef AT_FUNC_F1 +#undef AT_FUNC_POST_FILE_PARAM_DECLS +#undef AT_FUNC_POST_FILE_ARGS +#undef AT_FUNC_RESULT diff --git a/lib/symlinkat.c b/lib/symlinkat.c index c01b3228d..57cd5c5f8 100644 --- a/lib/symlinkat.c +++ b/lib/symlinkat.c @@ -74,29 +74,3 @@ symlinkat (char const *contents, int fd, char const *file) } #endif /* HAVE_SYMLINK */ - -/* Gnulib provides a readlink stub for mingw; use it for distinction - between EINVAL and ENOENT, rather than always failing with ENOSYS. */ - -/* POSIX 2008 says that unlike readlink, readlinkat returns 0 for - success instead of the buffer length. But this would render - readlinkat worthless since readlink does not guarantee a - NUL-terminated buffer. Assume this was a bug in POSIX. */ - -/* Read the contents of symlink FILE into buffer BUF of size LEN, in the - directory open on descriptor FD. If possible, do it without changing - the working directory. Otherwise, resort to using save_cwd/fchdir, - then readlink/restore_cwd. If either the save_cwd or the restore_cwd - fails, then give a diagnostic and exit nonzero. */ - -#define AT_FUNC_NAME readlinkat -#define AT_FUNC_F1 readlink -#define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len -#define AT_FUNC_POST_FILE_ARGS , buf, len -#define AT_FUNC_RESULT ssize_t -#include "at-func.c" -#undef AT_FUNC_NAME -#undef AT_FUNC_F1 -#undef AT_FUNC_POST_FILE_PARAM_DECLS -#undef AT_FUNC_POST_FILE_ARGS -#undef AT_FUNC_RESULT diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 49f6badf4..4c9a4a8f9 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -1097,7 +1097,7 @@ _GL_CXXALIASWARN (readlinkat); # undef readlinkat # if HAVE_RAW_DECL_READLINKAT _GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " - "use gnulib module symlinkat for portability"); + "use gnulib module readlinkat for portability"); # endif #endif diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4 new file mode 100644 index 000000000..a3897498a --- /dev/null +++ b/m4/readlinkat.m4 @@ -0,0 +1,21 @@ +# serial 1 +# See if we need to provide readlinkat replacement. + +dnl Copyright (C) 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Written by Eric Blake. + +AC_DEFUN([gl_FUNC_READLINKAT], +[ + AC_REQUIRE([gl_FUNC_OPENAT]) + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + AC_CHECK_FUNCS_ONCE([readlinkat]) + if test $ac_cv_func_readlinkat = no; then + HAVE_READLINKAT=0 + AC_LIBOBJ([readlinkat]) + fi +]) diff --git a/m4/symlinkat.m4 b/m4/symlinkat.m4 index 8466944a5..ed8bb87cd 100644 --- a/m4/symlinkat.m4 +++ b/m4/symlinkat.m4 @@ -1,5 +1,5 @@ -# serial 3 -# See if we need to provide symlinkat/readlinkat replacement. +# serial 4 +# See if we need to provide symlinkat replacement. dnl Copyright (C) 2009-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation @@ -13,11 +13,9 @@ AC_DEFUN([gl_FUNC_SYMLINKAT], AC_REQUIRE([gl_FUNC_OPENAT]) AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - AC_CHECK_FUNCS_ONCE([symlinkat readlinkat]) + AC_CHECK_FUNCS_ONCE([symlinkat]) if test $ac_cv_func_symlinkat = no; then - # No known system has readlinkat but not symlinkat HAVE_SYMLINKAT=0 - HAVE_READLINKAT=0 AC_LIBOBJ([symlinkat]) fi ]) diff --git a/modules/readlinkat b/modules/readlinkat new file mode 100644 index 000000000..593f2c257 --- /dev/null +++ b/modules/readlinkat @@ -0,0 +1,29 @@ +Description: +readlinkat(): read symlinks relative to a directory + +Files: +lib/readlinkat.c +m4/readlinkat.m4 + +Depends-on: +extensions +fcntl-h +openat +readlink +unistd + +configure.ac: +gl_FUNC_READLINKAT +gl_UNISTD_MODULE_INDICATOR([readlinkat]) + +Makefile.am: + +Include: + + + +License: +GPL + +Maintainer: +Jim Meyering, Eric Blake diff --git a/modules/readlinkat-tests b/modules/readlinkat-tests new file mode 100644 index 000000000..de23df8dd --- /dev/null +++ b/modules/readlinkat-tests @@ -0,0 +1,16 @@ +Files: +tests/test-readlink.h +tests/test-readlinkat.c +tests/signature.h +tests/macros.h + +Depends-on: +ignore-value +symlinkat + +configure.ac: + +Makefile.am: +TESTS += test-readlinkat +check_PROGRAMS += test-readlinkat +test_readlinkat_LDADD = $(LDADD) @LIBINTL@ diff --git a/modules/symlinkat b/modules/symlinkat index 1a065fdfe..16646be69 100644 --- a/modules/symlinkat +++ b/modules/symlinkat @@ -1,5 +1,5 @@ Description: -symlinkat() and readlinkat(): manage symlinks relative to a directory +symlinkat(): create symlinks relative to a directory Files: lib/symlinkat.c @@ -9,14 +9,12 @@ Depends-on: extensions fcntl-h openat -readlink symlink unistd configure.ac: gl_FUNC_SYMLINKAT gl_UNISTD_MODULE_INDICATOR([symlinkat]) -gl_UNISTD_MODULE_INDICATOR([readlinkat]) Makefile.am: diff --git a/modules/symlinkat-tests b/modules/symlinkat-tests index c1678c021..90331494a 100644 --- a/modules/symlinkat-tests +++ b/modules/symlinkat-tests @@ -1,5 +1,4 @@ Files: -tests/test-readlink.h tests/test-symlink.h tests/test-symlinkat.c tests/signature.h diff --git a/tests/test-readlinkat.c b/tests/test-readlinkat.c new file mode 100644 index 000000000..5a5d80681 --- /dev/null +++ b/tests/test-readlinkat.c @@ -0,0 +1,108 @@ +/* Tests of readlinkat. + Copyright (C) 2009, 2010 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 . */ + +/* Written by Eric Blake , 2009. */ + +#include + +#include + +#include "signature.h" +SIGNATURE_CHECK (readlinkat, ssize_t, (int, char const *, char *, size_t)); + +#include +#include +#include +#include +#include +#include +#include + +#include "ignore-value.h" +#include "macros.h" + +#ifndef HAVE_SYMLINK +# define HAVE_SYMLINK 0 +#endif + +#define BASE "test-readlinkat.t" + +#include "test-readlink.h" + +static int dfd = AT_FDCWD; + +static ssize_t +do_readlink (char const *name, char *buf, size_t len) +{ + return readlinkat (dfd, name, buf, len); +} + +int +main (void) +{ + char buf[80]; + int result; + + /* Remove any leftovers from a previous partial run. */ + ignore_value (system ("rm -rf " BASE "*")); + + /* Perform same checks as counterpart functions. */ + result = test_readlink (do_readlink, false); + dfd = openat (AT_FDCWD, ".", O_RDONLY); + ASSERT (0 <= dfd); + ASSERT (test_readlink (do_readlink, false) == result); + + /* Now perform some cross-directory checks. Skip everything else on + mingw. */ + if (HAVE_SYMLINK) + { + const char *contents = "don't matter!"; + ssize_t exp = strlen (contents); + + /* Create link while cwd is '.', then read it in '..'. */ + ASSERT (symlinkat (contents, AT_FDCWD, BASE "link") == 0); + errno = 0; + ASSERT (symlinkat (contents, dfd, BASE "link") == -1); + ASSERT (errno == EEXIST); + ASSERT (chdir ("..") == 0); + errno = 0; + ASSERT (readlinkat (AT_FDCWD, BASE "link", buf, sizeof buf) == -1); + ASSERT (errno == ENOENT); + ASSERT (readlinkat (dfd, BASE "link", buf, sizeof buf) == exp); + ASSERT (strncmp (contents, buf, exp) == 0); + ASSERT (unlinkat (dfd, BASE "link", 0) == 0); + + /* Create link while cwd is '..', then read it in '.'. */ + ASSERT (symlinkat (contents, dfd, BASE "link") == 0); + ASSERT (fchdir (dfd) == 0); + errno = 0; + ASSERT (symlinkat (contents, AT_FDCWD, BASE "link") == -1); + ASSERT (errno == EEXIST); + buf[0] = '\0'; + ASSERT (readlinkat (AT_FDCWD, BASE "link", buf, sizeof buf) == exp); + ASSERT (strncmp (contents, buf, exp) == 0); + buf[0] = '\0'; + ASSERT (readlinkat (dfd, BASE "link", buf, sizeof buf) == exp); + ASSERT (strncmp (contents, buf, exp) == 0); + ASSERT (unlink (BASE "link") == 0); + } + + ASSERT (close (dfd) == 0); + if (result == 77) + fputs ("skipping test: symlinks not supported on this file system\n", + stderr); + return result; +} diff --git a/tests/test-symlinkat.c b/tests/test-symlinkat.c index c3dec293d..8cdc86d79 100644 --- a/tests/test-symlinkat.c +++ b/tests/test-symlinkat.c @@ -1,4 +1,4 @@ -/* Tests of symlinkat and readlinkat. +/* Tests of symlinkat. Copyright (C) 2009, 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -22,7 +22,6 @@ #include "signature.h" SIGNATURE_CHECK (symlinkat, int, (char const *, int, char const *)); -SIGNATURE_CHECK (readlinkat, ssize_t, (int, char const *, char *, size_t)); #include #include @@ -41,7 +40,6 @@ SIGNATURE_CHECK (readlinkat, ssize_t, (int, char const *, char *, size_t)); #define BASE "test-symlinkat.t" -#include "test-readlink.h" #include "test-symlink.h" static int dfd = AT_FDCWD; @@ -52,12 +50,6 @@ do_symlink (char const *contents, char const *name) return symlinkat (contents, dfd, name); } -static ssize_t -do_readlink (char const *name, char *buf, size_t len) -{ - return readlinkat (dfd, name, buf, len); -} - int main (void) { @@ -68,48 +60,11 @@ main (void) ignore_value (system ("rm -rf " BASE "*")); /* Perform same checks as counterpart functions. */ - result = test_readlink (do_readlink, false); - ASSERT (test_symlink (do_symlink, false) == result); + result = test_symlink (do_symlink, false); dfd = openat (AT_FDCWD, ".", O_RDONLY); ASSERT (0 <= dfd); - ASSERT (test_readlink (do_readlink, false) == result); ASSERT (test_symlink (do_symlink, false) == result); - /* Now perform some cross-directory checks. Skip everything else on - mingw. */ - if (HAVE_SYMLINK) - { - const char *contents = "don't matter!"; - ssize_t exp = strlen (contents); - - /* Create link while cwd is '.', then read it in '..'. */ - ASSERT (symlinkat (contents, AT_FDCWD, BASE "link") == 0); - errno = 0; - ASSERT (symlinkat (contents, dfd, BASE "link") == -1); - ASSERT (errno == EEXIST); - ASSERT (chdir ("..") == 0); - errno = 0; - ASSERT (readlinkat (AT_FDCWD, BASE "link", buf, sizeof buf) == -1); - ASSERT (errno == ENOENT); - ASSERT (readlinkat (dfd, BASE "link", buf, sizeof buf) == exp); - ASSERT (strncmp (contents, buf, exp) == 0); - ASSERT (unlinkat (dfd, BASE "link", 0) == 0); - - /* Create link while cwd is '..', then read it in '.'. */ - ASSERT (symlinkat (contents, dfd, BASE "link") == 0); - ASSERT (fchdir (dfd) == 0); - errno = 0; - ASSERT (symlinkat (contents, AT_FDCWD, BASE "link") == -1); - ASSERT (errno == EEXIST); - buf[0] = '\0'; - ASSERT (readlinkat (AT_FDCWD, BASE "link", buf, sizeof buf) == exp); - ASSERT (strncmp (contents, buf, exp) == 0); - buf[0] = '\0'; - ASSERT (readlinkat (dfd, BASE "link", buf, sizeof buf) == exp); - ASSERT (strncmp (contents, buf, exp) == 0); - ASSERT (unlink (BASE "link") == 0); - } - ASSERT (close (dfd) == 0); if (result == 77) fputs ("skipping test: symlinks not supported on this file system\n",