1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-05-13 15:13:36 +00:00

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 <eblake@redhat.com>
This commit is contained in:
Eric Blake
2010-08-09 11:16:07 -06:00
parent acc2624907
commit be5bb85c5c
14 changed files with 250 additions and 84 deletions

View File

@@ -1,3 +1,21 @@
2010-08-09 Eric Blake <eblake@redhat.com>
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 <bruno@clisp.org>
memxfrm: Speed up.

3
NEWS
View File

@@ -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.

View File

@@ -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

47
lib/readlinkat.c Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>. */
/* written by Eric Blake */
#include <config.h>
#include <unistd.h>
/* 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

View File

@@ -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

View File

@@ -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

21
m4/readlinkat.m4 Normal file
View File

@@ -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
])

View File

@@ -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
])

29
modules/readlinkat Normal file
View File

@@ -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:
<fcntl.h>
<unistd.h>
License:
GPL
Maintainer:
Jim Meyering, Eric Blake

16
modules/readlinkat-tests Normal file
View File

@@ -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@

View File

@@ -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:

View File

@@ -1,5 +1,4 @@
Files:
tests/test-readlink.h
tests/test-symlink.h
tests/test-symlinkat.c
tests/signature.h

108
tests/test-readlinkat.c Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>. */
/* Written by Eric Blake <ebb9@byu.net>, 2009. */
#include <config.h>
#include <unistd.h>
#include "signature.h"
SIGNATURE_CHECK (readlinkat, ssize_t, (int, char const *, char *, size_t));
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#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;
}

View File

@@ -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 <fcntl.h>
#include <errno.h>
@@ -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",