Annotation of embedaddon/libiconv/srclib/lstat.c, revision 1.1.1.1
1.1 misho 1: /* Work around a bug of lstat on some systems
2:
3: Copyright (C) 1997-2006, 2008-2011 Free Software Foundation, Inc.
4:
5: This program is free software: you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by
7: the Free Software Foundation; either version 3 of the License, or
8: (at your option) any later version.
9:
10: This program is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
16: along with this program. If not, see <http://www.gnu.org/licenses/>. */
17:
18: /* written by Jim Meyering */
19:
20: #include <config.h>
21:
22: #if !HAVE_LSTAT
23: /* On systems that lack symlinks, our replacement <sys/stat.h> already
24: defined lstat as stat, so there is nothing further to do other than
25: avoid an empty file. */
26: typedef int dummy;
27: #else /* HAVE_LSTAT */
28:
29: /* Get the original definition of lstat. It might be defined as a macro. */
30: # define __need_system_sys_stat_h
31: # include <sys/types.h>
32: # include <sys/stat.h>
33: # undef __need_system_sys_stat_h
34:
35: static inline int
36: orig_lstat (const char *filename, struct stat *buf)
37: {
38: return lstat (filename, buf);
39: }
40:
41: /* Specification. */
42: # include <sys/stat.h>
43:
44: # include <string.h>
45: # include <errno.h>
46:
47: /* lstat works differently on Linux and Solaris systems. POSIX (see
48: `pathname resolution' in the glossary) requires that programs like
49: `ls' take into consideration the fact that FILE has a trailing slash
50: when FILE is a symbolic link. On Linux and Solaris 10 systems, the
51: lstat function already has the desired semantics (in treating
52: `lstat ("symlink/", sbuf)' just like `lstat ("symlink/.", sbuf)',
53: but on Solaris 9 and earlier it does not.
54:
55: If FILE has a trailing slash and specifies a symbolic link,
56: then use stat() to get more info on the referent of FILE.
57: If the referent is a non-directory, then set errno to ENOTDIR
58: and return -1. Otherwise, return stat's result. */
59:
60: int
61: rpl_lstat (const char *file, struct stat *sbuf)
62: {
63: size_t len;
64: int lstat_result = orig_lstat (file, sbuf);
65:
66: if (lstat_result != 0)
67: return lstat_result;
68:
69: /* This replacement file can blindly check against '/' rather than
70: using the ISSLASH macro, because all platforms with '\\' either
71: lack symlinks (mingw) or have working lstat (cygwin) and thus do
72: not compile this file. 0 len should have already been filtered
73: out above, with a failure return of ENOENT. */
74: len = strlen (file);
75: if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
76: return 0;
77:
78: /* At this point, a trailing slash is only permitted on
79: symlink-to-dir; but it should have found information on the
80: directory, not the symlink. Call stat() to get info about the
81: link's referent. Our replacement stat guarantees valid results,
82: even if the symlink is not pointing to a directory. */
83: if (!S_ISLNK (sbuf->st_mode))
84: {
85: errno = ENOTDIR;
86: return -1;
87: }
88: return stat (file, sbuf);
89: }
90:
91: #endif /* HAVE_LSTAT */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>