320-modules-fallocate-posix.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. --- /dev/null
  2. +++ b/modules/fallocate-posix
  3. @@ -0,0 +1,43 @@
  4. +Description:
  5. +posix_fallocate function that is glibc compatible.
  6. +
  7. +Files:
  8. +lib/posix_fallocate.c
  9. +m4/fcntl_h.m4
  10. +m4/posix_fallocate.m4
  11. +
  12. +Depends-on:
  13. +errno [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  14. +fcntl [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  15. +fstat [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  16. +ftruncate [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  17. +pread [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  18. +pwrite [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  19. +stdint [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  20. +sys_stat [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  21. +unistd [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]
  22. +fcntl-h
  23. +
  24. +configure.ac:
  25. +gl_FUNC_POSIX_FALLOCATE
  26. +gl_CONDITIONAL([GL_COND_OBJ_POSIX_FALLOCATE],
  27. + [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1])
  28. +AM_COND_IF([GL_COND_OBJ_POSIX_FALLOCATE], [
  29. + gl_PREREQ_POSIX_FALLOCATE
  30. +])
  31. +gl_MODULE_INDICATOR([fallocate-posix])
  32. +gl_FCNTL_MODULE_INDICATOR([fallocate-posix])
  33. +
  34. +Makefile.am:
  35. +if GL_COND_OBJ_POSIX_FALLOCATE
  36. +lib_SOURCES += posix_fallocate.c
  37. +endif
  38. +
  39. +Include:
  40. +<fcntl.h>
  41. +
  42. +License:
  43. +LGPLv2+
  44. +
  45. +Maintainer:
  46. +all
  47. --- /dev/null
  48. +++ b/m4/posix_fallocate.m4
  49. @@ -0,0 +1,20 @@
  50. +# posix_fallocate.m4 serial 1
  51. +dnl Copyright (C) 2024 Free Software Foundation, Inc.
  52. +dnl This file is free software; the Free Software Foundation
  53. +dnl gives unlimited permission to copy and/or distribute it,
  54. +dnl with or without modifications, as long as this notice is preserved.
  55. +
  56. +AC_DEFUN([gl_FUNC_POSIX_FALLOCATE],
  57. +[
  58. + AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
  59. + gl_CHECK_FUNCS_ANDROID([posix_fallocate], [[#include <fcntl.h>]])
  60. + if test "$ac_cv_func_posix_fallocate" = no; then
  61. + HAVE_FALLOCATE_POSIX=0
  62. + case "$gl_cv_onwards_func_posix_fallocate" in
  63. + future*) REPLACE_FALLOCATE_POSIX=1 ;;
  64. + esac
  65. + fi
  66. +])
  67. +
  68. +# Prerequisites of lib/posix_fallocate.c.
  69. +AC_DEFUN([gl_PREREQ_POSIX_FALLOCATE], [:])
  70. --- a/m4/fcntl_h.m4
  71. +++ b/m4/fcntl_h.m4
  72. @@ -26,7 +26,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H],
  73. dnl corresponding gnulib module is not in use, if it is not common
  74. dnl enough to be declared everywhere.
  75. gl_WARN_ON_USE_PREPARE([[#include <fcntl.h>
  76. - ]], [fcntl openat])
  77. + ]], [fcntl openat posix_fallocate])
  78. ])
  79. # gl_FCNTL_MODULE_INDICATOR([modulename])
  80. @@ -53,6 +53,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS],
  81. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_NONBLOCKING])
  82. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPEN])
  83. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPENAT])
  84. + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FALLOCATE_POSIX])
  85. dnl Support Microsoft deprecated alias function names by default.
  86. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_CREAT], [1])
  87. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_OPEN], [1])
  88. @@ -64,10 +65,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS],
  89. AC_DEFUN([gl_FCNTL_H_DEFAULTS],
  90. [
  91. dnl Assume proper GNU behavior unless another module says otherwise.
  92. - HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL])
  93. - HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT])
  94. - REPLACE_CREAT=0; AC_SUBST([REPLACE_CREAT])
  95. - REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL])
  96. - REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN])
  97. - REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
  98. + HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL])
  99. + HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT])
  100. + HAVE_FALLOCATE_POSIX=1; AC_SUBST([HAVE_FALLOCATE_POSIX])
  101. + REPLACE_CREAT=0; AC_SUBST([REPLACE_CREAT])
  102. + REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL])
  103. + REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN])
  104. + REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
  105. + REPLACE_FALLOCATE_POSIX=0; AC_SUBST([REPLACE_FALLOCATE_POSIX])
  106. ])
  107. --- a/modules/fcntl-h
  108. +++ b/modules/fcntl-h
  109. @@ -40,14 +40,17 @@ fcntl.h: fcntl.in.h $(top_builddir)/conf
  110. -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \
  111. -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \
  112. -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \
  113. + -e 's/@''GNULIB_FALLOCATE_POSIX''@/$(GNULIB_FALLOCATE_POSIX)/g' \
  114. -e 's/@''GNULIB_MDA_CREAT''@/$(GNULIB_MDA_CREAT)/g' \
  115. -e 's/@''GNULIB_MDA_OPEN''@/$(GNULIB_MDA_OPEN)/g' \
  116. -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
  117. -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \
  118. + -e 's|@''HAVE_FALLOCATE_POSIX''@|$(HAVE_FALLOCATE_POSIX)|g' \
  119. -e 's|@''REPLACE_CREAT''@|$(REPLACE_CREAT)|g' \
  120. -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \
  121. -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \
  122. -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \
  123. + -e 's|@''REPLACE_FALLOCATE_POSIX''@|$(REPLACE_FALLOCATE_POSIX)|g' \
  124. -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
  125. -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
  126. -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
  127. --- a/lib/fcntl.in.h
  128. +++ b/lib/fcntl.in.h
  129. @@ -241,6 +241,33 @@ _GL_WARN_ON_USE (openat, "openat is not
  130. # endif
  131. #endif
  132. +#if @GNULIB_FALLOCATE_POSIX@
  133. +# if @REPLACE_FALLOCATE_POSIX@
  134. +# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
  135. +# undef posix_fallocate
  136. +# define posix_fallocate rpl_posix_fallocate
  137. +# endif
  138. +_GL_FUNCDECL_RPL (posix_fallocate, int,
  139. + (int fd, off_t offset, off_t len));
  140. +_GL_CXXALIAS_RPL (posix_fallocate, int,
  141. + (int fd, off_t offset, off_t len));
  142. +# else
  143. +# if !@HAVE_FALLOCATE_POSIX@
  144. +_GL_FUNCDECL_SYS (posix_fallocate, int,
  145. + (int fd, off_t offset, off_t len));
  146. +# endif
  147. +_GL_CXXALIAS_SYS (posix_fallocate, int,
  148. + (int fd, off_t offset, off_t len));
  149. +# endif
  150. +_GL_CXXALIASWARN (posix_fallocate);
  151. +#elif defined GNULIB_POSIXCHECK
  152. +# undef posix_fallocate
  153. +# if HAVE_RAW_DECL_POSIX_FALLOCATE
  154. +_GL_WARN_ON_USE (posix_fallocate, "posix_fallocate is not portable - "
  155. + "use gnulib module fallocate-posix for portability");
  156. +# endif
  157. +#endif
  158. +
  159. /* Fix up the FD_* macros, only known to be missing on mingw. */
  160. --- /dev/null
  161. +++ b/lib/posix_fallocate.c
  162. @@ -0,0 +1,150 @@
  163. +/* posix_fallocate function that is glibc compatible.
  164. +
  165. + Copyright (C) 2024 Free Software Foundation, Inc.
  166. +
  167. + This file is free software: you can redistribute it and/or modify
  168. + it under the terms of the GNU Lesser General Public License as
  169. + published by the Free Software Foundation; either version 2.1 of the
  170. + License, or (at your option) any later version.
  171. +
  172. + This file is distributed in the hope that it will be useful,
  173. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  174. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  175. + GNU Lesser General Public License for more details.
  176. +
  177. + You should have received a copy of the GNU Lesser General Public License
  178. + along with this program. If not, see <https://www.gnu.org/licenses/>. */
  179. +
  180. +#include <config.h>
  181. +
  182. +#include <errno.h>
  183. +#include <fcntl.h>
  184. +#include <unistd.h>
  185. +#include <stdint.h>
  186. +#include <sys/fcntl.h>
  187. +#include <sys/stat.h>
  188. +
  189. +#ifdef __APPLE__
  190. +# include <sys/param.h>
  191. +# include <sys/mount.h>
  192. +#else
  193. +# include <sys/statfs.h>
  194. +#endif
  195. +
  196. +/* Reserve storage for the data of the file associated with FD. This
  197. + emulation is far from perfect, but the kernel cannot do not much
  198. + better for network file systems, either. */
  199. +
  200. +int
  201. +posix_fallocate (int fd, off_t offset, off_t len)
  202. +{
  203. + int ret;
  204. + struct stat st;
  205. +
  206. + if (fd < 0 || offset < 0 || len < 0)
  207. + return EINVAL;
  208. +
  209. + /* Perform overflow check. The outer cast relies on a GCC
  210. + extension. */
  211. + if ((off_t) ((uint64_t) offset + (uint64_t) len) < 0)
  212. + return EFBIG;
  213. +
  214. + /* pwrite below will not do the right thing in O_APPEND mode. */
  215. + {
  216. + int flags = fcntl (fd, F_GETFL, 0);
  217. + if (flags < 0 || (flags & O_APPEND) != 0)
  218. + return EBADF;
  219. + }
  220. +
  221. + /* We have to make sure that this is really a regular file. */
  222. + if (fstat (fd, &st) != 0)
  223. + return EBADF;
  224. + if (S_ISFIFO (st.st_mode))
  225. + return ESPIPE;
  226. + if (! S_ISREG (st.st_mode))
  227. + return ENODEV;
  228. +
  229. + if (len == 0)
  230. + {
  231. + /* This is racy, but there is no good way to satisfy a
  232. + zero-length allocation request. */
  233. + if (st.st_size < offset)
  234. + {
  235. + ret = ftruncate (fd, offset);
  236. +
  237. + if (ret != 0)
  238. + ret = errno;
  239. + return ret;
  240. + }
  241. + return ret;
  242. + }
  243. +
  244. +#ifdef __APPLE__
  245. + fstore_t sto = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, offset + len, 0};
  246. + /* allocate continuous */
  247. + ret = fcntl (fd, F_PREALLOCATE, &sto);
  248. + if (ret < 0)
  249. + {
  250. + /* allocate non-continuous */
  251. + sto.fst_flags = F_ALLOCATEALL;
  252. + ret = fcntl (fd, F_PREALLOCATE, &sto);
  253. + if (ret < 0)
  254. + {
  255. + return ret;
  256. + }
  257. + }
  258. + ret = ftruncate(fd, offset + len);
  259. +#else
  260. +
  261. + /* Minimize data transfer for network file systems, by issuing
  262. + single-byte write requests spaced by the file system block size.
  263. + (Most local file systems have fallocate support, so this fallback
  264. + code is not used there.) */
  265. +
  266. + unsigned increment;
  267. + {
  268. + struct statfs f;
  269. +
  270. + if (fstatfs (fd, &f) != 0)
  271. + return errno;
  272. + if (f.f_bsize == 0)
  273. + increment = 512;
  274. + else if (f.f_bsize < 4096)
  275. + increment = f.f_bsize;
  276. + else
  277. + /* NFS does not propagate the block size of the underlying
  278. + storage and may report a much larger value which would still
  279. + leave holes after the loop below, so we cap the increment at
  280. + 4096. */
  281. + increment = 4096;
  282. + }
  283. +
  284. + /* Write a null byte to every block. This is racy; we currently
  285. + lack a better option. Compare-and-swap against a file mapping
  286. + might additional local races, but requires interposition of a
  287. + signal handler to catch SIGBUS. */
  288. + for (offset += (len - 1) % increment; len > 0; offset += increment)
  289. + {
  290. + len -= increment;
  291. +
  292. + if (offset < st.st_size)
  293. + {
  294. + unsigned char c;
  295. + ssize_t rsize = pread (fd, &c, 1, offset);
  296. +
  297. + if (rsize < 0)
  298. + return errno;
  299. + /* If there is a non-zero byte, the block must have been
  300. + allocated already. */
  301. + else if (rsize == 1 && c != 0)
  302. + continue;
  303. + }
  304. +
  305. + if (pwrite (fd, "", 1, offset) != 1)
  306. + return errno;
  307. + }
  308. +
  309. +#endif /* __APPLE__ */
  310. +
  311. + return ret;
  312. +}
  313. --- a/MODULES.html.sh
  314. +++ b/MODULES.html.sh
  315. @@ -2555,6 +2555,7 @@ func_all_modules ()
  316. func_module execve
  317. func_module execvp
  318. func_module execvpe
  319. + func_module fallocate-posix
  320. func_module fchdir
  321. func_module fclose
  322. func_module fcntl-h