# HG changeset patch
# User Kim Alvefur <zash@zash.se>
# Date 1686107223 -7200
# Node ID d16845afb3e23f3c3488125e79d0802aba70aec2
# Parent  33b114fbb5defa61dfc0c0c15cf248481945c002
util.pposix: Add remove_blocks() for deleting parts of files

Allows implementing e.g. a FIFO

Will probably only work on some Linux file systems like ext4.

diff -r 33b114fbb5de -r d16845afb3e2 teal-src/prosody/util/pposix.d.tl
--- a/teal-src/prosody/util/pposix.d.tl	Wed Jul 12 11:42:41 2023 +0200
+++ b/teal-src/prosody/util/pposix.d.tl	Wed Jun 07 05:07:03 2023 +0200
@@ -97,6 +97,7 @@
 	meminfo : function () : memoryinfo
 
 	atomic_append : function (f : FILE, s : string) : boolean, string, integer
+	remove_blocks : function (f : FILE, integer, integer)
 
 	isatty : function(FILE) : boolean
 
diff -r 33b114fbb5de -r d16845afb3e2 util-src/pposix.c
--- a/util-src/pposix.c	Wed Jul 12 11:42:41 2023 +0200
+++ b/util-src/pposix.c	Wed Jun 07 05:07:03 2023 +0200
@@ -802,6 +802,41 @@
 	return 3;
 }
 
+static int lc_remove_blocks(lua_State *L) {
+#if defined(__linux__)
+	int err;
+
+	FILE *f = *(FILE **) luaL_checkudata(L, 1, LUA_FILEHANDLE);
+	off_t offset = (off_t)luaL_checkinteger(L, 2);
+	off_t length = (off_t)luaL_checkinteger(L, 3);
+
+	errno = 0;
+
+	if((err = fallocate(fileno(f), FALLOC_FL_COLLAPSE_RANGE, offset, length))) {
+		if(errno != 0) {
+			/* Some old versions of Linux apparently use the return value instead of errno */
+			err = errno;
+		}
+
+		switch(err) {
+			default: /* Other issues */
+				luaL_pushfail(L);
+				lua_pushstring(L, strerror(err));
+				lua_pushinteger(L, err);
+				return 3;
+		}
+	}
+
+	lua_pushboolean(L, err == 0);
+	return 1;
+#else
+	luaL_pushfail(L);
+	lua_pushstring(L, strerror(EOPNOTSUPP));
+	lua_pushinteger(L, EOPNOTSUPP);
+	return 3;
+#endif
+}
+
 static int lc_isatty(lua_State *L) {
 	FILE *f = *(FILE **) luaL_checkudata(L, 1, LUA_FILEHANDLE);
 	const int fd = fileno(f);
@@ -847,6 +882,7 @@
 #endif
 
 		{ "atomic_append", lc_atomic_append },
+		{ "remove_blocks", lc_remove_blocks },
 
 		{ "isatty", lc_isatty },