Files
my-website-base/lib/seek.c
2025-11-26 17:24:20 +02:00

93 lines
1.8 KiB
C

// For some fucking reason, libuv hasn't implemented lseek() (WHY??)
// Here, a sync version is implemented (as i cannot be bothered with callbacks)
#include <errno.h>
#include <lauxlib.h>
#include <lua.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef _WIN32
#include <io.h>
#include <windows.h>
#define off_t LONGLONG
#define _LARGEFILE_SOURCE
#endif
static int luafunc_seek(lua_State *ctx) {
int fd = lua_tointeger(ctx, 1);
off_t offset = lua_isnoneornil(ctx, 2) ? 0 : luaL_checkinteger(ctx, 2);
int whence = SEEK_CUR;
if (!lua_isnoneornil(ctx, 3)) {
const char *swhence = luaL_checkstring(ctx, 3);
if (!strcmp(swhence, "set")) {
whence = SEEK_SET;
}
else if (!strcmp(swhence, "cur")) {
whence = SEEK_CUR;
}
else if (!strcmp(swhence, "end")) {
whence = SEEK_END;
}
else {
luaL_typeerror(ctx, 3, "'set', 'cur' or 'end'");
}
}
#ifdef _WIN32
HANDLE fh;
LARGE_INTEGER new_offset;
fh = (HANDLE)_get_osfhandle(fd);
if (fh == (HANDLE)-1) {
errno = EBADF;
return -1;
}
DWORD method;
switch (whence) {
case SEEK_SET:
method = FILE_BEGIN;
break;
case SEEK_CUR:
method = FILE_CURRENT;
break;
case SEEK_END:
method = FILE_END;
break;
default:
errno = EINVAL;
return -1;
}
LARGE_INTEGER distance;
distance.QuadPart = offset;
if (!SetFilePointerEx(fh, distance, &new_offset, method)) {
lua_pushnil(ctx);
lua_pushstring(ctx, strerror(EINVAL));
return 2;
}
off_t offs = new_offset.QuadPart;
#else
off_t offs = lseek(fd, offset, whence);
if (offs < 0) {
lua_pushnil(ctx);
lua_pushstring(ctx, strerror(errno));
return 2;
}
#endif
lua_pushinteger(ctx, offs);
return 1;
}
int luaopen_seek(lua_State *ctx) {
lua_pushcfunction(ctx, luafunc_seek);
return 1;
}