- diff --git a/newlib/libc/include/sys/_default_fcntl.h b/newlib/libc/include/sys/_default_fcntl.h
- index b3222d452..c8f0bb1f7 100644
- --- a/newlib/libc/include/sys/_default_fcntl.h
- +++ b/newlib/libc/include/sys/_default_fcntl.h
- @@ -155,6 +155,17 @@ extern "C" {
- #define F_OFD_SETLKW 17 /* Set or Clear OFD lock (Blocking) */
- #endif
- +/*
- + * { Solaris, FreeBSD, SUPER/UX, ... }-style file space allocation/freeing.
- + *
- + * |F_ALLOCSP|/|F_FREESP| take |struct flock *|.
- + *
- + * |l_len| == 0 means "to EOF". Negative |l_len| follows the usual flock
- + * range convention and names [l_start + l_len, l_start].
- + */
- +#define F_ALLOCSP 18
- +#define F_FREESP 19
- +
- /* fcntl(2) flags (l_type field of flock structure) */
- #define F_RDLCK 1 /* read lock */
- #define F_WRLCK 2 /* write lock */
- diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc
- index 2bc52edb0..bf6d47542 100644
- --- a/winsup/cygwin/fcntl.cc
- +++ b/winsup/cygwin/fcntl.cc
- @@ -7,6 +7,8 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
- details. */
- #include "winsup.h"
- +#include <limits.h>
- +#include <sys/stat.h>
- #include <unistd.h>
- #include "cygerrno.h"
- #include "security.h"
- @@ -16,6 +18,195 @@ details. */
- #include "cygheap.h"
- #include "cygtls.h"
- +/*
- + * In the Cygwin DLL build, these prototypes are not always visible from
- + * <unistd.h> in this translation unit, even though the symbols are part of
- + * the public Cygwin API. Declare them explicitly for use by the fcntl()
- + * space-management helpers below.
- + */
- +extern "C" off_t lseek (int, off_t, int);
- +extern "C" int ftruncate (int, off_t);
- +
- +struct fcntl_space_range
- +{
- + off_t start;
- + off_t len;
- + bool to_eof;
- +};
- +
- +static inline bool
- +off_add_overflow (off_t a, off_t b, off_t *r)
- +{
- + return __builtin_add_overflow (a, b, r);
- +}
- +
- +static int
- +fcntl_space_resolve_range (int fd, short whence, off_t offset, off_t flen,
- + fcntl_space_range *range)
- +{
- + struct stat st;
- + off_t base;
- + off_t start;
- +
- + switch (whence)
- + {
- + case SEEK_SET:
- + base = 0;
- + break;
- + case SEEK_CUR:
- + base = lseek (fd, 0, SEEK_CUR);
- + if (base == (off_t) -1)
- + return -1;
- + break;
- + case SEEK_END:
- + if (fstat (fd, &st) < 0)
- + return -1;
- + base = st.st_size;
- + break;
- + default:
- + set_errno (EINVAL);
- + return -1;
- + }
- +
- + if (off_add_overflow (base, offset, &start))
- + {
- + set_errno (EOVERFLOW);
- + return -1;
- + }
- +
- + /*
- + Follow normal struct flock byte-range conventions:
- +
- + l_len > 0: [start, start + l_len)
- + l_len == 0: [start, EOF)
- + l_len < 0: [start + l_len, start)
- + */
- + if (flen < 0)
- + {
- + if (flen == (off_t) LONG_MIN)
- + {
- + set_errno (EOVERFLOW);
- + return -1;
- + }
- +
- + if (off_add_overflow (start, flen, &start))
- + {
- + set_errno (EOVERFLOW);
- + return -1;
- + }
- +
- + flen = -flen;
- + range->to_eof = false;
- + }
- + else if (flen == 0)
- + {
- + range->to_eof = true;
- + }
- + else
- + {
- + range->to_eof = false;
- + }
- +
- + if (start < 0)
- + {
- + set_errno (EINVAL);
- + return -1;
- + }
- +
- + range->start = start;
- + range->len = flen;
- + return 0;
- +}
- +
- +static int
- +fcntl_allocsp_range (int fd, const fcntl_space_range *range)
- +{
- + struct stat st;
- + off_t len = range->len;
- +
- + /*
- + For |F_ALLOCSP| with |l_len == 0|, allocate from start to current EOF.
- + If start is at or beyond EOF, the range is empty and this is a no-op.
- + */
- + if (range->to_eof)
- + {
- + if (fstat (fd, &st) < 0)
- + return -1;
- +
- + if (range->start >= st.st_size)
- + return 0;
- +
- + len = st.st_size - range->start;
- + }
- +
- + if (len == 0)
- + return 0;
- +
- + return fallocate (fd, 0, range->start, len);
- +}
- +
- +static int
- +fcntl_freesp_range (int fd, const fcntl_space_range *range)
- +{
- + struct stat st;
- + off_t end;
- +
- + if (fstat (fd, &st) < 0)
- + return -1;
- +
- + if (range->start >= st.st_size)
- + return 0;
- +
- + /*
- + |F_FREESP| to EOF shrinks the file. Hole punching keeps the
- + logical file size unchanged, so use ftruncate for tail ranges.
- + */
- + if (range->to_eof)
- + return ftruncate (fd, range->start);
- +
- + if (range->len == 0)
- + return 0;
- +
- + if (off_add_overflow (range->start, range->len, &end))
- + {
- + set_errno (EOVERFLOW);
- + return -1;
- + }
- +
- + if (end >= st.st_size)
- + return ftruncate (fd, range->start);
- +
- + return fallocate (fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
- + range->start, range->len);
- +}
- +
- +static int
- +fcntl_space_common (int fd, int cmd, short whence, off_t start, off_t len)
- +{
- + fcntl_space_range range;
- +
- + if (fcntl_space_resolve_range (fd, whence, start, len, &range) < 0)
- + return -1;
- +
- + switch (cmd)
- + {
- + case F_ALLOCSP:
- + return fcntl_allocsp_range (fd, &range);
- + case F_FREESP:
- + return fcntl_freesp_range (fd, &range);
- + default:
- + set_errno (EINVAL);
- + return -1;
- + }
- +}
- +
- +static int
- +fcntl_space_flock (int fd, int cmd, const struct flock *fl)
- +{
- + return fcntl_space_common (fd, cmd, fl->l_whence,
- + fl->l_start, fl->l_len);
- +}
- +
- extern "C" int
- fcntl (int fd, int cmd, ...)
- {
- @@ -68,6 +259,10 @@ fcntl (int fd, int cmd, ...)
- res = -1;
- }
- break;
- + case F_ALLOCSP:
- + case F_FREESP:
- + res = fcntl_space_flock (fd, cmd, (const struct flock *) arg);
- + break;
- default:
- res = cfd->fcntl (cmd, arg);
- break;
cygwin370_fcntl_allocsp_freesp20260630_002.diff
Posted by Anonymous on Tue 30th Jun 2026 13:46
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
nrubsig.kpaste.net RSS