Disk: Linux impl working

This commit is contained in:
Linus Dierheimer
2022-10-17 13:19:48 +02:00
parent 973eb8127e
commit 19a9b18c69
16 changed files with 301 additions and 166 deletions
+25 -46
View File
@@ -1,56 +1,35 @@
#include "fastfetch.h"
#include "disk.h"
#include "detection/internal.h"
#include <sys/statvfs.h>
void ffDetectDisksImpl(FFDiskResult* disks);
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result)
static int compareDisks(const void* disk1, const void* disk2)
{
ffStrbufInitS(&result->path, folderPath);
result->used = result->total = 0;
ffStrbufInit(&result->error);
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
}
struct statvfs newFs;
const FFDiskResult* ffDetectDisks()
{
FF_DETECTION_INTERNAL_GUARD(FFDiskResult,
ffStrbufInit(&result.error);
ffListInitA(&result.disks, sizeof(FFDisk), 4);
if(fs == NULL)
{
fs = &newFs;
int ret = statvfs(folderPath, fs);
if(ret != 0)
ffDetectDisksImpl(&result);
if(result.disks.length == 0 && result.error.length == 0)
ffStrbufAppendS(&result.error, "No disks found");
for(uint32_t i = 0; i < result.disks.length; ++i)
{
ffStrbufAppendF(&result->error, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
return;
FFDisk* disk = ffListGet(&result.disks, i);
disk->bytesPercentage = (uint8_t) (((long double) disk->bytesUsed / (long double) disk->bytesTotal) * 100.0);
disk->filesPercentage = (uint8_t) (((long double) disk->filesUsed / (long double) disk->filesTotal) * 100.0);
}
}
result->total = fs->f_blocks * fs->f_frsize;
if(result->total == 0)
{
ffStrbufAppendF(&result->error, "statvfs for %s returned size 0", folderPath);
return;
}
result->used = result->total - (fs->f_bavail * fs->f_frsize);
result->files = (uint32_t) (fs->f_files - fs->f_ffree);
result->removable = false; //To be set at other place
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
{
ffStrbufTrim(&instance->config.diskFolders, ':');
if(instance->config.diskFolders.length == 0)
return false;
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
instance->config.diskFolders.chars[colonIndex] = '\0';
ffDetectDiskWithStatvfs(instance->config.diskFolders.chars + startIndex, NULL, (FFDiskResult*)ffListAdd(folders));
startIndex = colonIndex + 1;
}
return true;
//We need to sort the disks, so that we can detect, which disk a path resides on
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
//Note that we sort alphabetically here for a better ordering when printing the list,
// so the check must be done in reverse order
ffListSort(&result.disks, compareDisks);
);
}
+30 -7
View File
@@ -5,17 +5,40 @@
#include "fastfetch.h"
typedef enum FFDiskType
{
FF_DISK_TYPE_REGULAR,
FF_DISK_TYPE_HIDDEN,
FF_DISK_TYPE_EXTERNAL
} FFDiskType;
typedef struct FFDisk
{
FFstrbuf mountpoint;
FFstrbuf filesystem;
FFDiskType type;
uint64_t bytesUsed;
uint64_t bytesTotal;
uint8_t bytesPercentage;
uint32_t filesUsed;
uint32_t filesTotal;
uint8_t filesPercentage;
} FFDisk;
typedef struct FFDiskResult
{
FFstrbuf path;
uint64_t used;
uint64_t total;
uint32_t files;
bool removable;
FFstrbuf error;
FFlist disks; //List of FFDisk
} FFDiskResult;
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders);
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders);
/**
* Returns a List of FFDisk, sorted alphabetically by mountpoint.
* If error is not set, disks contains at least one disk.
*
* @return const FFDiskResult*
*/
const FFDiskResult* ffDetectDisks();
#endif
+6 -4
View File
@@ -3,15 +3,17 @@
#include <sys/statvfs.h>
#import <Foundation/Foundation.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
void ffDetectDisksImpl(FFDiskResult* disks)
{
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil];
NSArray *urls = [NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys:keys
options:NSVolumeEnumerationSkipHiddenVolumes];
if(urls == nil)
return "[NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys] failed";
{
ffStrbufAppendS(&disks->error, "[NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys] failed");
return;
}
for (NSURL *url in urls) {
NSError *error;
+71 -14
View File
@@ -1,24 +1,81 @@
#include "disk.h"
#include <ctype.h>
#include <sys/statvfs.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
void ffDetectDisksImpl(FFDiskResult* disks)
{
FF_UNUSED(instance);
FILE* mountsFile = fopen("/proc/mounts", "r");
if(mountsFile == NULL)
{
ffStrbufAppendS(&disks->error, "fopen(\"/proc/mounts\", \"r\") == NULL");
return;
}
struct statvfs fsRoot;
int rootRet = statvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot);
if(rootRet != 0)
return "statvfs(\"/\") failed";
char* line = NULL;
size_t len = 0;
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot, (FFDiskResult*)ffListAdd(folders));
while(getline(&line, &len, mountsFile) != EOF)
{
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
char* currentPos = line;
struct statvfs fsHome;
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
if(homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid))
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome, (FFDiskResult*)ffListAdd(folders));
//Non pseudo filesystems have their device in /dev/, we only add those
if(strncasecmp(currentPos, "/dev/", 5) != 0)
continue;
return NULL;
//Skip /dev/
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);
ffStrbufAppendSUntilC(&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;
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;
//Detects stats
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);
}
if(line != NULL)
free(line);
fclose(mountsFile);
}
+53 -54
View File
@@ -1,66 +1,65 @@
#include "disk.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <windows.h>
static void detectDrive(const char* folderPath, uint32_t pathLen, FFDiskResult* result)
void ffDetectDisksImpl(FFDiskResult* disks)
{
ffStrbufInitNS(&result->path, pathLen, folderPath);
result->removable = false; //To be set at other place
result->files = 0; //Unsupported
//According to https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa
//GetDiskFreeSpaceExA does not have to specify the root directory on a disk. The function accepts any directory on a disk.
uint64_t freeBytes;
if(GetDiskFreeSpaceExA(folderPath, NULL, (PULARGE_INTEGER)&result->total, (PULARGE_INTEGER)&freeBytes)) {
result->used = result->total - freeBytes;
ffStrbufInit(&result->error);
}
else
ffStrbufInitS(&result->error, "GetDiskFreeSpaceExA() failed");
}
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
{
FF_UNUSED(instance);
char buf[128]; // "C:\\\0D:\\\0"
uint32_t length = GetLogicalDriveStringsA(sizeof(buf) / sizeof(*buf), buf);
for(size_t i = 0; i < length;)
uint32_t length = GetLogicalDriveStringsA(0, NULL);
if(length == 0)
{
const char* drive = buf + i;
uint32_t driveLen = (uint32_t) strlen(drive);
i += driveLen + 1;
ffStrbufAppendS(&disks->error, "GetLogicalDriveStringsA failed");
return;
}
bool removable = GetDriveTypeA(drive) == DRIVE_REMOVABLE;
if(removable && !instance->config.diskRemovable)
char* buff = malloc(length + 1);
GetLogicalDriveStringsA(length, buf);
for(uint32_t i = 0; i < length; i++)
{
const char* mountpoint = buf + i;
UINT driveType = GetDriveTypeA(mountpoint);
if(driveType == DRIVE_NO_ROOT_DIR)
{
i += strlen(mountpoint);
continue;
}
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
detectDrive(drive, driveLen, folder);
folder->removable = removable;
FFDisk* disk = ffListAdd(&disks->disks);
ffStrbufInitS(&disk->mountpoint, mountpoint);
uint64_t bytesFree;
if(!GetDiskFreeSpaceExA(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
{
disk->bytesTotal = 0;
bytesFree = 0;
}
disk->bytesUsed = disk->bytesTotal - bytesFree;
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
disk->type = FF_DISK_TYPE_EXTERNAL;
else if(driveType == DRIVE_FIXED)
disk->type = FF_DISK_TYPE_REGULAR;
else
disk->type = FF_DISK_TYPE_HIDDEN;
ffStrbufInitA(&disk->filesystem, MAX_PATH + 1);
GetVolumeInformationA(mountpoint
NULL, 0, //Volume name
NULL, //Serial number
NULL, //Max component length
NULL, //File system flags
disk->filesystem.chars, ffStrbufGetFree(&disk->filesystem)
);
ffStrbufRecalculateLength(&disk->filesystem);
//TODO: implement
disk->filesUsed = 0;
disk->filesTotal = 0;
i += disk->mountpoint.length;
}
return NULL;
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
{
ffStrbufTrim(&instance->config.diskFolders, ';');
if(instance->config.diskFolders.length == 0)
return false;
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ';');
instance->config.diskFolders.chars[colonIndex] = '\0';
detectDrive(instance->config.diskFolders.chars + startIndex, colonIndex - startIndex, (FFDiskResult*)ffListAdd(folders));
startIndex = colonIndex + 1;
}
return true;
free(buff);
}