From 19a9b18c696bacb0aaa76d5016147f1290365de0 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Mon, 17 Oct 2022 13:19:48 +0200 Subject: [PATCH] Disk: Linux impl working --- CMakeLists.txt | 3 +- src/common/format.c | 5 +- src/common/format.h | 5 +- src/common/init.c | 3 +- src/common/printing.c | 4 +- src/detection/disk/disk.c | 71 +++++++------------- src/detection/disk/disk.h | 37 ++++++++-- src/detection/disk/disk_apple.m | 10 +-- src/detection/disk/disk_linux.c | 85 +++++++++++++++++++---- src/detection/disk/disk_windows.c | 107 +++++++++++++++-------------- src/fastfetch.c | 2 - src/fastfetch.h | 3 +- src/modules/disk.c | 108 +++++++++++++++++++++--------- src/util/FFlist.h | 6 ++ src/util/FFstrbuf.c | 12 ++++ src/util/FFstrbuf.h | 6 ++ 16 files changed, 301 insertions(+), 166 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0cf1b4d..990441a6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,7 @@ set(LIBFASTFETCH_SRC src/detection/terminalshell/terminalshell.c src/detection/media/media.c src/detection/packages/packages.c + src/detection/disk/disk.c src/modules/break.c src/modules/custom.c src/modules/title.c @@ -285,13 +286,13 @@ set(LIBFASTFETCH_SRC src/modules/opengl.c src/modules/opencl.c src/modules/users.c + src/detection/disk/disk_apple.m ) if(LINUX OR APPLE OR ANDROID OR BSD) list(APPEND LIBFASTFETCH_SRC src/common/processing_linux.c src/detection/users/users_linux.c - src/detection/disk/disk.c src/detection/terminalshell/terminalshell_linux.c src/detection/localip/localip_linux.c ) diff --git a/src/common/format.c b/src/common/format.c index 19d5d289d..136b053d2 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -20,6 +20,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE) ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value); + else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL) + ffStrbufAppendS(buffer, formatarg->value != NULL ? "true" : "false"); else if(formatarg->type == FF_FORMAT_ARG_TYPE_LIST) { const FFlist* list = formatarg->value; @@ -74,7 +76,8 @@ static inline bool formatArgSet(const FFformatarg* arg) (arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) || (arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) || (arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) || - (arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) + (arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) || + (arg->type == FF_FORMAT_ARG_TYPE_BOOL && arg->value != NULL) ); } diff --git a/src/common/format.h b/src/common/format.h index 51413a1fb..d860dbd29 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -13,7 +13,8 @@ typedef enum FFformatargtype FF_FORMAT_ARG_TYPE_STRING, FF_FORMAT_ARG_TYPE_STRBUF, FF_FORMAT_ARG_TYPE_DOUBLE, - FF_FORMAT_ARG_TYPE_LIST + FF_FORMAT_ARG_TYPE_LIST, + FF_FORMAT_ARG_TYPE_BOOL } FFformatargtype; typedef struct FFformatarg @@ -25,4 +26,6 @@ typedef struct FFformatarg void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg); void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments); +#define FF_FORMAT_ARG_VALUE_BOOL(xpr) ((xpr) ? (const void*) 1 : NULL) + #endif diff --git a/src/common/init.c b/src/common/init.c index 0427d419b..af4ab7bfe 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -253,7 +253,8 @@ static void defaultConfig(FFinstance* instance) instance->config.titleFQDN = false; ffStrbufInitA(&instance->config.diskFolders, 0); - instance->config.diskRemovable = false; + instance->config.diskShowRemovable = true; + instance->config.diskShowHidden = false; ffStrbufInitA(&instance->config.batteryDir, 0); diff --git a/src/common/printing.c b/src/common/printing.c index a6911db15..148266d26 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -93,7 +93,9 @@ static void printError(FFinstance* instance, const char* moduleName, uint8_t mod vprintf(message, arguments); if(!instance->config.pipe) - puts(FASTFETCH_TEXT_MODIFIER_RESET); + fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); + + putchar('\n'); } } diff --git a/src/detection/disk/disk.c b/src/detection/disk/disk.c index 7d469c2ba..3ce33aed5 100644 --- a/src/detection/disk/disk.c +++ b/src/detection/disk/disk.c @@ -1,56 +1,35 @@ -#include "fastfetch.h" #include "disk.h" +#include "detection/internal.h" -#include +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); + ); } diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index a68347fde..30243d73c 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -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 diff --git a/src/detection/disk/disk_apple.m b/src/detection/disk/disk_apple.m index 8341ef74e..a4e38376d 100644 --- a/src/detection/disk/disk_apple.m +++ b/src/detection/disk/disk_apple.m @@ -3,15 +3,17 @@ #include #import -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; diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index eb8ceb0f3..bbf4e22a8 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -1,24 +1,81 @@ #include "disk.h" +#include #include -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: " ..." (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); } diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 27117a017..b3c50456c 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -1,66 +1,65 @@ #include "disk.h" #define WIN32_LEAN_AND_MEAN 1 -#include +#include -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); } diff --git a/src/fastfetch.c b/src/fastfetch.c index 6d1a2b8d2..f395d808b 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1314,8 +1314,6 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.titleFQDN = optionParseBoolean(value); else if(strcasecmp(key, "--disk-folders") == 0) optionParseString(key, value, &instance->config.diskFolders); - else if(strcasecmp(key, "--disk-removable") == 0) - instance->config.diskRemovable = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index afb697cbf..d62348e80 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -168,7 +168,8 @@ typedef struct FFconfig bool titleFQDN; FFstrbuf diskFolders; - bool diskRemovable; + bool diskShowRemovable; + bool diskShowHidden; FFstrbuf batteryDir; diff --git a/src/modules/disk.c b/src/modules/disk.c index 1a2c97be8..88dd6634d 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -4,78 +4,120 @@ #include "detection/disk/disk.h" #define FF_DISK_MODULE_NAME "Disk" -#define FF_DISK_NUM_FORMAT_ARGS 4 +#define FF_DISK_NUM_FORMAT_ARGS 9 -static void printFolder(FFinstance* instance, FFDiskResult* folder) +static void printDisk(FFinstance* instance, const FFDisk* disk) { FFstrbuf key; ffStrbufInit(&key); if(instance->config.disk.key.length == 0) { - ffStrbufAppendF(&key, "%s (%*s)", FF_DISK_MODULE_NAME, folder->path.length, folder->path.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_DISK_MODULE_NAME, disk->mountpoint.chars); } else { ffParseFormatString(&key, &instance->config.disk.key, 1, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &folder->path} + {FF_FORMAT_ARG_TYPE_STRBUF, &disk->mountpoint} }); } - uint8_t percentage = (uint8_t) (((long double) folder->used / (long double) folder->total) * 100.0); - FFstrbuf usedPretty; ffStrbufInit(&usedPretty); - ffParseSize(folder->used, instance->config.binaryPrefixType, &usedPretty); + ffParseSize(disk->bytesUsed, instance->config.binaryPrefixType, &usedPretty); FFstrbuf totalPretty; ffStrbufInit(&totalPretty); - ffParseSize(folder->total, instance->config.binaryPrefixType, &totalPretty); + ffParseSize(disk->bytesTotal, instance->config.binaryPrefixType, &totalPretty); if(instance->config.disk.outputFormat.length == 0) { ffPrintLogoAndKey(instance, key.chars, 0, NULL); - printf("%s / %s (%u%%)%s\n", usedPretty.chars, totalPretty.chars, percentage, folder->removable ? " [Removable]" : ""); + printf("%s / %s (%u%%)", usedPretty.chars, totalPretty.chars, disk->bytesPercentage); + if(disk->type == FF_DISK_TYPE_EXTERNAL) + printf(" [Removable]"); + putchar('\n'); } else { ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, - {FF_FORMAT_ARG_TYPE_UINT8, &percentage}, - {FF_FORMAT_ARG_TYPE_UINT, &folder->files}, + {FF_FORMAT_ARG_TYPE_UINT8, &disk->bytesPercentage}, + {FF_FORMAT_ARG_TYPE_UINT, &disk->filesUsed}, + {FF_FORMAT_ARG_TYPE_UINT, &disk->filesTotal}, + {FF_FORMAT_ARG_TYPE_UINT8, &disk->filesPercentage}, + {FF_FORMAT_ARG_TYPE_BOOL, FF_FORMAT_ARG_VALUE_BOOL(disk->type == FF_DISK_TYPE_EXTERNAL)}, + {FF_FORMAT_ARG_TYPE_BOOL, FF_FORMAT_ARG_VALUE_BOOL(disk->type == FF_DISK_TYPE_HIDDEN)}, + {FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem} }); } - ffStrbufDestroy(&key); ffStrbufDestroy(&totalPretty); ffStrbufDestroy(&usedPretty); + ffStrbufDestroy(&key); +} + +static void printMountpoint(FFinstance* instance, const FFlist* disks, const char* mountpoint) +{ + for(uint32_t i = disks->length; i > 0; i--) + { + FFDisk* disk = ffListGet(disks, i - 1); + if(strncmp(mountpoint, disk->mountpoint.chars, disk->mountpoint.length) == 0) + { + printDisk(instance, disk); + return; + } + } + + ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "No disk found for mountpoint: %s", mountpoint); +} + +static void printMountpoints(FFinstance* instance, const FFlist* disks) +{ + FFstrbuf mountpoints; + ffStrbufInitCopy(&mountpoints, &instance->config.diskFolders); + ffStrbufTrim(&mountpoints, ':'); + + uint32_t startIndex = 0; + while(startIndex < mountpoints.length) + { + uint32_t colonIndex = ffStrbufNextIndexC(&mountpoints, startIndex, ':'); + mountpoints.chars[colonIndex] = '\0'; + + printMountpoint(instance, disks, mountpoints.chars + startIndex); + + startIndex = colonIndex + 1; + } +} + +static void printAutodetected(FFinstance* instance, const FFlist* disks) +{ + for(uint32_t i = 0; i < disks->length; i++) + { + const FFDisk* disk = ffListGet(disks, i); + + if(disk->type == FF_DISK_TYPE_EXTERNAL && !instance->config.diskShowRemovable) + continue; + + if(disk->type == FF_DISK_TYPE_HIDDEN && !instance->config.diskShowHidden) + continue; + + printDisk(instance, disk); + } } void ffPrintDisk(FFinstance* instance) { - FFlist folders; - ffListInit(&folders, sizeof(FFDiskResult)); - - const char* error = NULL; - - if(!ffDiskDetectDiskFolders(instance, &folders)) - error = ffDiskAutodetectFolders(instance, &folders); - - if(error) + const FFDiskResult* disks = ffDetectDisks(); + if(disks->error.length > 0) { - ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error); + ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", disks->error.chars); + return; } + + if(instance->config.diskFolders.length == 0) + printAutodetected(instance, &disks->disks); else - { - for(uint32_t i = 0; i < folders.length; ++i) - { - FFDiskResult* folder = (FFDiskResult*)ffListGet(&folders, i); - printFolder(instance, folder); - ffStrbufDestroy(&folder->path); - ffStrbufDestroy(&folder->error); - } - } - - ffListDestroy(&folders); + printMountpoints(instance, &disks->disks); } diff --git a/src/util/FFlist.h b/src/util/FFlist.h index d1eee05ad..d9d516792 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -8,6 +8,7 @@ #include #include #include +#include #define FF_LIST_DEFAULT_ALLOC 16 @@ -39,4 +40,9 @@ static inline void* ffListGet(const FFlist* list, uint32_t index) return list->data + (index * list->elementSize); } +static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void*)) +{ + qsort(list->data, list->length, list->elementSize, compar); +} + #endif diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index b302bce0a..415ec6fb7 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -155,6 +155,18 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) strbuf->chars[strbuf->length] = '\0'; } +void ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until) +{ + if(value == NULL) + return; + + char* end = strchr(value, until); + if(end == NULL) + ffStrbufAppendS(strbuf, value); + else + ffStrbufAppendNS(strbuf, (uint32_t) (end - value), value); +} + void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...) { assert(format != NULL); diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 11ce0518b..736e1d26d 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -45,6 +45,7 @@ void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* va void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int)); FF_C_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); +void ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until); void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value); @@ -147,6 +148,11 @@ static inline int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp) return memcmp(strbuf->chars, comp->chars, length + 1); } +static inline int ffStrbufCompAlphabetically(const FFstrbuf* strbuf, const FFstrbuf* comp) +{ + return strcmp(strbuf->chars, comp->chars); +} + static inline FF_C_NODISCARD bool ffStrbufEqual(const FFstrbuf* strbuf, const FFstrbuf* comp) { return ffStrbufComp(strbuf, comp) == 0;