mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
135 lines
4.0 KiB
C
135 lines
4.0 KiB
C
#include "disk.h"
|
|
#include "common/io/io.h"
|
|
#include "util/stringUtils.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);
|
|
|
|
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;
|
|
|
|
//We have a valid device, add it to the list
|
|
FFDisk* disk = ffListAdd(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;
|
|
}
|