2009-09-17 Eric Blake <ebb9@byu.net>
+ canonicalize-lgpl: reject non-directory with trailing slash
+ * lib/canonicalize-lgpl.c (__realpath): Synchronize with glibc.
+ * tests/test-canonicalize-lgpl.c (main): Enhance test. This
+ catches failures in glibc 2.3.5.
+ * tests/test-canonicalize.c (main): Likewise.
+
canonicalize-lgpl: use native realpath if it works
* lib/canonicalize-lgpl.c (realpath): Guard with
FUNC_REALPATH_WORKS.
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 1996-2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include <config.h>
+#ifndef _LIBC
+# include <config.h>
+#endif
#if !HAVE_CANONICALIZE_FILE_NAME || defined _LIBC
-#include <alloca.h>
-
/* Specification. */
#include <stdlib.h>
-#include <stddef.h>
+#include <alloca.h>
#include <string.h>
#include <unistd.h>
-
#include <limits.h>
-
#if HAVE_SYS_PARAM_H || defined _LIBC
# include <sys/param.h>
#endif
-#ifndef MAXSYMLINKS
-# ifdef SYMLOOP_MAX
-# define MAXSYMLINKS SYMLOOP_MAX
-# else
-# define MAXSYMLINKS 20
-# endif
-#endif
-
#include <sys/stat.h>
-
#include <errno.h>
-#ifndef _LIBC
-# define __set_errno(e) errno = (e)
-#endif
+#include <stddef.h>
#ifdef _LIBC
# include <shlib-compat.h>
# define __getcwd(buf, max) getwd (buf)
# endif
# define __readlink readlink
+# define __set_errno(e) errno = (e)
+# ifndef MAXSYMLINKS
+# ifdef SYMLOOP_MAX
+# define MAXSYMLINKS SYMLOOP_MAX
+# else
+# define MAXSYMLINKS 20
+# endif
+# endif
#endif
#if !FUNC_REALPATH_WORKS || defined _LIBC
#else
struct stat st;
#endif
+ int n;
/* Skip sequence of multiple path-separators. */
while (*start == '/')
{
char *buf;
size_t len;
- int n;
if (++num_links > MAXSYMLINKS)
{
if (dest > rpath + 1)
while ((--dest)[-1] != '/');
}
+ else if (!S_ISDIR (st.st_mode) && *end != '\0')
+ {
+ __set_errno (ENOTDIR);
+ goto error;
+ }
}
}
if (dest > rpath + 1 && dest[-1] == '/')
if (extra_buf)
freea (extra_buf);
- return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;
+ return rpath;
error:
{
int saved_errno = errno;
if (extra_buf)
freea (extra_buf);
- if (resolved)
- strcpy (resolved, rpath);
- else
+ if (resolved == NULL)
free (rpath);
errno = saved_errno;
}
#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3)
char *
+attribute_compat_text_section
__old_realpath (const char *name, char *resolved)
{
if (resolved == NULL)
ASSERT (errno == EINVAL);
}
+ /* Check that a non-directory with trailing slash yields NULL. */
+ {
+ char *result;
+ errno = 0;
+ result = canonicalize_file_name (BASE "/tra/");
+ ASSERT (result == NULL);
+ ASSERT (errno == ENOTDIR);
+ }
+
+ /* Check that a missing directory yields NULL. */
+ {
+ char *result;
+ errno = 0;
+ result = canonicalize_file_name (BASE "/zzz/..");
+ ASSERT (result == NULL);
+ ASSERT (errno == ENOENT);
+ }
+
/* From here on out, tests involve symlinks. */
if (symlink (BASE "/ket", "ise") != 0)
{
ASSERT (errno == ENOENT);
}
+ /* Check that a non-directory symlink with trailing slash yields NULL. */
+ {
+ char *result;
+ errno = 0;
+ result = canonicalize_file_name (BASE "/huk/");
+ ASSERT (result == NULL);
+ ASSERT (errno == ENOTDIR);
+ }
+
+ /* Check that a missing directory via symlink yields NULL. */
+ {
+ char *result;
+ errno = 0;
+ result = canonicalize_file_name (BASE "/ouk/..");
+ ASSERT (result == NULL);
+ ASSERT (errno == ENOENT);
+ }
+
/* Check that a loop of symbolic links is detected. */
{
char *result;
ASSERT (errno == EINVAL);
}
+ /* Check that a non-directory with trailing slash yields NULL. */
+ {
+ char *result1;
+ char *result2;
+ errno = 0;
+ result1 = canonicalize_file_name (BASE "/tra/");
+ ASSERT (result1 == NULL);
+ ASSERT (errno == ENOTDIR);
+ errno = 0;
+ result2 = canonicalize_filename_mode (BASE "/tra/", CAN_EXISTING);
+ ASSERT (result2 == NULL);
+ ASSERT (errno == ENOTDIR);
+ }
+
+ /* Check that a missing directory yields NULL. */
+ {
+ char *result1;
+ char *result2;
+ errno = 0;
+ result1 = canonicalize_file_name (BASE "/zzz/..");
+ ASSERT (result1 == NULL);
+ ASSERT (errno == ENOENT);
+ errno = 0;
+ result2 = canonicalize_filename_mode (BASE "/zzz/..", CAN_EXISTING);
+ ASSERT (result2 == NULL);
+ ASSERT (errno == ENOENT);
+ }
+
/* From here on out, tests involve symlinks. */
if (symlink (BASE "/ket", "ise") != 0)
{
ASSERT (errno == ENOENT);
}
+ /* Check that a non-directory symlink with trailing slash yields NULL. */
+ {
+ char *result1;
+ char *result2;
+ errno = 0;
+ result1 = canonicalize_file_name (BASE "/huk/");
+ ASSERT (result1 == NULL);
+ ASSERT (errno == ENOTDIR);
+ errno = 0;
+ result2 = canonicalize_filename_mode (BASE "/huk/", CAN_EXISTING);
+ ASSERT (result2 == NULL);
+ ASSERT (errno == ENOTDIR);
+ }
+
+ /* Check that a missing directory via symlink yields NULL. */
+ {
+ char *result1;
+ char *result2;
+ errno = 0;
+ result1 = canonicalize_file_name (BASE "/ouk/..");
+ ASSERT (result1 == NULL);
+ ASSERT (errno == ENOENT);
+ errno = 0;
+ result2 = canonicalize_filename_mode (BASE "/ouk/..", CAN_EXISTING);
+ ASSERT (result2 == NULL);
+ ASSERT (errno == ENOENT);
+ }
+
/* Check that a loop of symbolic links is detected. */
{
char *result1;