aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/allocator.h2
-rw-r--r--lib/fstatat.c12
-rw-r--r--lib/intprops.h6
-rw-r--r--lib/lstat.c39
-rw-r--r--lib/signal.in.h2
-rw-r--r--lib/stat-time.h45
-rw-r--r--lib/stdio-impl.h4
-rw-r--r--lib/stdio.in.h2
-rw-r--r--lib/timespec.h2
9 files changed, 85 insertions, 29 deletions
diff --git a/lib/allocator.h b/lib/allocator.h
index 8f79d7435c3..fc3d646aa54 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -29,7 +29,7 @@ struct allocator
29 /* Do not use GCC attributes such as __attribute__ ((malloc)) with 29 /* Do not use GCC attributes such as __attribute__ ((malloc)) with
30 the function types pointed at by these members, because these 30 the function types pointed at by these members, because these
31 attributes do not work with pointers to functions. See 31 attributes do not work with pointers to functions. See
32 <https://lists.gnu.org/archive/html/bug-gnulib/2011-04/msg00007.html>. */ 32 <https://lists.gnu.org/r/bug-gnulib/2011-04/msg00007.html>. */
33 33
34 /* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE 34 /* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE
35 should return NULL, though not necessarily set errno. When given 35 should return NULL, though not necessarily set errno. When given
diff --git a/lib/fstatat.c b/lib/fstatat.c
index 294861f51b1..237e68c5da7 100644
--- a/lib/fstatat.c
+++ b/lib/fstatat.c
@@ -41,6 +41,8 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
41 above. */ 41 above. */
42#include "sys/stat.h" 42#include "sys/stat.h"
43 43
44#include "stat-time.h"
45
44#include <errno.h> 46#include <errno.h>
45#include <fcntl.h> 47#include <fcntl.h>
46#include <string.h> 48#include <string.h>
@@ -51,6 +53,12 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
51# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0 53# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
52# endif 54# endif
53 55
56static int
57normal_fstatat (int fd, char const *file, struct stat *st, int flag)
58{
59 return stat_time_normalize (orig_fstatat (fd, file, st, flag), st);
60}
61
54/* fstatat should always follow symbolic links that end in /, but on 62/* fstatat should always follow symbolic links that end in /, but on
55 Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. 63 Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified.
56 Likewise, trailing slash on a non-directory should be an error. 64 Likewise, trailing slash on a non-directory should be an error.
@@ -63,7 +71,7 @@ orig_fstatat (int fd, char const *filename, struct stat *buf, int flags)
63int 71int
64rpl_fstatat (int fd, char const *file, struct stat *st, int flag) 72rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
65{ 73{
66 int result = orig_fstatat (fd, file, st, flag); 74 int result = normal_fstatat (fd, file, st, flag);
67 size_t len; 75 size_t len;
68 76
69 if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0) 77 if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0)
@@ -79,7 +87,7 @@ rpl_fstatat (int fd, char const *file, struct stat *st, int flag)
79 errno = ENOTDIR; 87 errno = ENOTDIR;
80 return -1; 88 return -1;
81 } 89 }
82 result = orig_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); 90 result = normal_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW);
83 } 91 }
84 /* Fix stat behavior. */ 92 /* Fix stat behavior. */
85 if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/') 93 if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/')
diff --git a/lib/intprops.h b/lib/intprops.h
index a34e81c7b5e..2df7b1f9f69 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -26,7 +26,7 @@
26#define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) 26#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
27 27
28/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see 28/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
29 <https://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */ 29 <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */
30#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v)) 30#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
31 31
32/* The extra casts in the following macros work around compiler bugs, 32/* The extra casts in the following macros work around compiler bugs,
@@ -179,7 +179,7 @@
179/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. 179/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
180 See above for restrictions. Avoid && and || as they tickle 180 See above for restrictions. Avoid && and || as they tickle
181 bugs in Sun C 5.11 2010/08/13 and other compilers; see 181 bugs in Sun C 5.11 2010/08/13 and other compilers; see
182 <https://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */ 182 <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */
183#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ 183#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \
184 ((b) < 0 \ 184 ((b) < 0 \
185 ? ((a) < 0 \ 185 ? ((a) < 0 \
@@ -443,7 +443,7 @@
443 implementation-defined result or signal for values outside T's 443 implementation-defined result or signal for values outside T's
444 range. However, code that works around this theoretical problem 444 range. However, code that works around this theoretical problem
445 runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: 445 runs afoul of a compiler bug in Oracle Studio 12.3 x86. See:
446 https://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00049.html 446 https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
447 As the compiler bug is real, don't try to work around the 447 As the compiler bug is real, don't try to work around the
448 theoretical problem. */ 448 theoretical problem. */
449 449
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 */
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 9c32b14962f..e8107c37bf5 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -200,7 +200,7 @@ typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1];
200/* When also using extern inline, suppress the use of static inline in 200/* When also using extern inline, suppress the use of static inline in
201 standard headers of problematic Apple configurations, as Libc at 201 standard headers of problematic Apple configurations, as Libc at
202 least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., 202 least through Libc-825.26 (2013-04-09) mishandles it; see, e.g.,
203 <https://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>. 203 <https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html>.
204 Perhaps Apple will fix this some day. */ 204 Perhaps Apple will fix this some day. */
205#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ 205#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \
206 && (defined __i386__ || defined __x86_64__)) 206 && (defined __i386__ || defined __x86_64__))
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 47a3bf8f21e..1cf821992ed 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -20,6 +20,10 @@
20#ifndef STAT_TIME_H 20#ifndef STAT_TIME_H
21#define STAT_TIME_H 1 21#define STAT_TIME_H 1
22 22
23#include "intprops.h"
24
25#include <errno.h>
26#include <stddef.h>
23#include <sys/stat.h> 27#include <sys/stat.h>
24#include <time.h> 28#include <time.h>
25 29
@@ -202,6 +206,47 @@ get_stat_birthtime (struct stat const *st)
202 return t; 206 return t;
203} 207}
204 208
209/* If a stat-like function returned RESULT, normalize the timestamps
210 in *ST, in case this platform suffers from the Solaris 11 bug where
211 tv_nsec might be negative. Return the adjusted RESULT, setting
212 errno to EOVERFLOW if normalization overflowed. This function
213 is intended to be private to this .h file. */
214_GL_STAT_TIME_INLINE int
215stat_time_normalize (int result, struct stat *st)
216{
217#if defined __sun && defined STAT_TIMESPEC
218 if (result == 0)
219 {
220 long int timespec_resolution = 1000000000;
221 short int const ts_off[] = { offsetof (struct stat, st_atim),
222 offsetof (struct stat, st_mtim),
223 offsetof (struct stat, st_ctim) };
224 int i;
225 for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++)
226 {
227 struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]);
228 long int q = ts->tv_nsec / timespec_resolution;
229 long int r = ts->tv_nsec % timespec_resolution;
230 if (r < 0)
231 {
232 r += timespec_resolution;
233 q--;
234 }
235 ts->tv_nsec = r;
236 /* Overflow is possible, as Solaris 11 stat can yield
237 tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000.
238 INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */
239 if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec))
240 {
241 errno = EOVERFLOW;
242 return -1;
243 }
244 }
245 }
246#endif
247 return result;
248}
249
205#ifdef __cplusplus 250#ifdef __cplusplus
206} 251}
207#endif 252#endif
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 8960333687e..329801ad23b 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -81,7 +81,7 @@
81#ifdef __TANDEM /* NonStop Kernel */ 81#ifdef __TANDEM /* NonStop Kernel */
82# ifndef _IOERR 82# ifndef _IOERR
83/* These values were determined by the program 'stdioext-flags' at 83/* These values were determined by the program 'stdioext-flags' at
84 <https://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00165.html>. */ 84 <https://lists.gnu.org/r/bug-gnulib/2010-12/msg00165.html>. */
85# define _IOERR 0x40 85# define _IOERR 0x40
86# define _IOREAD 0x80 86# define _IOREAD 0x80
87# define _IOWRT 0x4 87# define _IOWRT 0x4
@@ -132,7 +132,7 @@ struct _gl_real_FILE
132# define fp_ ((struct _gl_real_FILE *) fp) 132# define fp_ ((struct _gl_real_FILE *) fp)
133 133
134/* These values were determined by a program similar to the one at 134/* These values were determined by a program similar to the one at
135 <https://lists.gnu.org/archive/html/bug-gnulib/2010-12/msg00165.html>. */ 135 <https://lists.gnu.org/r/bug-gnulib/2010-12/msg00165.html>. */
136# define _IOREAD 0x1 136# define _IOREAD 0x1
137# define _IOWRT 0x2 137# define _IOWRT 0x2
138# define _IORW 0x4 138# define _IORW 0x4
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 066e08eba9a..505f3f49f4e 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -152,7 +152,7 @@
152/* When also using extern inline, suppress the use of static inline in 152/* When also using extern inline, suppress the use of static inline in
153 standard headers of problematic Apple configurations, as Libc at 153 standard headers of problematic Apple configurations, as Libc at
154 least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., 154 least through Libc-825.26 (2013-04-09) mishandles it; see, e.g.,
155 <https://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>. 155 <https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html>.
156 Perhaps Apple will fix this some day. */ 156 Perhaps Apple will fix this some day. */
157#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ 157#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \
158 && defined __GNUC__ && defined __STDC__) 158 && defined __GNUC__ && defined __STDC__)
diff --git a/lib/timespec.h b/lib/timespec.h
index cc34067374f..84c8146a3ea 100644
--- a/lib/timespec.h
+++ b/lib/timespec.h
@@ -87,7 +87,7 @@ timespec_cmp (struct timespec a, struct timespec b)
87 return 1; 87 return 1;
88 88
89 /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02). See: 89 /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02). See:
90 http://lists.gnu.org/archive/html/bug-gnulib/2017-10/msg00006.html */ 90 http://lists.gnu.org/r/bug-gnulib/2017-10/msg00006.html */
91 assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_RESOLUTION); 91 assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_RESOLUTION);
92 assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_RESOLUTION); 92 assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_RESOLUTION);
93 93