# bsdiskinfo A lightweight, modular, and dependency-free FreeBSD C library along with high-performance native Lua bindings for extracting precise hardware disk identity properties, active filesystem mounts, and raw S.M.A.R.T. metrics. The architecture strictly separates the system-level extraction engine from execution layers, allowing easy integration with multiple runtime environments (Lua, Python, Go, etc.) without inflating overhead or calling external binaries. ## Features - **Advanced Identity Verification**: Direct hardware query via `libcam` taskfiles. Successfully bypasses standard USB bridge constraints using SCSI SAT ATA PASS-THROUGH (16) to pull authentic models, serial numbers, firmware versions, WWN identifiers, and native sector geometry configs. - **Granular Type Classification**: Employs robust heuristics to accurately identify target media storage profiles (`ssd`, `hdd`, `nvme`, `sdcard`, or standard `usb` drive tokens). - **Fast Mount Traversal**: Scans active filesystem topologies directly via kernel `getfsstat` wrappers with non-blocking configurations, safely mitigating hung network storage paths. - **Isolated S.M.A.R.T. Matrix Layout**: Exposes full 30-slot attribute maps to user space, eliminating raw hex-parsing complexities inside scripting architectures. ## Repository Structure ```text bsdiskinfo ├── examples │   ├── tree_view.lua # Complex hardware tree mapping layout example │   └── tree_view.pl ├── include │   └── bsdiskinfo.h # Public standalone C API header ├── modules │   ├── lua │   │   ├── lua_bsdiskinfo.c # High-performance C-to-Lua binding translator │   │   └── Makefile # Dynamic Lua module build configurations │   └── perl │   ├── lib │   │   └── bsdiskinfo.pm # Public Perl module interface and POD docs │   ├── bsdiskinfo.xs # Core C-to-Perl XS translator bridge │   └── Makefile.PL # Perl ExtUtils::MakeMaker build script ├── src │   ├── cli.c # POSIX-compliant administrative CLI testbed │   ├── libbsdiskinfo.c # Core library implementation layers │   └── smart.h # Shared structural S.M.A.R.T. hardware definitions ├── LICENSE # BSD 2-Clause Simplified License └── Makefile # Native FreeBSD root pmake script ``` ## Building and Installation The build workflow utilizes native FreeBSD `bmake` engines and standard `pkg-config` routines to automatically discover installed platform toolchains. ### Build Everything (Library + CLI + Lua Module) ```bash make ``` ### Build Library Only (Headless C Environment) ```bash make WITHOUT_CLI=1 WITHOUT_LUA=1 ``` ### Build Targeting a Specific Lua Environment ```bash make LUA_VER=5.1 ``` ### Build without Perl XS module bindings ```bash make WITHOUT_PERL=1 ``` ### Build targeting a specific custom Perl layout ```bash cd modules/perl && perl Makefile.PL PREFIX=/my/path && make ``` ### Standard System Deployment ```bash sudo make install ``` *Installs components under `/usr/local/` paths (`lib/`, `include/`, `sbin/`, and corresponding Lua runtime folders).* ## Installation via FreeBSD Ports (Custom Overlay) The project is packaged for FreeBSD through a dedicated, standalone ports repository overlay. If you manage a local ports overlay or want to build a clean native package via `poudriere`/`bmake`, add the port definition from the tracking tree repository: * **Ports Overlay Repository**: [https://git.dc365.ru/digital-freak/ports](https://git.dc365.ru/digital-freak/ports) To build and install the toolkit from the overlay manually: ```bash # Navigate to the port directory inside your overlay tree cd /usr/ports/devel/bsdiskinfo # Configure, build, and install with selected bindings (Lua/Perl) sudo make config sudo make install clean ``` ## Usage Profiles ### Binary CLI Diagnostic Tool You can invoke the isolated diagnostics executable directly via administrative flags (`-i` identity, `-m` mounts, `-s` S.M.A.R.T.): ```bash # Print identity and active storage mount points for a block device node ./bsdiskinfo-cli -im ada0 ``` ### Lua Scripting Layer Integration A production-ready implementation mapping out the whole physical ecosystem using `devel/lua-sysctl` looks like this: ```lua local bsdiskinfo = require("bsdiskinfo") local sysctl = require("sysctl") local disks_str = sysctl.get("kern.disks") or "" for disk in disks_str:gmatch("%S+") do local props = bsdiskinfo.get_properties(disk) if props then print(string.format("Drive: /dev/%s [Model: %s, Serial: %s, Type: %s]", disk, props.model, props.serial, props.type)) -- Process mount objects safely local mounts = bsdiskinfo.get_mounts(disk) or {} for _, mnt in ipairs(mounts) do print(string.format(" └─ Mounted partition %s at %s", mnt.device, mnt.path)) end end end ``` *(See more extensive processing inside `examples/tree_view.lua`).* ### Perl5 Scripting Layer Integration A production-ready Perl 5 execution layer maps out the storage ecosystem using high-performance native XS structures. For direct kernel MIB tree traversal without spawning shell processes, the `sysutils/p5-BSD-Sysctl` port is highly recommended as a companion dependency. The integration utilizes standard UTF-8 stream handling to seamlessly draw complex nested topology layouts: ```perl #!/usr/bin/env perl use strict; use warnings; use utf8; use open qw/:std :encoding(utf8)/; # Ensures proper UTF-8 printing bounds use bsdiskinfo; use BSD::Sysctl; # Native FreeBSD kernel MIB traversal bindings # Query available physical drives straight from the kernel tree my $disks_str = BSD::Sysctl::sysctl('kern.disks') || ""; for my $disk (sort (split /\s+/,$disks_str)) { # Protect routing logic by verifying character device existence next unless bsdiskinfo::exists($disk); my $props = get_properties($disk); if ($props) { print "Drive: /dev/$disk [Model: $props->{model}, Type: $props->{type}]\n"; # Traverse active slices and mounted partitions my $mounts = get_mounts($disk) || []; for my $mnt (@$mounts) { print " └─ Partition $mnt->{device} mounted at $mnt->{path} ($mnt->{fstype})\n"; } } } ``` *(See `examples/tree_view.pl` for an expanded implementation containing full raw S.M.A.R.T. matrix unpacking).* ## Device Access & Permissions By default, raw character device nodes under `/dev/` (e.g., `/dev/ada*`, `/dev/da*`) are strictly accessible only by the `root` user in FreeBSD. Running the binary CLI tool or calling the Lua module as an unprivileged user will fail during transport library initialization (`Permission denied`). To safely grant a specific non-root user or daemon group (e.g., `operator`) execution rights to query hardware parameters without escalating system-wide privileges, configure the native FreeBSD `devfs` rules subsystem. ### 1. Append Rules to `/etc/devfs.rules` Create or modify the local rulesets configuration file to assign proper ownership and read/write accessibility maps to storage targets: ```text [local_devices=10] add path 'ada*' mode 0660 group operator add path 'da*' mode 0660 group operator add path 'nvme*' mode 0660 group operator ``` ### 2. Enable the Ruleset inside `/etc/rc.conf` Instruct the kernel subsystem init profiles to mount the default active `/dev` structure bound strictly against your custom ruleset index sequence: ```text devfs_system_ruleset="local_devices" ``` ### 3. Apply Changes Immediately Restart the system-wide device filesystem management daemon wrapper layer to evaluate state mutations on the fly: ```bash sudo service devfs restart ``` Ensure your unprivileged target runtime user account belongs to the configured destination group mapping bounds (e.g., `pw groupmod operator -m myuser`). ## License This project is licensed under the terms of the **BSD 2-Clause Simplified License**. See `LICENSE` for details.