#include "acl-internal.h"
+#include "minmax.h"
+
#if USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+# include <stdckdint.h>
# include <string.h>
# include <arpa/inet.h>
# include <sys/xattr.h>
&& errno == ERANGE)
{
free (heapbuf);
- listbufsize = listxattr (name, NULL, 0);
- if (listbufsize < 0)
- return -1;
- if (SIZE_MAX < listbufsize)
+ ssize_t newsize = listxattr (name, NULL, 0);
+ if (newsize <= 0)
+ return newsize;
+
+ /* Grow LISTBUFSIZE to at least NEWSIZE. Grow it by a
+ nontrivial amount too, to defend against denial of
+ service by an adversary that fiddles with ACLs. */
+ bool overflow = ckd_add (&listbufsize, listbufsize, listbufsize >> 1);
+ listbufsize = MAX (listbufsize, newsize);
+ if (overflow || SIZE_MAX < listbufsize)
{
errno = ENOMEM;
return -1;
}
+
listbuf = heapbuf = malloc (listbufsize);
if (!listbuf)
return -1;
}
+ /* In Fedora 39, a file can have both NFSv4 and POSIX ACLs,
+ but if it has an NFSv4 ACL that's the one that matters.
+ In earlier Fedora the two types of ACLs were mutually exclusive.
+ Attempt to work correctly on both kinds of systems. */
+ bool nfsv4_acl
+ = 0 < listsize && have_xattr (XATTR_NAME_NFSV4_ACL, listbuf, listsize);
int ret
- = (listsize < 0 ? -1
- : (have_xattr (XATTR_NAME_POSIX_ACL_ACCESS, listbuf, listsize)
+ = (listsize <= 0 ? listsize
+ : (nfsv4_acl
+ || have_xattr (XATTR_NAME_POSIX_ACL_ACCESS, listbuf, listsize)
|| (S_ISDIR (sb->st_mode)
&& have_xattr (XATTR_NAME_POSIX_ACL_DEFAULT,
listbuf, listsize))));
- bool nfsv4_acl_but_no_posix_acl
- = ret == 0 && have_xattr (XATTR_NAME_NFSV4_ACL, listbuf, listsize);
free (heapbuf);
- /* If there is an NFSv4 ACL but no POSIX ACL, follow up with a
- getxattr syscall to see whether the NFSv4 ACL is nontrivial. */
- if (nfsv4_acl_but_no_posix_acl)
+ /* If there is an NFSv4 ACL, follow up with a getxattr syscall
+ to see whether the NFSv4 ACL is nontrivial. */
+ if (nfsv4_acl)
{
ret = getxattr (name, XATTR_NAME_NFSV4_ACL,
stackbuf.xattr, sizeof stackbuf.xattr);
#else
struct timeval tv;
gettimeofday (&tv, NULL);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
+ *ts = (struct timespec) { .tv_sec = tv.tv_sec,
+ .tv_nsec = tv.tv_usec * 1000 };
#endif
}
ULONGLONG since_1970 =
since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000;
ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10;
- tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000;
- tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000;
+ *tv = (struct timeval) {
+ .tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000,
+ .tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000
+ };
return 0;
struct timeval otv;
int result = gettimeofday (&otv, (struct timezone *) tz);
if (result == 0)
- {
- tv->tv_sec = otv.tv_sec;
- tv->tv_usec = otv.tv_usec;
- }
+ *tv = otv;
# else
int result = gettimeofday (tv, (struct timezone *) tz);
# endif
# error "Only 1-second nominal clock resolution found. Is that intended?" \
"If so, compile with the -DOK_TO_USE_1S_CLOCK option."
# endif
- tv->tv_sec = time (NULL);
- tv->tv_usec = 0;
+ *tv = (struct timeval) { .tv_sec = time (NULL), .tv_usec = 0 };
return 0;
static_assert (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);
const time_t limit = 24 * 24 * 60 * 60;
time_t seconds = requested_delay->tv_sec;
- struct timespec intermediate;
- intermediate.tv_nsec = requested_delay->tv_nsec;
+ struct timespec intermediate = *requested_delay;
while (limit < seconds)
{
return -1;
}
- tv.tv_sec = timeout->tv_sec;
- tv.tv_usec = (timeout->tv_nsec + 999) / 1000;
+ tv = (struct timeval) {
+ .tv_sec = timeout->tv_sec,
+ .tv_usec = (timeout->tv_nsec + 999) / 1000
+ };
tvp = &tv;
}
else
#ifdef STAT_TIMESPEC
return STAT_TIMESPEC (st, st_atim);
#else
- struct timespec t;
- t.tv_sec = st->st_atime;
- t.tv_nsec = get_stat_atime_ns (st);
- return t;
+ return (struct timespec) { .tv_sec = st->st_atime,
+ .tv_nsec = get_stat_atime_ns (st) };
#endif
}
#ifdef STAT_TIMESPEC
return STAT_TIMESPEC (st, st_ctim);
#else
- struct timespec t;
- t.tv_sec = st->st_ctime;
- t.tv_nsec = get_stat_ctime_ns (st);
- return t;
+ return (struct timespec) { .tv_sec = st->st_ctime,
+ .tv_nsec = get_stat_ctime_ns (st) };
#endif
}
#ifdef STAT_TIMESPEC
return STAT_TIMESPEC (st, st_mtim);
#else
- struct timespec t;
- t.tv_sec = st->st_mtime;
- t.tv_nsec = get_stat_mtime_ns (st);
- return t;
+ return (struct timespec) { .tv_sec = st->st_mtime,
+ .tv_nsec = get_stat_mtime_ns (st) };
#endif
}
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
t = STAT_TIMESPEC (st, st_birthtim);
#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
- t.tv_sec = st->st_birthtime;
- t.tv_nsec = st->st_birthtimensec;
+ t = (struct timespec) { .tv_sec = st->st_birthtime,
+ .tv_nsec = st->st_birthtimensec };
#elif defined _WIN32 && ! defined __CYGWIN__
/* Native Windows platforms (but not Cygwin) put the "file creation
time" in st_ctime (!). See
# if _GL_WINDOWS_STAT_TIMESPEC
t = st->st_ctim;
# else
- t.tv_sec = st->st_ctime;
- t.tv_nsec = 0;
+ t = (struct timespec) { .tv_sec = st->st_ctime };
# endif
#else
/* Birth time is not supported. */
- t.tv_sec = -1;
- t.tv_nsec = -1;
+ t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 };
#endif
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
sometimes returns junk in the birth time fields; work around this
bug if it is detected. */
if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
- {
- t.tv_sec = -1;
- t.tv_nsec = -1;
- }
+ t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 };
#endif
return t;
_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
- struct timespec r;
- r.tv_sec = s;
- r.tv_nsec = ns;
- return r;
+ return (struct timespec) { .tv_sec = s, .tv_nsec = ns };
}
/* Return negative, zero, positive if A < B, A == B, A > B, respectively. */
struct timeval *t;
if (ts)
{
- timeval[0].tv_sec = ts[0].tv_sec;
- timeval[0].tv_usec = ts[0].tv_nsec / 1000;
- timeval[1].tv_sec = ts[1].tv_sec;
- timeval[1].tv_usec = ts[1].tv_nsec / 1000;
+ timeval[0] = (struct timeval) { .tv_sec = ts[0].tv_sec,
+ .tv_usec = ts[0].tv_nsec / 1000 };
+ timeval[1] = (struct timeval) { .tv_sec = ts[1].tv_sec,
+ .tv_usec = ts[1].tv_nsec / 1000 };
t = timeval;
}
else
struct utimbuf *ut;
if (ts)
{
- utimbuf.actime = ts[0].tv_sec;
- utimbuf.modtime = ts[1].tv_sec;
+ utimbuf = (struct utimbuf) { .actime = ts[0].tv_sec,
+ .modtime = ts[1].tv_sec };
ut = &utimbuf;
}
else
int result;
if (ts)
{
- timeval[0].tv_sec = ts[0].tv_sec;
- timeval[0].tv_usec = ts[0].tv_nsec / 1000;
- timeval[1].tv_sec = ts[1].tv_sec;
- timeval[1].tv_usec = ts[1].tv_nsec / 1000;
+ timeval[0] = (struct timeval) { .tv_sec = ts[0].tv_sec,
+ .tv_usec = ts[0].tv_nsec / 1000 };
+ timeval[1] = (struct timeval) { .tv_sec = ts[1].tv_sec,
+ .tv_usec = ts[1].tv_nsec / 1000 };
t = timeval;
}
else
-# gnulib-common.m4 serial 86
+# gnulib-common.m4 serial 87
dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl -Wno-float-conversion >= 4.9 >= 3.9
dnl -Wno-float-equal >= 3 >= 3.9
dnl -Wimplicit-fallthrough >= 7 >= 3.9
+ dnl -Wno-missing-field-initializers >= 4.0, < 11
dnl -Wno-pedantic >= 4.8 >= 3.9
dnl -Wno-sign-compare >= 3 >= 3.9
dnl -Wno-sign-conversion >= 4.3 >= 3.9
#if __GNUC__ >= 7 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
-Wimplicit-fallthrough
#endif
+ #if __GNUC__ >= 4 && __GNUC__ < 11 && !defined __clang__
+ -Wno-missing-field-initializers
+ #endif
#if __GNUC__ + (__GNUC_MINOR__ >= 8) > 4 || (__clang_major__ + (__clang_minor__ >= 9) > 3)
-Wno-pedantic
#endif