diff --git a/main.c b/main.c index eafdae8..a73f3ad 100644 --- a/main.c +++ b/main.c @@ -12,10 +12,69 @@ #include #include +// Constants for terminal and display #define TERM_FALLBACK_WIDTH 80 #define VERSION "1.0.0" +#define COLOR_BUFFER_SIZE 32 +#define MAX_UNITS 5 +#define BYTES_PER_KB 1024.0 +#define MAX_UNIT_INDEX 4 +#define PERCENTAGE_MULTIPLIER 100.0 +#define USAGE_PERCENT_DIVISOR 100.0 -char colorbuf[32]; // For bar colors +// Constants for device path lengths +#define DEV_SD_PREFIX_LEN 7 +#define DEV_NVME_PREFIX_LEN 9 +#define DEV_HD_PREFIX_LEN 7 +#define NETWORK_PATH_PREFIX_LEN 2 +#define FUSE_PREFIX_LEN 5 + +// Constants for file paths and buffers +#define MAX_PATH_LENGTH 1024 +#define MAX_GVFS_PATH_LENGTH 256 +#define MAX_SIZE_STR_LENGTH 64 +#define MAX_PERCENT_TEXT_LENGTH 16 +#define MAX_TEMP_BUFFER_LENGTH 128 +#define MAX_BAR_BUFFER_MULTIPLIER 64 +#define BARLINE_BUFFER_EXTRA 16 + +// Constants for terminal width calculations +#define TERMINAL_WIDTH_PERCENTAGE 80 +#define TERMINAL_WIDTH_DIVISOR 5 +#define MAX_BOX_WIDTH 120 +#define MIN_BOX_WIDTH 40 +#define FRAME_PADDING 4 +#define BRACKET_PADDING 2 +#define MIN_BAR_LENGTH 10 + +// Constants for color values +#define MAX_COLOR_VALUE 255 +#define COLOR_RATIO_MULTIPLIER 2 +#define COLOR_RATIO_HALF 0.5f +#define GRAY_BACKGROUND_R 64 +#define GRAY_BACKGROUND_G 64 +#define GRAY_BACKGROUND_B 64 +#define GRAY_FOREGROUND_R 160 +#define GRAY_FOREGROUND_G 160 +#define GRAY_FOREGROUND_B 160 +#define BLUE_TEXT_R 0 +#define BLUE_TEXT_G 0 +#define BLUE_TEXT_B 255 + +// Constants for string formatting +#define PERCENT_FORMAT "%.1f%%" +#define COLOR_FORMAT "\033[38;2;%d;%d;%dm" +#define BACKGROUND_COLOR_FORMAT "\033[48;2;%d;%d;%dm" +#define BLUE_TEXT_FORMAT "\033[38;2;%d;%d;%dm" +#define RESET_FORMAT "\033[0m" +#define BOLD_YELLOW_FORMAT "\033[1;33m" +#define RESET_COLOR_FORMAT "\033[0m" + +// Constants for file system types +#define MOUNT_TABLE_PATH "/proc/mounts" +#define GVFS_BASE_PATH "/run/user/%d/gvfs" + +char colorbuf[COLOR_BUFFER_SIZE]; // For bar colors // Function to display help text void show_help(const char *program_name) @@ -56,9 +115,9 @@ void format_bytes(unsigned long long bytes, char *buffer, size_t buffer_size) int unit_index = 0; double size = bytes; - while (size >= 1024.0 && unit_index < 4) + while (size >= BYTES_PER_KB && unit_index < MAX_UNIT_INDEX) { - size /= 1024.0; + size /= BYTES_PER_KB; unit_index++; } @@ -78,23 +137,23 @@ double calculate_usage_percent(unsigned long long total, unsigned long long avai if (total == 0) return 0.0; unsigned long long used = total - available; - return ((double)used / total) * 100.0; + return ((double)used / total) * PERCENTAGE_MULTIPLIER; } int is_physical_device(const char *fsname) { // Check for /dev/sd*, /dev/nvme*, /dev/hd* - return (strncmp(fsname, "/dev/sd", 7) == 0 || - strncmp(fsname, "/dev/nvme", 9) == 0 || - strncmp(fsname, "/dev/hd", 7) == 0); + return (strncmp(fsname, "/dev/sd", DEV_SD_PREFIX_LEN) == 0 || + strncmp(fsname, "/dev/nvme", DEV_NVME_PREFIX_LEN) == 0 || + strncmp(fsname, "/dev/hd", DEV_HD_PREFIX_LEN) == 0); } int is_network_device(const char *fsname) { // Check for network file systems - return (strncmp(fsname, "//", 2) == 0 || // SMB/CIFS shares - strncmp(fsname, "\\\\", 2) == 0 || // Windows network paths - strstr(fsname, ":") != NULL); // NFS and other network protocols + return (strncmp(fsname, "//", NETWORK_PATH_PREFIX_LEN) == 0 || // SMB/CIFS shares + strncmp(fsname, "\\\\", NETWORK_PATH_PREFIX_LEN) == 0 || // Windows network paths + strstr(fsname, ":") != NULL); // NFS and other network protocols } int is_network_filesystem(const char *fstype) @@ -107,8 +166,8 @@ int is_network_filesystem(const char *fstype) strcmp(fstype, "smb3") == 0 || strcmp(fstype, "fuse.sshfs") == 0 || strcmp(fstype, "fuse.rclone") == 0 || - strcmp(fstype, "fuse.gvfsd-fuse") == 0 || // GVFS for cloud storage - strncmp(fstype, "fuse.", 5) == 0); // Other FUSE-based network file systems + strcmp(fstype, "fuse.gvfsd-fuse") == 0 || // GVFS for cloud storage + strncmp(fstype, "fuse.", FUSE_PREFIX_LEN) == 0); // Other FUSE-based network file systems } int is_appimage_or_temp(const char *fsname, const char *mountpoint) @@ -125,21 +184,21 @@ void get_bar_color(int idx, int max, char *buffer, size_t size) // New gradient: 0% = green (0,255,0), 50% = yellow (255,255,0), 100% = red (255,0,0) float ratio = (float)idx / (float)(max - 1); int r, g, b; - if (ratio < 0.5f) + if (ratio < COLOR_RATIO_HALF) { // Green to Yellow - r = (int)(ratio * 2 * 255); - g = 255; + r = (int)(ratio * COLOR_RATIO_MULTIPLIER * MAX_COLOR_VALUE); + g = MAX_COLOR_VALUE; b = 0; } else { // Yellow to Red - r = 255; - g = (int)((1.0f - (ratio - 0.5f) * 2) * 255); + r = MAX_COLOR_VALUE; + g = (int)((1.0f - (ratio - COLOR_RATIO_HALF) * COLOR_RATIO_MULTIPLIER) * MAX_COLOR_VALUE); b = 0; } - snprintf(buffer, size, "\033[38;2;%d;%d;%dm", r, g, b); + snprintf(buffer, size, COLOR_FORMAT, r, g, b); } // Helper: visible length of a string without ANSI sequences @@ -186,7 +245,7 @@ int is_cloud_storage_directory(const char *path) { // Use stat if d_type is not available struct stat st; - char full_path[1024]; + char full_path[MAX_PATH_LENGTH]; snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode) && @@ -217,7 +276,7 @@ void get_cloud_storage_info(const char *gvfs_path, int *drive_count) { // Use stat if d_type is not available struct stat st; - char full_path[1024]; + char full_path[MAX_PATH_LENGTH]; snprintf(full_path, sizeof(full_path), "%s/%s", gvfs_path, entry->d_name); if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode) && @@ -240,33 +299,33 @@ void get_cloud_storage_info(const char *gvfs_path, int *drive_count) unsigned long long used_bytes = total_bytes - available_bytes; // Format sizes for output - char total_str[64], used_str[64], available_str[64]; + char total_str[MAX_SIZE_STR_LENGTH], used_str[MAX_SIZE_STR_LENGTH], available_str[MAX_SIZE_STR_LENGTH]; format_bytes(total_bytes, total_str, sizeof(total_str)); format_bytes(used_bytes, used_str, sizeof(used_str)); format_bytes(available_bytes, available_str, sizeof(available_str)); // Target width calculation (same as before) int terminal_width = get_terminal_width(); - int box_width = terminal_width * 4 / 5; - if (box_width > 120) - box_width = 120; - if (box_width < 40) - box_width = 40; - int content_width = box_width - 4; - int bar_length = content_width - 2; - if (bar_length < 10) - bar_length = 10; + int box_width = terminal_width * TERMINAL_WIDTH_PERCENTAGE / TERMINAL_WIDTH_DIVISOR; + if (box_width > MAX_BOX_WIDTH) + box_width = MAX_BOX_WIDTH; + if (box_width < MIN_BOX_WIDTH) + box_width = MIN_BOX_WIDTH; + int content_width = box_width - FRAME_PADDING; + int bar_length = content_width - BRACKET_PADDING; + if (bar_length < MIN_BAR_LENGTH) + bar_length = MIN_BAR_LENGTH; // Calculate usage double usage_percent = calculate_usage_percent(total_bytes, available_bytes); - int filled_length = (int)((usage_percent / 100.0) * bar_length); - char percent_text[16]; - snprintf(percent_text, sizeof(percent_text), "%.1f%%", usage_percent); + int filled_length = (int)((usage_percent / USAGE_PERCENT_DIVISOR) * bar_length); + char percent_text[MAX_PERCENT_TEXT_LENGTH]; + snprintf(percent_text, sizeof(percent_text), PERCENT_FORMAT, usage_percent); int text_length = strlen(percent_text); int text_start = filled_length > text_length ? (filled_length - text_length) / 2 : 0; // Create progress bar (same logic as before) - size_t bar_bufsize = bar_length * 64 + 1; + size_t bar_bufsize = bar_length * MAX_BAR_BUFFER_MULTIPLIER + 1; char *bar = malloc(bar_bufsize); if (!bar) { @@ -280,16 +339,16 @@ void get_cloud_storage_info(const char *gvfs_path, int *drive_count) { get_bar_color(i, bar_length, colorbuf, sizeof(colorbuf)); int r, g, b; - sscanf(colorbuf, "\033[38;2;%d;%d;%dm", &r, &g, &b); - char tmp[128]; - snprintf(tmp, sizeof(tmp), "\033[48;2;%d;%d;%dm\033[38;2;0;0;255m%c\033[0m", r, g, b, percent_text[i - text_start]); + sscanf(colorbuf, COLOR_FORMAT, &r, &g, &b); + char tmp[MAX_TEMP_BUFFER_LENGTH]; + snprintf(tmp, sizeof(tmp), BACKGROUND_COLOR_FORMAT BLUE_TEXT_FORMAT "%c" RESET_FORMAT, r, g, b, BLUE_TEXT_R, BLUE_TEXT_G, BLUE_TEXT_B, percent_text[i - text_start]); strncat(bar, tmp, bar_bufsize - strlen(bar) - 1); } else if (i < filled_length) { get_bar_color(i, bar_length, colorbuf, sizeof(colorbuf)); strncat(bar, colorbuf, bar_bufsize - strlen(bar) - 1); - strncat(bar, "█\033[0m", bar_bufsize - strlen(bar) - 1); + strncat(bar, "█" RESET_FORMAT, bar_bufsize - strlen(bar) - 1); } else { @@ -317,7 +376,7 @@ void get_cloud_storage_info(const char *gvfs_path, int *drive_count) } // Output - printf(" \033[1;33mNetwork Drive %d (%s)\033[0m\n", *drive_count + 1, service_name); + printf(" " BOLD_YELLOW_FORMAT "Network Drive %d (%s)" RESET_COLOR_FORMAT "\n", *drive_count + 1, service_name); printf(" Mount point: %s\n", full_path); printf(" Filesystem: %s\n", "fuse.gvfsd-fuse"); printf(" Device: %s\n", entry->d_name); @@ -355,7 +414,7 @@ int main(int argc, char *argv[]) printf("\n"); // Open the mount table - FILE *mtab = setmntent("/proc/mounts", "r"); + FILE *mtab = setmntent(MOUNT_TABLE_PATH, "r"); if (mtab == NULL) { perror("Error opening mount table"); @@ -416,33 +475,33 @@ int main(int argc, char *argv[]) unsigned long long used_bytes = total_bytes - available_bytes; // Format sizes for output - char total_str[64], used_str[64], available_str[64]; + char total_str[MAX_SIZE_STR_LENGTH], used_str[MAX_SIZE_STR_LENGTH], available_str[MAX_SIZE_STR_LENGTH]; format_bytes(total_bytes, total_str, sizeof(total_str)); format_bytes(used_bytes, used_str, sizeof(used_str)); format_bytes(available_bytes, available_str, sizeof(available_str)); // Target width: 80% of terminal width or max. 120 characters int terminal_width = get_terminal_width(); - int box_width = terminal_width * 4 / 5; - if (box_width > 120) - box_width = 120; - if (box_width < 40) - box_width = 40; - int content_width = box_width - 4; // for frame - int bar_length = content_width - 2; // for [ and ] - if (bar_length < 10) - bar_length = 10; + int box_width = terminal_width * TERMINAL_WIDTH_PERCENTAGE / TERMINAL_WIDTH_DIVISOR; + if (box_width > MAX_BOX_WIDTH) + box_width = MAX_BOX_WIDTH; + if (box_width < MIN_BOX_WIDTH) + box_width = MIN_BOX_WIDTH; + int content_width = box_width - FRAME_PADDING; // for frame + int bar_length = content_width - BRACKET_PADDING; // for [ and ] + if (bar_length < MIN_BAR_LENGTH) + bar_length = MIN_BAR_LENGTH; // Calculate usage double usage_percent = calculate_usage_percent(total_bytes, available_bytes); - int filled_length = (int)((usage_percent / 100.0) * bar_length); - char percent_text[16]; - snprintf(percent_text, sizeof(percent_text), "%.1f%%", usage_percent); + int filled_length = (int)((usage_percent / USAGE_PERCENT_DIVISOR) * bar_length); + char percent_text[MAX_PERCENT_TEXT_LENGTH]; + snprintf(percent_text, sizeof(percent_text), PERCENT_FORMAT, usage_percent); int text_length = strlen(percent_text); int text_start = filled_length > text_length ? (filled_length - text_length) / 2 : 0; // Dynamically allocate progress bar - size_t bar_bufsize = bar_length * 64 + 1; + size_t bar_bufsize = bar_length * MAX_BAR_BUFFER_MULTIPLIER + 1; char *bar = malloc(bar_bufsize); if (!bar) { @@ -456,23 +515,23 @@ int main(int argc, char *argv[]) { get_bar_color(i, bar_length, colorbuf, sizeof(colorbuf)); int r, g, b; - sscanf(colorbuf, "\033[38;2;%d;%d;%dm", &r, &g, &b); - char tmp[128]; - snprintf(tmp, sizeof(tmp), "\033[48;2;%d;%d;%dm\033[38;2;0;0;255m%c\033[0m", r, g, b, percent_text[i - text_start]); + sscanf(colorbuf, COLOR_FORMAT, &r, &g, &b); + char tmp[MAX_TEMP_BUFFER_LENGTH]; + snprintf(tmp, sizeof(tmp), BACKGROUND_COLOR_FORMAT BLUE_TEXT_FORMAT "%c" RESET_FORMAT, r, g, b, BLUE_TEXT_R, BLUE_TEXT_G, BLUE_TEXT_B, percent_text[i - text_start]); strncat(bar, tmp, bar_bufsize - strlen(bar) - 1); } else if (i < filled_length) { get_bar_color(i, bar_length, colorbuf, sizeof(colorbuf)); strncat(bar, colorbuf, bar_bufsize - strlen(bar) - 1); - strncat(bar, "█\033[0m", bar_bufsize - strlen(bar) - 1); + strncat(bar, "█" RESET_FORMAT, bar_bufsize - strlen(bar) - 1); } else { strncat(bar, "\033[48;2;64;64;64m\033[38;2;160;160;160m░\033[0m", bar_bufsize - strlen(bar) - 1); } } - size_t barline_bufsize = bar_bufsize + 16; + size_t barline_bufsize = bar_bufsize + BARLINE_BUFFER_EXTRA; char *barline = malloc(barline_bufsize); if (!barline) { @@ -497,7 +556,7 @@ int main(int argc, char *argv[]) { drive_type = "Other Drive"; } - printf(" \033[1;33m%s %d\033[0m\n", drive_type, drive_count + 1); + printf(" " BOLD_YELLOW_FORMAT "%s %d" RESET_COLOR_FORMAT "\n", drive_type, drive_count + 1); printf(" Mount point: %s\n", entry->mnt_dir); printf(" Filesystem: %s\n", entry->mnt_type); printf(" Device: %s\n", entry->mnt_fsname); @@ -517,8 +576,8 @@ int main(int argc, char *argv[]) endmntent(mtab); // Check for GVFS-based cloud storage - char gvfs_path[256]; - snprintf(gvfs_path, sizeof(gvfs_path), "/run/user/%d/gvfs", getuid()); + char gvfs_path[MAX_GVFS_PATH_LENGTH]; + snprintf(gvfs_path, sizeof(gvfs_path), GVFS_BASE_PATH, getuid()); if (is_cloud_storage_directory(gvfs_path)) { get_cloud_storage_info(gvfs_path, &drive_count);