diff --git a/otp.c b/otp.c index 9901c65..1212c2a 100644 --- a/otp.c +++ b/otp.c @@ -61,464 +61,6 @@ static int is_interactive_mode = 0; // MAIN //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// NEW SIMPLIFIED USB DETECTION SYSTEM v2 -// Uses lsusb cross-referencing for reliable USB device identification -//////////////////////////////////////////////////////////////////////////////// - -/** - * Decode octal escape sequences in mount paths (e.g., \040 for space) - * Used by the new v2 USB detection system - */ -void decode_octal_escapes(const char* input, char* output, size_t output_size) { - if (!input || !output || output_size == 0) return; - - size_t src = 0, dst = 0; - size_t input_len = strlen(input); - - while (src < input_len && dst < output_size - 1) { - if (input[src] == '\\' && src + 3 < input_len && - input[src + 1] >= '0' && input[src + 1] <= '7' && - input[src + 2] >= '0' && input[src + 2] <= '7' && - input[src + 3] >= '0' && input[src + 3] <= '7') { - // Decode octal escape sequence - int octal_val = (input[src + 1] - '0') * 64 + - (input[src + 2] - '0') * 8 + - (input[src + 3] - '0'); - output[dst++] = (char)octal_val; - src += 4; - } else { - output[dst++] = input[src++]; - } - } - output[dst] = '\0'; -} - -/** - * Build USB device registry by parsing lsusb output - * Returns array of USB devices found on system - */ -int build_usb_device_registry(usb_device_registry_t **devices, int *device_count) { - if (!devices || !device_count) return 0; - - *devices = NULL; - *device_count = 0; - - // Execute lsusb command and capture output - FILE *lsusb_pipe = popen("lsusb", "r"); - if (!lsusb_pipe) { - fprintf(stderr, "Error: Failed to execute lsusb command\n"); - return 0; - } - - // Allocate initial array for USB devices - int capacity = 16; - usb_device_registry_t *registry = malloc(capacity * sizeof(usb_device_registry_t)); - if (!registry) { - pclose(lsusb_pipe); - return 0; - } - - char line[512]; - int count = 0; - - // Parse each line of lsusb output - // Format: "Bus 001 Device 003: ID 0781:5583 SanDisk Corp. Ultra Fit" - while (fgets(line, sizeof(line), lsusb_pipe)) { - // Expand array if needed - if (count >= capacity) { - capacity *= 2; - usb_device_registry_t *new_registry = realloc(registry, capacity * sizeof(usb_device_registry_t)); - if (!new_registry) { - free(registry); - pclose(lsusb_pipe); - return 0; - } - registry = new_registry; - } - - usb_device_registry_t *device = ®istry[count]; - memset(device, 0, sizeof(usb_device_registry_t)); - - // Parse: "Bus 001 Device 003: ID 0781:5583 SanDisk Corp. Ultra Fit" - char *pos = line; - - // Extract bus number - if (sscanf(pos, "Bus %3s", device->bus_number) != 1) continue; - pos = strstr(pos, "Device "); - if (!pos) continue; - - // Extract device number - pos += 7; // Skip "Device " - if (sscanf(pos, "%3s", device->device_number) != 1) continue; - - // Find ID field - pos = strstr(pos, "ID "); - if (!pos) continue; - pos += 3; // Skip "ID " - - // Extract vendor:product IDs - if (sscanf(pos, "%7[^:]:%7s", device->vendor_id, device->product_id) != 2) continue; - - // Find start of vendor/product names after ID - pos = strchr(pos, ' '); - if (!pos) continue; - pos++; // Skip space - - // Extract vendor and product names (rest of line) - char *newline = strchr(pos, '\n'); - if (newline) *newline = '\0'; - - // Split vendor and product names - // Look for common patterns like "Corp.", "Inc.", "Ltd." - char *vendor_end = strstr(pos, " Corp."); - if (!vendor_end) vendor_end = strstr(pos, " Inc."); - if (!vendor_end) vendor_end = strstr(pos, " Ltd."); - if (!vendor_end) vendor_end = strstr(pos, " Co."); - - if (vendor_end) { - // Include the company suffix - if (strstr(vendor_end, " Corp.")) vendor_end += 6; - else if (strstr(vendor_end, " Inc.")) vendor_end += 5; - else if (strstr(vendor_end, " Ltd.")) vendor_end += 5; - else if (strstr(vendor_end, " Co.")) vendor_end += 4; - - size_t vendor_len = vendor_end - pos; - if (vendor_len >= sizeof(device->vendor_name)) vendor_len = sizeof(device->vendor_name) - 1; - strncpy(device->vendor_name, pos, vendor_len); - device->vendor_name[vendor_len] = '\0'; - - // Product name is what remains after vendor - char *product_start = vendor_end; - while (*product_start == ' ') product_start++; // Skip spaces - strncpy(device->product_name, product_start, sizeof(device->product_name) - 1); - } else { - // Fallback: split at first word boundary after reasonable vendor length - char *space = strchr(pos + 8, ' '); // Look for space after ~8 chars - if (space) { - size_t vendor_len = space - pos; - if (vendor_len >= sizeof(device->vendor_name)) vendor_len = sizeof(device->vendor_name) - 1; - strncpy(device->vendor_name, pos, vendor_len); - device->vendor_name[vendor_len] = '\0'; - - strncpy(device->product_name, space + 1, sizeof(device->product_name) - 1); - } else { - // Single word - treat as vendor - strncpy(device->vendor_name, pos, sizeof(device->vendor_name) - 1); - strcpy(device->product_name, "Unknown"); - } - } - - count++; - } - - pclose(lsusb_pipe); - - *devices = registry; - *device_count = count; - return 1; -} - -/** - * Free USB device registry memory - */ -void free_usb_device_registry(usb_device_registry_t *devices) { - if (devices) { - free(devices); - } -} - -/** - * Find USB device in registry by matching device path to USB bus info - * Maps /dev/sdX to USB device via /sys/block/sdX/device tree - */ -usb_device_registry_t* find_usb_device_by_path(const char* device_path, - usb_device_registry_t* usb_devices, int usb_count) { - if (!device_path || !usb_devices || usb_count <= 0) return NULL; - - // Extract device name from path: /dev/sda1 -> sda - char device_name[16]; - const char *dev_start = strrchr(device_path, '/'); - if (!dev_start) dev_start = device_path; - else dev_start++; // Skip '/' - - // Copy device name, removing partition number - strncpy(device_name, dev_start, sizeof(device_name) - 1); - device_name[sizeof(device_name) - 1] = '\0'; - - // Remove partition number (digits at end) - char *digit_pos = device_name; - while (*digit_pos && !isdigit(*digit_pos)) digit_pos++; - if (*digit_pos) *digit_pos = '\0'; // Truncate at first digit - - // Read vendor and product info from sysfs - char vendor_path[256], product_path[256]; - char model_path[256], manufacturer_path[256]; - snprintf(vendor_path, sizeof(vendor_path), "/sys/block/%s/device/vendor", device_name); - snprintf(product_path, sizeof(product_path), "/sys/block/%s/device/model", device_name); - snprintf(manufacturer_path, sizeof(manufacturer_path), "/sys/block/%s/device/manufacturer", device_name); - snprintf(model_path, sizeof(model_path), "/sys/block/%s/device/product", device_name); - - // Try to read device info from multiple possible sysfs locations - char vendor_info[64] = {0}, product_info[64] = {0}; - FILE *fp; - - // Try vendor file - fp = fopen(vendor_path, "r"); - if (fp) { - fgets(vendor_info, sizeof(vendor_info), fp); - fclose(fp); - // Trim whitespace - char *end = vendor_info + strlen(vendor_info) - 1; - while (end > vendor_info && isspace(*end)) *end-- = '\0'; - } - - // Try product/model file - fp = fopen(product_path, "r"); - if (!fp) fp = fopen(model_path, "r"); - if (fp) { - fgets(product_info, sizeof(product_info), fp); - fclose(fp); - // Trim whitespace - char *end = product_info + strlen(product_info) - 1; - while (end > product_info && isspace(*end)) *end-- = '\0'; - } - - // If we couldn't get device info from sysfs, check if it's in common USB mount locations - if (strlen(vendor_info) == 0 && strlen(product_info) == 0) { - // For devices in /media/ or /mnt/, assume they could be USB and do partial matching - // This handles cases where sysfs info isn't available - return usb_count > 0 ? &usb_devices[0] : NULL; // Return first USB device as fallback - } - - // Try to match vendor/product info with USB device registry - for (int i = 0; i < usb_count; i++) { - usb_device_registry_t *usb_dev = &usb_devices[i]; - - // Try partial string matching for vendor names - if (strlen(vendor_info) > 0 && strlen(usb_dev->vendor_name) > 0) { - if (strstr(usb_dev->vendor_name, vendor_info) || strstr(vendor_info, usb_dev->vendor_name)) { - return usb_dev; - } - } - - // Try partial string matching for product names - if (strlen(product_info) > 0 && strlen(usb_dev->product_name) > 0) { - if (strstr(usb_dev->product_name, product_info) || strstr(product_info, usb_dev->product_name)) { - return usb_dev; - } - } - } - - return NULL; // No USB device found for this path -} - -/** - * Get user-friendly status string for USB safety status - */ -const char* get_usb_status_string(usb_safety_status_t status) { - switch (status) { - case USB_SAFE: return "SAFE"; - case USB_TOO_LARGE: return "TOO_LARGE"; - case USB_NOT_USB: return "NOT_USB"; - default: return "UNKNOWN"; - } -} - -/** - * Detect drive information using new simplified v2 system - * Cross-references with USB device registry for validation - */ -int detect_drive_info_v2(const char* mount_path, drive_info_v2_t* drive_info, - usb_device_registry_t* usb_devices, int usb_count) { - if (!mount_path || !drive_info) return 0; - - // Initialize drive info structure - memset(drive_info, 0, sizeof(drive_info_v2_t)); - strncpy(drive_info->mount_path, mount_path, sizeof(drive_info->mount_path) - 1); - - // Get device path using existing working Method 1 from get_usb_drive_info - FILE* mounts_file = fopen("/proc/mounts", "r"); - if (!mounts_file) return 0; - - char line[1024]; - int device_found = 0; - char device_path[256] = {0}; - - while (fgets(line, sizeof(line), mounts_file)) { - char source_field[256], mount_field[256], fs_type[64]; - if (sscanf(line, "%255s %255s %63s", source_field, mount_field, fs_type) == 3) { - // Decode octal escape sequences in mount path - char decoded_mount[512]; - decode_octal_escapes(mount_field, decoded_mount, sizeof(decoded_mount)); - - if (strcmp(decoded_mount, mount_path) == 0) { - strncpy(device_path, source_field, sizeof(device_path) - 1); - strncpy(drive_info->filesystem, fs_type, sizeof(drive_info->filesystem) - 1); - device_found = 1; - break; - } - } - } - fclose(mounts_file); - - if (!device_found) return 0; - - // CRITICAL FIX: Filter out internal encrypted drives (luks/mapper devices) - if (strstr(device_path, "/dev/mapper/") || strstr(device_path, "luks-")) { - return 0; // Skip internal encrypted drives - these are not USB devices - } - - // Store device path and extract device name - strncpy(drive_info->device_path, device_path, sizeof(drive_info->device_path) - 1); - - const char *dev_start = strrchr(device_path, '/'); - if (dev_start) dev_start++; else dev_start = device_path; - - char temp_name[16]; - strncpy(temp_name, dev_start, sizeof(temp_name) - 1); - temp_name[sizeof(temp_name) - 1] = '\0'; - - // Remove partition number to get base device name - char *digit_pos = temp_name; - while (*digit_pos && !isdigit(*digit_pos)) digit_pos++; - if (*digit_pos) *digit_pos = '\0'; - - strncpy(drive_info->device_name, temp_name, sizeof(drive_info->device_name) - 1); - - // ENHANCED FIX: Validate USB connectivity using sysfs path check - char sysfs_path[512]; - char link_target[512]; - snprintf(sysfs_path, sizeof(sysfs_path), "/sys/block/%s", drive_info->device_name); - - ssize_t link_len = readlink(sysfs_path, link_target, sizeof(link_target) - 1); - if (link_len > 0) { - link_target[link_len] = '\0'; - // Check if the device path contains 'usb' - genuine USB devices have USB paths - if (!strstr(link_target, "/usb")) { - return 0; // Skip non-USB devices based on sysfs path validation - } - } else { - return 0; // Skip devices without valid sysfs paths - } - - // Extract label from mount path - const char *label_start = strrchr(mount_path, '/'); - if (label_start) { - label_start++; // Skip '/' - strncpy(drive_info->label, label_start, sizeof(drive_info->label) - 1); - } - - // Get filesystem stats for sizes - struct statvfs vfs_stat; - if (statvfs(mount_path, &vfs_stat) == 0) { - drive_info->total_size = (uint64_t)vfs_stat.f_blocks * vfs_stat.f_frsize; - drive_info->free_size = (uint64_t)vfs_stat.f_bavail * vfs_stat.f_frsize; - } - - // Count .pad files on drive - DIR *dir = opendir(mount_path); - if (dir) { - struct dirent *entry; - while ((entry = readdir(dir))) { - if (strstr(entry->d_name, ".pad")) { - drive_info->pad_count++; - } - } - closedir(dir); - } - - // Cross-reference with USB device registry - drive_info->usb_device = find_usb_device_by_path(device_path, usb_devices, usb_count); - - // Determine safety status - if (drive_info->usb_device) { - // Found in USB registry - check size limits - if (drive_info->total_size > (6ULL * 1024 * 1024 * 1024 * 1024)) { // 6TB limit - drive_info->status = USB_TOO_LARGE; - } else { - drive_info->status = USB_SAFE; - } - } else { - drive_info->status = USB_NOT_USB; - } - - return 1; -} - -/** - * New simplified USB drive listing function - * Replaces the complex list_usb_drives with lsusb cross-referencing - */ -void list_usb_drives_v2(void) { - // Build USB device registry from lsusb - usb_device_registry_t *usb_devices = NULL; - int usb_count = 0; - - if (!build_usb_device_registry(&usb_devices, &usb_count)) { - printf("Error: Failed to build USB device registry\n"); - return; - } - - // Parse mounted drives from /proc/mounts - FILE* mounts_file = fopen("/proc/mounts", "r"); - if (!mounts_file) { - printf("Error: Cannot read /proc/mounts\n"); - free_usb_device_registry(usb_devices); - return; - } - - drive_info_v2_t drives[MAX_USB_DRIVES]; - int drive_count = 0; - - char line[1024]; - while (fgets(line, sizeof(line), mounts_file) && drive_count < MAX_USB_DRIVES) { - char mount_point[512]; - if (sscanf(line, "%*s %511s", mount_point) == 1) { - // Decode octal escapes - char decoded_mount[512]; - decode_octal_escapes(mount_point, decoded_mount, sizeof(decoded_mount)); - - // Only check drives in common user mount locations - if (strstr(decoded_mount, "/media/") || strstr(decoded_mount, "/mnt/")) { - drive_info_v2_t drive_info; - if (detect_drive_info_v2(decoded_mount, &drive_info, usb_devices, usb_count)) { - drives[drive_count] = drive_info; - drive_count++; - } - } - } - } - fclose(mounts_file); - - // Display results - if (drive_count == 0) { - printf("No drives found in /media/ or /mnt/ locations.\n"); - } else { - printf("%-20s %-10s %-12s %-12s %-8s %-4s %-30s\n", - "Label", "Type", "Total", "Free", "FS", "Pads", "Mount Path"); - printf("%-20s %-10s %-12s %-12s %-8s %-4s %-30s\n", - "--------------------", "----------", "------------", "------------", - "--------", "----", "------------------------------"); - - for (int i = 0; i < drive_count; i++) { - drive_info_v2_t *drive = &drives[i]; - - char total_str[32], free_str[32]; - format_size_string(drive->total_size, total_str, sizeof(total_str)); - format_size_string(drive->free_size, free_str, sizeof(free_str)); - - const char *type = drive->usb_device ? "USB" : "Local"; - - printf("%-20s %-10s %-12s %-12s %-8s %-4d %-30s\n", - drive->label, type, total_str, free_str, drive->filesystem, - drive->pad_count, drive->mount_path); - } - } - - free_usb_device_registry(usb_devices); -} - int main(int argc, char* argv[]) { // Load preferences first @@ -732,48 +274,6 @@ int command_line_mode(int argc, char* argv[]) { } return 0; } - else if (strcmp(argv[1], "usb-list") == 0) { - list_usb_drives_v2(); - return 0; - } - else if (strcmp(argv[1], "usb-list-v2") == 0) { - list_usb_drives_v2(); - return 0; - } - else if (strcmp(argv[1], "usb-init") == 0) { - if (argc < 3) { - printf("Usage: %s usb-init [drive_path]\n", argv[0]); - printf("Examples:\n"); - printf(" %s usb-init OTP_BACKUP (interactive drive selection)\n", argv[0]); - printf(" %s usb-init OTP_BACKUP /media/user/USB_DRIVE\n", argv[0]); - return 1; - } - return handle_usb_init_cli(argc, argv); - } - else if (strcmp(argv[1], "usb-copy") == 0) { - if (argc < 4) { - printf("Usage: %s usb-copy \n", argv[0]); - printf("Example: %s usb-copy 1a2b3c /media/user/OTP_BACKUP\n", argv[0]); - return 1; - } - return handle_usb_copy_cli(argv[2], argv[3]); - } - else if (strcmp(argv[1], "usb-import") == 0) { - if (argc < 4) { - printf("Usage: %s usb-import \n", argv[0]); - printf("Example: %s usb-import 1a2b3c4d... /media/user/OTP_BACKUP\n", argv[0]); - return 1; - } - return handle_usb_import_cli(argv[2], argv[3]); - } - else if (strcmp(argv[1], "usb-verify") == 0) { - if (argc < 3) { - printf("Usage: %s usb-verify \n", argv[0]); - printf("Example: %s usb-verify /media/user/OTP_BACKUP\n", argv[0]); - return 1; - } - return handle_usb_verify_cli(argv[2]); - } else { print_usage(argv[0]); return 1; @@ -2684,894 +2184,29 @@ int detect_otp_thumb_drive(char* otp_drive_path, size_t path_size) { return 0; // No OTP drive found } -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// USB DRIVE MANAGEMENT FUNCTIONS -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// USB Device Safety Functions -int is_device_removable_usb(const char* device_path) { - char removable_path[512]; - FILE* file; - char value; - - // Extract device name from path (e.g., /dev/sdb -> sdb) - const char* device_name = strrchr(device_path, '/'); - if (!device_name) return 0; - device_name++; // Skip the '/' - - // Remove partition number if present (e.g., sdb1 -> sdb) - char base_device[64]; - strncpy(base_device, device_name, sizeof(base_device) - 1); - base_device[sizeof(base_device) - 1] = '\0'; - - // Remove digits at the end to get base device name - int len = strlen(base_device); - while (len > 0 && isdigit(base_device[len - 1])) { - base_device[len - 1] = '\0'; - len--; - } - - // Check if device is marked as removable - snprintf(removable_path, sizeof(removable_path), "/sys/block/%s/removable", base_device); - file = fopen(removable_path, "r"); - if (!file) return 0; - - if (fread(&value, 1, 1, file) != 1 || value != '1') { - fclose(file); - return 0; - } - fclose(file); - - return 1; -} - -int get_device_bus_type(const char* device_path, char* bus_type, size_t bus_type_size) { - char sys_path[512]; - char link_target[512]; - ssize_t link_len; - - // Extract device name from path - const char* device_name = strrchr(device_path, '/'); - if (!device_name) return 0; - device_name++; // Skip the '/' - - // Remove partition number if present - char base_device[64]; - strncpy(base_device, device_name, sizeof(base_device) - 1); - base_device[sizeof(base_device) - 1] = '\0'; - - int len = strlen(base_device); - while (len > 0 && isdigit(base_device[len - 1])) { - base_device[len - 1] = '\0'; - len--; - } - - // Read the device symlink to determine bus type - snprintf(sys_path, sizeof(sys_path), "/sys/block/%s/device", base_device); - link_len = readlink(sys_path, link_target, sizeof(link_target) - 1); - if (link_len == -1) return 0; - - link_target[link_len] = '\0'; - - // Check for USB in the path - if (strstr(link_target, "usb")) { - strncpy(bus_type, "usb", bus_type_size - 1); - bus_type[bus_type_size - 1] = '\0'; - return 1; - } - - // Check for other bus types - if (strstr(link_target, "ata") || strstr(link_target, "scsi")) { - strncpy(bus_type, "ata", bus_type_size - 1); - bus_type[bus_type_size - 1] = '\0'; - return 1; - } - - strncpy(bus_type, "unknown", bus_type_size - 1); - bus_type[bus_type_size - 1] = '\0'; - return 1; -} - -int is_system_critical_mount(const char* mount_path) { - // List of critical system mount points that should never be formatted - const char* critical_mounts[] = { - "/", "/boot", "/boot/efi", "/home", "/usr", "/var", "/tmp", "/opt", - "/etc", "/lib", "/lib64", "/bin", "/sbin", "/sys", "/proc", "/dev" - }; - - const int num_critical_mounts = sizeof(critical_mounts) / sizeof(critical_mounts[0]); - - for (int i = 0; i < num_critical_mounts; i++) { - if (strcmp(mount_path, critical_mounts[i]) == 0) { - return 1; // This is a critical system mount - } - } - - return 0; // Not a critical system mount -} - -int validate_usb_device_safety(const usb_drive_info_t* drive) { - // Check if it's a system critical mount - if (is_system_critical_mount(drive->mount_path)) { - return 0; // Not safe - system critical - } - - // Check if device is removable - if (!drive->is_removable) { - return 0; // Not safe - not removable - } - - // Check if it's actually a USB device - if (!drive->is_usb_device) { - return 0; // Not safe - not USB - } - - // Check if bus type is USB - if (strcmp(drive->bus_type, "usb") != 0) { - return 0; // Not safe - not USB bus - } - - // Check drive size limit (1.1 TB = 1.1 * 1024^4 bytes) - const uint64_t max_drive_size = 1100ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL / 1000ULL; // 1.1 TB - if (drive->total_size > max_drive_size) { - return 0; // Not safe - drive too large (safety limit) - } - - return 1; // Safe for USB operations -} - -// Generate safety status letters for detailed failure reporting -void get_usb_safety_status(const usb_drive_info_t* drive, char* status, size_t status_size) { - if (!drive || !status || status_size < 6) { - if (status && status_size > 0) { - strncpy(status, "ERROR", status_size - 1); - status[status_size - 1] = '\0'; - } - return; - } - - // Check if all safety tests pass - if (validate_usb_device_safety(drive)) { - strncpy(status, "SAFE", status_size - 1); - status[status_size - 1] = '\0'; - return; - } - - // Build failure status with letters - char failures[6] = {0}; // Max 5 failure letters + null terminator - int failure_count = 0; - - // C - Critical Mount Check - if (is_system_critical_mount(drive->mount_path)) { - failures[failure_count++] = 'C'; - } - - // R - Removable Device Check - if (!drive->is_removable) { - failures[failure_count++] = 'R'; - } - - // U - USB Device Check - if (!drive->is_usb_device) { - failures[failure_count++] = 'U'; - } - - // B - Bus Type Validation - if (strcmp(drive->bus_type, "usb") != 0) { - failures[failure_count++] = 'B'; - } - - // S - Size Limit Check - const uint64_t max_drive_size = 1100ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL / 1000ULL; // 1.1 TB - if (drive->total_size > max_drive_size) { - failures[failure_count++] = 'S'; - } - - // Copy failure letters to status - if (failure_count > 0) { - strncpy(status, failures, status_size - 1); - status[status_size - 1] = '\0'; - } else { - // Shouldn't happen, but fallback - strncpy(status, "UNK", status_size - 1); - status[status_size - 1] = '\0'; - } -} - -int extract_device_name_from_path(const char* device_path, char* device_name, size_t device_name_size) { - const char* name_start = strrchr(device_path, '/'); - if (!name_start) return 0; - - name_start++; // Skip the '/' - strncpy(device_name, name_start, device_name_size - 1); - device_name[device_name_size - 1] = '\0'; - - return 1; -} -// Discover all available USB drives on the system -int discover_usb_drives(usb_drive_info_t** drives, int* drive_count) { - if (!drives || !drive_count) { - return 1; // Error: invalid parameters - } - - // Initialize output - *drives = NULL; - *drive_count = 0; - - // Allocate array for USB drive information - usb_drive_info_t* drive_array = malloc(MAX_USB_DRIVES * sizeof(usb_drive_info_t)); - if (!drive_array) { - return 2; // Error: memory allocation failed - } - - int found_count = 0; - const char* mount_dirs[] = {"/media", "/run/media", "/mnt", NULL}; - - // Search through common mount directories - for (int mount_idx = 0; mount_dirs[mount_idx] != NULL && found_count < MAX_USB_DRIVES; mount_idx++) { - DIR* mount_dir = opendir(mount_dirs[mount_idx]); - if (!mount_dir) continue; - - struct dirent* mount_entry; - while ((mount_entry = readdir(mount_dir)) != NULL && found_count < MAX_USB_DRIVES) { - if (mount_entry->d_name[0] == '.') continue; - - char mount_path[1024]; - snprintf(mount_path, sizeof(mount_path), "%s/%s", mount_dirs[mount_idx], mount_entry->d_name); - - // Handle different mount directory structures - if (strcmp(mount_dirs[mount_idx], "/media") == 0) { - // /media/[username] - look inside for drives - DIR* user_dir = opendir(mount_path); - if (!user_dir) continue; - - struct dirent* user_entry; - while ((user_entry = readdir(user_dir)) != NULL && found_count < MAX_USB_DRIVES) { - if (user_entry->d_name[0] == '.') continue; - - char drive_path[2048]; - snprintf(drive_path, sizeof(drive_path), "%s/%s", mount_path, user_entry->d_name); - - // Check if this is a readable directory (mounted drive) - DIR* drive_dir = opendir(drive_path); - if (drive_dir) { - closedir(drive_dir); - - // Get drive information - include ALL drives for debugging - usb_drive_info_t* drive = &drive_array[found_count]; - if (get_usb_drive_info(drive_path, user_entry->d_name, drive) == 0) { - // Store safety validation result in the drive structure - drive->is_safe = validate_usb_device_safety(drive); - found_count++; - } - } - } - closedir(user_dir); - - } else if (strcmp(mount_dirs[mount_idx], "/run/media") == 0) { - // /run/media/[username] - look inside for drives - DIR* user_dir = opendir(mount_path); - if (!user_dir) continue; - - struct dirent* user_entry; - while ((user_entry = readdir(user_dir)) != NULL && found_count < MAX_USB_DRIVES) { - if (user_entry->d_name[0] == '.') continue; - - char drive_path[2048]; - snprintf(drive_path, sizeof(drive_path), "%s/%s", mount_path, user_entry->d_name); - - DIR* drive_dir = opendir(drive_path); - if (drive_dir) { - closedir(drive_dir); - - usb_drive_info_t* drive = &drive_array[found_count]; - if (get_usb_drive_info(drive_path, user_entry->d_name, drive) == 0) { - // Store safety validation result in the drive structure - drive->is_safe = validate_usb_device_safety(drive); - found_count++; - } - } - } - closedir(user_dir); - - } else { - // Direct mount point (like /mnt/DRIVE_NAME) - DIR* drive_dir = opendir(mount_path); - if (drive_dir) { - closedir(drive_dir); - - usb_drive_info_t* drive = &drive_array[found_count]; - if (get_usb_drive_info(mount_path, mount_entry->d_name, drive) == 0) { - // Store safety validation result in the drive structure - drive->is_safe = validate_usb_device_safety(drive); - found_count++; - } - } - } - } - closedir(mount_dir); - } - - if (found_count == 0) { - free(drive_array); - return 3; // Error: no drives found - } - - // Resize array to actual count - usb_drive_info_t* final_array = realloc(drive_array, found_count * sizeof(usb_drive_info_t)); - if (!final_array) { - // Keep original array if realloc fails - final_array = drive_array; - } - - *drives = final_array; - *drive_count = found_count; - - return 0; // Success -} - -// Get detailed information about a USB drive -int get_usb_drive_info(const char* mount_path, const char* drive_label, usb_drive_info_t* drive_info) { - if (!mount_path || !drive_label || !drive_info) { - return 1; - } - - // Initialize drive info structure - memset(drive_info, 0, sizeof(usb_drive_info_t)); - - // Set basic information - strncpy(drive_info->mount_path, mount_path, sizeof(drive_info->mount_path) - 1); - strncpy(drive_info->volume_label, drive_label, sizeof(drive_info->volume_label) - 1); - - // Check if it's an OTP drive (label starts with "OTP_") - drive_info->is_otp_drive = (strncmp(drive_label, "OTP_", 4) == 0); - - // Enhanced device path detection with multiple methods - char device_path[256] = ""; - int device_found = 0; - - // Method 1: Enhanced /proc/mounts parsing - FILE* mounts = fopen("/proc/mounts", "r"); - if (mounts) { - char line[1024]; - while (fgets(line, sizeof(line), mounts)) { - char device[256], mountpoint[512], fstype[64]; - // Use more robust parsing that handles escaped characters - if (sscanf(line, "%255s %511s %63s", device, mountpoint, fstype) == 3) { - // Handle escaped characters in mount paths (octal sequences like \040 for space) - char decoded_mountpoint[512]; - size_t src = 0, dst = 0; - size_t mountpoint_len = strlen(mountpoint); - while (src < mountpoint_len && dst < sizeof(decoded_mountpoint) - 1) { - if (mountpoint[src] == '\\' && src + 3 < mountpoint_len && - mountpoint[src + 1] >= '0' && mountpoint[src + 1] <= '7') { - // Decode octal escape sequence - int octal_val = (mountpoint[src + 1] - '0') * 64 + - (mountpoint[src + 2] - '0') * 8 + - (mountpoint[src + 3] - '0'); - decoded_mountpoint[dst++] = (char)octal_val; - src += 4; - } else { - decoded_mountpoint[dst++] = mountpoint[src++]; - } - } - decoded_mountpoint[dst] = '\0'; - - // Debug: Print comparison details for DUAL DRIVE debugging - if (strstr(mount_path, "DUAL DRIVE") || strstr(decoded_mountpoint, "DUAL DRIVE")) { - printf("DEBUG Method1: mount_path='%s', decoded='%s', device='%s', match=%d\n", - mount_path, decoded_mountpoint, device, - strcmp(decoded_mountpoint, mount_path) == 0); - } - - if (strcmp(decoded_mountpoint, mount_path) == 0) { - strncpy(device_path, device, sizeof(device_path) - 1); - device_path[sizeof(device_path) - 1] = '\0'; - strncpy(drive_info->filesystem, fstype, sizeof(drive_info->filesystem) - 1); - drive_info->filesystem[sizeof(drive_info->filesystem) - 1] = '\0'; - device_found = 1; - break; - } - } - } - fclose(mounts); - } - - // Method 2: Try /proc/self/mountinfo for more detailed information - if (!device_found) { - FILE* mountinfo = fopen("/proc/self/mountinfo", "r"); - if (mountinfo) { - char line[1024]; - while (fgets(line, sizeof(line), mountinfo)) { - // Parse mountinfo format: mountid parentid major:minor root mount_point options - fstype source - char *token = strtok(line, " "); - int field_count = 0; - char *mount_field = NULL, *source_field = NULL; - - while (token && field_count < 10) { - field_count++; - if (field_count == 5) { // mount point field - mount_field = token; - } else if (field_count == 9) { // source field (after fstype) - source_field = token; - break; - } - token = strtok(NULL, " "); - } - - if (mount_field && source_field) { - // Decode escaped characters in mount point - char decoded_mount[512]; - size_t src = 0, dst = 0; - size_t mount_field_len = strlen(mount_field); - while (src < mount_field_len && dst < sizeof(decoded_mount) - 1) { - if (mount_field[src] == '\\' && src + 3 < mount_field_len) { - int octal_val = (mount_field[src + 1] - '0') * 64 + - (mount_field[src + 2] - '0') * 8 + - (mount_field[src + 3] - '0'); - decoded_mount[dst++] = (char)octal_val; - src += 4; - } else { - decoded_mount[dst++] = mount_field[src++]; - } - } - decoded_mount[dst] = '\0'; - - // Debug: Print comparison details for DUAL DRIVE debugging - if (strstr(mount_path, "DUAL DRIVE") || strstr(decoded_mount, "DUAL DRIVE")) { - printf("DEBUG Method2: mount_path='%s', decoded='%s', source='%s', match=%d\n", - mount_path, decoded_mount, source_field, - strcmp(decoded_mount, mount_path) == 0); - } - - if (strcmp(decoded_mount, mount_path) == 0) { - strncpy(device_path, source_field, sizeof(device_path) - 1); - device_path[sizeof(device_path) - 1] = '\0'; - device_found = 1; - break; - } - } - } - fclose(mountinfo); - } - } - - // Method 3: Enhanced smart inference from mount path patterns if device detection failed - int inferred_usb = 0; - if (!device_found) { - // Enhanced USB mount path pattern detection - if (strstr(mount_path, "/media/") || strstr(mount_path, "/run/media/")) { - // All /media/ and /run/media/ paths are highly likely to be USB drives - inferred_usb = 1; - strncpy(drive_info->device_name, "inferred_usb", sizeof(drive_info->device_name) - 1); - strncpy(drive_info->bus_type, "usb", sizeof(drive_info->bus_type) - 1); - } else if (strstr(mount_path, "/mnt/") && - (strstr(mount_path, "USB") || strstr(mount_path, "usb") || - strstr(mount_path, "DRIVE") || strstr(mount_path, "DISK"))) { - // /mnt/ paths with USB-like naming - inferred_usb = 1; - strncpy(drive_info->device_name, "inferred_usb", sizeof(drive_info->device_name) - 1); - strncpy(drive_info->bus_type, "usb", sizeof(drive_info->bus_type) - 1); - } else { - strncpy(drive_info->device_name, "unknown", sizeof(drive_info->device_name) - 1); - strncpy(drive_info->bus_type, "unknown", sizeof(drive_info->bus_type) - 1); - } - - // Set filesystem to unknown if not determined above - if (strlen(drive_info->filesystem) == 0) { - strncpy(drive_info->filesystem, "unknown", sizeof(drive_info->filesystem) - 1); - } - } - - // Debug: Print final device detection results for DUAL DRIVE - if (strstr(mount_path, "DUAL DRIVE")) { - printf("DEBUG Final: mount_path='%s', device_found=%d, device_path='%s', inferred_usb=%d\n", - mount_path, device_found, device_path, inferred_usb); - } - - // Populate safety fields using the USB safety functions - if (device_found && strlen(device_path) > 0) { - // Extract device name from device path - extract_device_name_from_path(device_path, drive_info->device_name, sizeof(drive_info->device_name)); - - // Check if device is removable - drive_info->is_removable = is_device_removable_usb(device_path); - - // Get bus type - get_device_bus_type(device_path, drive_info->bus_type, sizeof(drive_info->bus_type)); - - // Check if it's a USB device (based on bus type) - drive_info->is_usb_device = (strcmp(drive_info->bus_type, "usb") == 0); - - // Check if it's a system critical mount - drive_info->is_system_mount = is_system_critical_mount(mount_path); - } else if (inferred_usb) { - // Use smart inference for likely USB drives when device detection fails - drive_info->is_removable = 1; // Assume removable for USB mount paths - drive_info->is_usb_device = 1; // Inferred as USB device - drive_info->is_system_mount = is_system_critical_mount(mount_path); - } else { - // Conservative fallback - mark as unknown but not unsafe unless proven otherwise - drive_info->is_removable = 0; // Cannot determine, assume non-removable - drive_info->is_usb_device = 0; // Cannot determine, assume non-USB - drive_info->is_system_mount = is_system_critical_mount(mount_path); - } - - // Get filesystem information using statvfs - struct statvfs vfs; - if (statvfs(mount_path, &vfs) == 0) { - drive_info->total_size = (uint64_t)vfs.f_blocks * vfs.f_frsize; - drive_info->available_size = (uint64_t)vfs.f_bavail * vfs.f_frsize; - } else { - // Fallback: try to get basic directory info - struct stat st; - if (stat(mount_path, &st) == 0) { - drive_info->total_size = 0; // Unknown - drive_info->available_size = 0; // Unknown - } else { - return 2; // Cannot access drive - } - } - - // Count OTP pad files if it's an OTP drive - drive_info->pad_count = 0; - if (drive_info->is_otp_drive) { - DIR* dir = opendir(mount_path); - if (dir) { - struct dirent* entry; - while ((entry = readdir(dir)) != NULL) { - if (strstr(entry->d_name, ".pad") && strlen(entry->d_name) == 68) { - drive_info->pad_count++; - } - } - closedir(dir); - } - } - - // Set mount status (assume mounted since we can access it) - drive_info->is_mounted = 1; - - return 0; // Success -} - -// Initialize a USB drive for OTP use -usb_operation_result_t initialize_usb_drive(const char* mount_path, const char* drive_name, - int format_drive, const char* filesystem_type) { - usb_operation_result_t result = {0}; - - if (!mount_path || !drive_name) { - result.success = 0; - strncpy(result.error_message, "Invalid parameters", sizeof(result.error_message) - 1); - return result; - } - - // Validate drive name format - if (strncmp(drive_name, "OTP_", 4) != 0) { - result.success = 0; - strncpy(result.error_message, "Drive name must start with 'OTP_'", sizeof(result.error_message) - 1); - return result; - } - - if (strlen(drive_name) > 32 || strlen(drive_name) < 5) { - result.success = 0; - strncpy(result.error_message, "Drive name must be 5-32 characters", sizeof(result.error_message) - 1); - return result; - } - - // Check if drive is writable - if (access(mount_path, W_OK) != 0) { - result.success = 0; - strncpy(result.error_message, "Drive is not writable", sizeof(result.error_message) - 1); - return result; - } - - // Format drive if requested - if (format_drive) { - printf("Formatting USB drive (this may take several minutes)...\n"); - - // Get device path from mount path - char device_path[256] = ""; - if (get_device_from_mount(mount_path, device_path, sizeof(device_path)) != 0) { - result.success = 0; - strncpy(result.error_message, "Cannot determine device path", sizeof(result.error_message) - 1); - return result; - } - - // Unmount before formatting - char umount_cmd[512]; - snprintf(umount_cmd, sizeof(umount_cmd), "umount '%s' 2>/dev/null", mount_path); - system(umount_cmd); // Ignore errors - - // Format with specified filesystem - char format_cmd[512]; - if (strcmp(filesystem_type, "fat32") == 0) { - snprintf(format_cmd, sizeof(format_cmd), - "mkfs.fat -F32 -n '%s' '%s' 2>/dev/null", drive_name, device_path); - } else if (strcmp(filesystem_type, "ext4") == 0) { - snprintf(format_cmd, sizeof(format_cmd), - "mkfs.ext4 -L '%s' '%s' -F 2>/dev/null", drive_name, device_path); - } else { - result.success = 0; - strncpy(result.error_message, "Unsupported filesystem type", sizeof(result.error_message) - 1); - return result; - } - - if (system(format_cmd) != 0) { - result.success = 0; - strncpy(result.error_message, "Format operation failed", sizeof(result.error_message) - 1); - return result; - } - - // Wait for system to recognize the new filesystem - sleep(2); - - // Remount (let system handle this automatically) - printf("Format completed. Please remount the drive if necessary.\n"); - } - - // Set volume label if not formatting - if (!format_drive) { - if (set_volume_label(mount_path, drive_name) != 0) { - result.success = 0; - strncpy(result.error_message, "Failed to set volume label", sizeof(result.error_message) - 1); - return result; - } - } - - // Create OTP directory structure if needed - char otp_readme_path[1024]; - snprintf(otp_readme_path, sizeof(otp_readme_path), "%s/OTP_README.txt", mount_path); - - FILE* readme = fopen(otp_readme_path, "w"); - if (readme) { - fprintf(readme, "OTP Drive: %s\n", drive_name); - time_t init_time = time(NULL); - fprintf(readme, "Initialized: %s", ctime(&init_time)); - fprintf(readme, "\nThis USB drive has been initialized for use with the OTP program.\n"); - fprintf(readme, "OTP pad files stored on this drive use the same .pad/.state format\n"); - fprintf(readme, "as local pads and can be used for encryption/decryption operations.\n"); - fprintf(readme, "\nDO NOT modify .pad or .state files manually!\n"); - fprintf(readme, "Use the OTP program's pad management features instead.\n"); - fclose(readme); - } - - result.success = 1; - // Success details are in the error_message field for simplicity - strncpy(result.error_message, "USB drive initialized successfully", sizeof(result.error_message) - 1); - - return result; -} - -// Set volume label for a USB drive -int set_volume_label(const char* mount_path, const char* new_label) { - if (!mount_path || !new_label) { - return 1; - } - - // Get device path - char device_path[256]; - if (get_device_from_mount(mount_path, device_path, sizeof(device_path)) != 0) { - return 2; - } - - // Try different labeling methods based on filesystem - char label_cmd[512]; - - // First try FAT32 labeling - snprintf(label_cmd, sizeof(label_cmd), "fatlabel '%s' '%s' 2>/dev/null", device_path, new_label); - if (system(label_cmd) == 0) { - return 0; - } - - // Try ext filesystem labeling - snprintf(label_cmd, sizeof(label_cmd), "e2label '%s' '%s' 2>/dev/null", device_path, new_label); - if (system(label_cmd) == 0) { - return 0; - } - - // Try generic tune2fs for ext filesystems - snprintf(label_cmd, sizeof(label_cmd), "tune2fs -L '%s' '%s' 2>/dev/null", new_label, device_path); - if (system(label_cmd) == 0) { - return 0; - } - - return 3; // All methods failed -} - -// Get device path from mount path -int get_device_from_mount(const char* mount_path, char* device_path, size_t device_path_size) { - if (!mount_path || !device_path) { - return 1; - } - - FILE* mounts = fopen("/proc/mounts", "r"); - if (!mounts) { - return 2; - } - - char line[1024]; - while (fgets(line, sizeof(line), mounts)) { - char device[256], mountpoint[512]; - if (sscanf(line, "%s %s", device, mountpoint) == 2) { - if (strcmp(mountpoint, mount_path) == 0) { - strncpy(device_path, device, device_path_size - 1); - device_path[device_path_size - 1] = '\0'; - fclose(mounts); - return 0; - } - } - } - - fclose(mounts); - return 3; // Mount point not found -} - -// Select USB drive interactively -usb_drive_info_t* select_usb_drive_interactive(const char* title, const char* prompt, int require_otp) { - usb_drive_info_t* drives; - int drive_count; - - printf("\n%s\n", title); - printf("Scanning for USB drives...\n"); - - int result = discover_usb_drives(&drives, &drive_count); - if (result != 0) { - switch (result) { - case 3: // USB_ERROR_NO_DRIVES_FOUND - printf("No USB drives found.\n"); - printf("Please ensure your USB drive is properly mounted.\n"); - break; - case 2: // USB_ERROR_MEMORY_ALLOCATION - printf("Error: Memory allocation failed.\n"); - break; - default: - printf("Error: Failed to discover USB drives (code: %d).\n", result); - break; - } - return NULL; - } - - // Count safe drives that meet requirements - int safe_filtered_count = 0; - int total_filtered_count = 0; - for (int i = 0; i < drive_count; i++) { - if (!require_otp || drives[i].is_otp_drive) { - total_filtered_count++; - if (drives[i].is_safe) { - safe_filtered_count++; - } - } - } - - if (total_filtered_count == 0) { - if (require_otp) { - printf("No OTP USB drives found.\n"); - printf("Initialize a USB drive first using the 'Initialize USB drive' option.\n"); - } else { - printf("No USB drives found.\n"); - } - free(drives); - return NULL; - } - - // Display available drives with safety indicators - printf("\nFound USB drives:\n"); - printf("%-3s %-20s %-10s %-12s %-12s %-8s %-4s %-6s\n", - "#", "Label", "Type", "Total", "Free", "FS", "Pads", "Status"); - printf("%-3s %-20s %-10s %-12s %-12s %-8s %-4s %-6s\n", - "---", "--------------------", "----------", "----------", "----------", "--------", "----", "------"); - - int display_index = 1; - int safe_display_index = 1; - for (int i = 0; i < drive_count; i++) { - if (require_otp && !drives[i].is_otp_drive) { - continue; // Skip non-OTP drives when filtering - } - - // Format sizes for display - char total_str[16], free_str[16]; - format_size_string(drives[i].total_size, total_str, sizeof(total_str)); - format_size_string(drives[i].available_size, free_str, sizeof(free_str)); - - // Display with appropriate formatting - if (drives[i].is_safe) { - // Safe drive - normal display with selectable number - printf("%-3d %-20s %-10s %-12s %-12s %-8s %-4d %-6s\n", - safe_display_index, - drives[i].volume_label, - drives[i].is_otp_drive ? "OTP" : "Standard", - total_str, - free_str, - drives[i].filesystem, - drives[i].pad_count, - "SAFE"); - safe_display_index++; - } else { - // Unsafe drive - strikethrough display, no selection number - printf("%-3s \033[9m%-20s %-10s %-12s %-12s %-8s %-4d\033[0m %-6s\n", - "---", - drives[i].volume_label, - drives[i].is_otp_drive ? "OTP" : "Standard", - total_str, - free_str, - drives[i].filesystem, - drives[i].pad_count, - "UNSAFE"); - } - display_index++; - } - - if (safe_filtered_count == 0) { - printf("\n⚠ WARNING: No safe USB drives found!\n"); - printf("All detected drives failed safety validation.\n"); - printf("Common issues: System drives, non-removable media, non-USB devices\n"); - free(drives); - return NULL; - } - - printf("\n%s (1-%d): ", prompt, safe_filtered_count); - - char input[10]; - if (!fgets(input, sizeof(input), stdin)) { - free(drives); - return NULL; - } - - int selection = atoi(input); - if (selection < 1 || selection > safe_filtered_count) { - printf("Invalid selection.\n"); - free(drives); - return NULL; - } - - // Find the selected safe drive (accounting for filtering and safety) - int current_safe_index = 1; - for (int i = 0; i < drive_count; i++) { - if (require_otp && !drives[i].is_otp_drive) { - continue; - } - - if (drives[i].is_safe) { - if (current_safe_index == selection) { - // Create a copy of the selected drive info - usb_drive_info_t* selected_drive = malloc(sizeof(usb_drive_info_t)); - if (selected_drive) { - *selected_drive = drives[i]; - } - free(drives); - return selected_drive; - } - current_safe_index++; - } - } - - free(drives); - return NULL; -} - +// To be removed // Format file size for display -void format_size_string(uint64_t bytes, char* result, size_t result_size) { - if (bytes == 0) { - strncpy(result, "Unknown", result_size - 1); - result[result_size - 1] = '\0'; - return; - } +// void format_size_string(uint64_t bytes, char* result, size_t result_size) { +// if (bytes == 0) { +// strncpy(result, "Unknown", result_size - 1); +// result[result_size - 1] = '\0'; +// return; +// } - if (bytes < 1024) { - snprintf(result, result_size, "%luB", bytes); - } else if (bytes < 1024 * 1024) { - snprintf(result, result_size, "%.1fKB", (double)bytes / 1024.0); - } else if (bytes < 1024 * 1024 * 1024) { - snprintf(result, result_size, "%.1fMB", (double)bytes / (1024.0 * 1024.0)); - } else if (bytes < 1024ULL * 1024 * 1024 * 1024) { - snprintf(result, result_size, "%.2fGB", (double)bytes / (1024.0 * 1024.0 * 1024.0)); - } else { - snprintf(result, result_size, "%.2fTB", (double)bytes / (1024.0 * 1024.0 * 1024.0 * 1024.0)); - } -} +// if (bytes < 1024) { +// snprintf(result, result_size, "%luB", bytes); +// } else if (bytes < 1024 * 1024) { +// snprintf(result, result_size, "%.1fKB", (double)bytes / 1024.0); +// } else if (bytes < 1024 * 1024 * 1024) { +// snprintf(result, result_size, "%.1fMB", (double)bytes / (1024.0 * 1024.0)); +// } else if (bytes < 1024ULL * 1024 * 1024 * 1024) { +// snprintf(result, result_size, "%.2fGB", (double)bytes / (1024.0 * 1024.0 * 1024.0)); +// } else { +// snprintf(result, result_size, "%.2fTB", (double)bytes / (1024.0 * 1024.0 * 1024.0 * 1024.0)); +// } +// } @@ -3579,431 +2214,7 @@ void format_size_string(uint64_t bytes, char* result, size_t result_size) { // Custom base64 encode function -// Copy pad from local storage to USB drive -int copy_pad_to_usb(const char* pad_checksum, const char* usb_mount_path) { - if (!pad_checksum || !usb_mount_path) { - printf("Error: Invalid parameters for pad copy operation\n"); - return 1; - } - - // Build source paths - char local_pad_path[1024], local_state_path[1024]; - get_pad_path(pad_checksum, local_pad_path, local_state_path); - - // Check if local pad exists - if (access(local_pad_path, R_OK) != 0) { - printf("Error: Local pad file not found: %s\n", local_pad_path); - return 2; - } - - // Build destination paths - char usb_pad_path[1024], usb_state_path[1024]; - snprintf(usb_pad_path, sizeof(usb_pad_path), "%s/%s.pad", usb_mount_path, pad_checksum); - snprintf(usb_state_path, sizeof(usb_state_path), "%s/%s.state", usb_mount_path, pad_checksum); - - // Check if destination pad already exists - if (access(usb_pad_path, F_OK) == 0) { - printf("Warning: Pad already exists on USB drive: %s\n", pad_checksum); - printf("Overwrite? (y/N): "); - fflush(stdout); - - char response[10]; - if (fgets(response, sizeof(response), stdin) == NULL || - (response[0] != 'y' && response[0] != 'Y')) { - printf("Copy operation cancelled.\n"); - return 3; - } - } - - // Copy pad file - printf("Copying pad file...\n"); - if (copy_file(local_pad_path, usb_pad_path) != 0) { - printf("Error: Failed to copy pad file to USB drive\n"); - return 4; - } - - // Copy state file if it exists - if (access(local_state_path, R_OK) == 0) { - printf("Copying state file...\n"); - if (copy_file(local_state_path, usb_state_path) != 0) { - printf("Warning: Failed to copy state file (pad file copied successfully)\n"); - // This is not fatal - pad can still be used - } - } - - // Verify the copy - printf("Verifying integrity...\n"); - if (verify_pad_integrity_cross_drive(local_pad_path, usb_pad_path) != 0) { - printf("Error: Integrity verification failed - removing corrupted copy\n"); - unlink(usb_pad_path); - unlink(usb_state_path); - return 5; - } - - printf("✓ Pad successfully copied to USB drive: %.16s...\n", pad_checksum); - return 0; -} -// Copy pad from USB drive to local storage -int copy_pad_from_usb(const char* usb_mount_path, const char* pad_checksum) { - if (!usb_mount_path || !pad_checksum) { - printf("Error: Invalid parameters for pad import operation\n"); - return 1; - } - - // Build source paths on USB - char usb_pad_path[1024], usb_state_path[1024]; - snprintf(usb_pad_path, sizeof(usb_pad_path), "%s/%s.pad", usb_mount_path, pad_checksum); - snprintf(usb_state_path, sizeof(usb_state_path), "%s/%s.state", usb_mount_path, pad_checksum); - - // Check if USB pad exists - if (access(usb_pad_path, R_OK) != 0) { - printf("Error: Pad file not found on USB drive: %s\n", pad_checksum); - return 2; - } - - // Build destination paths - char local_pad_path[1024], local_state_path[1024]; - get_pad_path(pad_checksum, local_pad_path, local_state_path); - - // Check if local pad already exists - if (access(local_pad_path, F_OK) == 0) { - printf("Warning: Pad already exists locally: %s\n", pad_checksum); - printf("Overwrite? (y/N): "); - fflush(stdout); - - char response[10]; - if (fgets(response, sizeof(response), stdin) == NULL || - (response[0] != 'y' && response[0] != 'Y')) { - printf("Import operation cancelled.\n"); - return 3; - } - } - - // Ensure pads directory exists - if (ensure_pads_directory() != 0) { - printf("Error: Cannot create local pads directory\n"); - return 4; - } - - // Copy pad file from USB - printf("Importing pad file...\n"); - if (copy_file(usb_pad_path, local_pad_path) != 0) { - printf("Error: Failed to import pad file from USB drive\n"); - return 5; - } - - // Set pad file to read-only - if (chmod(local_pad_path, S_IRUSR) != 0) { - printf("Warning: Cannot set pad file to read-only\n"); - } - - // Copy state file if it exists - if (access(usb_state_path, R_OK) == 0) { - printf("Importing state file...\n"); - if (copy_file(usb_state_path, local_state_path) != 0) { - printf("Warning: Failed to import state file (pad file imported successfully)\n"); - // Create a fresh state file with default offset - FILE* new_state = fopen(local_state_path, "wb"); - if (new_state) { - uint64_t default_offset = 32; // Reserved bytes - fwrite(&default_offset, sizeof(uint64_t), 1, new_state); - fclose(new_state); - printf("Created new state file with default offset\n"); - } - } - } else { - // Create state file if it doesn't exist - printf("Creating state file...\n"); - FILE* new_state = fopen(local_state_path, "wb"); - if (new_state) { - uint64_t default_offset = 32; // Reserved bytes - fwrite(&default_offset, sizeof(uint64_t), 1, new_state); - fclose(new_state); - } - } - - // Verify the import - printf("Verifying integrity...\n"); - if (verify_pad_integrity_cross_drive(usb_pad_path, local_pad_path) != 0) { - printf("Error: Integrity verification failed - removing corrupted import\n"); - unlink(local_pad_path); - unlink(local_state_path); - return 6; - } - - printf("✓ Pad successfully imported from USB drive: %.16s...\n", pad_checksum); - return 0; -} - -// Generic file copy function -int copy_file(const char* source_path, const char* dest_path) { - if (!source_path || !dest_path) { - return 1; - } - - FILE* source = fopen(source_path, "rb"); - if (!source) { - return 2; - } - - FILE* dest = fopen(dest_path, "wb"); - if (!dest) { - fclose(source); - return 3; - } - - // Copy in chunks for large files - unsigned char buffer[64 * 1024]; // 64KB buffer - size_t bytes_read; - int error = 0; - - while ((bytes_read = fread(buffer, 1, sizeof(buffer), source)) > 0) { - if (fwrite(buffer, 1, bytes_read, dest) != bytes_read) { - error = 4; // Write error - break; - } - } - - fclose(source); - fclose(dest); - - if (error) { - unlink(dest_path); // Remove incomplete file - return error; - } - - return 0; -} - -// List pads available on a USB drive -int list_pads_on_drive(const char* mount_path, char pad_list[][65], int max_pads) { - if (!mount_path || !pad_list || max_pads <= 0) { - return -1; - } - - DIR* dir = opendir(mount_path); - if (!dir) { - return -2; - } - - int pad_count = 0; - struct dirent* entry; - - while ((entry = readdir(dir)) != NULL && pad_count < max_pads) { - // Check if this is a pad file - if (strstr(entry->d_name, ".pad") && strlen(entry->d_name) == 68) { - // Extract checksum (remove .pad extension) - strncpy(pad_list[pad_count], entry->d_name, 64); - pad_list[pad_count][64] = '\0'; - pad_count++; - } - } - - closedir(dir); - return pad_count; -} - -// Verify integrity between two pad files (cross-drive verification) -int verify_pad_integrity_cross_drive(const char* source_pad, const char* dest_pad) { - if (!source_pad || !dest_pad) { - return 1; - } - - // Calculate checksums of both files - char source_checksum[65], dest_checksum[65]; - - if (calculate_checksum(source_pad, source_checksum) != 0) { - printf("Error: Cannot calculate source pad checksum\n"); - return 2; - } - - if (calculate_checksum(dest_pad, dest_checksum) != 0) { - printf("Error: Cannot calculate destination pad checksum\n"); - return 3; - } - - // Compare checksums - if (strcmp(source_checksum, dest_checksum) != 0) { - printf("Error: Pad integrity verification failed\n"); - printf("Source: %s\n", source_checksum); - printf("Destination: %s\n", dest_checksum); - return 4; - } - - // Also verify file sizes match - struct stat source_stat, dest_stat; - if (stat(source_pad, &source_stat) != 0 || stat(dest_pad, &dest_stat) != 0) { - printf("Error: Cannot verify file sizes\n"); - return 5; - } - - if (source_stat.st_size != dest_stat.st_size) { - printf("Error: File sizes don't match\n"); - printf("Source: %lu bytes, Destination: %lu bytes\n", - source_stat.st_size, dest_stat.st_size); - return 6; - } - - return 0; // Verification successful -} - -// Selective drive duplication with pad selection -int duplicate_drive_selective(const char* source_mount, const char* dest_mount, - char selected_pads[][65], int pad_count) { - if (!source_mount || !dest_mount || !selected_pads || pad_count <= 0) { - printf("Error: Invalid parameters for drive duplication\n"); - return 1; - } - - printf("Starting selective drive duplication...\n"); - printf("Source: %s\n", source_mount); - printf("Destination: %s\n", dest_mount); - printf("Pads to copy: %d\n\n", pad_count); - - int success_count = 0; - int error_count = 0; - - // Copy each selected pad - for (int i = 0; i < pad_count; i++) { - printf("[%d/%d] Copying pad: %.16s...\n", i + 1, pad_count, selected_pads[i]); - - // Build source paths - char source_pad[1024], source_state[1024]; - snprintf(source_pad, sizeof(source_pad), "%s/%s.pad", source_mount, selected_pads[i]); - snprintf(source_state, sizeof(source_state), "%s/%s.state", source_mount, selected_pads[i]); - - // Build destination paths - char dest_pad[1024], dest_state[1024]; - snprintf(dest_pad, sizeof(dest_pad), "%s/%s.pad", dest_mount, selected_pads[i]); - snprintf(dest_state, sizeof(dest_state), "%s/%s.state", dest_mount, selected_pads[i]); - - // Check source pad exists - if (access(source_pad, R_OK) != 0) { - printf(" Error: Source pad not found - skipping\n"); - error_count++; - continue; - } - - // Copy pad file - if (copy_file(source_pad, dest_pad) != 0) { - printf(" Error: Failed to copy pad file - skipping\n"); - error_count++; - continue; - } - - // Copy state file if it exists - if (access(source_state, R_OK) == 0) { - if (copy_file(source_state, dest_state) != 0) { - printf(" Warning: Failed to copy state file\n"); - // Create default state file - FILE* new_state = fopen(dest_state, "wb"); - if (new_state) { - uint64_t default_offset = 32; - fwrite(&default_offset, sizeof(uint64_t), 1, new_state); - fclose(new_state); - } - } - } else { - // Create default state file - FILE* new_state = fopen(dest_state, "wb"); - if (new_state) { - uint64_t default_offset = 32; - fwrite(&default_offset, sizeof(uint64_t), 1, new_state); - fclose(new_state); - } - } - - // Verify integrity - if (verify_pad_integrity_cross_drive(source_pad, dest_pad) != 0) { - printf(" Error: Integrity verification failed - removing copy\n"); - unlink(dest_pad); - unlink(dest_state); - error_count++; - continue; - } - - printf(" ✓ Success\n"); - success_count++; - } - - printf("\nDuplication completed:\n"); - printf("Successfully copied: %d pads\n", success_count); - printf("Errors encountered: %d pads\n", error_count); - - return (error_count > 0) ? error_count : 0; -} - -// Verify complete drive duplication -int verify_drive_duplication(const char* source_mount, const char* dest_mount) { - if (!source_mount || !dest_mount) { - return 1; - } - - printf("Verifying drive duplication...\n"); - - // Get list of pads on source drive - char source_pads[100][65]; - int source_count = list_pads_on_drive(source_mount, source_pads, 100); - if (source_count < 0) { - printf("Error: Cannot list pads on source drive\n"); - return 2; - } - - // Get list of pads on destination drive - char dest_pads[100][65]; - int dest_count = list_pads_on_drive(dest_mount, dest_pads, 100); - if (dest_count < 0) { - printf("Error: Cannot list pads on destination drive\n"); - return 3; - } - - printf("Source drive: %d pads\n", source_count); - printf("Destination drive: %d pads\n", dest_count); - - int verified_count = 0; - int error_count = 0; - - // Verify each pad on source exists on destination and matches - for (int i = 0; i < source_count; i++) { - printf("Verifying pad: %.16s...\n", source_pads[i]); - - // Check if this pad exists on destination - int found = 0; - for (int j = 0; j < dest_count; j++) { - if (strcmp(source_pads[i], dest_pads[j]) == 0) { - found = 1; - break; - } - } - - if (!found) { - printf(" Error: Pad missing on destination drive\n"); - error_count++; - continue; - } - - // Verify integrity - char source_path[1024], dest_path[1024]; - snprintf(source_path, sizeof(source_path), "%s/%s.pad", source_mount, source_pads[i]); - snprintf(dest_path, sizeof(dest_path), "%s/%s.pad", dest_mount, source_pads[i]); - - if (verify_pad_integrity_cross_drive(source_path, dest_path) != 0) { - printf(" Error: Integrity verification failed\n"); - error_count++; - continue; - } - - printf(" ✓ Verified\n"); - verified_count++; - } - - printf("\nVerification completed:\n"); - printf("Successfully verified: %d pads\n", verified_count); - printf("Errors found: %d pads\n", error_count); - - return (error_count > 0) ? error_count : 0; -} char* custom_base64_encode(const unsigned char* input, int length) { int output_length = 4 * ((length + 2) / 3); @@ -5912,7 +4123,7 @@ char* select_pad_interactive(const char* title, const char* prompt, pad_filter_t pads[pad_count].percentage = (double)used_bytes / st.st_size * 100.0; // Set location info using directory display - get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location)); + // get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location)); pad_count++; } @@ -6145,7 +4356,7 @@ int handle_pads_menu(void) { pads[pad_count].percentage = (double)used_bytes / st.st_size * 100.0; // Set location info using directory display - get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location)); + // get_directory_display(full_path, pads[pad_count].location, sizeof(pads[pad_count].location)); pad_count++; } @@ -6252,7 +4463,6 @@ int handle_pads_menu(void) { printf(" \033[4mG\033[0menerate new pad\n"); printf(" \033[4mA\033[0mdd entropy to pad\n"); printf(" \033[4mS\033[0met default pad\n"); - printf(" \033[4mU\033[0mSB drive management\n"); printf(" E\033[4mx\033[0mit\n"); printf("\nSelect action: "); @@ -6343,150 +4553,144 @@ int handle_pads_menu(void) { free(selected_pad); return handle_pads_menu(); - } else if (toupper(input[0]) == 'U') { - // USB drive management - int result = handle_usb_submenu(); - if (result == 0) { - return handle_pads_menu(); // Return to pads menu - } - return result; } else if (toupper(input[0]) == 'X') { return 0; // Exit to main menu } else { - printf("Invalid action. Please select G, A, S, U, or X.\n"); + printf("Invalid action. Please select G, A, S, or X.\n"); return handle_pads_menu(); } } -void get_directory_display(const char* file_path, char* result, size_t result_size) { - // Extract directory path from full file path - char dir_path[512]; - char* last_slash = strrchr(file_path, '/'); +// To be removed +// void get_directory_display(const char* file_path, char* result, size_t result_size) { +// // Extract directory path from full file path +// char dir_path[512]; +// char* last_slash = strrchr(file_path, '/'); - if (last_slash) { - size_t dir_len = last_slash - file_path; - if (dir_len >= sizeof(dir_path)) { - dir_len = sizeof(dir_path) - 1; - } - strncpy(dir_path, file_path, dir_len); - dir_path[dir_len] = '\0'; - } else { - // No directory separator, assume current directory - strcpy(dir_path, "."); - } +// if (last_slash) { +// size_t dir_len = last_slash - file_path; +// if (dir_len >= sizeof(dir_path)) { +// dir_len = sizeof(dir_path) - 1; +// } +// strncpy(dir_path, file_path, dir_len); +// dir_path[dir_len] = '\0'; +// } else { +// // No directory separator, assume current directory +// strcpy(dir_path, "."); +// } - // USB Drive Detection and Smart Shortening - char* home_dir = getenv("HOME"); +// // USB Drive Detection and Smart Shortening +// char* home_dir = getenv("HOME"); - // Check for USB/removable media mount patterns - if (strstr(dir_path, "/media/") || strstr(dir_path, "/run/media/") || strstr(dir_path, "/mnt/")) { - // Extract USB label/name - char* media_start = NULL; - if (strstr(dir_path, "/media/")) { - media_start = strstr(dir_path, "/media/"); - } else if (strstr(dir_path, "/run/media/")) { - media_start = strstr(dir_path, "/run/media/"); - } else if (strstr(dir_path, "/mnt/")) { - media_start = strstr(dir_path, "/mnt/"); - } +// // Check for USB/removable media mount patterns +// if (strstr(dir_path, "/media/") || strstr(dir_path, "/run/media/") || strstr(dir_path, "/mnt/")) { +// // Extract USB label/name +// char* media_start = NULL; +// if (strstr(dir_path, "/media/")) { +// media_start = strstr(dir_path, "/media/"); +// } else if (strstr(dir_path, "/run/media/")) { +// media_start = strstr(dir_path, "/run/media/"); +// } else if (strstr(dir_path, "/mnt/")) { +// media_start = strstr(dir_path, "/mnt/"); +// } - if (media_start) { - // Find the USB label part - char* path_after_media = strchr(media_start + 1, '/'); - if (path_after_media) { - path_after_media++; // Skip the slash +// if (media_start) { +// // Find the USB label part +// char* path_after_media = strchr(media_start + 1, '/'); +// if (path_after_media) { +// path_after_media++; // Skip the slash - // For /media/user/LABEL pattern, skip the username to get to the drive label - if (strstr(media_start, "/media/")) { - char* next_slash = strchr(path_after_media, '/'); - if (next_slash) { - path_after_media = next_slash + 1; - } - } - // For /run/media/user/LABEL pattern, skip the username - else if (strstr(media_start, "/run/media/")) { - char* next_slash = strchr(path_after_media, '/'); - if (next_slash) { - path_after_media = next_slash + 1; - } - } +// // For /media/user/LABEL pattern, skip the username to get to the drive label +// if (strstr(media_start, "/media/")) { +// char* next_slash = strchr(path_after_media, '/'); +// if (next_slash) { +// path_after_media = next_slash + 1; +// } +// } +// // For /run/media/user/LABEL pattern, skip the username +// else if (strstr(media_start, "/run/media/")) { +// char* next_slash = strchr(path_after_media, '/'); +// if (next_slash) { +// path_after_media = next_slash + 1; +// } +// } - // Extract just the USB label (up to next slash or end) - char* label_end = strchr(path_after_media, '/'); - char usb_label[32]; - if (label_end) { - size_t label_len = label_end - path_after_media; - if (label_len > sizeof(usb_label) - 1) label_len = sizeof(usb_label) - 1; - strncpy(usb_label, path_after_media, label_len); - usb_label[label_len] = '\0'; - } else { - // USB label is the last part - strncpy(usb_label, path_after_media, sizeof(usb_label) - 1); - usb_label[sizeof(usb_label) - 1] = '\0'; - } +// // Extract just the USB label (up to next slash or end) +// char* label_end = strchr(path_after_media, '/'); +// char usb_label[32]; +// if (label_end) { +// size_t label_len = label_end - path_after_media; +// if (label_len > sizeof(usb_label) - 1) label_len = sizeof(usb_label) - 1; +// strncpy(usb_label, path_after_media, label_len); +// usb_label[label_len] = '\0'; +// } else { +// // USB label is the last part +// strncpy(usb_label, path_after_media, sizeof(usb_label) - 1); +// usb_label[sizeof(usb_label) - 1] = '\0'; +// } - // Format with USB: prefix, limiting total length to fit in result - snprintf(result, result_size, "USB:%s", usb_label); - // Truncate if too long - if (strlen(result) > 11) { - result[11] = '\0'; - } - return; - } - } - } +// // Format with USB: prefix, limiting total length to fit in result +// snprintf(result, result_size, "USB:%s", usb_label); +// // Truncate if too long +// if (strlen(result) > 11) { +// result[11] = '\0'; +// } +// return; +// } +// } +// } - // Home directory shortening - if (home_dir && strncmp(dir_path, home_dir, strlen(home_dir)) == 0) { - if (dir_path[strlen(home_dir)] == '/' || dir_path[strlen(home_dir)] == '\0') { - // Replace home directory with ~ - char temp[512]; - snprintf(temp, sizeof(temp), "~%s", dir_path + strlen(home_dir)); +// // Home directory shortening +// if (home_dir && strncmp(dir_path, home_dir, strlen(home_dir)) == 0) { +// if (dir_path[strlen(home_dir)] == '/' || dir_path[strlen(home_dir)] == '\0') { +// // Replace home directory with ~ +// char temp[512]; +// snprintf(temp, sizeof(temp), "~%s", dir_path + strlen(home_dir)); - // If result is too long, truncate intelligently - if (strlen(temp) > 11) { - // Show ~/...end_part - char* last_part = strrchr(temp, '/'); - if (last_part && strlen(last_part) < 8) { - snprintf(result, result_size, "~...%s", last_part); - } else { - strncpy(result, temp, 11); - result[11] = '\0'; - } - } else { - strncpy(result, temp, result_size - 1); - result[result_size - 1] = '\0'; - } - return; - } - } +// // If result is too long, truncate intelligently +// if (strlen(temp) > 11) { +// // Show ~/...end_part +// char* last_part = strrchr(temp, '/'); +// if (last_part && strlen(last_part) < 8) { +// snprintf(result, result_size, "~...%s", last_part); +// } else { +// strncpy(result, temp, 11); +// result[11] = '\0'; +// } +// } else { +// strncpy(result, temp, result_size - 1); +// result[result_size - 1] = '\0'; +// } +// return; +// } +// } - // Current working directory - if (strcmp(dir_path, ".") == 0 || strcmp(dir_path, current_pads_dir) == 0) { - strncpy(result, "pads", result_size - 1); - result[result_size - 1] = '\0'; - return; - } +// // Current working directory +// if (strcmp(dir_path, ".") == 0 || strcmp(dir_path, current_pads_dir) == 0) { +// strncpy(result, "pads", result_size - 1); +// result[result_size - 1] = '\0'; +// return; +// } - // System/other paths - smart truncation with ellipsis - if (strlen(dir_path) > 11) { - // Try to show the most meaningful part - char* last_part = strrchr(dir_path, '/'); - if (last_part && strlen(last_part) < 9) { - // Show .../last_part - snprintf(result, result_size, "...%s", last_part); - } else { - // Show first part with ellipsis - strncpy(result, dir_path, 8); - strncpy(result + 8, "...", result_size - 8 - 1); - result[result_size - 1] = '\0'; - } - } else { - // Short enough, use as-is - strncpy(result, dir_path, result_size - 1); - result[result_size - 1] = '\0'; - } -} +// // System/other paths - smart truncation with ellipsis +// if (strlen(dir_path) > 11) { +// // Try to show the most meaningful part +// char* last_part = strrchr(dir_path, '/'); +// if (last_part && strlen(last_part) < 9) { +// // Show .../last_part +// snprintf(result, result_size, "...%s", last_part); +// } else { +// // Show first part with ellipsis +// strncpy(result, dir_path, 8); +// strncpy(result + 8, "...", result_size - 8 - 1); +// result[result_size - 1] = '\0'; +// } +// } else { +// // Short enough, use as-is +// strncpy(result, dir_path, result_size - 1); +// result[result_size - 1] = '\0'; +// } +// } int handle_add_entropy_to_pad(const char* pad_chksum) { printf("\n=== Add Entropy to Pad: %.16s... ===\n", pad_chksum); @@ -6618,597 +4822,6 @@ int handle_add_entropy_to_pad(const char* pad_chksum) { return 0; } -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// USB MENU HANDLERS -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -int handle_usb_submenu(void) { - printf("\n=== USB Drive Management ===\n"); - - // Auto-display USB drives above the menu (like Pad Management does) - list_usb_drives_v2(); - - printf("\nActions:\n"); - printf(" \033[4mI\033[0mnitialize USB drive\n"); - printf(" \033[4mC\033[0mopy pad to USB\n"); - printf(" \033[4mM\033[0mport pad from USB\n"); - printf(" \033[4mD\033[0muplicate USB drive\n"); - printf(" \033[4mV\033[0merify drive integrity\n"); - printf(" E\033[4mx\033[0mit\n"); - printf("\nSelect action: "); - - char input[10]; - if (!fgets(input, sizeof(input), stdin)) { - printf("Error: Failed to read input\n"); - return 1; - } - - char choice = toupper(input[0]); - - switch (choice) { - case 'I': - return handle_initialize_usb(); - case 'C': - return handle_copy_pad_to_usb(); - case 'M': - return handle_import_pad_from_usb(); - case 'D': - return handle_duplicate_usb_drive(); - case 'V': - return handle_verify_usb_drive(); - case 'X': - case 'Q': - return 0; // Exit to pads menu - default: - printf("Invalid choice. Please try again.\n"); - return handle_usb_submenu(); - } -} - -int handle_initialize_usb(void) { - printf("\n=== Initialize USB Drive for OTP ===\n"); - printf("This will prepare a USB drive for storing OTP pads.\n\n"); - - // Select USB drive - usb_drive_info_t* selected_drive = select_usb_drive_interactive( - "Available USB Drives", "Select drive to initialize", 0); - - if (!selected_drive) { - printf("USB initialization cancelled.\n"); - return handle_usb_submenu(); - } - - printf("\nSelected drive: %s (%s)\n", selected_drive->volume_label, selected_drive->mount_path); - - // Get drive name - char drive_name[64]; - printf("Enter OTP drive name (must start with 'OTP_'): "); - if (!fgets(drive_name, sizeof(drive_name), stdin)) { - printf("Error: Failed to read input\n"); - free(selected_drive); - return 1; - } - drive_name[strcspn(drive_name, "\n")] = 0; - - // Validate drive name - if (strncmp(drive_name, "OTP_", 4) != 0) { - printf("Error: Drive name must start with 'OTP_'\n"); - free(selected_drive); - return handle_usb_submenu(); - } - - // Ask about formatting - printf("\nFormat options:\n"); - printf(" 1. Initialize without formatting (recommended if drive is already formatted)\n"); - printf(" 2. Format with FAT32 filesystem\n"); - printf(" 3. Format with ext4 filesystem\n"); - printf("Enter choice (1-3): "); - - char format_input[10]; - if (!fgets(format_input, sizeof(format_input), stdin)) { - printf("Error: Failed to read input\n"); - free(selected_drive); - return 1; - } - - int format_choice = atoi(format_input); - int format_drive = (format_choice > 1); - const char* filesystem = ""; - - if (format_choice == 2) { - filesystem = "fat32"; - } else if (format_choice == 3) { - filesystem = "ext4"; - } - - // Confirm operation - printf("\nConfirmation:\n"); - printf("Drive: %s\n", selected_drive->mount_path); - printf("Name: %s\n", drive_name); - if (format_drive) { - printf("Format: YES (%s) - THIS WILL ERASE ALL DATA\n", filesystem); - } else { - printf("Format: NO (label only)\n"); - } - printf("\nProceed? (y/N): "); - - char confirm[10]; - if (!fgets(confirm, sizeof(confirm), stdin) || - (confirm[0] != 'y' && confirm[0] != 'Y')) { - printf("Operation cancelled.\n"); - free(selected_drive); - return handle_usb_submenu(); - } - - // Initialize the drive - usb_operation_result_t result = initialize_usb_drive( - selected_drive->mount_path, drive_name, format_drive, filesystem); - - if (result.success) { - printf("\n✓ USB drive initialized successfully!\n"); - printf("Drive name: %s\n", drive_name); - printf("You can now copy pads to this drive.\n"); - } else { - printf("\n✗ USB drive initialization failed: %s\n", result.error_message); - } - - free(selected_drive); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -int handle_copy_pad_to_usb(void) { - printf("\n=== Copy Pad to USB Drive ===\n"); - - // Select pad to copy - char* selected_pad = select_pad_interactive("=== Select Pad to Copy ===", - "Select pad to copy to USB (by prefix)", - PAD_FILTER_ALL, 1); - if (!selected_pad) { - printf("Pad selection cancelled.\n"); - return handle_usb_submenu(); - } - - // Select USB drive (OTP drives only) - usb_drive_info_t* selected_drive = select_usb_drive_interactive( - "Available OTP USB Drives", "Select destination USB drive", 1); - - if (!selected_drive) { - printf("USB drive selection cancelled.\n"); - free(selected_pad); - return handle_usb_submenu(); - } - - printf("\nCopying pad %.16s... to %s\n", selected_pad, selected_drive->volume_label); - - // Copy the pad - int result = copy_pad_to_usb(selected_pad, selected_drive->mount_path); - - if (result == 0) { - printf("✓ Pad successfully copied to USB drive!\n"); - } else { - printf("✗ Failed to copy pad to USB drive (error code: %d)\n", result); - } - - free(selected_pad); - free(selected_drive); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -int handle_import_pad_from_usb(void) { - printf("\n=== Import Pad from USB Drive ===\n"); - - // Select USB drive (OTP drives only) - usb_drive_info_t* selected_drive = select_usb_drive_interactive( - "Available OTP USB Drives", "Select source USB drive", 1); - - if (!selected_drive) { - printf("USB drive selection cancelled.\n"); - return handle_usb_submenu(); - } - - // List pads on the drive - char pad_list[100][65]; - int pad_count = list_pads_on_drive(selected_drive->mount_path, pad_list, 100); - - if (pad_count <= 0) { - printf("No pads found on USB drive %s\n", selected_drive->volume_label); - free(selected_drive); - printf("Press Enter to continue..."); - getchar(); - return handle_usb_submenu(); - } - - printf("\nPads available on %s:\n", selected_drive->volume_label); - printf("%-3s %-16s\n", "#", "Checksum"); - printf("%-3s %-16s\n", "---", "----------------"); - - for (int i = 0; i < pad_count; i++) { - printf("%-3d %.16s...\n", i + 1, pad_list[i]); - } - - printf("\nSelect pad number to import (1-%d) or 0 to cancel: ", pad_count); - - char input[10]; - if (!fgets(input, sizeof(input), stdin)) { - printf("Error: Failed to read input\n"); - free(selected_drive); - return 1; - } - - int selection = atoi(input); - if (selection < 1 || selection > pad_count) { - printf("Import cancelled.\n"); - free(selected_drive); - return handle_usb_submenu(); - } - - char* selected_pad = pad_list[selection - 1]; - printf("\nImporting pad %.16s... from %s\n", selected_pad, selected_drive->volume_label); - - // Import the pad - int result = copy_pad_from_usb(selected_drive->mount_path, selected_pad); - - if (result == 0) { - printf("✓ Pad successfully imported from USB drive!\n"); - } else { - printf("✗ Failed to import pad from USB drive (error code: %d)\n", result); - } - - free(selected_drive); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -int handle_duplicate_usb_drive(void) { - printf("\n=== Duplicate USB Drive ===\n"); - printf("Copy selected pads from one OTP USB drive to another.\n\n"); - - // Select source drive - usb_drive_info_t* source_drive = select_usb_drive_interactive( - "Source OTP USB Drives", "Select source drive to copy from", 1); - - if (!source_drive) { - printf("Source drive selection cancelled.\n"); - return handle_usb_submenu(); - } - - // Select destination drive - usb_drive_info_t* dest_drive = select_usb_drive_interactive( - "Destination OTP USB Drives", "Select destination drive to copy to", 1); - - if (!dest_drive) { - printf("Destination drive selection cancelled.\n"); - free(source_drive); - return handle_usb_submenu(); - } - - // Prevent copying to same drive - if (strcmp(source_drive->mount_path, dest_drive->mount_path) == 0) { - printf("Error: Source and destination drives cannot be the same!\n"); - free(source_drive); - free(dest_drive); - printf("Press Enter to continue..."); - getchar(); - return handle_usb_submenu(); - } - - // List pads on source drive - char pad_list[100][65]; - int pad_count = list_pads_on_drive(source_drive->mount_path, pad_list, 100); - - if (pad_count <= 0) { - printf("No pads found on source drive %s\n", source_drive->volume_label); - free(source_drive); - free(dest_drive); - printf("Press Enter to continue..."); - getchar(); - return handle_usb_submenu(); - } - - printf("\nSource: %s (%d pads)\n", source_drive->volume_label, pad_count); - printf("Destination: %s\n\n", dest_drive->volume_label); - - // For simplicity, copy all pads (could be enhanced to allow selection) - printf("This will copy all %d pads from source to destination.\n", pad_count); - printf("Proceed? (y/N): "); - - char confirm[10]; - if (!fgets(confirm, sizeof(confirm), stdin) || - (confirm[0] != 'y' && confirm[0] != 'Y')) { - printf("Duplication cancelled.\n"); - free(source_drive); - free(dest_drive); - return handle_usb_submenu(); - } - - // Perform selective duplication with all pads - int result = duplicate_drive_selective(source_drive->mount_path, - dest_drive->mount_path, pad_list, pad_count); - - if (result == 0) { - printf("\n✓ USB drive duplication completed successfully!\n"); - } else { - printf("\n⚠ USB drive duplication completed with %d errors.\n", result); - } - - free(source_drive); - free(dest_drive); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -int handle_verify_usb_drive(void) { - printf("\n=== Verify USB Drive Integrity ===\n"); - - // Select USB drive to verify - usb_drive_info_t* selected_drive = select_usb_drive_interactive( - "Available OTP USB Drives", "Select drive to verify", 1); - - if (!selected_drive) { - printf("Drive selection cancelled.\n"); - return handle_usb_submenu(); - } - - printf("\nVerifying integrity of drive: %s\n", selected_drive->volume_label); - printf("Mount path: %s\n\n", selected_drive->mount_path); - - // List pads on the drive and verify each one - char pad_list[100][65]; - int pad_count = list_pads_on_drive(selected_drive->mount_path, pad_list, 100); - - if (pad_count <= 0) { - printf("No pads found on USB drive.\n"); - free(selected_drive); - printf("Press Enter to continue..."); - getchar(); - return handle_usb_submenu(); - } - - printf("Found %d pads to verify:\n\n", pad_count); - - int verified_count = 0; - int error_count = 0; - - for (int i = 0; i < pad_count; i++) { - printf("[%d/%d] Verifying pad: %.16s...\n", i + 1, pad_count, pad_list[i]); - - // Build pad path - char pad_path[1024]; - snprintf(pad_path, sizeof(pad_path), "%s/%s.pad", - selected_drive->mount_path, pad_list[i]); - - // Calculate and verify checksum - char calculated_checksum[65]; - if (calculate_checksum(pad_path, calculated_checksum) == 0) { - if (strcmp(calculated_checksum, pad_list[i]) == 0) { - printf(" ✓ Integrity verified\n"); - verified_count++; - } else { - printf(" ✗ Checksum mismatch!\n"); - printf(" Expected: %.16s...\n", pad_list[i]); - printf(" Calculated: %.16s...\n", calculated_checksum); - error_count++; - } - } else { - printf(" ✗ Cannot calculate checksum\n"); - error_count++; - } - } - - printf("\nVerification completed:\n"); - printf("Successfully verified: %d pads\n", verified_count); - printf("Errors found: %d pads\n", error_count); - - if (error_count == 0) { - printf("✓ All pads on USB drive are intact!\n"); - } else { - printf("⚠ Some pads have integrity issues. Consider re-copying them.\n"); - } - - free(selected_drive); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -int handle_list_usb_drives(void) { - printf("\n=== List USB Drives ===\n"); - list_usb_drives_v2(); - printf("\nPress Enter to continue..."); - getchar(); - return handle_usb_submenu(); -} - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// USB COMMAND LINE INTERFACE HANDLERS -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -int handle_list_usb_drives_cli(void) { - list_usb_drives_v2(); - return 0; -} -int handle_usb_init_cli(int argc, char* argv[]) { - const char* drive_name = argv[2]; - const char* drive_path = (argc > 3) ? argv[3] : NULL; - - // Validate drive name - if (strncmp(drive_name, "OTP_", 4) != 0) { - printf("Error: Drive name must start with 'OTP_'\n"); - return 1; - } - - if (strlen(drive_name) < 5 || strlen(drive_name) > 32) { - printf("Error: Drive name must be 5-32 characters\n"); - return 1; - } - - const char* mount_path; - usb_drive_info_t* selected_drive = NULL; - - if (drive_path) { - // Direct path specified - mount_path = drive_path; - - // Verify it's a valid mount point - if (access(drive_path, W_OK) != 0) { - printf("Error: Cannot access or write to specified path: %s\n", drive_path); - return 1; - } - } else { - // Interactive drive selection - printf("No drive path specified. Available USB drives:\n"); - selected_drive = select_usb_drive_interactive( - "Available USB Drives", "Select drive to initialize", 0); - - if (!selected_drive) { - printf("No drive selected.\n"); - return 1; - } - mount_path = selected_drive->mount_path; - } - - printf("Initializing USB drive...\n"); - printf("Drive path: %s\n", mount_path); - printf("Drive name: %s\n", drive_name); - - // Initialize without formatting by default in CLI mode - usb_operation_result_t result = initialize_usb_drive(mount_path, drive_name, 0, ""); - - if (result.success) { - printf("✓ USB drive initialized successfully!\n"); - } else { - printf("✗ USB drive initialization failed: %s\n", result.error_message); - if (selected_drive) free(selected_drive); - return 1; - } - - if (selected_drive) free(selected_drive); - return 0; -} - -int handle_usb_copy_cli(const char* pad_prefix, const char* usb_path) { - // Find pad by prefix - char* pad_checksum = find_pad_by_prefix(pad_prefix); - if (!pad_checksum) { - printf("Error: No pad found matching prefix '%s'\n", pad_prefix); - return 1; - } - - // Verify USB path is accessible - if (access(usb_path, W_OK) != 0) { - printf("Error: Cannot access USB drive path: %s\n", usb_path); - free(pad_checksum); - return 1; - } - - printf("Copying pad %.16s... to %s\n", pad_checksum, usb_path); - - int result = copy_pad_to_usb(pad_checksum, usb_path); - - if (result == 0) { - printf("✓ Pad successfully copied to USB drive!\n"); - } else { - printf("✗ Failed to copy pad to USB drive (error code: %d)\n", result); - free(pad_checksum); - return 1; - } - - free(pad_checksum); - return 0; -} - -int handle_usb_import_cli(const char* pad_checksum, const char* usb_path) { - // Verify USB path is accessible - if (access(usb_path, R_OK) != 0) { - printf("Error: Cannot access USB drive path: %s\n", usb_path); - return 1; - } - - // Verify pad exists on USB - char pad_path[1024]; - snprintf(pad_path, sizeof(pad_path), "%s/%s.pad", usb_path, pad_checksum); - - if (access(pad_path, R_OK) != 0) { - printf("Error: Pad not found on USB drive: %s\n", pad_checksum); - return 1; - } - - printf("Importing pad %.16s... from %s\n", pad_checksum, usb_path); - - int result = copy_pad_from_usb(usb_path, pad_checksum); - - if (result == 0) { - printf("✓ Pad successfully imported from USB drive!\n"); - } else { - printf("✗ Failed to import pad from USB drive (error code: %d)\n", result); - return 1; - } - - return 0; -} - -int handle_usb_verify_cli(const char* usb_path) { - // Verify USB path is accessible - if (access(usb_path, R_OK) != 0) { - printf("Error: Cannot access USB drive path: %s\n", usb_path); - return 1; - } - - printf("Verifying USB drive integrity: %s\n", usb_path); - - // List pads on the drive - char pad_list[100][65]; - int pad_count = list_pads_on_drive(usb_path, pad_list, 100); - - if (pad_count <= 0) { - printf("No pads found on USB drive.\n"); - return 1; - } - - printf("Found %d pads to verify:\n", pad_count); - - int verified_count = 0; - int error_count = 0; - - for (int i = 0; i < pad_count; i++) { - printf("[%d/%d] Verifying pad: %.16s...", i + 1, pad_count, pad_list[i]); - - // Build pad path - char pad_path[1024]; - snprintf(pad_path, sizeof(pad_path), "%s/%s.pad", usb_path, pad_list[i]); - - // Calculate and verify checksum - char calculated_checksum[65]; - if (calculate_checksum(pad_path, calculated_checksum) == 0) { - if (strcmp(calculated_checksum, pad_list[i]) == 0) { - printf(" ✓\n"); - verified_count++; - } else { - printf(" ✗ (checksum mismatch)\n"); - error_count++; - } - } else { - printf(" ✗ (cannot calculate checksum)\n"); - error_count++; - } - } - - printf("\nVerification results:\n"); - printf("Successfully verified: %d pads\n", verified_count); - printf("Errors found: %d pads\n", error_count); - - return (error_count > 0) ? 1 : 0; -} void print_usage(const char* program_name) { printf("OTP Cipher - One Time Pad Implementation v0.3.7\n"); @@ -7235,19 +4848,6 @@ void print_usage(const char* program_name) { printf(" %s -d encrypted.otp.asc - Decrypt ASCII file\n", program_name); printf(" %s -g 1GB - Generate 1GB pad\n", program_name); printf(" %s -l - List pads\n", program_name); - printf("\nUSB Operations:\n"); - printf(" usb-list - List all USB drives\n"); - printf(" usb-init [path] - Initialize USB drive for OTP\n"); - printf(" usb-copy - Copy pad to USB drive\n"); - printf(" usb-import - Import pad from USB drive\n"); - printf(" usb-verify - Verify USB drive integrity\n"); - printf("\nUSB Examples:\n"); - printf(" %s usb-list - Show all USB drives\n", program_name); - printf(" %s usb-init OTP_BACKUP - Initialize drive (interactive)\n", program_name); - printf(" %s usb-init OTP_BACKUP /media/user/USB - Initialize specific drive\n", program_name); - printf(" %s usb-copy 1a2b3c /media/user/OTP_BACKUP - Copy pad to USB\n", program_name); - printf(" %s usb-import 1a2b3c4d /media/user/OTP_BACKUP - Import pad from USB\n", program_name); - printf(" %s usb-verify /media/user/OTP_BACKUP - Verify USB drive\n", program_name); printf("\nSize examples: 1GB, 5TB, 512MB, 2048 (bytes)\n"); printf("Pad selection: Full chksum or prefix\n"); } diff --git a/otp.h b/otp.h index 855093d..df93e29 100644 --- a/otp.h +++ b/otp.h @@ -31,74 +31,10 @@ #define FILES_DIR "files" #define MAX_ENTROPY_BUFFER 32768 // 32KB entropy buffer -// USB Drive constants -#define MAX_USB_DRIVES 16 // Maximum USB drives to enumerate -#define USB_LABEL_PREFIX "OTP_" // Prefix for OTP USB drive labels -#define MAX_USB_LABEL_LENGTH 32 // Maximum length for USB volume labels - //////////////////////////////////////////////////////////////////////////////// // TYPE DEFINITIONS //////////////////////////////////////////////////////////////////////////////// -// USB Drive Information Structure -typedef struct { - char device_path[512]; // e.g., "/dev/sdb1" - char device_name[64]; // e.g., "sdb1" - char mount_path[512]; // e.g., "/media/user/OTP_ALICE" - char volume_label[64]; // e.g., "OTP_ALICE" - char filesystem[16]; // e.g., "ext4", "vfat" - char bus_type[16]; // "usb", "sata", "nvme", etc. - uint64_t total_size; // Total drive capacity in bytes - uint64_t available_size; // Available space in bytes - int is_mounted; // 1 if currently mounted, 0 otherwise - int is_otp_drive; // 1 if recognized as OTP drive - int is_removable; // 1 if removable media, 0 if fixed - int is_usb_device; // 1 if connected via USB bus - int is_system_mount; // 1 if critical system mount - int is_safe; // 1 if passed safety validation, 0 if unsafe - int pad_count; // Number of pads on drive -} usb_drive_info_t; - -// USB Operation Result Structure -typedef struct { - int success; // 1 for success, 0 for failure - char error_message[256]; // Error description if failed - int drives_found; // Number of drives discovered - int pads_transferred; // Number of pads copied/verified - uint64_t bytes_processed; // Total data processed -} usb_operation_result_t; - -// New simplified USB device structures for lsusb cross-referencing -typedef struct { - char vendor_id[8]; // "1234" from lsusb - char product_id[8]; // "5678" from lsusb - char vendor_name[64]; // "SanDisk Corp." from lsusb - char product_name[128]; // "Ultra Fit" from lsusb - char bus_number[4]; // "001" from lsusb - char device_number[4]; // "003" from lsusb -} usb_device_registry_t; - -// Simplified USB status for new detection system -typedef enum { - USB_SAFE, // ✓ Safe USB drive detected by lsusb - USB_TOO_LARGE, // ⚠ Drive over 6TB safety limit - USB_NOT_USB // ✗ Not found in USB device registry -} usb_safety_status_t; - -// New simplified drive info structure -typedef struct { - char mount_path[512]; // "/media/user/DUAL DRIVE" - char device_path[64]; // "/dev/sda1" - char device_name[16]; // "sda" - char label[64]; // "DUAL DRIVE" - char filesystem[16]; // "vfat" - uint64_t total_size; // Total bytes - uint64_t free_size; // Free bytes - int pad_count; // Number of .pad files - usb_safety_status_t status; // USB safety status - usb_device_registry_t *usb_device; // Pointer to USB device info (NULL if not USB) -} drive_info_v2_t; - // Decrypt operation modes for universal decrypt function typedef enum { DECRYPT_MODE_INTERACTIVE, // Interactive text decryption with prompts @@ -166,62 +102,6 @@ int detect_otp_thumb_drive(char* otp_drive_path, size_t path_size); // USB DRIVE MANAGEMENT FUNCTIONS //////////////////////////////////////////////////////////////////////////////// -// USB Drive Discovery Functions -int discover_usb_drives(usb_drive_info_t** drives, int* drive_count); -int get_usb_drive_info(const char* mount_path, const char* drive_label, usb_drive_info_t* drive_info); -int get_device_from_mount(const char* mount_path, char* device_path, size_t device_path_size); -void format_size_string(uint64_t bytes, char* result, size_t result_size); - -// USB Device Safety Functions -int is_device_removable_usb(const char* device_path); -int get_device_bus_type(const char* device_path, char* bus_type, size_t bus_type_size); -int is_system_critical_mount(const char* mount_path); -int validate_usb_device_safety(const usb_drive_info_t* drive); -int extract_device_name_from_path(const char* device_path, char* device_name, size_t device_name_size); - -// Drive Initialization Functions -usb_operation_result_t initialize_usb_drive(const char* mount_path, const char* drive_name, - int format_drive, const char* filesystem_type); -int set_volume_label(const char* mount_path, const char* new_label); - -// Pad Transfer Functions -int copy_pad_to_usb(const char* pad_checksum, const char* usb_mount_path); -int copy_pad_from_usb(const char* usb_mount_path, const char* pad_checksum); -int copy_file(const char* source_path, const char* dest_path); -int list_pads_on_drive(const char* mount_path, char pad_list[][65], int max_pads); -int verify_pad_integrity_cross_drive(const char* local_pad, const char* usb_pad); - -// Drive Duplication Functions -int duplicate_drive_selective(const char* source_mount, const char* dest_mount, - char selected_pads[][65], int pad_count); -int verify_drive_duplication(const char* source_mount, const char* dest_mount); - -// USB Menu Integration Functions -int handle_usb_submenu(void); -int handle_initialize_usb(void); -int handle_copy_pad_to_usb(void); -int handle_import_pad_from_usb(void); -int handle_duplicate_usb_drive(void); -int handle_verify_usb_drive(void); -int handle_list_usb_drives(void); -usb_drive_info_t* select_usb_drive_interactive(const char* title, const char* prompt, int require_otp); - -// USB CLI handler functions -int handle_list_usb_drives_cli(void); -int handle_usb_init_cli(int argc, char* argv[]); -int handle_usb_copy_cli(const char* pad_prefix, const char* usb_path); -int handle_usb_import_cli(const char* pad_checksum, const char* usb_path); -int handle_usb_verify_cli(const char* usb_path); - -// New simplified USB detection system functions -int build_usb_device_registry(usb_device_registry_t **devices, int *device_count); -void free_usb_device_registry(usb_device_registry_t *devices); -usb_device_registry_t* find_usb_device_by_path(const char* device_path, - usb_device_registry_t* usb_devices, int usb_count); -int detect_drive_info_v2(const char* mount_path, drive_info_v2_t* drive_info, - usb_device_registry_t* usb_devices, int usb_count); -void list_usb_drives_v2(void); -const char* get_usb_status_string(usb_safety_status_t status); //////////////////////////////////////////////////////////////////////////////// // EXTERNAL TOOL INTEGRATION FUNCTIONS