changeset 6912:314715e0260d

Merge from coreutils.
author Paul Eggert <eggert@cs.ucla.edu>
date Mon, 03 Jul 2006 08:32:46 +0000
parents 8e002ebcf4b6
children 68c943c7c310
files ChangeLog MODULES.html.sh lib/.cppi-disable lib/.cvsignore lib/ChangeLog lib/backupfile.c lib/basename.c lib/chdir-safer.c lib/cycle-check.c lib/cycle-check.h lib/dirname.c lib/dirname.h lib/filemode.c lib/filemode.h lib/filenamecat.c lib/fsusage.c lib/fsusage.h lib/fts-cycle.c lib/getcwd.c lib/same-inode.h lib/same.c lib/stat-macros.h lib/stripslash.c lib/xstrtod.c lib/xstrtod.h lib/xstrtold.c m4/ChangeLog m4/c-strtod.m4 m4/chdir-safer.m4 m4/dirname.m4 m4/dos.m4 m4/double-slash-root.m4 m4/filemode.m4 m4/ftruncate.m4 m4/getcwd-abort-bug.m4 m4/getcwd-path-max.m4 m4/getcwd.m4 m4/lib-ignore.m4 m4/same.m4 m4/xstrtod.m4 modules/cycle-check modules/dirname modules/getcwd modules/mkdir-p modules/same modules/xstrtold
diffstat 46 files changed, 943 insertions(+), 412 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-07-03  Paul Eggert  <eggert@cs.ucla.edu>
+
+	Merge from coreutils.
+	* MODULES.html.sh: Add xstrtold.
+	* modules/xstrtold: New file.
+	* modules/cycle-check (Files): Add lib/same-inode.h.
+	* modules/dirname (Files): Add m4/double-slash-root.m4.
+	* modules/getcwd (Files): Add m4/getcwd-abort-bug.m4.
+	* modules/mkdir-p (Files): Add lib/same-inode.h.
+	* modules/same (Files): Add lib/same-inode.h.
+
 2006-07-01  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* modules/inttypes (Depends-on): No longer depends on stdint.
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1551,6 +1551,7 @@
   func_module c-strtold
   func_module xstrtod
   func_module xstrtol
+  func_module xstrtold
   func_end_table
 
   element="Date and time <time.h>"
--- a/lib/.cppi-disable
+++ b/lib/.cppi-disable
@@ -31,6 +31,7 @@
 regex_internal.h
 stat-time.h
 stdbool_.h
+stdint_.h
 strcase.h
 strdup.h
 strndup.h
--- a/lib/.cvsignore
+++ b/lib/.cvsignore
@@ -14,6 +14,7 @@
 search.h
 stat.c
 stdbool.h
