1
1
/* Work around a bug of lstat on some systems
3
Copyright (C) 1997-1999, 2000-2006, 2008 Free Software Foundation, Inc.
3
Copyright (C) 1997-2006, 2008-2010 Free Software Foundation, Inc.
5
5
This program is free software: you can redistribute it and/or modify
6
6
it under the terms of the GNU General Public License as published by
20
20
#include <config.h>
22
/* Get the original definition of open. It might be defined as a macro. */
23
#define __need_system_sys_stat_h
24
#include <sys/types.h>
26
#undef __need_system_sys_stat_h
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. */
27
#else /* HAVE_LSTAT */
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
29
36
orig_lstat (const char *filename, struct stat *buf)
57
64
int lstat_result = orig_lstat (file, sbuf);
59
if (lstat_result != 0 || !S_ISLNK (sbuf->st_mode))
66
if (lstat_result != 0)
60
67
return lstat_result;
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. */
62
74
len = strlen (file);
63
if (len == 0 || file[len - 1] != '/')
66
/* FILE refers to a symbolic link and the name ends with a slash.
67
Call stat() to get info about the link's referent. */
69
/* If stat fails, then we do the same. */
70
if (stat (file, sbuf) != 0)
73
/* If FILE references a directory, return 0. */
74
if (S_ISDIR (sbuf->st_mode))
77
/* Here, we know stat succeeded and FILE references a non-directory.
78
But it was specified via a name including a trailing slash.
79
Fail with errno set to ENOTDIR to indicate the contradiction. */
75
if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
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))
88
return stat (file, sbuf);
91
#endif /* HAVE_LSTAT */