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:
18
ChangeLog
18
ChangeLog
@@ -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
3
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.
|
||||
|
||||
@@ -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
47
lib/readlinkat.c
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
21
m4/readlinkat.m4
Normal 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
|
||||
])
|
||||
@@ -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
29
modules/readlinkat
Normal 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
16
modules/readlinkat-tests
Normal 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@
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
108
tests/test-readlinkat.c
Normal 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;
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user