+stdint.h
 sysexit.h
 t-fpending
 unlocked-io.h
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,108 @@
+2006-07-03  Paul Eggert  <eggert@cs.ucla.edu>
+
+	Merge from coreutils.
+
+	* .cppi-disable: Add stdint_.h.
+	* .cvsignore: Add stdint.h.
+
+	2006-06-30  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* xstrtod.c (XSTRTOD, DOUBLE): New macros, so that we can support
+	both double and long double versions.
+	(XSTRTOD): Renamed from xstrtod.  Use DOUBLE internally.
+	* xstrtold.c: New file.
+	* xstrtod.h (xstrtold): New decl.
+
+	2006-05-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* filemode.c (setst): Remove.
+	(strmode): Rewrite to avoid setst.  This makes the code shorter,
+	(arguably) clearer, and the generated code is a bit smaller on my
+	Debian GNU/Linux stable x86 host.
+
+	2006-04-17  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* filemode.c: Include "filemode.h" first, to test the interface.
+	Assume that filemode.h includes sys/types.h and sys/stat.h.
+	(HAVE_ST_DM_MODE): New macro, moved here from ls.c.
+	(ftypelet): Reorder to put common cases first, for efficiency.
+	Add 'P', 'w'.  Remove 'M', since it's now the caller's responsibility
+	to do 'M'.
+	(strmode): Renamed from mode_string, and now stores 12 bytes instead
+	of 10, for compatibility with FreeBSD.  All callers changed.
+	(filemodestring): Now stores 12 bytes instead of 10, and sets file types
+	that can't be deduced solely from st_mode.  First arg is now a const
+	pointer.
+	* filemode.h (HAVE_DECL_STRMODE): Include <string.h> for strmode.
+	(strmode): Renamed from mode_string.
+	(filemodestring): New decl.
+	* stat-macros.h: Don't undef S_ISDOOR, since it's never buggy.
+	(S_ISDOOR): Don't bother with S_IFDOOR, since that code is never needed.
+	(S_ISPORT, S_ISWHT): New macros, if not already defined.
+
+	2006-04-12  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* fsusage.c: Don't include <inttypes.h> or <stdint.h>, since
+	fsusage.h now does that.  Include fsusage.h first, to test interface.
+	Prefer statvfs if it works, since it's blessed by POSIX.  Attempt
+	at most one method (the old code could have generated decls that
+	didn't conform to C89, not that this was ever exercised).
+	* fsusage.h: Include <inttypes.h> and <stdint.h> if they exist.
+
+	2006-03-19  Jim Meyering  <jim@meyering.net>
+
+	Work even in a chroot where d_ino values for entries in "/"
+	don't match the stat.st_ino values for the same names.
+	* getcwd.c (__getcwd): When no d_ino value matches the target inode
+	number, iterate through all entries again, using lstat instead.
+	Reported by Kenshi Muto in http://bugs.debian.org/355810, and by
+	Zouhir Hafidi in https://bugzilla.redhat.com/bugzilla/190656.
+
+	* getcwd.c (__getcwd): Clarify a comment.
+	Use memcpy in place of a call to strcpy.
+
+	2006-03-12  Jim Meyering  <jim@meyering.net>
+
+	* fts-cycle.c (leave_dir): If cycle-check's saved dev-ino pair matches
+	that of the current directory (which we're about to chdir ".." out of),
+	then save the dev-ino of the parent, instead.
+
+	* same-inode.h (SAME_INODE): New file/macro.
+	* chdir-safer.c (SAME_INODE): Remove definition.
+	Include "same-inode.h", instead.
+	* same.c: Likewise.
+	* cycle-check.h: Include "same-inode.h".
+	(CYCLE_CHECK_REFLECT_CHDIR_UP): Define.
+	* cycle-check.c (SAME_INODE): Remove definition.
+	* root-dev-ino.h: Include "same-inode.h".
+
+	2006-03-11  Eric Blake  <ebb9@byu.net>
+
+	* same.c (same_name): s/base_name/last_component/
+	* backupfile.c (check_extension, numbered_backup): Likewise.
+	* filenamecat.c (file_name_concat): Likewise.
+
+	2006-03-11  Eric Blake  <ebb9@byu.net>,
+		    Paul Eggert  <eggert@cs.ucla.edu>
+
+	* dirname.h (FILE_SYSTEM_PREFIX_LEN): Move here from dos.m4.
+	[FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX]: Don't treat 1: as a
+	drive prefix.
+	(IS_ABSOLUTE_FILE_NAME): Treat all drive letters as absolute on
+	platforms like cygwin with FILE_SYSTEM_DRIVE_PREFIX_IS_ABSOLUTE.
+	(last_component): New method.
+	* dirname.c (dir_len): Determine when drive letters need a
+	subsequent slash.  Preserve // when it is special.
+	(dir_name): Don't append dot when drive letter is absolute.
+	[TEST_DIRNAME]: Move into a full-blown gnulib test.
+	* basename.c (base_name): New semantics - malloc the result.
+	Preserve // when it is special.  Preserve relative files that look
+	like drive letters.
+	(base_len): Preserve // when it is special.
+	(last_component): New method, similar to old base_name semantics.
+	* stripslash.c (strip_trailing_slashes): Use last_component, not
+	base_name.  Strip redundant slashes from ///.
+
 2006-07-02  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* stdint_.h (intmax_t, uintmax_t): Prefer long to long long if
--- a/lib/backupfile.c
+++ b/lib/backupfile.c
@@ -1,7 +1,8 @@
 /* backupfile.c -- make Emacs style backup file names
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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
@@ -115,7 +116,7 @@
 static void
 check_extension (char *file, size_t filelen, char e)
 {
-  char *base = base_name (file);
+  char *base = last_component (file);
   size_t baselen = base_len (base);
   size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM;
 
@@ -202,7 +203,7 @@
   struct dirent *dp;
   char *buf = *buffer;
   size_t versionlenmax = 1;
-  char *base = base_name (buf);
+  char *base = last_component (buf);
   size_t base_offset = base - buf;
   size_t baselen = base_len (base);
 
--- a/lib/basename.c
+++ b/lib/basename.c
@@ -1,6 +1,6 @@
 /* basename.c -- return the last element in a file name
 
-   Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free
+   Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free
    Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -22,58 +22,110 @@
 #endif
 
 #include "dirname.h"
-#include <string.h>
 
-/* In general, we can't use the builtin `basename' function if available,
-   since it has different meanings in different environments.
-   In some environments the builtin `basename' modifies its argument.
+#include <string.h>
+#include "xalloc.h"
+#include "xstrndup.h"
 
-   Return the address of the last file name component of NAME.  If
-   NAME has no file name components because it is all slashes, return
-   NAME if it is empty, the address of its last slash otherwise.  */
+/* Return the address of the last file name component of NAME.  If
+   NAME has no relative file name components because it is a file
+   system root, return the empty string.  */
 
 char *
-base_name (char const *name)
+last_component (char const *name)
 {
   char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
   char const *p;
+  bool saw_slash = false;
+
+  while (ISSLASH (*base))
+    base++;
 
   for (p = base; *p; p++)
     {
       if (ISSLASH (*p))
+	saw_slash = true;
+      else if (saw_slash)
 	{
-	  /* Treat multiple adjacent slashes like a single slash.  */
-	  do p++;
-	  while (ISSLASH (*p));
-
-	  /* If the file name ends in slash, use the trailing slash as
-	     the basename if no non-slashes have been found.  */
-	  if (! *p)
-	    {
-	      if (ISSLASH (*base))
-		base = p - 1;
-	      break;
-	    }
-
-	  /* *P is a non-slash preceded by a slash.  */
 	  base = p;
+	  saw_slash = false;
 	}
     }
 
   return (char *) base;
 }
 
-/* Return the length of of the basename NAME.  Typically NAME is the
-   value returned by base_name.  Act like strlen (NAME), except omit
-   redundant trailing slashes.  */
+
+/* In general, we can't use the builtin `basename' function if available,
+   since it has different meanings in different environments.
+   In some environments the builtin `basename' modifies its argument.
+
+   Return the last file name component of NAME, allocated with
+   xmalloc.  On systems with drive letters, a leading "./"
+   distinguishes relative names that would otherwise look like a drive
+   letter.  Unlike POSIX basename(), NAME cannot be NULL,
+   base_name("") returns "", and the first trailing slash is not
+   stripped.
+
+   If lstat (NAME) would succeed, then { chdir (dir_name (NAME));
+   lstat (base_name (NAME)); } will access the same file.  Likewise,
+   if the sequence { chdir (dir_name (NAME));
+   rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME
+   to "foo" in the same directory NAME was in.  */
+
+char *
+base_name (char const *name)
+{
+  char const *base = last_component (name);
+  size_t length;
+
+  /* If there is no last component, then name is a file system root or the
+     empty string.  */
+  if (! *base)
+    return xstrndup (name, base_len (name));
+
+  /* Collapse a sequence of trailing slashes into one.  */
+  length = base_len (base);
+  if (ISSLASH (base[length]))
+    length++;
+
+  /* On systems with drive letters, `a/b:c' must return `./b:c' rather
+     than `b:c' to avoid confusion with a drive letter.  On systems
+     with pure POSIX semantics, this is not an issue.  */
+  if (FILE_SYSTEM_PREFIX_LEN (base))
+    {
+      char *p = xmalloc (length + 3);
+      p[0] = '.';
+      p[1] = '/';
+      memcpy (p + 2, base, length);
+      p[length + 2] = '\0';
+      return p;
+    }
+
+  /* Finally, copy the basename.  */
+  return xstrndup (base, length);
+}
+
+/* Return the length of the basename NAME.  Typically NAME is the
+   value returned by base_name or last_component.  Act like strlen
+   (NAME), except omit all trailing slashes.  */
 
 size_t
 base_len (char const *name)
 {
   size_t len;
+  size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
 
   for (len = strlen (name);  1 < len && ISSLASH (name[len - 1]);  len--)
     continue;
 
+  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
+      && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
+    return 2;
+
+  if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
+      && len == prefix_len && ISSLASH (name[prefix_len]))
+    return prefix_len + 1;
+
   return len;
 }
--- a/lib/chdir-safer.c
+++ b/lib/chdir-safer.c
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include "same-inode.h"
 
 #ifndef O_DIRECTORY
 # define O_DIRECTORY 0
@@ -39,10 +40,6 @@
 # define O_NOFOLLOW 0
 #endif
 
-#define SAME_INODE(Stat_buf_1, Stat_buf_2) \
-  ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
-   && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
-
 /* Like chdir, but fail if DIR is a symbolic link to a directory (or
    similar funny business), or if DIR is not readable.  This avoids a
    minor race condition between when a directory is created or statted
--- a/lib/cycle-check.c
+++ b/lib/cycle-check.c
@@ -1,6 +1,6 @@
 /* help detect directory cycles efficiently
 
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 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
@@ -33,10 +33,6 @@
 
 #include "cycle-check.h"
 
-#define SAME_INODE(Stat_buf_1, Stat_buf_2) \
-  ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
-   && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
-
 #define CC_MAGIC 9827862
 
 /* Return true if I is a power of 2, or is zero.  */
--- a/lib/cycle-check.h
+++ b/lib/cycle-check.h
@@ -1,6 +1,6 @@
 /* help detect directory cycles efficiently
 
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 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
@@ -30,6 +30,7 @@
 # endif
 # include <stdbool.h>
 # include "dev-ino.h"
+# include "same-inode.h"
 
 struct cycle_check_state
 {
@@ -41,4 +42,15 @@
 void cycle_check_init (struct cycle_check_state *state);
 bool cycle_check (struct cycle_check_state *state, struct stat const *sb);
 
+# define CYCLE_CHECK_REFLECT_CHDIR_UP(State, SB_dir, SB_subdir)	\
+  do								\
+    {								\
+      if (SAME_INODE ((State)->dev_ino, SB_subdir))		\
+	{							\
+	  (State)->dev_ino.st_dev = (SB_dir).st_dev;		\
+	  (State)->dev_ino.st_ino = (SB_dir).st_ino;		\
+	}							\
+    }								\
+  while (0)
+
 #endif
--- a/lib/dirname.c
+++ b/lib/dirname.c
@@ -1,6 +1,6 @@
 /* dirname.c -- return all but the last element in a file name
 
-   Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005 Free Software
+   Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -26,96 +26,62 @@
 #include <string.h>
 #include "xalloc.h"
 
-/* Return the length of `dirname (FILE)', or zero if FILE is
-   in the working directory.  Works properly even if
-   there are trailing slashes (by effectively ignoring them).  */
+/* Return the length of the prefix of FILE that will be used by
+   dir_name.  If FILE is in the working directory, this returns zero
+   even though `dir_name (FILE)' will return ".".  Works properly even
+   if there are trailing slashes (by effectively ignoring them).  */
+
 size_t
 dir_len (char const *file)
 {
   size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
   size_t length;
 
+  /* Advance prefix_length beyond important leading slashes.  */
+  prefix_length += (prefix_length != 0
+		    ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+		       && ISSLASH (file[prefix_length]))
+		    : (ISSLASH (file[0])
+		       ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
+			   && ISSLASH (file[1]) && ! ISSLASH (file[2])
+			   ? 2 : 1))
+		       : 0));
+
   /* Strip the basename and any redundant slashes before it.  */
-  for (length = base_name (file) - file;  prefix_length < length;  length--)
+  for (length = last_component (file) - file;
+       prefix_length < length; length--)
     if (! ISSLASH (file[length - 1]))
-      return length;
-
-  /* But don't strip the only slash from "/".  */
-  return prefix_length + ISSLASH (file[prefix_length]);
+      break;
+  return length;
 }
 
-/* Return the leading directories part of FILE,
-   allocated with xmalloc.
-   Works properly even if there are trailing slashes
-   (by effectively ignoring them).  */
+
+/* In general, we can't use the builtin `dirname' function if available,
+   since it has different meanings in different environments.
+   In some environments the builtin `dirname' modifies its argument.
+
+   Return the leading directories part of FILE, allocated with xmalloc.
+   Works properly even if there are trailing slashes (by effectively
+   ignoring them).  Unlike POSIX dirname(), FILE cannot be NULL.
+
+   If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
+   lstat (base_name (FILE)); } will access the same file.  Likewise,
+   if the sequence { chdir (dir_name (FILE));
+   rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
+   to "foo" in the same directory FILE was in.  */
 
 char *
 dir_name (char const *file)
 {
   size_t length = dir_len (file);
-  bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (file));
+  bool append_dot = (length == 0
+		     || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+			 && length == FILE_SYSTEM_PREFIX_LEN (file)
+			 && file[2] != '\0' && ! ISSLASH (file[2])));
   char *dir = xmalloc (length + append_dot + 1);
   memcpy (dir, file, length);
   if (append_dot)
     dir[length++] = '.';
-  dir[length] = 0;
+  dir[length] = '\0';
   return dir;
 }
