aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lstat.c
diff options
context:
space:
mode:
authorPaul Eggert2017-11-25 22:28:31 -0800
committerPaul Eggert2017-11-25 22:48:09 -0800
commit8be3aee2813f528b02bc913ca4d79e34e72b1754 (patch)
treeaf1e8e35cedfe601076eade046a1a12303b93e84 /lib/lstat.c
parent265cee553f9d59a989d92e28865f6cc6fc02dcc9 (diff)
downloademacs-8be3aee2813f528b02bc913ca4d79e34e72b1754.tar.gz
emacs-8be3aee2813f528b02bc913ca4d79e34e72b1754.zip
Merge from Gnulib
This incorporates: 2017-11-23 stat: work around Solaris bug with tv_nsec < 0 2017-11-12 maint: shorten https://lists.gnu.org/archive/html/... links * build-aux/config.sub, doc/misc/texinfo.tex, lib/allocator.h: * lib/fstatat.c, lib/intprops.h, lib/lstat.c, lib/signal.in.h: * lib/stat-time.h, lib/stdio-impl.h, lib/stdio.in.h: * lib/timespec.h, m4/alloca.m4, m4/extern-inline.m4: * m4/faccessat.m4, m4/fstatat.m4, m4/gnulib-common.m4: * m4/lstat.m4, m4/std-gnu11.m4, m4/sys_types_h.m4: * m4/vararrays.m4: Copy from Gnulib.
Diffstat (limited to 'lib/lstat.c')
-rw-r--r--lib/lstat.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/lib/lstat.c b/lib/lstat.c
index c721a4e641c..f3c61779540 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -47,6 +47,8 @@ orig_lstat (const char *filename, struct stat *buf)
47 above. */ 47 above. */
48# include "sys/stat.h" 48# include "sys/stat.h"
49 49
50# include "stat-time.h"
51
50# include <string.h> 52# include <string.h>
51# include <errno.h> 53# include <errno.h>
52 54
@@ -66,32 +68,33 @@ orig_lstat (const char *filename, struct stat *buf)
66int 68int
67rpl_lstat (const char *file, struct stat *sbuf) 69rpl_lstat (const char *file, struct stat *sbuf)
68{ 70{
69 size_t len; 71 int result = orig_lstat (file, sbuf);
70 int lstat_result = orig_lstat (file, sbuf);
71
72 if (lstat_result != 0)
73 return lstat_result;
74 72
75 /* This replacement file can blindly check against '/' rather than 73 /* This replacement file can blindly check against '/' rather than
76 using the ISSLASH macro, because all platforms with '\\' either 74 using the ISSLASH macro, because all platforms with '\\' either
77 lack symlinks (mingw) or have working lstat (cygwin) and thus do 75 lack symlinks (mingw) or have working lstat (cygwin) and thus do
78 not compile this file. 0 len should have already been filtered 76 not compile this file. 0 len should have already been filtered
79 out above, with a failure return of ENOENT. */ 77 out above, with a failure return of ENOENT. */
80 len = strlen (file); 78 if (result == 0)
81 if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
82 return 0;
83
84 /* At this point, a trailing slash is only permitted on
85 symlink-to-dir; but it should have found information on the
86 directory, not the symlink. Call stat() to get info about the
87 link's referent. Our replacement stat guarantees valid results,
88 even if the symlink is not pointing to a directory. */
89 if (!S_ISLNK (sbuf->st_mode))
90 { 79 {
91 errno = ENOTDIR; 80 if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/')
92 return -1; 81 result = stat_time_normalize (result, sbuf);
82 else
83 {
84 /* At this point, a trailing slash is permitted only on
85 symlink-to-dir; but it should have found information on the
86 directory, not the symlink. Call 'stat' to get info about the
87 link's referent. Our replacement stat guarantees valid results,
88 even if the symlink is not pointing to a directory. */
89 if (!S_ISLNK (sbuf->st_mode))
90 {
91 errno = ENOTDIR;
92 return -1;
93 }
94 result = stat (file, sbuf);
95 }
93 } 96 }
94 return stat (file, sbuf); 97 return result;
95} 98}
96 99
97#endif /* HAVE_LSTAT */ 100#endif /* HAVE_LSTAT */