diff options
Diffstat (limited to 'src/detection/disk/disk_sunos.c')
| -rw-r--r-- | src/detection/disk/disk_sunos.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/detection/disk/disk_sunos.c b/src/detection/disk/disk_sunos.c new file mode 100644 index 0000000..3d811e0 --- /dev/null +++ b/src/detection/disk/disk_sunos.c @@ -0,0 +1,145 @@ +#include "disk.h" +#include "common/io.h" +#include "common/strutil.h" + +#include <sys/mntent.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <sys/mount.h> +#include <sys/mnttab.h> + +static bool isPhysicalDevice(const struct mnttab* device) { + // Always show the root path + if (ffStrEquals(device->mnt_mountp, "/")) { + return true; + } + + if (ffStrEquals(device->mnt_special, "none")) { + return false; + } + + // ZFS pool + if (ffStrEquals(device->mnt_fstype, "zfs")) { + return true; + } + + // Pseudo filesystems don't have a device in /dev + if (!ffStrStartsWith(device->mnt_special, "/dev/")) { + return false; + } + + struct stat deviceStat; + if (stat(device->mnt_special, &deviceStat) != 0) { + return false; + } + + // Ignore all devices that are not block devices + if (!S_ISBLK(deviceStat.st_mode)) { + return false; + } + + return true; +} + +static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) { + if (ffStrbufEqualS(¤tDisk->filesystem, "zfs")) { + // ZFS subvolumes + uint32_t index = ffStrbufFirstIndexC(¤tDisk->mountFrom, '/'); + if (index == currentDisk->mountFrom.length) { + return false; + } + + FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->mountFrom.chars); + for (uint32_t i = 0; i < disks->length - 1; i++) { + const FFDisk* otherDevice = FF_LIST_GET(FFDisk, *disks, i); + if (ffStrbufEqualS(&otherDevice->filesystem, "zfs") && ffStrbufStartsWith(&otherDevice->mountFrom, &zpoolName)) { + return true; + } + } + + return false; + } else { + // Filter all disks which device was already found. This catches BTRFS subvolumes. + for (uint32_t i = 0; i < disks->length - 1; i++) { + const FFDisk* otherDevice = FF_LIST_GET(FFDisk, *disks, i); + + if (ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom)) { + return true; + } + } + } + + return false; +} + +static void detectType(const FFlist* disks, FFDisk* currentDisk, struct mnttab* device) { + if (hasmntopt(device, MNTOPT_NOBROWSE)) { + currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; + } else if (isSubvolume(disks, currentDisk)) { + currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; + } else { + currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; + } + if (hasmntopt(device, MNTOPT_RO)) { + currentDisk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; + } +} + +static void detectStats(FFDisk* disk) { + struct statvfs fs; + if (statvfs(disk->mountpoint.chars, &fs) != 0) { + memset(&fs, 0, sizeof(fs)); + } + + disk->bytesTotal = fs.f_blocks * fs.f_frsize; + disk->bytesFree = fs.f_bfree * fs.f_frsize; + disk->bytesAvailable = fs.f_bavail * fs.f_frsize; + disk->bytesUsed = 0; // To be filled in ./disk.c + + disk->filesTotal = (uint32_t) fs.f_files; + disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); + + ffStrbufSetS(&disk->name, fs.f_fstr); + ffStrbufTrimRightSpace(&disk->name); + + disk->createTime = 0; +} + +const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) { + FF_AUTO_CLOSE_FILE FILE* mountsFile = fopen(MNTTAB, "r"); + if (mountsFile == NULL) { + return "fopen(\"" MNTTAB "\", \"r\") == NULL"; + } + + struct mnttab device; + + while (getmntent(mountsFile, &device) == 0) { + if (__builtin_expect(options->folders.length, 0)) { + if (!ffStrbufSeparatedContainS(&options->folders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR)) { + continue; + } + } else if (!isPhysicalDevice(&device)) { + continue; + } + + if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR)) { + continue; + } + + if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, device.mnt_fstype, ':')) { + continue; + } + + // We have a valid device, add it to the list + FFDisk* disk = FF_LIST_ADD(FFDisk, *disks); + disk->type = FF_DISK_VOLUME_TYPE_NONE; + ffStrbufInitS(&disk->mountFrom, device.mnt_special); + ffStrbufInitS(&disk->mountpoint, device.mnt_mountp); + ffStrbufInitS(&disk->filesystem, device.mnt_fstype); + ffStrbufInit(&disk->name); + detectType(disks, disk, &device); + detectStats(disk); + } + + return NULL; +} |