From cf52274c2cd0737988dab36fe0e67f387edd0c4d Mon Sep 17 00:00:00 2001 From: Laan Tungir Date: Sat, 20 Dec 2025 09:25:38 -0400 Subject: [PATCH] Version v0.3.34 - Fixed usb space reporting --- README.md | 18 +++++--------- build.sh | 9 ++++--- src/main.h | 2 +- src/pads.c | 72 +++++++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index e465626..f05ea12 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Introduction -A secure one-time pad (OTP) cipher implementation in C. +A secure one-time pad (OTP) cipher implementation in C99. ## Why One-Time Pads @@ -58,20 +58,19 @@ One-time pads can be trivially encrypted and decrypted using pencil and paper, m ### Download Pre-Built Binaries -**[Download Current Linux x86](https://git.laantungir.net/laantungir/otp/releases/download/v0.3.32/otp-v0.3.32-linux-x86_64)** +**[Download Current Linux x86](https://git.laantungir.net/laantungir/otp/releases/download/v0.3.33/otp-v0.3.33-linux-x86_64)** -**[Download Current Raspberry Pi 64](https://git.laantungir.net/laantungir/otp/releases/download/v0.3.32/otp-v0.3.32-linux-arm64)** +**[Download Current Raspberry Pi 64](https://git.laantungir.net/laantungir/otp/releases/download/v0.3.33/otp-v0.3.33-linux-arm64)** After downloading: ```bash -# Make executable and rename for convenience -chmod +x otp-v0.3.32-linux-x86_64 -mv otp-v0.3.32-linux-x86_64 otp +# Rename for convenience, then make executable +mv otp-v0.3.33-linux-x86_64 otp +chmod +x otp # Run it ./otp ``` - ### First Steps 1. **Generate your first pad:** @@ -93,11 +92,6 @@ mv otp-v0.3.32-linux-x86_64 otp - - - - - ## Building from Source ### Prerequisites diff --git a/build.sh b/build.sh index af50bab..190def4 100755 --- a/build.sh +++ b/build.sh @@ -169,9 +169,12 @@ update_source_version() { After downloading: \`\`\`bash -# Make executable and run -chmod +x otp-${NEW_VERSION}-linux-x86_64 -./otp-${NEW_VERSION}-linux-x86_64 +# Rename for convenience, then make executable +mv otp-${NEW_VERSION}-linux-x86_64 otp +chmod +x otp + +# Run it +./otp \`\`\`" # Use awk to replace the section between "### Download Pre-Built Binaries" and "### First Steps" diff --git a/src/main.h b/src/main.h index 0854662..eba0325 100644 --- a/src/main.h +++ b/src/main.h @@ -23,7 +23,7 @@ #include // Version - Updated automatically by build.sh -#define OTP_VERSION "v0.3.32" +#define OTP_VERSION "v0.3.33" // Constants #define MAX_INPUT_SIZE 4096 diff --git a/src/pads.c b/src/pads.c index 216dc67..8f5e4c2 100644 --- a/src/pads.c +++ b/src/pads.c @@ -89,18 +89,18 @@ int generate_pad(uint64_t size_bytes, int display_progress) { const char* pads_dir = get_current_pads_dir(); struct statvfs stat; if (statvfs(pads_dir, &stat) == 0) { - // Use f_bfree (total free blocks) instead of f_bavail (available to non-root) - // This gives the actual free space on the filesystem, which is more accurate - // for removable media and user-owned directories - uint64_t available_bytes = stat.f_bfree * stat.f_frsize; + // Use f_bavail (available to non-root users) for accurate space reporting + // This accounts for filesystem reserved space (e.g., 5% on ext4) + uint64_t available_bytes = stat.f_bavail * stat.f_frsize; double available_gb = (double)available_bytes / (1024.0 * 1024.0 * 1024.0); double required_gb = (double)size_bytes / (1024.0 * 1024.0 * 1024.0); if (available_bytes < size_bytes) { printf("\n⚠ WARNING: Insufficient disk space!\n"); - printf(" Required: %.2f GB\n", required_gb); - printf(" Available: %.2f GB\n", available_gb); + printf(" Required: %.2f GB (%lu bytes)\n", required_gb, size_bytes); + printf(" Available: %.2f GB (%lu bytes)\n", available_gb, available_bytes); printf(" Shortfall: %.2f GB\n", required_gb - available_gb); + printf(" Location: %s\n", pads_dir); printf("\nContinue anyway? (y/N): "); char response[10]; @@ -129,11 +129,54 @@ int generate_pad(uint64_t size_bytes, int display_progress) { FILE* pad_file = fopen(temp_filename, "wb"); if (!pad_file) { - printf("Error: Cannot create temporary pad file %s\n", temp_filename); + printf("Error: Cannot create temporary pad file '%s': %s (errno %d)\n", + temp_filename, strerror(errno), errno); fclose(urandom); return 1; } + // Preallocate full file size using posix_fallocate for guaranteed space reservation + // This actually allocates disk blocks (unlike ftruncate which creates sparse files) + int fd = fileno(pad_file); + double size_gb = (double)size_bytes / (1024.0 * 1024.0 * 1024.0); + + if (display_progress) { + printf("Allocating %.2f GB on disk...\n", size_gb); + } + + int alloc_result = posix_fallocate(fd, 0, (off_t)size_bytes); + if (alloc_result != 0) { + printf("Error: Failed to allocate %.2f GB temp file: %s (errno %d)\n", + size_gb, strerror(alloc_result), alloc_result); + printf(" Temp file: %s\n", temp_filename); + printf(" Location: %s\n", pads_dir); + + if (alloc_result == ENOSPC) { + printf(" Cause: No space left on device\n"); + printf(" This means the actual available space is less than reported\n"); + } else if (alloc_result == EOPNOTSUPP) { + printf(" Cause: Filesystem doesn't support posix_fallocate\n"); + printf(" Falling back to ftruncate (sparse file)...\n"); + if (ftruncate(fd, (off_t)size_bytes) != 0) { + printf(" Fallback failed: %s\n", strerror(errno)); + fclose(pad_file); + fclose(urandom); + unlink(temp_filename); + return 1; + } + } else { + printf(" Possible causes: quota limits, filesystem restrictions\n"); + fclose(pad_file); + fclose(urandom); + unlink(temp_filename); + return 1; + } + } + + if (display_progress && alloc_result == 0) { + printf("✓ Allocated %.2f GB on disk (guaranteed space)\n", size_gb); + } + unsigned char buffer[64 * 1024]; // 64KB buffer uint64_t bytes_written = 0; time_t start_time = time(NULL); @@ -149,7 +192,8 @@ int generate_pad(uint64_t size_bytes, int display_progress) { } if (fread(buffer, 1, (size_t)chunk_size, urandom) != (size_t)chunk_size) { - printf("Error: Failed to read from /dev/urandom\n"); + printf("Error: Failed to read %lu bytes from /dev/urandom at position %lu: %s (errno %d)\n", + chunk_size, bytes_written, strerror(errno), errno); fclose(urandom); fclose(pad_file); unlink(temp_filename); @@ -157,7 +201,11 @@ int generate_pad(uint64_t size_bytes, int display_progress) { } if (fwrite(buffer, 1, (size_t)chunk_size, pad_file) != (size_t)chunk_size) { - printf("Error: Failed to write to pad file\n"); + printf("Error: fwrite failed for %lu bytes at position %lu/%lu (%.1f%%): %s (errno %d)\n", + chunk_size, bytes_written, size_bytes, + (double)bytes_written / size_bytes * 100.0, strerror(errno), errno); + printf(" Temp file: %s\n", temp_filename); + printf(" Disk space was checked - possible causes: fragmentation, I/O timeout, quota\n"); fclose(urandom); fclose(pad_file); unlink(temp_filename); @@ -216,8 +264,10 @@ int generate_pad(uint64_t size_bytes, int display_progress) { return 1; } - double size_gb = (double)size_bytes / (1024.0 * 1024.0 * 1024.0); - printf("Generated pad: %s (%.2f GB)\n", pad_path, size_gb); + if (display_progress) { + double final_size_gb = (double)size_bytes / (1024.0 * 1024.0 * 1024.0); + printf("Generated pad: %s (%.2f GB)\n", pad_path, final_size_gb); + } printf("Pad checksum: %s\n", chksum_hex); printf("State file: %s\n", state_path); printf("Pad file set to read-only\n");