pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


cygwin370_fcntl_allocsp_freesp20260630_002.diff
Posted by Anonymous on Tue 30th Jun 2026 13:46
raw | new post

  1. diff --git a/newlib/libc/include/sys/_default_fcntl.h b/newlib/libc/include/sys/_default_fcntl.h
  2. index b3222d452..c8f0bb1f7 100644
  3. --- a/newlib/libc/include/sys/_default_fcntl.h
  4. +++ b/newlib/libc/include/sys/_default_fcntl.h
  5. @@ -155,6 +155,17 @@ extern "C" {
  6.  #define        F_OFD_SETLKW    17      /* Set or Clear OFD lock (Blocking) */
  7.  #endif
  8.  
  9. +/*
  10. + * { Solaris, FreeBSD, SUPER/UX, ... }-style file space allocation/freeing.
  11. + *
  12. + * |F_ALLOCSP|/|F_FREESP| take |struct flock *|.
  13. + *
  14. + * |l_len| == 0 means "to EOF".  Negative |l_len| follows the usual flock
  15. + * range convention and names [l_start + l_len, l_start].
  16. + */
  17. +#define        F_ALLOCSP       18
  18. +#define        F_FREESP        19
  19. +
  20.  /* fcntl(2) flags (l_type field of flock structure) */
  21.  #define        F_RDLCK         1       /* read lock */
  22.  #define        F_WRLCK         2       /* write lock */
  23. diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc
  24. index 2bc52edb0..bf6d47542 100644
  25. --- a/winsup/cygwin/fcntl.cc
  26. +++ b/winsup/cygwin/fcntl.cc
  27. @@ -7,6 +7,8 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
  28.  details. */
  29.  
  30.  #include "winsup.h"
  31. +#include <limits.h>
  32. +#include <sys/stat.h>
  33.  #include <unistd.h>
  34.  #include "cygerrno.h"
  35.  #include "security.h"
  36. @@ -16,6 +18,195 @@ details. */
  37.  #include "cygheap.h"
  38.  #include "cygtls.h"
  39.  
  40. +/*
  41. + * In the Cygwin DLL build, these prototypes are not always visible from
  42. + * <unistd.h> in this translation unit, even though the symbols are part of
  43. + * the public Cygwin API.  Declare them explicitly for use by the fcntl()
  44. + * space-management helpers below.
  45. + */
  46. +extern "C" off_t lseek (int, off_t, int);
  47. +extern "C" int ftruncate (int, off_t);
  48. +
  49. +struct fcntl_space_range
  50. +{
  51. +  off_t start;
  52. +  off_t len;
  53. +  bool to_eof;
  54. +};
  55. +
  56. +static inline bool
  57. +off_add_overflow (off_t a, off_t b, off_t *r)
  58. +{
  59. +  return __builtin_add_overflow (a, b, r);
  60. +}
  61. +
  62. +static int
  63. +fcntl_space_resolve_range (int fd, short whence, off_t offset, off_t flen,
  64. +    fcntl_space_range *range)
  65. +{
  66. +  struct stat st;
  67. +  off_t base;
  68. +  off_t start;
  69. +
  70. +  switch (whence)
  71. +    {
  72. +    case SEEK_SET:
  73. +      base = 0;
  74. +      break;
  75. +    case SEEK_CUR:
  76. +      base = lseek (fd, 0, SEEK_CUR);
  77. +      if (base == (off_t) -1)
  78. +       return -1;
  79. +      break;
  80. +    case SEEK_END:
  81. +      if (fstat (fd, &st) < 0)
  82. +       return -1;
  83. +      base = st.st_size;
  84. +      break;
  85. +    default:
  86. +      set_errno (EINVAL);
  87. +      return -1;
  88. +    }
  89. +
  90. +  if (off_add_overflow (base, offset, &start))
  91. +    {
  92. +      set_errno (EOVERFLOW);
  93. +      return -1;
  94. +    }
  95. +
  96. +  /*
  97. +     Follow normal struct flock byte-range conventions:
  98. +
  99. +       l_len > 0:  [start, start + l_len)
  100. +       l_len == 0: [start, EOF)
  101. +       l_len < 0:  [start + l_len, start)
  102. +  */
  103. +  if (flen < 0)
  104. +    {
  105. +      if (flen == (off_t) LONG_MIN)
  106. +       {
  107. +         set_errno (EOVERFLOW);
  108. +         return -1;
  109. +       }
  110. +
  111. +      if (off_add_overflow (start, flen, &start))
  112. +       {
  113. +         set_errno (EOVERFLOW);
  114. +         return -1;
  115. +       }
  116. +
  117. +      flen = -flen;
  118. +      range->to_eof = false;
  119. +    }
  120. +  else if (flen == 0)
  121. +    {
  122. +      range->to_eof = true;
  123. +    }
  124. +  else
  125. +    {
  126. +      range->to_eof = false;
  127. +    }
  128. +
  129. +  if (start < 0)
  130. +    {
  131. +      set_errno (EINVAL);
  132. +      return -1;
  133. +    }
  134. +
  135. +  range->start = start;
  136. +  range->len = flen;
  137. +  return 0;
  138. +}
  139. +
  140. +static int
  141. +fcntl_allocsp_range (int fd, const fcntl_space_range *range)
  142. +{
  143. +  struct stat st;
  144. +  off_t len = range->len;
  145. +
  146. +  /*
  147. +     For |F_ALLOCSP| with |l_len == 0|, allocate from start to current EOF.
  148. +     If start is at or beyond EOF, the range is empty and this is a no-op.
  149. +  */
  150. +  if (range->to_eof)
  151. +    {
  152. +      if (fstat (fd, &st) < 0)
  153. +       return -1;
  154. +
  155. +      if (range->start >= st.st_size)
  156. +       return 0;
  157. +
  158. +      len = st.st_size - range->start;
  159. +    }
  160. +
  161. +  if (len == 0)
  162. +    return 0;
  163. +
  164. +  return fallocate (fd, 0, range->start, len);
  165. +}
  166. +
  167. +static int
  168. +fcntl_freesp_range (int fd, const fcntl_space_range *range)
  169. +{
  170. +  struct stat st;
  171. +  off_t end;
  172. +
  173. +  if (fstat (fd, &st) < 0)
  174. +    return -1;
  175. +
  176. +  if (range->start >= st.st_size)
  177. +    return 0;
  178. +
  179. +  /*
  180. +     |F_FREESP| to EOF shrinks the file. Hole punching keeps the
  181. +     logical file size unchanged, so use ftruncate for tail ranges.
  182. +  */
  183. +  if (range->to_eof)
  184. +    return ftruncate (fd, range->start);
  185. +
  186. +  if (range->len == 0)
  187. +    return 0;
  188. +
  189. +  if (off_add_overflow (range->start, range->len, &end))
  190. +    {
  191. +      set_errno (EOVERFLOW);
  192. +      return -1;
  193. +    }
  194. +
  195. +  if (end >= st.st_size)
  196. +    return ftruncate (fd, range->start);
  197. +
  198. +  return fallocate (fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
  199. +                   range->start, range->len);
  200. +}
  201. +
  202. +static int
  203. +fcntl_space_common (int fd, int cmd, short whence, off_t start, off_t len)
  204. +{
  205. +  fcntl_space_range range;
  206. +
  207. +  if (fcntl_space_resolve_range (fd, whence, start, len, &range) < 0)
  208. +    return -1;
  209. +
  210. +  switch (cmd)
  211. +    {
  212. +    case F_ALLOCSP:
  213. +      return fcntl_allocsp_range (fd, &range);
  214. +    case F_FREESP:
  215. +      return fcntl_freesp_range (fd, &range);
  216. +    default:
  217. +      set_errno (EINVAL);
  218. +      return -1;
  219. +    }
  220. +}
  221. +
  222. +static int
  223. +fcntl_space_flock (int fd, int cmd, const struct flock *fl)
  224. +{
  225. +  return fcntl_space_common (fd, cmd, fl->l_whence,
  226. +    fl->l_start, fl->l_len);
  227. +}
  228. +
  229.  extern "C" int
  230.  fcntl (int fd, int cmd, ...)
  231.  {
  232. @@ -68,6 +259,10 @@ fcntl (int fd, int cmd, ...)
  233.               res = -1;
  234.             }
  235.           break;
  236. +       case F_ALLOCSP:
  237. +       case F_FREESP:
  238. +         res = fcntl_space_flock (fd, cmd, (const struct flock *) arg);
  239. +         break;
  240.         default:
  241.           res = cfd->fcntl (cmd, arg);
  242.           break;

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at