-
-#ifdef TEST_DIRNAME
-/*
-
-Run the test like this (expect no output):
-  gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \
-     basename.c dirname.c xmalloc.c error.c
-  sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out
-
-If it's been built on a DOS or Windows platforms, run another test like
-this (again, expect no output):
-  sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out
-
-BEGIN-DATA
-foo//// .
-bar/foo//// bar
-foo/ .
-/ /
-. .
-a .
-END-DATA
-
-BEGIN-DOS-DATA
-c:///// c:/
-c:/ c:/
-c:/. c:/
-c:foo c:.
-c:foo/bar c:foo
-END-DOS-DATA
-
-*/
-
-# define MAX_BUFF_LEN 1024
-# include <stdio.h>
-
-char *program_name;
-
-int
-main (int argc, char *argv[])
-{
-  char buff[MAX_BUFF_LEN + 1];
-
-  program_name = argv[0];
-
-  buff[MAX_BUFF_LEN] = 0;
-  while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
-    {
-      char file[MAX_BUFF_LEN];
-      char expected_result[MAX_BUFF_LEN];
-      char const *result;
-      sscanf (buff, "%s %s", file, expected_result);
-      result = dir_name (file);
-      if (strcmp (result, expected_result))
-	printf ("%s: got %s, expected %s\n", file, result, expected_result);
-    }
-  return 0;
-}
-#endif
--- a/lib/dirname.h
+++ b/lib/dirname.h
@@ -1,6 +1,6 @@
 /*  Take file names apart into directory and base names.
 
-    Copyright (C) 1998, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+    Copyright (C) 1998, 2001, 2003-2006 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
@@ -31,16 +31,39 @@
 # endif
 
 # ifndef FILE_SYSTEM_PREFIX_LEN
-#  define FILE_SYSTEM_PREFIX_LEN(File_name) 0
+#  if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+    /* This internal macro assumes ASCII, but all hosts that support drive
+       letters use ASCII.  */
+#   define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
+				<= 'z' - 'a')
+#   define FILE_SYSTEM_PREFIX_LEN(Filename) \
+	   (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
+#  else
+#   define FILE_SYSTEM_PREFIX_LEN(Filename) 0
+#  endif
 # endif
 
-# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+#  define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# endif
+
+# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+#  define DOUBLE_SLASH_IS_DISTINCT_ROOT 1
+# endif
+
+# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
+#  define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
+# else
+#  define IS_ABSOLUTE_FILE_NAME(F) \
+	  (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
+# endif
 # define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
 
 char *base_name (char const *file);
 char *dir_name (char const *file);
 size_t base_len (char const *file);
 size_t dir_len (char const *file);
+char *last_component (char const *file);
 
 bool strip_trailing_slashes (char *file);
 
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -1,5 +1,7 @@
 /* filemode.c -- make a string describing file modes
-   Copyright (C) 1985, 1990, 1993, 1998-2000, 2004 Free Software Foundation, Inc.
+
+   Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006 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
@@ -19,129 +21,120 @@
 # include <config.h>
 #endif
 
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "filemode.h"
 
-#include "filemode.h"
 #include "stat-macros.h"
 
-
-/* Set the 's' and 't' flags in file attributes string CHARS,
-   according to the file mode BITS.  */
+/* The following is for Cray DMF (Data Migration Facility), which is a
+   HSM file system.  A migrated file has a `st_dm_mode' that is
+   different from the normal `st_mode', so any tests for migrated
+   files should use the former.  */
+#if HAVE_ST_DM_MODE
+# define IS_MIGRATED_FILE(statp) \
+    (S_ISOFD (statp->st_dm_mode) || S_ISOFL (statp->st_dm_mode))
+#else
+# define IS_MIGRATED_FILE(statp) 0
+#endif
 
-static void
-setst (mode_t bits, char *chars)
-{
-  if (bits & S_ISUID)
-    {
-      if (chars[3] != 'x')
-	/* Set-uid, but not executable by owner.  */
-	chars[3] = 'S';
-      else
-	chars[3] = 's';
-    }
-  if (bits & S_ISGID)
-    {
-      if (chars[6] != 'x')
-	/* Set-gid, but not executable by group.  */
-	chars[6] = 'S';
-      else
-	chars[6] = 's';
-    }
-  if (bits & S_ISVTX)
-    {
-      if (chars[9] != 'x')
-	/* Sticky, but not executable by others.  */
-	chars[9] = 'T';
-      else
-	chars[9] = 't';
-    }
-}
+#if ! HAVE_DECL_STRMODE
 
 /* Return a character indicating the type of file described by
    file mode BITS:
-   'd' for directories
-   'D' for doors
-   'b' for block special files
-   'c' for character special files
-   'n' for network special files
-   'm' for multiplexor files
-   'M' for an off-line (regular) file
-   'l' for symbolic links
-   's' for sockets
-   'p' for fifos
-   'C' for contigous data files
-   '-' for regular files
-   '?' for any other file type.  */
+   '-' regular file
+   'b' block special file
+   'c' character special file
+   'C' high performance ("contiguous data") file
+   'd' directory
+   'D' door
+   'l' symbolic link
+   'm' multiplexed file (7th edition Unix; obsolete)
+   'n' network special file (HP-UX)
+   'p' fifo (named pipe)
+   'P' port
+   's' socket
+   'w' whiteout (4.4BSD)
+   '?' some other file type  */
 
 static char
 ftypelet (mode_t bits)
 {
+  /* These are the most common, so test for them first.  */
+  if (S_ISREG (bits))
+    return '-';
+  if (S_ISDIR (bits))
+    return 'd';
+
+  /* Other letters standardized by POSIX 1003.1-2004.  */
   if (S_ISBLK (bits))
     return 'b';
   if (S_ISCHR (bits))
     return 'c';
-  if (S_ISDIR (bits))
-    return 'd';
-  if (S_ISREG (bits))
-    return '-';
+  if (S_ISLNK (bits))
+    return 'l';
   if (S_ISFIFO (bits))
     return 'p';
-  if (S_ISLNK (bits))
-    return 'l';
+
+  /* Other file types (though not letters) standardized by POSIX.  */
   if (S_ISSOCK (bits))
     return 's';
-  if (S_ISMPC (bits))
+
+  /* Nonstandard file types.  */
+  if (S_ISCTG (bits))
+    return 'C';
+  if (S_ISDOOR (bits))
+    return 'D';
+  if (S_ISMPB (bits) || S_ISMPC (bits))
     return 'm';
   if (S_ISNWK (bits))
     return 'n';
-  if (S_ISDOOR (bits))
-    return 'D';
-  if (S_ISCTG (bits))
-    return 'C';
+  if (S_ISPORT (bits))
+    return 'P';
+  if (S_ISWHT (bits))
+    return 'w';
 
-  /* The following two tests are for Cray DMF (Data Migration
-     Facility), which is a HSM file system.  A migrated file has a
-     `st_dm_mode' that is different from the normal `st_mode', so any
-     tests for migrated files should use the former.  */
-
-  if (S_ISOFD (bits))
-    /* off line, with data  */
-    return 'M';
-  /* off line, with no data  */
-  if (S_ISOFL (bits))
-    return 'M';
   return '?';
 }
 
-/* Like filemodestring, but only the relevant part of the `struct stat'
-   is given as an argument.  */
+/* Like filemodestring, but rely only on MODE.  */
 
 void
-mode_string (mode_t mode, char *str)
+strmode (mode_t mode, char *str)
 {
   str[0] = ftypelet (mode);
   str[1] = mode & S_IRUSR ? 'r' : '-';
   str[2] = mode & S_IWUSR ? 'w' : '-';
-  str[3] = mode & S_IXUSR ? 'x' : '-';
+  str[3] = (mode & S_ISUID
+	    ? (mode & S_IXUSR ? 's' : 'S')
+	    : (mode & S_IXUSR ? 'x' : '-'));
   str[4] = mode & S_IRGRP ? 'r' : '-';
   str[5] = mode & S_IWGRP ? 'w' : '-';
-  str[6] = mode & S_IXGRP ? 'x' : '-';
+  str[6] = (mode & S_ISGID
+	    ? (mode & S_IXGRP ? 's' : 'S')
+	    : (mode & S_IXGRP ? 'x' : '-'));
   str[7] = mode & S_IROTH ? 'r' : '-';
   str[8] = mode & S_IWOTH ? 'w' : '-';
-  str[9] = mode & S_IXOTH ? 'x' : '-';
-  setst (mode, str);
+  str[9] = (mode & S_ISVTX
+	    ? (mode & S_IXOTH ? 't' : 'T')
+	    : (mode & S_IXOTH ? 'x' : '-'));
+  str[10] = ' ';
+  str[11] = '\0';
 }
 
+#endif /* ! HAVE_DECL_STRMODE */
+
 /* filemodestring - fill in string STR with an ls-style ASCII
    representation of the st_mode field of file stats block STATP.
-   10 characters are stored in STR; no terminating null is added.
+   12 characters are stored in STR.
    The characters stored in STR are:
 
-   0	File type.  'd' for directory, 'c' for character
-	special, 'b' for block special, 'm' for multiplex,
-	'l' for symbolic link, 's' for socket, 'p' for fifo,
-	'-' for regular, '?' for any other file type
+   0	File type, as in ftypelet above, except that other letters are used
+        for files whose type cannot be determined solely from st_mode:
+
+	    'F' semaphore
+	    'M' migrated file (Cray DMF)
+	    'Q' message queue
+	    'S' shared memory object
+	    'T' typed memory object
 
    1	'r' if the owner may read, '-' otherwise.
 
@@ -167,10 +160,26 @@
    9	'x' if any user may execute, 't' if the file is "sticky"
 	(will be retained in swap space after execution), '-'
 	otherwise.
-	'T' if the file is sticky but not executable.  */
+	'T' if the file is sticky but not executable.
+
+   10   ' ' for compatibility with 4.4BSD strmode,
+	since this interface does not support ACLs.
+
+   11   '\0'.  */
 
 void
-filemodestring (struct stat *statp, char *str)
+filemodestring (struct stat const *statp, char *str)
 {
-  mode_string (statp->st_mode, str);
+  strmode (statp->st_mode, str);
+
+  if (S_TYPEISSEM (statp))
+    str[0] = 'F';
+  else if (IS_MIGRATED_FILE (statp))
+    str[0] = 'M';
+  else if (S_TYPEISMQ (statp))
+    str[0] = 'Q';
+  else if (S_TYPEISSHM (statp))
+    str[0] = 'S';
+  else if (S_TYPEISTMO (statp))
+    str[0] = 'T';
 }
--- a/lib/filemode.h
+++ b/lib/filemode.h
@@ -1,6 +1,6 @@
 /* Make a string describing file modes.
 
-   Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2003, 2006 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
@@ -19,7 +19,14 @@
 #ifndef FILEMODE_H_
 
 # include <sys/types.h>
+# include <sys/stat.h>
 
-void mode_string (mode_t mode, char *str);
+# if HAVE_DECL_STRMODE
+#  include <string.h>
+# else
+void strmode (mode_t mode, char *str);
+# endif
+
+void filemodestring (struct stat const *statp, char *str);
 
 #endif
--- a/lib/filenamecat.c
+++ b/lib/filenamecat.c
@@ -1,7 +1,7 @@
 /* Concatenate two arbitrary file names.
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
-   Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006 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
@@ -64,7 +64,7 @@
 char *
 file_name_concat (char const *dir, char const *abase, char **base_in_result)
 {
-  char const *dirbase = base_name (dir);
+  char const *dirbase = last_component (dir);
   size_t dirbaselen = base_len (dirbase);
   size_t dirlen = dirbase - dir + dirbaselen;
   size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1]));
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -1,6 +1,6 @@
 /* fsusage.c -- return space usage of mounted file systems
 
-   Copyright (C) 1991, 1992, 1996, 1998, 1999, 2002, 2003, 2004, 2005
+   Copyright (C) 1991, 1992, 1996, 1998, 1999, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -21,59 +21,47 @@
 # include <config.h>
 #endif
 
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#if HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <unistd.h>
-#ifndef UINTMAX_MAX
-# define UINTMAX_MAX ((uintmax_t) -1)
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
 #include "fsusage.h"
 
 #include <limits.h>
-
-#if HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
+#include <sys/types.h>
 
-#if HAVE_SYS_MOUNT_H
-# include <sys/mount.h>
-#endif
-
-#if HAVE_SYS_VFS_H
-# include <sys/vfs.h>
-#endif
-
-#if HAVE_SYS_FS_S5PARAM_H	/* Fujitsu UXP/V */
-# include <sys/fs/s5param.h>
+#if STAT_STATVFS		/* POSIX 1003.1-2001 (and later) with XSI */
+# include <sys/statvfs.h>
+#else
+/* Don't include backward-compatibility files unless they're needed.
+   Eventually we'd like to remove all this cruft.  */
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# if HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+# endif
+# if HAVE_SYS_MOUNT_H
+#  include <sys/mount.h>
+# endif
+# if HAVE_SYS_VFS_H
+#  include <sys/vfs.h>
+# endif
+# if HAVE_SYS_FS_S5PARAM_H	/* Fujitsu UXP/V */
+#  include <sys/fs/s5param.h>
+# endif
+# if defined HAVE_SYS_FILSYS_H && !defined _CRAY
+#  include <sys/filsys.h>	/* SVR2 */
+# endif
+# if HAVE_SYS_STATFS_H
+#  include <sys/statfs.h>
+# endif
+# if HAVE_DUSTAT_H		/* AIX PS/2 */
+#  include <sys/dustat.h>
+# endif
+# include "full-read.h"
 #endif
 
-#if defined HAVE_SYS_FILSYS_H && !defined _CRAY
-# include <sys/filsys.h>	/* SVR2 */
-#endif
-
-#include <fcntl.h>
-
-#if HAVE_SYS_STATFS_H
-# include <sys/statfs.h>
+#ifndef UINTMAX_MAX
+# define UINTMAX_MAX ((uintmax_t) -1)
 #endif
 
-#if HAVE_DUSTAT_H		/* AIX PS/2 */
-# include <sys/dustat.h>
-#endif
-
-#if HAVE_SYS_STATVFS_H		/* SVR4 */
-# include <sys/statvfs.h>
-#endif
-
-#include "full-read.h"
-
 /* Many space usage primitives use all 1 bits to denote a value that is
    not applicable or unknown.  Propagate this information by returning
    a uintmax_t value that is all 1 bits if X is all 1 bits, even if X
@@ -108,18 +96,19 @@
 int
 get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp)
 {
-#ifdef STAT_STATFS3_OSF1
+#if defined STAT_STATVFS		/* POSIX */
 
-  struct statfs fsd;
+  struct statvfs fsd;
 
-  if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
+  if (statvfs (file, &fsd) < 0)
     return -1;
 
-  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
+  /* f_frsize isn't guaranteed to be supported.  */
+  fsp->fsu_blocksize = (fsd.f_frsize
+			? PROPAGATE_ALL_ONES (fsd.f_frsize)
+			: PROPAGATE_ALL_ONES (fsd.f_bsize));
 
-#endif /* STAT_STATFS3_OSF1 */
-
-#ifdef STAT_STATFS2_FS_DATA	/* Ultrix */
+#elif defined STAT_STATFS2_FS_DATA	/* Ultrix */
 
   struct fs_data fsd;
 
@@ -134,9 +123,7 @@
   fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.fd_req.gtot);
   fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.fd_req.gfree);
 
