93 lines
1.8 KiB
C
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;
|
|
}
|