mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 00:37:23 +01:00
Disk (Linux): partition name impl & general refactor
This commit is contained in:
+165
-75
@@ -2,33 +2,137 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source)
|
||||
#ifdef __USE_LARGEFILE64
|
||||
#define stat stat64
|
||||
#define statvfs statvfs64
|
||||
#define dirent dirent64
|
||||
#define readdir readdir64
|
||||
#endif
|
||||
|
||||
static bool isPhysicalDevice(const char* device)
|
||||
{
|
||||
while(*source != '\0' && !isspace(*source))
|
||||
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
|
||||
if(strcmp(device, "drvfs") == 0)
|
||||
return true;
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
const char* devPrefix = "/dev/";
|
||||
if(strncmp(device, devPrefix, strlen(devPrefix)) != 0)
|
||||
return false;
|
||||
|
||||
//Skip /dev/ prefix
|
||||
device += strlen(devPrefix);
|
||||
|
||||
if(
|
||||
strncmp(device, "loop", 4) == 0 || //Ignore loop devices
|
||||
strncmp(device, "ram", 3) == 0 || //Ignore ram devices
|
||||
strncmp(device, "fd", 2) == 0 //Ignore fd devices
|
||||
) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void appendNextEntry(FFstrbuf* buffer, char** source)
|
||||
{
|
||||
//Read the current entry into the buffer
|
||||
while(**source != '\0' && !isspace(**source))
|
||||
{
|
||||
//After a backslash the next 3 characters are octal ascii codes
|
||||
if(*source == '\\' && strnlen(source, 4) == 4)
|
||||
if(**source == '\\' && strnlen(*source, 4) == 4)
|
||||
{
|
||||
char octal[4] = {0};
|
||||
strncpy(octal, source + 1, 3);
|
||||
strncpy(octal, *source + 1, 3);
|
||||
|
||||
long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr
|
||||
if(value > 0 && value < CHAR_MAX)
|
||||
{
|
||||
ffStrbufAppendC(mountpoint, (char) value);
|
||||
source += 4;
|
||||
ffStrbufAppendC(buffer, (char) value);
|
||||
*source += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendC(mountpoint, *source);
|
||||
++source;
|
||||
ffStrbufAppendC(buffer, **source);
|
||||
++*source;
|
||||
}
|
||||
|
||||
//Skip whitespace
|
||||
while(isspace(**source))
|
||||
++*source;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath)
|
||||
{
|
||||
DIR* dir = opendir(basePath->chars);
|
||||
if(dir == NULL)
|
||||
return;
|
||||
|
||||
uint32_t basePathLength = basePath->length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(basePath, entry->d_name);
|
||||
|
||||
struct stat entryStat;
|
||||
bool ret = stat(basePath->chars, &entryStat) == 0;
|
||||
|
||||
ffStrbufSubstrBefore(basePath, basePathLength);
|
||||
|
||||
if(!ret || deviceStat->st_ino != entryStat.st_ino)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&disk->name, entry->d_name);
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
{
|
||||
struct stat deviceStat;
|
||||
if(stat(device->chars, &deviceStat) != 0)
|
||||
return;
|
||||
|
||||
FFstrbuf basePath;
|
||||
ffStrbufInit(&basePath);
|
||||
|
||||
//Try partlabel first
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-partlabel/");
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
|
||||
//Try label second
|
||||
if(disk->name.length == 0)
|
||||
{
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-label/");
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&basePath);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options)
|
||||
{
|
||||
if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated"))
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/"))
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *allDisks)
|
||||
@@ -42,8 +146,34 @@ static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options)
|
||||
{
|
||||
if(isSubvolume(allDisks, currentDisk))
|
||||
currentDisk->type = FF_DISK_TYPE_SUBVOLUME;
|
||||
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi"))
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN;
|
||||
else
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void detectStats(FFDisk* disk)
|
||||
{
|
||||
struct statvfs fs;
|
||||
if(statvfs(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
|
||||
|
||||
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
|
||||
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
|
||||
|
||||
disk->filesTotal = (uint32_t) fs.f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
|
||||
}
|
||||
|
||||
void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
{
|
||||
FILE* mountsFile = fopen("/proc/mounts", "r");
|
||||
@@ -53,90 +183,50 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf device;
|
||||
ffStrbufInit(&device);
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, mountsFile) != EOF)
|
||||
{
|
||||
if(!isPhysicalDevice(line))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
|
||||
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
|
||||
char* currentPos = line;
|
||||
|
||||
//Non pseudo filesystems have their device in /dev/
|
||||
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
|
||||
if(strncmp(currentPos, "/dev/", 5) != 0 && strncmp(currentPos, "drvfs", 5) != 0)
|
||||
continue;
|
||||
//detect device
|
||||
ffStrbufClear(&device);
|
||||
appendNextEntry(&device, ¤tPos);
|
||||
|
||||
//Skip /dev/ or drvfs
|
||||
currentPos += 5;
|
||||
//detect mountpoint
|
||||
ffStrbufInit(&disk->mountpoint);
|
||||
appendNextEntry(&disk->mountpoint, ¤tPos);
|
||||
|
||||
//Don't show loop file systems
|
||||
if(strncasecmp(currentPos, "loop", 4) == 0)
|
||||
continue;
|
||||
//detect filesystem
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
appendNextEntry(&disk->filesystem, ¤tPos);
|
||||
|
||||
FFDisk* disk = ffListAdd(&disks->disks);
|
||||
//detect name
|
||||
ffStrbufInit(&disk->name);
|
||||
detectName(disk, &device);
|
||||
|
||||
//Go to mountpoint
|
||||
while(!isspace(*currentPos) && *currentPos != '\0')
|
||||
++currentPos;
|
||||
while(isspace(*currentPos))
|
||||
++currentPos;
|
||||
|
||||
ffStrbufInitA(&disk->mountpoint, 16);
|
||||
strbufAppendMountPoint(&disk->mountpoint, currentPos);
|
||||
|
||||
//Go to filesystem
|
||||
currentPos += disk->mountpoint.length;
|
||||
while(isspace(*currentPos))
|
||||
++currentPos;
|
||||
|
||||
ffStrbufInitA(&disk->filesystem, 16);
|
||||
ffStrbufAppendSUntilC(&disk->filesystem, currentPos, ' ');
|
||||
|
||||
//Go to options, detect type
|
||||
currentPos += disk->filesystem.length;
|
||||
while(isspace(*currentPos))
|
||||
++currentPos;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated"))
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/"))
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
#else
|
||||
if(isSubvolume(&disks->disks, disk))
|
||||
disk->type = FF_DISK_TYPE_SUBVOLUME;
|
||||
else if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL)
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL;
|
||||
else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi"))
|
||||
disk->type = FF_DISK_TYPE_HIDDEN;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_REGULAR;
|
||||
#endif
|
||||
//detect type
|
||||
detectType(&disks->disks, disk, currentPos);
|
||||
|
||||
//Detects stats
|
||||
#ifdef __USE_LARGEFILE64
|
||||
struct statvfs64 fs;
|
||||
if(statvfs64(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs64)); //Set all values to 0, so our values get initialized to 0 too
|
||||
#else
|
||||
struct statvfs fs;
|
||||
if(statvfs(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
|
||||
#endif
|
||||
|
||||
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
|
||||
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
|
||||
|
||||
disk->filesTotal = (uint32_t) fs.f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
|
||||
|
||||
ffStrbufInit(&disk->name); //TODO: implement this
|
||||
detectStats(disk);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
ffStrbufDestroy(&device);
|
||||
|
||||
fclose(mountsFile);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user