Added additional information to the output.

Update to version 1.0.4
This commit is contained in:
Lennart Martens
2025-07-04 18:34:15 +02:00
parent d11a083db9
commit 30d6ad50d8
5 changed files with 225 additions and 10 deletions
+2
View File
@@ -14,8 +14,10 @@ clean:
install: $(TARGET)
install -Dm755 drinfo /usr/local/bin/drinfo
install -Dm644 drinfo.1 /usr/share/man/man1/drinfo.1
sudo mandb > /dev/null 2>&1
uninstall:
sudo rm -f /usr/local/bin/$(TARGET)
sudo rm -f /usr/share/man/man1/$(TARGET).1
.PHONY: all clean install uninstall
+9 -3
View File
@@ -10,20 +10,26 @@ A lightweight command-line tool to monitor disk usage on Linux systems with beau
- **Colorful Progress Bars**: Visual representation of disk usage with gradient colors (green → yellow → red)
- **Human-Readable Sizes**: Displays sizes in B, KB, MB, GB, TB format
- **Terminal Responsive**: Adapts to terminal width for optimal display
- **Detailed Information**: Shows mount point, filesystem type, device path, and usage statistics
- **Detailed Information**: Shows mount point, filesystem type, device path, UUID, label, mount options, used, available and inodes + SMART status (only as root)
## Build
## Build executable: drinfo
```bash
make
```
## install
## install with man page
```bash
sudo make install
```
## Uninstall
```bash
sudo make uninstall
```
## Screenshot
![screenshot](screenshot.jpg)
+3 -2
View File
@@ -1,4 +1,4 @@
.TH DRINFO 1 "June 2024" "Version 1.0.2" "User Commands"
.TH DRINFO 1 "June 2024" "Version 1.0.4" "User Commands"
.SH NAME
drinfo \- display information about drives and their storage usage
.SH SYNOPSIS
@@ -6,7 +6,8 @@ drinfo \- display information about drives and their storage usage
.RI [ OPTION ]
.SH DESCRIPTION
.B drinfo
lists all detected local and network drives and shows their storage usage graphically in the terminal.
lists all detected local and network drives and Shows mount point, filesystem type, device path,
UUID, label, mount options, used, available and inodes + SMART status (only as root).
.SH OPTIONS
.TP
+211 -5
View File
@@ -12,10 +12,12 @@
#include <sys/stat.h>
#include <dirent.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/types.h>
// Constants for terminal and display
#define TERM_FALLBACK_WIDTH 80
#define VERSION "1.0.2"
#define VERSION "1.0.4"
#define COLOR_BUFFER_SIZE 32
#define MAX_UNITS 5
#define BYTES_PER_KB 1024.0
@@ -82,7 +84,8 @@
const char *skip_filesystems[] = {
"proc", "sysfs", "devpts", "tmpfs", "devtmpfs", "securityfs",
"cgroup", "cgroup2", "pstore", "efivarfs", "autofs", "debugfs",
"tracefs", "configfs", "fusectl", "fuse.gvfsd-fuse", "binfmt_misc"};
"tracefs", "configfs", "fusectl", "fuse.gvfsd-fuse", "binfmt_misc",
"fuse.portal"};
// Structure to hold drive information
typedef struct
@@ -90,6 +93,8 @@ typedef struct
char mount_point[MAX_PATH_LENGTH];
char filesystem[MAX_SIZE_STR_LENGTH];
char device[MAX_PATH_LENGTH];
char uuid[128];
char label[128];
char total_str[MAX_SIZE_STR_LENGTH];
char used_str[MAX_SIZE_STR_LENGTH];
char available_str[MAX_SIZE_STR_LENGTH];
@@ -101,6 +106,10 @@ typedef struct
char *progress_bar;
bool is_cloud_storage;
char cloud_service_name[MAX_SIZE_STR_LENGTH];
char mount_options[MAX_TEMP_BUFFER_LENGTH];
unsigned long long total_inodes;
unsigned long long used_inodes;
double inode_usage;
} drive_info_t;
char colorbuf[COLOR_BUFFER_SIZE]; // For bar colors
@@ -310,6 +319,8 @@ void fill_drive_info(drive_info_t *drive,
const char *mount_point,
const char *filesystem,
const char *device,
const char *uuid,
const char *label,
const char *total_str,
const char *used_str,
const char *available_str,
@@ -320,7 +331,11 @@ void fill_drive_info(drive_info_t *drive,
const char *drive_type,
char *progress_bar,
bool is_cloud_storage,
const char *cloud_service_name)
const char *cloud_service_name,
const char *mount_options,
unsigned long long total_inodes,
unsigned long long used_inodes,
double inode_usage)
{
strncpy(drive->mount_point, mount_point, sizeof(drive->mount_point) - 1);
drive->mount_point[sizeof(drive->mount_point) - 1] = '\0';
@@ -328,6 +343,24 @@ void fill_drive_info(drive_info_t *drive,
drive->filesystem[sizeof(drive->filesystem) - 1] = '\0';
strncpy(drive->device, device, sizeof(drive->device) - 1);
drive->device[sizeof(drive->device) - 1] = '\0';
if (uuid)
{
strncpy(drive->uuid, uuid, sizeof(drive->uuid) - 1);
drive->uuid[sizeof(drive->uuid) - 1] = '\0';
}
else
{
drive->uuid[0] = '\0';
}
if (label)
{
strncpy(drive->label, label, sizeof(drive->label) - 1);
drive->label[sizeof(drive->label) - 1] = '\0';
}
else
{
drive->label[0] = '\0';
}
snprintf(drive->total_str, sizeof(drive->total_str), "%s", total_str);
snprintf(drive->used_str, sizeof(drive->used_str), "%s", used_str);
snprintf(drive->available_str, sizeof(drive->available_str), "%s", available_str);
@@ -347,6 +380,18 @@ void fill_drive_info(drive_info_t *drive,
{
drive->cloud_service_name[0] = '\0';
}
if (mount_options)
{
strncpy(drive->mount_options, mount_options, sizeof(drive->mount_options) - 1);
drive->mount_options[sizeof(drive->mount_options) - 1] = '\0';
}
else
{
drive->mount_options[0] = '\0';
}
drive->total_inodes = total_inodes;
drive->used_inodes = used_inodes;
drive->inode_usage = inode_usage;
}
// Function to get cloud storage info from GVFS
@@ -464,9 +509,12 @@ void get_cloud_storage_info(const char *gvfs_path, drive_info_t *drives, int *dr
// Store information in drive_info_t structure
drive_info_t *drive = &drives[*drive_count];
fill_drive_info(drive, full_path, "fuse.gvfsd-fuse", entry->d_name,
NULL, NULL,
total_str, used_str, available_str,
total_bytes, used_bytes, available_bytes,
usage_percent, "Network Drive", bar, true, service_name);
usage_percent, "Network Drive", bar, true, service_name, NULL,
(unsigned long long)fs_info.f_blocks, (unsigned long long)fs_info.f_files,
(double)fs_info.f_files / (double)fs_info.f_blocks);
(*drive_count)++;
}
@@ -475,6 +523,133 @@ void get_cloud_storage_info(const char *gvfs_path, drive_info_t *drives, int *dr
closedir(dir);
}
void get_uuid_and_label(const char *device, char *uuid, size_t uuid_size, char *label, size_t label_size)
{
uuid[0] = '\0';
label[0] = '\0';
char resolved_device[PATH_MAX];
if (!realpath(device, resolved_device))
{
// Wenn das Gerät nicht auflösbar ist, abbrechen
return;
}
// UUID suchen
DIR *uuid_dir = opendir("/dev/disk/by-uuid/");
if (uuid_dir)
{
struct dirent *entry;
char full_path[PATH_MAX];
char resolved_link[PATH_MAX];
while ((entry = readdir(uuid_dir)) != NULL)
{
if (entry->d_name[0] == '.')
continue;
snprintf(full_path, sizeof(full_path), "/dev/disk/by-uuid/%s", entry->d_name);
if (realpath(full_path, resolved_link))
{
if (strcmp(resolved_link, resolved_device) == 0)
{
strncpy(uuid, entry->d_name, uuid_size - 1);
uuid[uuid_size - 1] = '\0';
break;
}
}
}
closedir(uuid_dir);
}
// Label suchen
DIR *label_dir = opendir("/dev/disk/by-label/");
if (label_dir)
{
struct dirent *entry;
char full_path[PATH_MAX];
char resolved_link[PATH_MAX];
while ((entry = readdir(label_dir)) != NULL)
{
if (entry->d_name[0] == '.')
continue;
snprintf(full_path, sizeof(full_path), "/dev/disk/by-label/%s", entry->d_name);
if (realpath(full_path, resolved_link))
{
if (strcmp(resolved_link, resolved_device) == 0)
{
strncpy(label, entry->d_name, label_size - 1);
label[label_size - 1] = '\0';
break;
}
}
}
closedir(label_dir);
}
}
// Helper function: Query SMART status (only for root and physical devices)
void get_smart_status(const char *device, char *status, size_t status_size)
{
status[0] = '\0';
if (geteuid() != 0)
return;
// Allow all /dev/sd*, /dev/nvme*, /dev/hd* (including partitions)
if (!(
strncmp(device, "/dev/sd", 7) == 0 ||
strncmp(device, "/dev/nvme", 9) == 0 ||
strncmp(device, "/dev/hd", 7) == 0))
return;
char cmd[256], line[256];
snprintf(cmd, sizeof(cmd), "smartctl -H %s 2>/dev/null", device);
FILE *fp = popen(cmd, "r");
if (!fp)
return;
while (fgets(line, sizeof(line), fp))
{
if (strstr(line, "SMART overall-health self-assessment test result") || strstr(line, "SMART Health Status"))
{
char *p = strchr(line, ':');
if (p)
{
p++;
while (*p == ' ' || *p == '\t')
p++;
strncpy(status, p, status_size - 1);
status[status_size - 1] = '\0';
char *nl = strchr(status, '\n');
if (nl)
*nl = '\0';
break;
}
}
if (strstr(line, "PASSED"))
{
strncpy(status, "PASSED", status_size - 1);
status[status_size - 1] = '\0';
break;
}
if (strstr(line, "FAILED"))
{
strncpy(status, "FAILED", status_size - 1);
status[status_size - 1] = '\0';
break;
}
if (strstr(line, "UNKNOWN"))
{
strncpy(status, "UNKNOWN", status_size - 1);
status[status_size - 1] = '\0';
break;
}
if (strstr(line, "NOT AVAILABLE"))
{
strncpy(status, "NOT AVAILABLE", status_size - 1);
status[status_size - 1] = '\0';
break;
}
}
pclose(fp);
}
int main(int argc, char *argv[])
{
if (argc > 1)
@@ -560,6 +735,12 @@ int main(int argc, char *argv[])
format_bytes(used_bytes, used_str, sizeof(used_str));
format_bytes(available_bytes, available_str, sizeof(available_str));
// Inode-Infos
unsigned long long total_inodes = fs_info.f_files;
unsigned long long free_inodes = fs_info.f_favail;
unsigned long long used_inodes = total_inodes > 0 ? total_inodes - free_inodes : 0;
double inode_usage = (total_inodes > 0) ? ((double)used_inodes / total_inodes) * 100.0 : 0.0;
// Target width: 80% of terminal width or max. 120 characters
int terminal_width = get_terminal_width();
int box_width = terminal_width * TERMINAL_WIDTH_PERCENTAGE / TERMINAL_WIDTH_DIVISOR;
@@ -627,12 +808,18 @@ int main(int argc, char *argv[])
drive_type = "Other Drive";
}
// UUID und Label ermitteln
char uuid[128], label[128];
get_uuid_and_label(entry->mnt_fsname, uuid, sizeof(uuid), label, sizeof(label));
// Store information in drive_info_t structure
drive_info_t *drive = &drives[drive_count];
fill_drive_info(drive, entry->mnt_dir, entry->mnt_type, entry->mnt_fsname,
uuid, label,
total_str, used_str, available_str,
total_bytes, used_bytes, available_bytes,
usage_percent, drive_type, bar, false, NULL);
usage_percent, drive_type, bar, false, NULL, entry->mnt_opts,
total_inodes, used_inodes, inode_usage);
drive_count++;
}
@@ -667,9 +854,28 @@ int main(int argc, char *argv[])
printf(" Mount point: %s\n", drive->mount_point);
printf(" Filesystem: %s\n", drive->filesystem);
printf(" Device: %s\n", drive->device);
printf(" UUID: %s\n", drive->uuid[0] ? drive->uuid : "-");
printf(" Label: %s\n", drive->label[0] ? drive->label : "-");
printf(" Mount options: %s\n", drive->mount_options);
printf(" Total size: %s\n", drive->total_str);
printf(" Used: %s\n", drive->used_str);
printf(" Available: %s\n", drive->available_str);
printf(" Inodes: %llu/%llu (%.1f%% used)\n", drive->used_inodes, drive->total_inodes, drive->inode_usage);
// SMART status only for root and physical devices
if (geteuid() == 0 && !drive->is_cloud_storage && strcmp(drive->drive_type, "Local Drive") == 0)
{
char smart_status[128];
get_smart_status(drive->device, smart_status, sizeof(smart_status));
if (smart_status[0])
{
printf(" SMART: %s\n", smart_status);
}
else
{
printf(" SMART: No data\n");
}
}
// Progress bar
int terminal_width = get_terminal_width();
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

After

Width:  |  Height:  |  Size: 244 KiB