-#endif /* STAT_STATFS2_FS_DATA */
-
-#ifdef STAT_READ_FILSYS		/* SVR2 */
+#elif defined STAT_READ_FILSYS		/* SVR2 */
 # ifndef SUPERBOFF
 #  define SUPERBOFF (SUPERB * 512)
 # endif
@@ -171,9 +158,16 @@
 		    : (fsd.s_isize - 2) * INOPB * (fsd.s_type == Fs2b ? 2 : 1));
   fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.s_tinode);
 
-#endif /* STAT_READ_FILSYS */
+#elif defined STAT_STATFS3_OSF1
+
+  struct statfs fsd;
 
-#ifdef STAT_STATFS2_BSIZE	/* 4.3BSD, SunOS 4, HP-UX, AIX */
+  if (statfs (file, &fsd, sizeof (struct statfs)) != 0)
+    return -1;
+
+  fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
+
+#elif defined STAT_STATFS2_BSIZE	/* 4.3BSD, SunOS 4, HP-UX, AIX */
 
   struct statfs fsd;
 
@@ -197,9 +191,7 @@
     }
 # endif /* STATFS_TRUNCATES_BLOCK_COUNTS */
 
-#endif /* STAT_STATFS2_BSIZE */
-
-#ifdef STAT_STATFS2_FSIZE	/* 4.4BSD */
+#elif defined STAT_STATFS2_FSIZE	/* 4.4BSD */
 
   struct statfs fsd;
 
@@ -208,9 +200,7 @@
 
   fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize);
 
-#endif /* STAT_STATFS2_FSIZE */
-
-#ifdef STAT_STATFS4		/* SVR3, Dynix, Irix, AIX */
+#elif defined STAT_STATFS4		/* SVR3, Dynix, Irix, AIX */
 
 # if !_AIX && !defined _SEQUENT_ && !defined DOLPHIN
 #  define f_bavail f_bfree
@@ -230,24 +220,10 @@
    fsp->fsu_blocksize = 512;
 # endif
 
-#endif /* STAT_STATFS4 */
-
-#ifdef STAT_STATVFS		/* SVR4 */
-
-  struct statvfs fsd;
-
-  if (statvfs (file, &fsd) < 0)
-    return -1;
+#endif
 
