From b35c7211dceecd8ce650f573bc045643ff839b8d Mon Sep 17 00:00:00 2001 From: Sergey Kiselev Date: Wed, 20 May 2026 13:23:39 +0500 Subject: [PATCH] Fetch hardware device models efficiently via kernel ioctl requests --- src/sysmount.c | 119 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 20 deletions(-) diff --git a/src/sysmount.c b/src/sysmount.c index ae20c42..bbb8832 100644 --- a/src/sysmount.c +++ b/src/sysmount.c @@ -1,37 +1,60 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include #include #include +// 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);