Files
fastfetch/src/detection/disk/disk_bsd.c
T

215 lines
6.9 KiB
C
Raw Normal View History

2022-10-27 14:58:29 +08:00
#include "disk.h"
2026-01-06 09:48:38 +08:00
#include "common/mallocHelper.h"
2026-05-28 15:58:08 +08:00
#include "common/strutil.h"
2022-10-27 14:58:29 +08:00
2026-04-09 16:20:59 +08:00
#include <stdalign.h>
2022-10-27 14:58:29 +08:00
#include <sys/mount.h>
2024-04-09 15:15:33 +08:00
#include <sys/stat.h>
2022-10-27 14:58:29 +08:00
#ifdef __NetBSD__
#include <sys/types.h>
#include <sys/statvfs.h>
#define statfs statvfs
#define f_flags f_flag
#define f_bsize f_frsize
#endif
2022-10-27 14:58:29 +08:00
#ifdef __FreeBSD__
#if __has_include(<libgeom.h>)
#include <libgeom.h>
2023-12-27 15:56:39 +08:00
2026-03-29 09:28:49 +08:00
static const char* detectFsLabel(struct statfs* fs, FFDisk* disk) {
if (!ffStrStartsWith(fs->f_mntfromname, "/dev/")) {
2023-12-27 15:56:39 +08:00
return "Only block devices are supported";
2026-03-29 09:28:49 +08:00
}
2023-12-27 15:56:39 +08:00
// Detect volume label in geom tree
static struct gmesh geomTree;
static struct gclass* cLabels;
2026-03-29 09:28:49 +08:00
if (!cLabels) {
if (geomTree.lg_ident) {
2023-12-27 15:56:39 +08:00
return "Previous geom_gettree() failed";
2026-03-29 09:28:49 +08:00
}
2023-12-27 15:56:39 +08:00
2026-03-29 09:28:49 +08:00
if (geom_gettree(&geomTree) < 0) {
geomTree.lg_ident = (void*) (intptr_t) -1;
2023-12-27 15:56:39 +08:00
return "geom_gettree() failed";
}
2025-03-26 14:42:55 +08:00
for (cLabels = geomTree.lg_class.lh_first; cLabels && !ffStrEquals(cLabels->lg_name, "LABEL"); cLabels = cLabels->lg_class.le_next);
2026-03-29 09:28:49 +08:00
if (!cLabels) {
2023-12-27 15:56:39 +08:00
return "Class LABEL is not found";
2026-03-29 09:28:49 +08:00
}
2023-12-27 15:56:39 +08:00
}
2026-03-29 09:28:49 +08:00
for (struct ggeom* label = cLabels->lg_geom.lh_first; label; label = label->lg_geom.le_next) {
2023-12-27 15:56:39 +08:00
struct gprovider* provider = label->lg_provider.lh_first;
2026-03-29 09:28:49 +08:00
if (!provider || !ffStrEquals(label->lg_name, fs->f_mntfromname + strlen("/dev/"))) {
continue;
}
2023-12-27 15:56:39 +08:00
const char* str = strchr(provider->lg_name, '/');
ffStrbufSetS(&disk->name, str ? str + 1 : provider->lg_name);
}
2026-07-10 18:08:04 +08:00
return nullptr;
2023-12-27 15:56:39 +08:00
}
#else
2026-04-09 16:20:59 +08:00
static const char* detectFsLabel(FF_A_UNUSED struct statfs* fs, FF_A_UNUSED FFDisk* disk) {
2024-11-03 08:35:11 +08:00
return "Fastfetch was compiled without libgeom support";
}
#endif
2023-12-27 15:56:39 +08:00
2026-03-29 09:28:49 +08:00
static void detectFsInfo(struct statfs* fs, FFDisk* disk) {
if (ffStrbufEqualS(&disk->filesystem, "zfs")) {
disk->type = !ffStrbufStartsWithS(&disk->mountFrom, "zroot/") || ffStrbufStartsWithS(&disk->mountFrom, "zroot/ROOT/")
2023-08-26 09:32:19 +08:00
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
: FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
2026-03-29 09:28:49 +08:00
} else if (fs->f_flags & MNT_IGNORE) {
2023-08-26 09:32:19 +08:00
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
2026-03-29 09:28:49 +08:00
} else if (!(fs->f_flags & MNT_LOCAL)) {
2023-08-26 09:32:19 +08:00
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
2026-03-29 09:28:49 +08:00
} else {
2023-08-26 09:32:19 +08:00
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
2026-03-29 09:28:49 +08:00
}
2023-12-27 15:56:39 +08:00
detectFsLabel(fs, disk);
}
#elif __APPLE__
#include "common/apple/cf_helpers.h"
2023-10-03 22:10:22 +08:00
#include <sys/attr.h>
#include <unistd.h>
#ifndef MAC_OS_X_VERSION_10_15
#define MNT_REMOVABLE 0x00000200
#endif
struct CmnAttrBuf {
2026-03-29 09:28:49 +08:00
uint32_t length;
attrreference_t nameRef;
2026-03-29 09:28:49 +08:00
char nameSpace[NAME_MAX * 3 + 1];
2026-04-09 16:20:59 +08:00
} FF_A_PACKED;
2026-03-29 09:28:49 +08:00
void detectFsInfo(struct statfs* fs, FFDisk* disk) {
if (fs->f_flags & MNT_DONTBROWSE) {
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
2026-03-29 09:28:49 +08:00
} else if (fs->f_flags & MNT_REMOVABLE || !(fs->f_flags & MNT_LOCAL)) {
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
2026-03-29 09:28:49 +08:00
} else {
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
2026-03-29 09:28:49 +08:00
}
2022-10-27 14:58:29 +08:00
2026-04-09 16:20:59 +08:00
alignas(4) struct CmnAttrBuf attrBuf;
if (getattrlist(disk->mountpoint.chars, &(struct attrlist) {
2026-03-29 09:28:49 +08:00
.bitmapcount = ATTR_BIT_MAP_COUNT,
.commonattr = ATTR_CMN_NAME,
},
&attrBuf,
sizeof(attrBuf),
0) == 0) {
ffStrbufInitNS(&disk->name, attrBuf.nameRef.attr_length - 1 /* excluding '\0' */, attrBuf.nameSpace);
2026-03-29 09:28:49 +08:00
}
2022-10-27 14:58:29 +08:00
}
2024-10-04 15:58:17 +08:00
#else
2026-03-29 09:28:49 +08:00
static void detectFsInfo(struct statfs* fs, FFDisk* disk) {
#ifdef MNT_IGNORE
2026-03-29 09:28:49 +08:00
if (fs->f_flags & MNT_IGNORE) {
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
2026-03-29 09:28:49 +08:00
} else
#endif
2026-03-29 09:28:49 +08:00
if (!(fs->f_flags & MNT_LOCAL)) {
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
2026-03-29 09:28:49 +08:00
} else {
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
2026-03-29 09:28:49 +08:00
}
2024-10-04 15:58:17 +08:00
}
2022-10-27 14:58:29 +08:00
#endif
2026-03-29 09:28:49 +08:00
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) {
#ifndef __NetBSD__
2026-07-10 18:08:04 +08:00
int size = getfsstat(nullptr, 0, MNT_WAIT);
2026-03-29 09:28:49 +08:00
if (size <= 0) {
2026-07-10 18:08:04 +08:00
return "getfsstat(nullptr, 0, MNT_WAIT) failed";
2026-03-29 09:28:49 +08:00
}
#else
2026-07-10 18:08:04 +08:00
int size = getvfsstat(nullptr, 0, ST_WAIT);
2026-03-29 09:28:49 +08:00
if (size <= 0) {
2026-07-10 18:08:04 +08:00
return "getvfsstat(nullptr, 0, ST_WAIT) failed";
2026-03-29 09:28:49 +08:00
}
#endif
FF_AUTO_FREE struct statfs* buf = malloc(sizeof(*buf) * (unsigned) size);
2026-03-29 09:28:49 +08:00
#ifndef __NetBSD__
if (getfsstat(buf, (int) (sizeof(*buf) * (unsigned) size), MNT_NOWAIT) <= 0) {
return "getfsstat(buf, size, MNT_NOWAIT) failed";
2026-03-29 09:28:49 +08:00
}
#else
if (getvfsstat(buf, sizeof(*buf) * (unsigned) size, ST_NOWAIT) <= 0) {
2025-01-21 09:41:40 +08:00
return "getvfsstat(buf, size, ST_NOWAIT) failed";
2026-03-29 09:28:49 +08:00
}
#endif
2022-10-27 14:58:29 +08:00
2026-03-29 09:28:49 +08:00
for (struct statfs* fs = buf; fs < buf + size; ++fs) {
if (__builtin_expect(options->folders.length > 0, 0)) {
if (!ffStrbufSeparatedContainS(&options->folders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR)) {
continue;
2026-03-29 09:28:49 +08:00
}
} else if (!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs") && !ffStrEquals(fs->f_fstypename, "fusefs.sshfs")) {
continue;
2026-03-29 09:28:49 +08:00
}
2026-03-29 09:28:49 +08:00
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR)) {
continue;
2026-03-29 09:28:49 +08:00
}
2026-03-29 09:28:49 +08:00
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, fs->f_fstypename, ':')) {
continue;
2026-03-29 09:28:49 +08:00
}
2026-03-29 09:28:49 +08:00
#ifdef __FreeBSD__
2022-10-27 14:58:29 +08:00
// f_bavail and f_ffree are signed on FreeBSD...
2026-03-29 09:28:49 +08:00
if (fs->f_bavail < 0) {
fs->f_bavail = 0;
}
if (fs->f_ffree < 0) {
fs->f_ffree = 0;
}
#endif
2022-10-27 14:58:29 +08:00
2026-04-14 10:41:18 +08:00
FFDisk* disk = FF_LIST_ADD(FFDisk, *disks);
2023-09-30 15:00:59 +08:00
2026-03-29 09:28:49 +08:00
disk->bytesTotal = (uint64_t) fs->f_blocks * (uint64_t) fs->f_bsize;
disk->bytesFree = (uint64_t) fs->f_bfree * (uint64_t) fs->f_bsize;
disk->bytesAvailable = (uint64_t) fs->f_bavail * (uint64_t) fs->f_bsize;
2023-08-26 10:36:00 +08:00
disk->bytesUsed = 0; // To be filled in ./disk.c
2022-10-27 14:58:29 +08:00
disk->filesTotal = (uint32_t) fs->f_files;
2025-06-05 04:52:18 +08:00
disk->filesUsed = (uint32_t) fs->f_files - (uint32_t) fs->f_ffree;
2022-10-27 14:58:29 +08:00
2023-09-17 20:08:46 +08:00
ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname);
2022-10-27 14:58:29 +08:00
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
ffStrbufInitS(&disk->filesystem, fs->f_fstypename);
ffStrbufInit(&disk->name);
disk->type = 0;
2024-05-18 13:09:37 +08:00
disk->createTime = 0;
2022-10-27 14:58:29 +08:00
detectFsInfo(fs, disk);
2023-08-26 12:50:45 +08:00
2026-03-29 09:28:49 +08:00
if (fs->f_flags & MNT_RDONLY) {
2023-08-26 12:50:45 +08:00
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
2026-03-29 09:28:49 +08:00
}
2024-04-09 15:15:33 +08:00
2026-03-29 09:28:49 +08:00
#ifdef __OpenBSD__
#define st_birthtimespec __st_birthtim
2026-03-29 09:28:49 +08:00
#endif
#ifndef __DragonFly__
2024-04-09 15:15:33 +08:00
struct stat st;
2026-03-29 09:28:49 +08:00
if (stat(fs->f_mntonname, &st) == 0 && st.st_birthtimespec.tv_sec > 0) {
disk->createTime = (uint64_t) (((uint64_t) st.st_birthtimespec.tv_sec * 1000) + ((uint64_t) st.st_birthtimespec.tv_nsec / 1000000));
}
#endif
2022-10-27 14:58:29 +08:00
}
2023-06-12 22:09:52 +08:00
2026-07-10 18:08:04 +08:00
return nullptr;
2022-10-27 14:58:29 +08:00
}