-  /* f_frsize isn't guaranteed to be supported.  */
-  fsp->fsu_blocksize = (fsd.f_frsize
-			? PROPAGATE_ALL_ONES (fsd.f_frsize)
-			: PROPAGATE_ALL_ONES (fsd.f_bsize));
-
-#endif /* STAT_STATVFS */
-
-#if !defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS
-				/* !Ultrix && !SVR2 */
+#if (defined STAT_STATVFS \
+     || (!defined STAT_STATFS2_FS_DATA && !defined STAT_READ_FILSYS))
 
   fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks);
   fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree);
@@ -256,7 +232,7 @@
   fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files);
   fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree);
 
-#endif /* not STAT_STATFS2_FS_DATA && not STAT_READ_FILSYS */
+#endif
 
   return 0;
 }
--- a/lib/fsusage.h
+++ b/lib/fsusage.h
@@ -1,6 +1,6 @@
 /* fsusage.h -- declarations for file system space usage info
 
-   Copyright (C) 1991, 1992, 1997, 2003, 2004, 2005 Free Software
+   Copyright (C) 1991, 1992, 1997, 2003, 2004, 2005, 2006 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,12 @@
 #if !defined FSUSAGE_H_
 # define FSUSAGE_H_
 
+# if HAVE_INTTYPES_H
+#  include <inttypes.h>
+# endif
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
 # include <stdbool.h>
 
 struct fs_usage
--- a/lib/fts-cycle.c
+++ b/lib/fts-cycle.c
@@ -1,6 +1,6 @@
 /* Detect cycles in file tree walks.
 
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    Written by Jim Meyering.
 
@@ -129,9 +129,9 @@
 static void
 leave_dir (FTS *fts, FTSENT *ent)
 {
+  struct stat const *st = ent->fts_statp;
   if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
     {
-      struct stat const *st = ent->fts_statp;
       struct Active_dir obj;
       void *found;
       obj.dev = st->st_dev;
@@ -141,6 +141,13 @@
 	abort ();
       free (found);
     }
+  else
+    {
+      FTSENT *parent = ent->fts_parent;
+      if (parent != NULL)
+	CYCLE_CHECK_REFLECT_CHDIR_UP (fts->fts_cycle.state,
+				      *(parent->fts_statp), *st);
+    }
 }
 
 /* Free any memory used for cycle detection.  */
--- a/lib/getcwd.c
+++ b/lib/getcwd.c
@@ -211,6 +211,7 @@
       int parent_status;
       size_t dirroom;
       size_t namlen;
+      bool use_d_ino = true;
 
       /* Look at the parent directory.  */
 #ifdef AT_FDCWD
@@ -257,11 +258,26 @@
 	     NULL.  */
 	  __set_errno (0);
 	  d = __readdir (dirstream);
+
+	  /* When we've iterated through all directory entries without finding
+	     one with a matching d_ino, rewind the stream and consider each
+	     name again, but this time, using lstat.  This is necessary in a
+	     chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
+	     .., ../.., ../../.., etc. all had the same device number, yet the
+	     d_ino values for entries in / did not match those obtained
+	     via lstat.  */
+	  if (d == NULL && errno == 0 && use_d_ino)
+	    {
+	      use_d_ino = false;
+	      rewinddir (dirstream);
+	      d = __readdir (dirstream);
+	    }
+
 	  if (d == NULL)
 	    {
 	      if (errno == 0)
-		/* EOF on dirstream, which means that the current directory
-		   has been removed.  */
+		/* EOF on dirstream, which can mean e.g., that the current
+		   directory has been removed.  */
 		__set_errno (ENOENT);
 	      goto lose;
 	    }
@@ -269,58 +285,65 @@
 	      (d->d_name[1] == '\0' ||
 	       (d->d_name[1] == '.' && d->d_name[2] == '\0')))
 	    continue;
-	  if (MATCHING_INO (d, thisino) || mount_point)
+
+	  if (use_d_ino)
 	    {
-	      int entry_status;
+	      bool match = (MATCHING_INO (d, thisino) || mount_point);
+	      if (! match)
+		continue;
+	    }
+
+	  {
+	    int entry_status;
 #ifdef AT_FDCWD
-	      entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
+	    entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
 #else
-	      /* Compute size needed for this file name, or for the file
-		 name ".." in the same directory, whichever is larger.
-	         Room for ".." might be needed the next time through
-		 the outer loop.  */
-	      size_t name_alloc = _D_ALLOC_NAMLEN (d);
-	      size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
+	    /* Compute size needed for this file name, or for the file
+	       name ".." in the same directory, whichever is larger.
+	       Room for ".." might be needed the next time through
+	       the outer loop.  */
+	    size_t name_alloc = _D_ALLOC_NAMLEN (d);
+	    size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
 
-	      if (filesize < dotlen)
-		goto memory_exhausted;
+	    if (filesize < dotlen)
+	      goto memory_exhausted;
 
-	      if (dotsize < filesize)
-		{
-		  /* My, what a deep directory tree you have, Grandma.  */
-		  size_t newsize = MAX (filesize, dotsize * 2);
-		  size_t i;
-		  if (newsize < dotsize)
-		    goto memory_exhausted;
-		  if (dotlist != dots)
-		    free (dotlist);
-		  dotlist = malloc (newsize);
-		  if (dotlist == NULL)
-		    goto lose;
-		  dotsize = newsize;
+	    if (dotsize < filesize)
+	      {
+		/* My, what a deep directory tree you have, Grandma.  */
+		size_t newsize = MAX (filesize, dotsize * 2);
+		size_t i;
+		if (newsize < dotsize)
+		  goto memory_exhausted;
+		if (dotlist != dots)
+		  free (dotlist);
+		dotlist = malloc (newsize);
+		if (dotlist == NULL)
+		  goto lose;
+		dotsize = newsize;
 
-		  i = 0;
-		  do
-		    {
-		      dotlist[i++] = '.';
-		      dotlist[i++] = '.';
-		      dotlist[i++] = '/';
-		    }
-		  while (i < dotlen);
-		}
+		i = 0;
+		do
+		  {
+		    dotlist[i++] = '.';
+		    dotlist[i++] = '.';
+		    dotlist[i++] = '/';
+		  }
+		while (i < dotlen);
+	      }
 
-	      strcpy (dotlist + dotlen, d->d_name);
-	      entry_status = __lstat (dotlist, &st);
+	    memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
+	    entry_status = __lstat (dotlist, &st);
 #endif
-	      /* We don't fail here if we cannot stat() a directory entry.
-		 This can happen when (network) file systems fail.  If this
-		 entry is in fact the one we are looking for we will find
-		 out soon as we reach the end of the directory without
-		 having found anything.  */
-	      if (entry_status == 0 && S_ISDIR (st.st_mode)
-		  && st.st_dev == thisdev && st.st_ino == thisino)
-		break;
-	    }
+	    /* We don't fail here if we cannot stat() a directory entry.
+	       This can happen when (network) file systems fail.  If this
+	       entry is in fact the one we are looking for we will find
+	       out soon as we reach the end of the directory without
+	       having found anything.  */
+	    if (entry_status == 0 && S_ISDIR (st.st_mode)
+		&& st.st_dev == thisdev && st.st_ino == thisino)
+	      break;
+	  }
 	}
 
       dirroom = dirp - dir;
new file mode 100644
--- /dev/null
+++ b/lib/same-inode.h
@@ -0,0 +1,26 @@
+/* Determine whether two stat buffers refer to the same file.
+
+   Copyright (C) 2006 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 2, 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, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef SAME_INODE_H
+# define SAME_INODE_H 1
+
+# define SAME_INODE(Stat_buf_1, Stat_buf_2) \
+   ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
+    && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
+
+#endif
--- a/lib/same.c
+++ b/lib/same.c
@@ -1,6 +1,6 @@
 /* Determine whether two file names refer to the same file.
 
-   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 Free
+   Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free
    Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -42,16 +42,13 @@
 #include "same.h"
 #include "dirname.h"
 #include "error.h"
+#include "same-inode.h"
 #include "xalloc.h"
 
 #ifndef MIN
 # define MIN(a, b) ((a) < (b) ? (a) : (b))
 #endif
 
-#define SAME_INODE(Stat_buf_1, Stat_buf_2) \
-  ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
-   && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
-
 /* Return nonzero if SOURCE and DEST point to the same name in the same
    directory.  */
 
