forked from LiBwrt/openwrt-6.x
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tools/gnulib: add fallocate-posix module
Add a module to gnulib to support posix_fallocate() for macOS and other systems that are missing it. Apple-specific code is sourced from Mozilla, and the rest from glibc, both licensed under LGPL. Signed-off-by: Michael Pratt <[email protected]> Link: openwrt/openwrt#15690 Signed-off-by: Robert Marko <[email protected]>
- Loading branch information
Showing
1 changed file
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,326 @@ | ||
--- /dev/null | ||
+++ b/modules/fallocate-posix | ||
@@ -0,0 +1,43 @@ | ||
+Description: | ||
+posix_fallocate function that is glibc compatible. | ||
+ | ||
+Files: | ||
+lib/posix_fallocate.c | ||
+m4/fcntl_h.m4 | ||
+m4/posix_fallocate.m4 | ||
+ | ||
+Depends-on: | ||
+errno [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+fcntl [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+fstat [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+ftruncate [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+pread [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+pwrite [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+stdint [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+sys_stat [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+unistd [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1] | ||
+fcntl-h | ||
+ | ||
+configure.ac: | ||
+gl_FUNC_POSIX_FALLOCATE | ||
+gl_CONDITIONAL([GL_COND_OBJ_POSIX_FALLOCATE], | ||
+ [test $HAVE_FALLOCATE_POSIX = 0 || test $REPLACE_FALLOCATE_POSIX = 1]) | ||
+AM_COND_IF([GL_COND_OBJ_POSIX_FALLOCATE], [ | ||
+ gl_PREREQ_POSIX_FALLOCATE | ||
+]) | ||
+gl_MODULE_INDICATOR([fallocate-posix]) | ||
+gl_FCNTL_MODULE_INDICATOR([fallocate-posix]) | ||
+ | ||
+Makefile.am: | ||
+if GL_COND_OBJ_POSIX_FALLOCATE | ||
+lib_SOURCES += posix_fallocate.c | ||
+endif | ||
+ | ||
+Include: | ||
+<fcntl.h> | ||
+ | ||
+License: | ||
+LGPLv2+ | ||
+ | ||
+Maintainer: | ||
+all | ||
--- /dev/null | ||
+++ b/m4/posix_fallocate.m4 | ||
@@ -0,0 +1,20 @@ | ||
+# posix_fallocate.m4 serial 1 | ||
+dnl Copyright (C) 2024 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 with or without modifications, as long as this notice is preserved. | ||
+ | ||
+AC_DEFUN([gl_FUNC_POSIX_FALLOCATE], | ||
+[ | ||
+ AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) | ||
+ gl_CHECK_FUNCS_ANDROID([posix_fallocate], [[#include <fcntl.h>]]) | ||
+ if test "$ac_cv_func_posix_fallocate" = no; then | ||
+ HAVE_FALLOCATE_POSIX=0 | ||
+ case "$gl_cv_onwards_func_posix_fallocate" in | ||
+ future*) REPLACE_FALLOCATE_POSIX=1 ;; | ||
+ esac | ||
+ fi | ||
+]) | ||
+ | ||
+# Prerequisites of lib/posix_fallocate.c. | ||
+AC_DEFUN([gl_PREREQ_POSIX_FALLOCATE], [:]) | ||
--- a/m4/fcntl_h.m4 | ||
+++ b/m4/fcntl_h.m4 | ||
@@ -23,7 +23,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H], | ||
dnl corresponding gnulib module is not in use, if it is not common | ||
dnl enough to be declared everywhere. | ||
gl_WARN_ON_USE_PREPARE([[#include <fcntl.h> | ||
- ]], [fcntl openat]) | ||
+ ]], [fcntl openat posix_fallocate]) | ||
]) | ||
|
||
# gl_FCNTL_MODULE_INDICATOR([modulename]) | ||
@@ -50,6 +50,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], | ||
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_NONBLOCKING]) | ||
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPEN]) | ||
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPENAT]) | ||
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FALLOCATE_POSIX]) | ||
dnl Support Microsoft deprecated alias function names by default. | ||
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_CREAT], [1]) | ||
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_OPEN], [1]) | ||
@@ -61,10 +62,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], | ||
AC_DEFUN([gl_FCNTL_H_DEFAULTS], | ||
[ | ||
dnl Assume proper GNU behavior unless another module says otherwise. | ||
- HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL]) | ||
- HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT]) | ||
- REPLACE_CREAT=0; AC_SUBST([REPLACE_CREAT]) | ||
- REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL]) | ||
- REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN]) | ||
- REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT]) | ||
+ HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL]) | ||
+ HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT]) | ||
+ HAVE_FALLOCATE_POSIX=1; AC_SUBST([HAVE_FALLOCATE_POSIX]) | ||
+ REPLACE_CREAT=0; AC_SUBST([REPLACE_CREAT]) | ||
+ REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL]) | ||
+ REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN]) | ||
+ REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT]) | ||
+ REPLACE_FALLOCATE_POSIX=0; AC_SUBST([REPLACE_FALLOCATE_POSIX]) | ||
]) | ||
--- a/modules/fcntl-h | ||
+++ b/modules/fcntl-h | ||
@@ -40,14 +40,17 @@ fcntl.h: fcntl.in.h $(top_builddir)/conf | ||
-e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \ | ||
-e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \ | ||
-e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \ | ||
+ -e 's/@''GNULIB_FALLOCATE_POSIX''@/$(GNULIB_FALLOCATE_POSIX)/g' \ | ||
-e 's/@''GNULIB_MDA_CREAT''@/$(GNULIB_MDA_CREAT)/g' \ | ||
-e 's/@''GNULIB_MDA_OPEN''@/$(GNULIB_MDA_OPEN)/g' \ | ||
-e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \ | ||
-e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ | ||
+ -e 's|@''HAVE_FALLOCATE_POSIX''@|$(HAVE_FALLOCATE_POSIX)|g' \ | ||
-e 's|@''REPLACE_CREAT''@|$(REPLACE_CREAT)|g' \ | ||
-e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \ | ||
-e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ | ||
-e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ | ||
+ -e 's|@''REPLACE_FALLOCATE_POSIX''@|$(REPLACE_FALLOCATE_POSIX)|g' \ | ||
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ | ||
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ | ||
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ | ||
--- a/lib/fcntl.in.h | ||
+++ b/lib/fcntl.in.h | ||
@@ -238,6 +238,33 @@ _GL_WARN_ON_USE (openat, "openat is not | ||
# endif | ||
#endif | ||
|
||
+#if @GNULIB_FALLOCATE_POSIX@ | ||
+# if @REPLACE_FALLOCATE_POSIX@ | ||
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE) | ||
+# undef posix_fallocate | ||
+# define posix_fallocate rpl_posix_fallocate | ||
+# endif | ||
+_GL_FUNCDECL_RPL (posix_fallocate, int, | ||
+ (int fd, off_t offset, off_t len)); | ||
+_GL_CXXALIAS_RPL (posix_fallocate, int, | ||
+ (int fd, off_t offset, off_t len)); | ||
+# else | ||
+# if !@HAVE_FALLOCATE_POSIX@ | ||
+_GL_FUNCDECL_SYS (posix_fallocate, int, | ||
+ (int fd, off_t offset, off_t len)); | ||
+# endif | ||
+_GL_CXXALIAS_SYS (posix_fallocate, int, | ||
+ (int fd, off_t offset, off_t len)); | ||
+# endif | ||
+_GL_CXXALIASWARN (posix_fallocate); | ||
+#elif defined GNULIB_POSIXCHECK | ||
+# undef posix_fallocate | ||
+# if HAVE_RAW_DECL_POSIX_FALLOCATE | ||
+_GL_WARN_ON_USE (posix_fallocate, "posix_fallocate is not portable - " | ||
+ "use gnulib module fallocate-posix for portability"); | ||
+# endif | ||
+#endif | ||
+ | ||
|
||
/* Fix up the FD_* macros, only known to be missing on mingw. */ | ||
|
||
--- /dev/null | ||
+++ b/lib/posix_fallocate.c | ||
@@ -0,0 +1,150 @@ | ||
+/* posix_fallocate function that is glibc compatible. | ||
+ | ||
+ Copyright (C) 2024 Free Software Foundation, Inc. | ||
+ | ||
+ This file is free software: you can redistribute it and/or modify | ||
+ it under the terms of the GNU Lesser General Public License as | ||
+ published by the Free Software Foundation; either version 2.1 of the | ||
+ License, or (at your option) any later version. | ||
+ | ||
+ This file is distributed in the hope that it will be useful, | ||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
+ GNU Lesser General Public License for more details. | ||
+ | ||
+ You should have received a copy of the GNU Lesser General Public License | ||
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
+ | ||
+#include <config.h> | ||
+ | ||
+#include <errno.h> | ||
+#include <fcntl.h> | ||
+#include <unistd.h> | ||
+#include <stdint.h> | ||
+#include <sys/fcntl.h> | ||
+#include <sys/stat.h> | ||
+ | ||
+#ifdef __APPLE__ | ||
+# include <sys/param.h> | ||
+# include <sys/mount.h> | ||
+#else | ||
+# include <sys/statfs.h> | ||
+#endif | ||
+ | ||
+/* Reserve storage for the data of the file associated with FD. This | ||
+ emulation is far from perfect, but the kernel cannot do not much | ||
+ better for network file systems, either. */ | ||
+ | ||
+int | ||
+posix_fallocate (int fd, off_t offset, off_t len) | ||
+{ | ||
+ int ret; | ||
+ struct stat st; | ||
+ | ||
+ if (fd < 0 || offset < 0 || len < 0) | ||
+ return EINVAL; | ||
+ | ||
+ /* Perform overflow check. The outer cast relies on a GCC | ||
+ extension. */ | ||
+ if ((off_t) ((uint64_t) offset + (uint64_t) len) < 0) | ||
+ return EFBIG; | ||
+ | ||
+ /* pwrite below will not do the right thing in O_APPEND mode. */ | ||
+ { | ||
+ int flags = fcntl (fd, F_GETFL, 0); | ||
+ if (flags < 0 || (flags & O_APPEND) != 0) | ||
+ return EBADF; | ||
+ } | ||
+ | ||
+ /* We have to make sure that this is really a regular file. */ | ||
+ if (fstat (fd, &st) != 0) | ||
+ return EBADF; | ||
+ if (S_ISFIFO (st.st_mode)) | ||
+ return ESPIPE; | ||
+ if (! S_ISREG (st.st_mode)) | ||
+ return ENODEV; | ||
+ | ||
+ if (len == 0) | ||
+ { | ||
+ /* This is racy, but there is no good way to satisfy a | ||
+ zero-length allocation request. */ | ||
+ if (st.st_size < offset) | ||
+ { | ||
+ ret = ftruncate (fd, offset); | ||
+ | ||
+ if (ret != 0) | ||
+ ret = errno; | ||
+ return ret; | ||
+ } | ||
+ return ret; | ||
+ } | ||
+ | ||
+#ifdef __APPLE__ | ||
+ fstore_t sto = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, offset + len, 0}; | ||
+ /* allocate continuous */ | ||
+ ret = fcntl (fd, F_PREALLOCATE, &sto); | ||
+ if (ret < 0) | ||
+ { | ||
+ /* allocate non-continuous */ | ||
+ sto.fst_flags = F_ALLOCATEALL; | ||
+ ret = fcntl (fd, F_PREALLOCATE, &sto); | ||
+ if (ret < 0) | ||
+ { | ||
+ return ret; | ||
+ } | ||
+ } | ||
+ ret = ftruncate(fd, offset + len); | ||
+#else | ||
+ | ||
+ /* Minimize data transfer for network file systems, by issuing | ||
+ single-byte write requests spaced by the file system block size. | ||
+ (Most local file systems have fallocate support, so this fallback | ||
+ code is not used there.) */ | ||
+ | ||
+ unsigned increment; | ||
+ { | ||
+ struct statfs f; | ||
+ | ||
+ if (fstatfs (fd, &f) != 0) | ||
+ return errno; | ||
+ if (f.f_bsize == 0) | ||
+ increment = 512; | ||
+ else if (f.f_bsize < 4096) | ||
+ increment = f.f_bsize; | ||
+ else | ||
+ /* NFS does not propagate the block size of the underlying | ||
+ storage and may report a much larger value which would still | ||
+ leave holes after the loop below, so we cap the increment at | ||
+ 4096. */ | ||
+ increment = 4096; | ||
+ } | ||
+ | ||
+ /* Write a null byte to every block. This is racy; we currently | ||
+ lack a better option. Compare-and-swap against a file mapping | ||
+ might additional local races, but requires interposition of a | ||
+ signal handler to catch SIGBUS. */ | ||
+ for (offset += (len - 1) % increment; len > 0; offset += increment) | ||
+ { | ||
+ len -= increment; | ||
+ | ||
+ if (offset < st.st_size) | ||
+ { | ||
+ unsigned char c; | ||
+ ssize_t rsize = pread (fd, &c, 1, offset); | ||
+ | ||
+ if (rsize < 0) | ||
+ return errno; | ||
+ /* If there is a non-zero byte, the block must have been | ||
+ allocated already. */ | ||
+ else if (rsize == 1 && c != 0) | ||
+ continue; | ||
+ } | ||
+ | ||
+ if (pwrite (fd, "", 1, offset) != 1) | ||
+ return errno; | ||
+ } | ||
+ | ||
+#endif /* __APPLE__ */ | ||
+ | ||
+ return ret; | ||
+} | ||
--- a/MODULES.html.sh | ||
+++ b/MODULES.html.sh | ||
@@ -2552,6 +2552,7 @@ func_all_modules () | ||
func_module execve | ||
func_module execvp | ||
func_module execvpe | ||
+ func_module fallocate-posix | ||
func_module fchdir | ||
func_module fclose | ||
func_module fcntl-h |