changeset 2043:3002e3481ea1

(slash_aware_lstat): New function. (rpl_@xstat@): Use it.
author Jim Meyering <jim@meyering.net>
date Sun, 19 Dec 1999 10:45:50 +0000
parents 210cdda9d73d
children 7c6352a7221c
files lib/xstat.in
diffstat 1 files changed, 64 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/lib/xstat.in
+++ b/lib/xstat.in
@@ -4,7 +4,7 @@
 /* Work around the bug in some systems whereby @xstat@ succeeds when
    given the zero-length file name argument.  The @xstat@ from SunOS4.1.4
    has this bug.
-   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999 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,58 @@
 #ifndef errno
 extern int errno;
 #endif
+@BEGIN_LSTAT_ONLY@
+
+#ifdef STAT_MACROS_BROKEN
+# undef S_ISLNK
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+
+char *xmalloc ();
+
+/* lstat works different on Linux and Solaris systems.  POSIX (see
+   `pathname resolution' in the glossary) requires that programs like `ls'
+   take into consideration the fact that FILE has a trailing slash when
+   FILE is a symbolic link.  On Linux systems, the lstat function already
+   has the desired semantics (in treating `lstat("symlink/",sbuf)' just like
+   `lstat("symlink/.",sbuf)', but on Solaris it does not.
+
+   If FILE has a trailing slash and specifies a symbolic link,
+   then append a `.' to FILE and call lstat a second time.  */
+
+static int
+slash_aware_lstat (const char *file, struct stat *sbuf)
+{
+  size_t len;
+  char *new_file;
+
+  int lstat_result = lstat (file, sbuf);
+
+  if (lstat_result != 0 || !S_ISLNK (sbuf->st_mode))
+    return lstat_result;
+
+  len = strlen (file);
+  if (file[len - 1] != '/')
+    return lstat_result;
+
+  /* FILE refers to a symbolic link and the name ends with a slash.
+     Append a `.' to FILE and repeat the lstat call.  */
+
+  /* Add one for the `.' we might have to append, and one more
+     for the trailing NUL.  */
+  new_file = xmalloc (len + 1 + 1);
+  memcpy (new_file, file, len);
+  new_file[len] = '.';
+  new_file[len + 1] = 0;
+
+  lstat_result = lstat (new_file, sbuf);
+  free (new_file);
+
+  return lstat_result;
+}
+@END_LSTAT_ONLY@
 
 /* This is a wrapper for @xstat@(2).
    If FILE is the empty string, fail with errno == ENOENT.
@@ -38,6 +90,11 @@
    This works around the bug in some systems whereby @xstat@ succeeds when
    given the zero-length file name argument.  The @xstat@ from SunOS4.1.4
    has this bug.  */
+@BEGIN_LSTAT_ONLY@
+
+/* This function also provides a version of lstat with consistent semantics
+   when FILE specifies a symbolic link and has a trailing slash.  */
+@END_LSTAT_ONLY@
 
 int
 rpl_@xstat@ (const char *file, struct stat *sbuf)
@@ -48,5 +105,10 @@
       return -1;
     }
 
-  return @xstat@ (file, sbuf);
+@BEGIN_LSTAT_ONLY@
+  return slash_aware_lstat (file, sbuf);
+@END_LSTAT_ONLY@
+@BEGIN_STAT_ONLY@
+  return stat (file, sbuf);
+@END_STAT_ONLY@
 }