@@ -59,8 +56,8 @@
 same_name (const char *source, const char *dest)
 {
   /* Compare the basenames.  */
-  char const *source_basename = base_name (source);
-  char const *dest_basename = base_name (dest);
+  char const *source_basename = last_component (source);
+  char const *dest_basename = last_component (dest);
   size_t source_baselen = base_len (source_basename);
   size_t dest_baselen = base_len (dest_basename);
   bool identical_basenames =
--- a/lib/stat-macros.h
+++ b/lib/stat-macros.h
@@ -1,6 +1,7 @@
 /* stat-related macros
 
-   Copyright (C) 1993, 1994, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 2001, 2002, 2004, 2006 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
@@ -33,7 +34,6 @@
 #  undef S_ISBLK
 #  undef S_ISCHR
 #  undef S_ISDIR
-#  undef S_ISDOOR
 #  undef S_ISFIFO
 #  undef S_ISLNK
 #  undef S_ISNAM
@@ -70,11 +70,7 @@
 # endif
 
 # ifndef S_ISDOOR /* Solaris 2.5 and up */
-#  ifdef S_IFDOOR
-#   define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
-#  else
-#   define S_ISDOOR(m) 0
-#  endif
+#  define S_ISDOOR(m) 0
 # endif
 
 # ifndef S_ISFIFO
@@ -119,6 +115,10 @@
 #  endif
 # endif
 
+# ifndef S_ISPORT /* Solaris 10 and up */
+#  define S_ISPORT(m) 0
+# endif
+
 # ifndef S_ISREG
 #  ifdef S_IFREG
 #   define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
@@ -161,7 +161,7 @@
 #  endif
 # endif
 
-/* contiguous */
+/* high performance ("contiguous data") */
 # ifndef S_ISCTG
 #  define S_ISCTG(p) 0
 # endif
@@ -176,6 +176,11 @@
 #  define S_ISOFL(p) 0
 # endif
 
+/* 4.4BSD whiteout */
+# ifndef S_ISWHT
+#  define S_ISWHT(m) 0
+# endif
+
 /* If any of the following are undefined,
    define them to their de facto standard values.  */
 # if !S_ISUID
--- a/lib/stripslash.c
+++ b/lib/stripslash.c
@@ -1,6 +1,6 @@
 /* stripslash.c -- remove redundant trailing slashes from a file name
 
-   Copyright (C) 1990, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1990, 2001, 2003-2006 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
@@ -22,19 +22,26 @@
 
 #include "dirname.h"
 
-/* Remove trailing slashes from FILE.
-   Return true if a trailing slash was removed.
-   This is useful when using file name completion from a shell that
-   adds a "/" after directory names (such as tcsh and bash), because
-   the Unix rename and rmdir system calls return an "Invalid argument" error
-   when given a file that ends in "/" (except for the root directory).  */
+/* Remove trailing slashes from FILE.  Return true if a trailing slash
+   was removed.  This is useful when using file name completion from a
+   shell that adds a "/" after directory names (such as tcsh and
+   bash), because on symlinks to directories, several system calls
+   have different semantics according to whether a trailing slash is
+   present.  */
 
 bool
 strip_trailing_slashes (char *file)
 {
-  char *base = base_name (file);
-  char *base_lim = base + base_len (base);
-  bool had_slash = (*base_lim != '\0');
+  char *base = last_component (file);
+  char *base_lim;
+  bool had_slash;
+
+  /* last_component returns "" for file system roots, but we need to turn
+     `///' into `/'.  */
+  if (! *base)
+    base = file;
+  base_lim = base + base_len (base);
+  had_slash = (*base_lim != '\0');
   *base_lim = '\0';
   return had_slash;
 }
--- a/lib/xstrtod.c
+++ b/lib/xstrtod.c
@@ -1,7 +1,7 @@
 /* error-checking interface to strtod-like functions
 
-   Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005 Free Software
-   Foundation, Inc.
+   Copyright (C) 1996, 1999, 2000, 2003, 2004, 2005, 2006 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
@@ -29,17 +29,26 @@
 #include <limits.h>
 #include <stdio.h>
 
-/* An interface to strtod that encapsulates all the error checking
-   one should usually perform.  Like strtod, but upon successful
+#if LONG
+# define XSTRTOD xstrtold
+# define DOUBLE long double
+#else
+# define XSTRTOD xstrtod
+# define DOUBLE double
+#endif
+
+/* An interface to a string-to-floating-point conversion function that
+   encapsulates all the error checking one should usually perform.
+   Like strtod/strtold, but upon successful
    conversion put the result in *RESULT and return true.  Return
    false and don't modify *RESULT upon any failure.  CONVERT
    specifies the conversion function, e.g., strtod itself.  */
 
 bool
-xstrtod (char const *str, char const **ptr, double *result,
-	 double (*convert) (char const *, char **))
+XSTRTOD (char const *str, char const **ptr, DOUBLE *result,
+	 DOUBLE (*convert) (char const *, char **))
 {
-  double val;
+  DOUBLE val;
   char *terminator;
   bool ok = true;
 
@@ -51,9 +60,9 @@
     ok = false;
   else
     {
-      /* Allow underflow (in which case strtod returns zero),
+      /* Allow underflow (in which case CONVERT returns zero),
 	 but flag overflow as an error. */
-      if (val != 0.0 && errno == ERANGE)
+      if (val != 0 && errno == ERANGE)
 	ok = false;
     }
 
--- a/lib/xstrtod.h
+++ b/lib/xstrtod.h
@@ -1,6 +1,6 @@
 /* Error-checking interface to strtod-like functions.
 
-   Copyright (C) 1996, 1998, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1998, 2003, 2004, 2006 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
@@ -25,5 +25,7 @@
 
 bool xstrtod (const char *str, const char **ptr, double *result,
 	      double (*convert) (char const *, char **));
+bool xstrtold (const char *str, const char **ptr, long double *result,
+	       long double (*convert) (char const *, char **));
 
 #endif /* not XSTRTOD_H */
new file mode 100644
--- /dev/null
+++ b/lib/xstrtold.c
@@ -0,0 +1,2 @@
+#define LONG 1
+#include "xstrtod.c"
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,61 @@
+2006-07-03  Paul Eggert  <eggert@cs.ucla.edu>
+
+	Merge from coreutils.
+
+	2006-06-30  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* c-strtod.m4 (gl_C_STRTOLD): Add c-strtod.c to LIBSOURCES.
+	Require gl_USE_SYSTEM_EXTENSIONS, not gl_C_STRTOD, since we don't
+	want to require the building of c-strtod.o.
+	* lib-check.m4 (cu_LIB_CHECK): Remove SEQ_LIBM, since seq no longer
+	needs -lm directly.
+	* xstrtod.m4 (gl_XSTRTOLD): New macro.
+
+	2006-06-19  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* lib-ignore.m4 (gl_IGNORE_UNUSED_LIBRARIES): Prefer binutils's
+	--as-needed option if available.  Problem reported by Albert Chin in
+	<http://lists.gnu.org/archive/html/bug-gnulib/2006-06/msg00114.html>.
+	However, use -Wl,--as-needed, not bare --as-needed, since HP-UX 11.11
+	cc merely issues a bunch of annoying warnings for --as-needed
+	(this problem was reported by Bob Proulx).  Also, try linking with
+	-lm to detect a bug in binutils 2.16 (this problem was reported
+	by Ralf Wildenhues).
+
+	2006-06-18  Jim Meyering  <jim@meyering.net>
+
+	Test for a bug that causes glibc's getcwd to suffer a failed assertion.
+	* getcwd-abort-bug.m4 (gl_FUNC_GETCWD_ABORT_BUG): New file and macro.
+	* getcwd.m4 (gl_FUNC_GETCWD): If we detect support for getcwd_null,
+	also check for glibc-2.4's abort-inducing bug.
+
+	* getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Fix typo.
+	Low-probability clean-up should be to use rmdir to get rid of
+	the just-created directory, not unlink.
+
+	* ftruncate.m4 (gl_FUNC_FTRUNCATE): If ftruncate is missing, make
+	configure fail, and request a bug report to inform us about it.
+	Add a comment that, barring reports to the contrary, in 2007 we'll
+	assume ftruncate is universally available.
+
+	2006-04-17  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* filemode.m4 (gl_FILEMODE): Check for strmode declaration.
+
+	2006-03-12  Jim Meyering  <jim@meyering.net>
+
+	* chdir-safer.m4 (gl_CHDIR_SAFER): Add same-inode.h to the list.
+	* cycle-check.m4 (gl_CYCLE_CHECK): Likewise.
+	* same.m4 (gl_SAME): Likewise.
+	* root-dev-ino.m4 (gl_ROOT_DEV_INO): Likewise.
+
+	2006-03-11  Eric Blake  <ebb9@byu.net>
+
+	* double-slash-root.m4: New file, provides gl_DOUBLE_SLASH_ROOT.
+	* dirname.m4 (gl_DIRNAME): Use gl_DOUBLE_SLASH_ROOT.
+	* dos.m4 (FILE_SYSTEM_PREFIX_LEN): Move from here to dirname.h.
+	(FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE): New define.
+
 2006-07-02  Eric Blake  <ebb9@byu.net>
 
 	* wcwidth.m4 (gl_FUNC_WCWIDTH): Simplify by using AC_CHECK_DECLS.
--- a/m4/c-strtod.m4
+++ b/m4/c-strtod.m4
@@ -1,4 +1,4 @@
-# c-strtod.m4 serial 7
+# c-strtod.m4 serial 8
 
 # Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -45,11 +45,11 @@
 
 AC_DEFUN([gl_C_STRTOLD],
 [
-  AC_LIBSOURCES([c-strtold.c, c-strtod.h])
+  AC_LIBSOURCES([c-strtod.c, c-strtold.c, c-strtod.h])
   AC_LIBOBJ([c-strtold])
 
   dnl Prerequisites of lib/c-strtold.c.
-  AC_REQUIRE([gl_C_STRTOD])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_C99_STRTOLD])
   :
 ])
