|
|
@ -1,37 +1,60 @@ |
|
|
#include <sys/param.h> |
|
|
#include <sys/param.h> |
|
|
#include <sys/ucred.h> |
|
|
#include <sys/ucred.h> |
|
|
#include <sys/mount.h> |
|
|
#include <sys/mount.h> |
|
|
|
|
|
#include <sys/sysctl.h> |
|
|
|
|
|
#include <sys/disk.h> |
|
|
|
|
|
#include <sys/ioctl.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
#include <fcntl.h> |
|
|
|
|
|
#include <unistd.h> |
|
|
#include <lua.h> |
|
|
#include <lua.h> |
|
|
#include <lauxlib.h> |
|
|
#include <lauxlib.h> |
|
|
|
|
|
|
|
|
|
|
|
// Function 1: Fetch active mount points via getfsstat
|
|
|
static int lua_getfsstat(lua_State *L) { |
|
|
static int lua_getfsstat(lua_State *L) { |
|
|
struct statfs *mntbuf; |
|
|
struct statfs *mntbuf = NULL; |
|
|
int num_mounts; |
|
|
int num_mounts = 0; |
|
|
|
|
|
size_t bufsize = 0; |
|
|
|
|
|
int attempts = 0; |
|
|
|
|
|
|
|
|
// Вызываем getfsstat первый раз с NULL, чтобы узнать точное количество монтирований
|
|
|
// Dynamic allocation loop to prevent race conditions if mounts change on the fly
|
|
|
num_mounts = getfsstat(NULL, 0, MNT_NOWAIT); |
|
|
while (attempts < 5) { |
|
|
if (num_mounts <= 0) { |
|
|
int expected = getfsstat(NULL, 0, MNT_NOWAIT); |
|
|
|
|
|
if (expected <= 0) { |
|
|
lua_pushnil(L); |
|
|
lua_pushnil(L); |
|
|
lua_pushstring(L, "Ошибка получения количества монтирований"); |
|
|
lua_pushstring(L, "Failed to count active mounts"); |
|
|
return 2; |
|
|
return 2; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Выделяем память под буфер структур statfs
|
|
|
size_t new_size = (expected + 4) * sizeof(struct statfs); |
|
|
mntbuf = malloc(num_mounts * sizeof(struct statfs)); |
|
|
struct statfs *new_buf = realloc(mntbuf, new_size); |
|
|
if (mntbuf == NULL) { |
|
|
if (!new_buf) { |
|
|
|
|
|
free(mntbuf); |
|
|
lua_pushnil(L); |
|
|
lua_pushnil(L); |
|
|
lua_pushstring(L, "Ошибка выделения памяти"); |
|
|
lua_pushstring(L, "Out of memory allocating mount buffer"); |
|
|
return 2; |
|
|
return 2; |
|
|
} |
|
|
} |
|
|
|
|
|
mntbuf = new_buf; |
|
|
|
|
|
bufsize = new_size; |
|
|
|
|
|
|
|
|
// Заполняем буфер реальными данными из ядра
|
|
|
num_mounts = getfsstat(mntbuf, bufsize, MNT_NOWAIT); |
|
|
num_mounts = getfsstat(mntbuf, num_mounts * sizeof(struct statfs), MNT_NOWAIT); |
|
|
if (num_mounts > expected + 4) { |
|
|
|
|
|
attempts++; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (num_mounts < 0) { |
|
|
|
|
|
free(mntbuf); |
|
|
|
|
|
lua_pushnil(L); |
|
|
|
|
|
lua_pushstring(L, "Failed to execute getfsstat"); |
|
|
|
|
|
return 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Создаем результирующий массив (таблицу) в Lua
|
|
|
|
|
|
lua_newtable(L); |
|
|
lua_newtable(L); |
|
|
for (int i = 0; i < num_mounts; i++) { |
|
|
for (int i = 0; i < num_mounts; i++) { |
|
|
// Создаем подтаблицу для конкретного монтирования
|
|
|
|
|
|
lua_newtable(L); |
|
|
lua_newtable(L); |
|
|
|
|
|
|
|
|
lua_pushstring(L, mntbuf[i].f_mntfromname); |
|
|
lua_pushstring(L, mntbuf[i].f_mntfromname); |
|
|
@ -43,18 +66,74 @@ static int lua_getfsstat(lua_State *L) { |
|
|
lua_pushstring(L, mntbuf[i].f_fstypename); |
|
|
lua_pushstring(L, mntbuf[i].f_fstypename); |
|
|
lua_setfield(L, -2, "type"); |
|
|
lua_setfield(L, -2, "type"); |
|
|
|
|
|
|
|
|
// Кладем подтаблицу в общий массив (индексация в Lua с 1)
|
|
|
|
|
|
lua_rawseti(L, -2, i + 1); |
|
|
lua_rawseti(L, -2, i + 1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
free(mntbuf); |
|
|
free(mntbuf); |
|
|
return 1; // Возвращаем одну таблицу
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Function 2: Fetch hardware device models efficiently via kernel ioctl requests
|
|
|
|
|
|
static int lua_get_disk_models(lua_State *L) { |
|
|
|
|
|
char *disks = NULL; |
|
|
|
|
|
size_t len = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (sysctlbyname("kern.disks", NULL, &len, NULL, 0) < 0) { |
|
|
|
|
|
lua_pushnil(L); |
|
|
|
|
|
lua_pushstring(L, "Failed to read kern.disks size"); |
|
|
|
|
|
return 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
disks = malloc(len); |
|
|
|
|
|
if (!disks) { |
|
|
|
|
|
lua_pushnil(L); |
|
|
|
|
|
lua_pushstring(L, "Out of memory allocating disk list buffer"); |
|
|
|
|
|
return 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (sysctlbyname("kern.disks", disks, &len, NULL, 0) < 0) { |
|
|
|
|
|
free(disks); |
|
|
|
|
|
lua_pushnil(L); |
|
|
|
|
|
lua_pushstring(L, "Failed to read kern.disks data"); |
|
|
|
|
|
return 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lua_newtable(L); // Returns table mapping { ["disk_name"] = "Model String", ... }
|
|
|
|
|
|
|
|
|
|
|
|
char *token = strtok(disks, " "); |
|
|
|
|
|
while (token != NULL) { |
|
|
|
|
|
char path[64]; |
|
|
|
|
|
snprintf(path, sizeof(path), "/dev/%s", token); |
|
|
|
|
|
|
|
|
|
|
|
int fd = open(path, O_RDONLY); |
|
|
|
|
|
if (fd >= 0) { |
|
|
|
|
|
struct diocgattr_arg arg; |
|
|
|
|
|
memset(&arg, 0, sizeof(arg)); |
|
|
|
|
|
strlcpy(arg.name, "GEOM::descr", sizeof(arg.name)); |
|
|
|
|
|
arg.len = sizeof(arg.value.str); // Safe buffer boundary verification
|
|
|
|
|
|
|
|
|
|
|
|
if (ioctl(fd, DIOCGATTR, &arg) == 0 && strlen(arg.value.str) > 0) { |
|
|
|
|
|
lua_pushstring(L, arg.value.str); |
|
|
|
|
|
} else { |
|
|
|
|
|
lua_pushstring(L, "Generic Drive"); |
|
|
|
|
|
} |
|
|
|
|
|
close(fd); |
|
|
|
|
|
} else { |
|
|
|
|
|
lua_pushstring(L, "Access Denied / Unreadable"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lua_setfield(L, -2, token); |
|
|
|
|
|
token = strtok(NULL, " "); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
free(disks); |
|
|
|
|
|
return 1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Точка входа для require("sysmount")
|
|
|
|
|
|
int luaopen_sysmount(lua_State *L) { |
|
|
int luaopen_sysmount(lua_State *L) { |
|
|
static const struct luaL_Reg mylib[] = { |
|
|
static const struct luaL_Reg mylib[] = { |
|
|
{ "getfsstat", lua_getfsstat }, |
|
|
{ "getfsstat", lua_getfsstat }, |
|
|
|
|
|
{ "get_disk_models", lua_get_disk_models }, |
|
|
{ NULL, NULL } |
|
|
{ NULL, NULL } |
|
|
}; |
|
|
}; |
|
|
luaL_newlib(L, mylib); |
|
|
luaL_newlib(L, mylib); |
|
|
|