X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fxstat.in;h=77c367eb736d7dadfbdf5e40bc54ba85e854b688;hb=7d8d614280a61d7bbdac8e218bfdc1aa849329c7;hp=d5420a4d3c9d4b8a1f7e78b9c5913f6152f5c3a4;hpb=fb17b99b4b5e7b06b7e745d77f2332b803a148d2;p=gnulib.git diff --git a/lib/xstat.in b/lib/xstat.in index d5420a4d3..77c367eb7 100644 --- 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-2001 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,68 @@ #ifndef errno extern int errno; #endif +@BEGIN_LSTAT_ONLY@ + +#if HAVE_STDLIB_H +# include +#endif + +#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 + +#ifndef HAVE_DECL_FREE +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_FREE +void free (); +#endif + +char *xmalloc (); + +/* lstat works differently 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'll 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 +100,11 @@ extern int errno; 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 +115,10 @@ rpl_@xstat@ (const char *file, struct stat *sbuf) 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@ }