--- a/m4/chdir-safer.m4
+++ b/m4/chdir-safer.m4
@@ -1,11 +1,11 @@
-#serial 1
-dnl Copyright (C) 2005 Free Software Foundation, Inc.
+#serial 2
+dnl Copyright (C) 2005, 2006 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.
 
 AC_DEFUN([gl_CHDIR_SAFER],
 [
-  AC_LIBSOURCES([chdir-safer.c, chdir-safer.h])
+  AC_LIBSOURCES([chdir-safer.c, chdir-safer.h, same-inode.h])
   AC_LIBOBJ([chdir-safer])
 ])
--- a/m4/dirname.m4
+++ b/m4/dirname.m4
@@ -1,5 +1,5 @@
-# dirname.m4 serial 5
-dnl Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#serial 6   -*- autoconf -*-
+dnl Copyright (C) 2002-2006 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.
@@ -11,6 +11,7 @@
 
   dnl Prerequisites of lib/dirname.h.
   AC_REQUIRE([gl_AC_DOS])
+  AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
 
   dnl No prerequisites of lib/basename.c, lib/dirname.c, lib/stripslash.c.
 ])
--- a/m4/dos.m4
+++ b/m4/dos.m4
@@ -1,9 +1,9 @@
-#serial 9
+#serial 10   -*- autoconf -*-
 
 # Define some macros required for proper operation of code in lib/*.c
 # on MSDOS/Windows systems.
 
-# Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -14,30 +14,38 @@
   [
     AC_CACHE_CHECK([whether system is Windows or MSDOS], [ac_cv_win_or_dos],
       [
-        AC_TRY_COMPILE([],
-        [#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __CYGWIN__
+	AC_TRY_COMPILE([],
+	[#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __CYGWIN__
 neither MSDOS nor Windows
 #endif],
-        [ac_cv_win_or_dos=yes],
-        [ac_cv_win_or_dos=no])
+	[ac_cv_win_or_dos=yes],
+	[ac_cv_win_or_dos=no])
       ])
 
     if test x"$ac_cv_win_or_dos" = xyes; then
       ac_fs_accepts_drive_letter_prefix=1
       ac_fs_backslash_is_file_name_separator=1
+      AC_CACHE_CHECK([whether drive letter can start relative path],
+		     [ac_cv_drive_letter_can_be_relative],
+	[
+	  AC_TRY_COMPILE([],
+	  [#if defined __CYGWIN__
+drive letters are always absolute
+#endif],
+	  [ac_cv_drive_letter_can_be_relative=yes],
+	  [ac_cv_drive_letter_can_be_relative=no])
+	])
+      if test x"$ac_cv_drive_letter_can_be_relative" = xyes; then
+	ac_fs_drive_letter_can_be_relative=1
+      else
+	ac_fs_drive_letter_can_be_relative=0
+      fi
     else
       ac_fs_accepts_drive_letter_prefix=0
       ac_fs_backslash_is_file_name_separator=0
+      ac_fs_drive_letter_can_be_relative=0
     fi
 
-    AH_VERBATIM(FILE_SYSTEM_PREFIX_LEN,
-    [#if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
-# define FILE_SYSTEM_PREFIX_LEN(Filename) \
-  ((Filename)[0] && (Filename)[1] == ':' ? 2 : 0)
-#else
-# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
-#endif])
-
     AC_DEFINE_UNQUOTED([FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX],
       $ac_fs_accepts_drive_letter_prefix,
       [Define on systems for which file names may have a so-called
@@ -55,4 +63,9 @@
       $ac_fs_backslash_is_file_name_separator,
       [Define if the backslash character may also serve as a file name
        component separator.])
+
+    AC_DEFINE_UNQUOTED([FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE],
+      $ac_fs_drive_letter_can_be_relative,
+      [Define if a drive letter prefix denotes a relative path if it is
+       not followed by a file name component separator.])
   ])
new file mode 100644
--- /dev/null
+++ b/m4/double-slash-root.m4
@@ -0,0 +1,43 @@
+#serial 1   -*- autoconf -*-
+dnl Copyright (C) 2006 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.
+
+AC_DEFUN([gl_DOUBLE_SLASH_ROOT],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_CACHE_CHECK([whether // is distinct from /], [ac_cv_double_slash_root],
+    [ if test x"$cross_compiling" = xyes ; then
+	# When cross-compiling, there is no way to tell whether // is special
+	# short of a list of hosts.  However, the only known hosts to date
+	# that have a distinct // are Apollo DomainOS (too old to port to)
+	# and Cygwin.  If anyone knows of another system for which // has
+	# special semantics and is distinct from /, please report it to
+	# <bug-coreutils@gnu.org>.
+	case $host in
+	  *-cygwin)
+	    ac_cv_double_slash_root=yes ;;
+	  *)
+	    # Be optimistic and assume that / and // are the same when we
+	    # don't know.
+	    ac_cv_double_slash_root='unknown, assuming no' ;;
+	esac
+      else
+	set x `ls -di / //`
+	if test $[2] = $[4]; then
+	  ac_cv_double_slash_root=no
+	else
+	  ac_cv_double_slash_root=yes
+	fi
+      fi])
+  if test x"$ac_cv_double_slash_root" = xyes; then
+    ac_double_slash_root=1
+  else
+    ac_double_slash_root=0
+  fi
+
+  AC_DEFINE_UNQUOTED([DOUBLE_SLASH_IS_DISTINCT_ROOT],
+   $ac_double_slash_root,
+   [Define to 1 if // is a file system root distinct from /.])
+])
--- a/m4/filemode.m4
+++ b/m4/filemode.m4
@@ -1,5 +1,5 @@
-# filemode.m4 serial 5
-dnl Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+# filemode.m4 serial 6
+dnl Copyright (C) 2002, 2005, 2006 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.
@@ -8,4 +8,5 @@
 [
   AC_LIBSOURCES([filemode.c, filemode.h])
   AC_LIBOBJ([filemode])
+  AC_CHECK_DECLS_ONCE([strmode])
 ])
--- a/m4/ftruncate.m4
+++ b/m4/ftruncate.m4
@@ -1,17 +1,29 @@
-#serial 8
+#serial 9
 
 # See if we need to emulate a missing ftruncate function using fcntl or chsize.
 
-# Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2003-2006 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
+# FIXME: remove this macro, along with all uses of HAVE_FTRUNCATE in 2007,
+# if the check below provokes no reports.
+
 AC_DEFUN([gl_FUNC_FTRUNCATE],
 [
   AC_REPLACE_FUNCS(ftruncate)
   if test $ac_cv_func_ftruncate = no; then
     gl_PREREQ_FTRUNCATE
+    # If someone lacks ftruncate, make configure fail, and request
+    # a bug report to inform us about it.
+    if test x"$SKIP_FTRUNCATE_CHECK" != xyes; then
+      AC_MSG_FAILURE([Your system lacks the ftruncate function.
+	  Please report this, along with the output of "uname -a", to the
+	  bug-coreutils@gnu.org mailing list.  To continue past this point,
+	  rerun configure with SKIP_FTRUNCATE_CHECK=yes set in the environment.
+	  E.g., env SKIP_FTRUNCATE_CHECK=yes ./configure])
+    fi
   fi
 ])
 
new file mode 100644
--- /dev/null
+++ b/m4/getcwd-abort-bug.m4
@@ -0,0 +1,106 @@
+#serial 1
+# Determine whether getcwd aborts when the length of the working directory
+# name is unusually large.  Any length between 4k and 16k trigger the bug
+# when using glibc-2.4.90-9 or older.
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# From Jim Meyering
+
+# gl_FUNC_GETCWD_ABORT_BUG([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+AC_DEFUN([gl_FUNC_GETCWD_ABORT_BUG],
+[
+  AC_CHECK_DECLS_ONCE(getcwd)
+  AC_CHECK_FUNCS(getpagesize)
+  AC_CACHE_CHECK([whether getcwd aborts when 4k < cwd_length < 16k],
+    gl_cv_func_getcwd_abort_bug,
+    [# Remove any remnants of a previous test.
+     rm -rf confdir-14B---
+     # Arrange for deletion of the temporary directory this test creates.
+     ac_clean_files="$ac_clean_files confdir-14B---"
+     AC_RUN_IFELSE(
+       [AC_LANG_SOURCE(
+	  [[
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* Don't get link errors because mkdir is redefined to rpl_mkdir.  */
+#undef mkdir
+
+#ifndef S_IRWXU
+# define S_IRWXU 0700
+#endif
+
+/* FIXME: skip the run-test altogether on systems without getpagesize.  */
+#if ! HAVE_GETPAGESIZE
+# define getpagesize() 0
+#endif
+
+/* This size is chosen to be larger than PATH_MAX (4k), yet smaller than
+   the 16kB pagesize on ia64 linux.  Those conditions make the code below
+   trigger a bug in glibc's getcwd implementation before 2.4.90-10.  */
+#define TARGET_LEN (5 * 1024)
+
+int
+main ()
+{
+  char const *dir_name = "confdir-14B---";
+  char *cwd;
+  size_t initial_cwd_len;
+  int fail = 0;
+  size_t desired_depth;
+  size_t d;
+
+  /* The bug is triggered when PATH_MAX < getpagesize (), so skip
+     this relative expensive and invasive test if that's not true.  */
+  if (getpagesize () <= PATH_MAX)
+    return 0;
+
+  cwd = getcwd (NULL, 0);
+  if (cwd == NULL)
+    return 0;
+
+  initial_cwd_len = strlen (cwd);
+  free (cwd);
+  desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
+		   / (1 + strlen (dir_name)));
+  for (d = 0; d < desired_depth; d++)
+    {
+      if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
+	{
+	  fail = 3; /* Unable to construct deep hierarchy.  */
+	  break;
+	}
+    }
+
+  /* If libc has the bug in question, this invocation of getcwd
+     results in a failed assertion.  */
+  cwd = getcwd (NULL, 0);
+  if (cwd == NULL)
+    fail = 4; /* getcwd failed.  This is ok, and expected.  */
+  free (cwd);
+
+  /* Call rmdir first, in case the above chdir failed.  */
+  rmdir (dir_name);
+  while (0 < d--)
+    {
+      if (chdir ("..") < 0)
+	break;
+      rmdir (dir_name);
+    }
+
+  return 0;
+}
+          ]])],
+    [gl_cv_func_getcwd_abort_bug=no],
+    [gl_cv_func_getcwd_abort_bug=yes],
+    [gl_cv_func_getcwd_abort_bug=yes])
+  ])
+  AS_IF([test $gl_cv_func_getcwd_abort_bug = yes], [$1], [$2])
+])
--- a/m4/getcwd-path-max.m4
+++ b/m4/getcwd-path-max.m4
@@ -1,4 +1,4 @@
-#serial 11
+#serial 12
 # Check for several getcwd bugs with long file names.
 # If so, arrange to compile the wrapper function.
 
@@ -157,8 +157,8 @@
   {
     size_t i;
 
-    /* Unlink first, in case the chdir failed.  */
-    unlink (DIR_NAME);
+    /* Try rmdir first, in case the chdir failed.  */
+    rmdir (DIR_NAME);
     for (i = 0; i <= n_chdirs; i++)
       {
 	if (chdir ("..") < 0)
--- a/m4/getcwd.m4
+++ b/m4/getcwd.m4
@@ -1,6 +1,6 @@
 # getcwd.m4 - check for working getcwd that is compatible with glibc
 
-# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -40,12 +40,15 @@
 [
   AC_REQUIRE([gl_FUNC_GETCWD_NULL])
 
+  gl_abort_bug=no
   case $gl_cv_func_getcwd_null in
-  yes) gl_FUNC_GETCWD_PATH_MAX;;
+  yes)
+    gl_FUNC_GETCWD_PATH_MAX
+    gl_FUNC_GETCWD_ABORT_BUG([gl_abort_bug=yes]);;
   esac
 
-  case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_path_max in
-  yes,yes) ;;
+  case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_path_max,$gl_abort_bug in
+  yes,yes,no) ;;
   *)
     AC_LIBOBJ([getcwd])
     AC_DEFINE([__GETCWD_PREFIX], [[rpl_]],
--- a/m4/lib-ignore.m4
+++ b/m4/lib-ignore.m4
@@ -13,15 +13,30 @@
     [gl_cv_ignore_unused_libraries],
     [gl_cv_ignore_unused_libraries=none
      gl_saved_ldflags=$LDFLAGS
+     gl_saved_libs=$LIBS
+     # Link with -lm to detect binutils 2.16 bug with --as-needed; see
+     # <http://lists.gnu.org/archive/html/bug-gnulib/2006-06/msg00131.html>.
+     LIBS="$LIBS -lm"
      # Use long option sequences like '-z ignore' to test for the feature,
      # to forestall problems with linkers that have -z, -i, -g, -n, etc. flags.
-     for gl_flags in '-Wl,-z,ignore' '-z ignore'; do
+     # GCC + binutils likes '-Wl,--as-needed'.
+     # GCC + Solaris ld likes '-Wl,-z,ignore'.
+     # Sun C likes '-z ignore'.
+     # Don't try bare '--as-needed'; nothing likes it and the HP-UX 11.11
+     # native cc issues annoying warnings and then ignores it,
+     # which would cause us to incorrectly conclude that it worked.
+     for gl_flags in \
+	'-Wl,--as-needed' \
+	'-Wl,-z,ignore' \
+	'-z ignore'
+     do
        LDFLAGS="$gl_flags $LDFLAGS"
        AC_LINK_IFELSE([AC_LANG_PROGRAM()],
 	 [gl_cv_ignore_unused_libraries=$gl_flags])
        LDFLAGS=$gl_saved_ldflags
        test "$gl_cv_ignore_unused_libraries" != none && break
-     done])
+     done
+     LIBS=$gl_saved_libs])
 
   test "$gl_cv_ignore_unused_libraries" != none &&
     LDFLAGS="$LDFLAGS $gl_cv_ignore_unused_libraries"
