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

142 lines
4.5 KiB
C
Raw Normal View History

#include "disk.h"
2022-12-29 23:19:44 +01:00
#include <limits.h>
2022-10-17 13:19:48 +02:00
#include <ctype.h>
#include <sys/statvfs.h>
2022-12-29 22:51:23 +01:00
static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source)
{
while(*source != '\0' && !isspace(*source))
{
2022-12-29 23:19:44 +01:00
//After a backslash the next 3 characters are octal ascii codes
if(*source == '\\' && strnlen(source, 4) == 4)
2022-12-29 22:58:29 +01:00
{
2022-12-29 23:19:44 +01:00
char octal[4] = {0};
strncpy(octal, source + 1, 3);
2022-12-29 22:58:29 +01:00
2022-12-29 23:19:44 +01:00
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;
continue;
}
2022-12-29 22:51:23 +01:00
}
ffStrbufAppendC(mountpoint, *source);
++source;
}
}
2023-01-16 11:52:54 +01:00
#ifndef __ANDROID__
static bool isSubvolume(const char* options)
{
const char* prefix = "subvol=/@"; //Btrfs subvolume
const char* subvolume = strstr(options, prefix);
if(subvolume == NULL)
return false;
subvolume += strlen(prefix);
//If there is no space or comma after the @, it is a btrfs subvolume
return *subvolume != ' ' && *subvolume != ',';
}
#endif
2022-10-17 13:19:48 +02:00
void ffDetectDisksImpl(FFDiskResult* disks)
{
2022-10-17 13:19:48 +02:00
FILE* mountsFile = fopen("/proc/mounts", "r");
if(mountsFile == NULL)
{
ffStrbufAppendS(&disks->error, "fopen(\"/proc/mounts\", \"r\") == NULL");
return;
}
char* line = NULL;
size_t len = 0;
while(getline(&line, &len, mountsFile) != EOF)
{
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
char* currentPos = line;
2022-10-28 01:02:00 +08:00
//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)
2022-10-17 13:19:48 +02:00
continue;
2022-12-29 22:51:23 +01:00
//Skip /dev/ or drvfs
2022-10-17 13:19:48 +02:00
currentPos += 5;
//Don't show loop file systems
if(strncasecmp(currentPos, "loop", 4) == 0)
continue;
FFDisk* disk = ffListAdd(&disks->disks);
//Go to mountpoint
while(!isspace(*currentPos) && *currentPos != '\0')
++currentPos;
while(isspace(*currentPos))
++currentPos;
ffStrbufInitA(&disk->mountpoint, 16);
2022-12-29 22:51:23 +01:00
strbufAppendMountPoint(&disk->mountpoint, currentPos);
2022-10-17 13:19:48 +02:00
//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__
2023-01-16 11:52:54 +01:00
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
2023-01-16 11:52:54 +01:00
if(isSubvolume(currentPos))
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
2022-10-17 13:19:48 +02:00
//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
2022-10-17 13:19:48 +02:00
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
2022-10-17 13:19:48 +02:00
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
2022-10-18 18:39:28 +08:00
ffStrbufInit(&disk->name); //TODO: implement this
2022-10-17 13:19:48 +02:00
}
2022-10-17 13:19:48 +02:00
if(line != NULL)
free(line);
2022-10-17 13:19:48 +02:00
fclose(mountsFile);
}