Compare commits

...
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

1 Commits

  1. 119
      src/sysmount.c

119
src/sysmount.c

@ -1,37 +1,60 @@
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <lua.h>
#include <lauxlib.h>
// Function 1: Fetch active mount points via getfsstat
static int lua_getfsstat(lua_State *L) {
struct statfs *mntbuf;
int num_mounts;
struct statfs *mntbuf = NULL;
int num_mounts = 0;
size_t bufsize = 0;
int attempts = 0;
// Вызываем getfsstat первый раз с NULL, чтобы узнать точное количество монтирований
num_mounts = getfsstat(NULL, 0, MNT_NOWAIT);
if (num_mounts <= 0) {
lua_pushnil(L);
lua_pushstring(L, "Ошибка получения количества монтирований");
return 2;
// Dynamic allocation loop to prevent race conditions if mounts change on the fly
while (attempts < 5) {
int expected = getfsstat(NULL, 0, MNT_NOWAIT);
if (expected <= 0) {
lua_pushnil(L);
lua_pushstring(L, "Failed to count active mounts");
return 2;
}
size_t new_size = (expected + 4) * sizeof(struct statfs);
struct statfs *new_buf = realloc(mntbuf, new_size);
if (!new_buf) {
free(mntbuf);
lua_pushnil(L);
lua_pushstring(L, "Out of memory allocating mount buffer");
return 2;
}
mntbuf = new_buf;
bufsize = new_size;
num_mounts = getfsstat(mntbuf, bufsize, MNT_NOWAIT);
if (num_mounts > expected + 4) {
attempts++;
continue;
}
break;
}
// Выделяем память под буфер структур statfs
mntbuf = malloc(num_mounts * sizeof(struct statfs));
if (mntbuf == NULL) {
if (num_mounts < 0) {
free(mntbuf);
lua_pushnil(L);
lua_pushstring(L, "Ошибка выделения памяти");
lua_pushstring(L, "Failed to execute getfsstat");
return 2;
}
// Заполняем буфер реальными данными из ядра
num_mounts = getfsstat(mntbuf, num_mounts * sizeof(struct statfs), MNT_NOWAIT);
// Создаем результирующий массив (таблицу) в Lua
lua_newtable(L);
for (int i = 0; i < num_mounts; i++) {
// Создаем подтаблицу для конкретного монтирования
lua_newtable(L);
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_setfield(L, -2, "type");
// Кладем подтаблицу в общий массив (индексация в Lua с 1)
lua_rawseti(L, -2, i + 1);
}
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) {
static const struct luaL_Reg mylib[] = {
{ "getfsstat", lua_getfsstat },
{ "get_disk_models", lua_get_disk_models },
{ NULL, NULL }
};
luaL_newlib(L, mylib);