--- a/m4/same.m4
+++ b/m4/same.m4
@@ -1,12 +1,12 @@
-# same.m4 serial 6
-dnl Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#serial 7
+dnl Copyright (C) 2002, 2003, 2005, 2006 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.
 
 AC_DEFUN([gl_SAME],
 [
-  AC_LIBSOURCES([same.c, same.h])
+  AC_LIBSOURCES([same.c, same.h, same-inode.h])
   AC_LIBOBJ([same])
 
   dnl Prerequisites of lib/same.c.
--- a/m4/xstrtod.m4
+++ b/m4/xstrtod.m4
@@ -1,5 +1,5 @@
-#serial 4
-dnl Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#serial 5
+dnl Copyright (C) 2002, 2003, 2005, 2006 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.
@@ -10,3 +10,10 @@
   AC_LIBSOURCES([xstrtod.c, xstrtod.h])
   AC_LIBOBJ([xstrtod])
 ])
+
+# Prerequisites of lib/xstrtold.c.
+AC_DEFUN([gl_XSTRTOLD],
+[
+  AC_LIBSOURCES([xstrtold.c, xstrtod.c, xstrtod.h])
+  AC_LIBOBJ([xstrtold])
+])
--- a/modules/cycle-check
+++ b/modules/cycle-check
@@ -4,6 +4,7 @@
 Files:
 lib/cycle-check.c
 lib/cycle-check.h
+lib/same-inode.h
 lib/dev-ino.h
 
 Depends-on:
--- a/modules/dirname
+++ b/modules/dirname
@@ -8,6 +8,7 @@
 lib/stripslash.c
 m4/dos.m4
 m4/dirname.m4
+m4/double-slash-root.m4
 
 Depends-on:
 xalloc
--- a/modules/getcwd
+++ b/modules/getcwd
@@ -5,6 +5,7 @@
 lib/getcwd.h
 lib/getcwd.c
 m4/d-ino.m4
+m4/getcwd-abort-bug.m4
 m4/getcwd-path-max.m4
 m4/getcwd.m4
 
--- a/modules/mkdir-p
+++ b/modules/mkdir-p
@@ -7,6 +7,7 @@
 lib/lchmod.h
 lib/mkdir-p.c
 lib/mkdir-p.h
+lib/same-inode.h
 m4/afs.m4
 m4/chdir-safer.m4
 m4/lchmod.m4
--- a/modules/same
+++ b/modules/same
@@ -1,10 +1,11 @@
 Description:
-Determine whether two pathnames refer to the same directory entry of the same
+Determine whether two file names refer to the same directory entry of the same
 directory.
 
 Files:
 lib/same.h
 lib/same.c
+lib/same-inode.h
 m4/same.m4
 
 Depends-on:
new file mode 100644
--- /dev/null
+++ b/modules/xstrtold
@@ -0,0 +1,25 @@
+Description:
+Convert string to 'long double', with error checking.
+
+Files:
+lib/xstrtod.h
+lib/xstrtod.c
+lib/xstrtold.c
+m4/xstrtod.m4
+
+Depends-on:
+stdbool
+
+configure.ac:
+gl_XSTRTOLD
+
+Makefile.am:
+
+Include:
+"xstrtod.h"
+
+License:
+GPL
+
+Maintainer:
+Jim Meyering