Added size suffixes
This commit is contained in:
84
main.c
84
main.c
@@ -24,6 +24,7 @@
|
||||
#include <ctype.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Define CRTSCTS if not available
|
||||
#ifndef CRTSCTS
|
||||
@@ -63,12 +64,71 @@ struct Options options;
|
||||
// Global variables
|
||||
static int ones_in_byte[256];
|
||||
|
||||
// Parse byte size with optional suffix (K, MB, GB, TB)
|
||||
// Returns: parsed size in bytes, or -1 on error
|
||||
// Sets *error to 1 if parsing fails, 0 on success
|
||||
long long parse_byte_size(const char* size_str, int* error) {
|
||||
if (!size_str || !error) {
|
||||
if (error) *error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*error = 0;
|
||||
char* endptr;
|
||||
double value = strtod(size_str, &endptr);
|
||||
|
||||
if (value < 0) {
|
||||
*error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If no suffix, return the value as bytes (backward compatibility)
|
||||
if (*endptr == '\0') {
|
||||
if (value > LLONG_MAX) {
|
||||
*error = 1;
|
||||
return -1;
|
||||
}
|
||||
return (long long)value;
|
||||
}
|
||||
|
||||
// Parse suffix (case-insensitive)
|
||||
char suffix[4] = {0};
|
||||
int i = 0;
|
||||
while (*endptr && i < 3) {
|
||||
suffix[i++] = toupper(*endptr++);
|
||||
}
|
||||
|
||||
// Determine multiplier
|
||||
long long multiplier = 1;
|
||||
if (strcmp(suffix, "K") == 0 || strcmp(suffix, "KB") == 0) {
|
||||
multiplier = 1024LL;
|
||||
} else if (strcmp(suffix, "M") == 0 || strcmp(suffix, "MB") == 0) {
|
||||
multiplier = 1024LL * 1024LL;
|
||||
} else if (strcmp(suffix, "G") == 0 || strcmp(suffix, "GB") == 0) {
|
||||
multiplier = 1024LL * 1024LL * 1024LL;
|
||||
} else if (strcmp(suffix, "T") == 0 || strcmp(suffix, "TB") == 0) {
|
||||
multiplier = 1024LL * 1024LL * 1024LL * 1024LL;
|
||||
} else {
|
||||
*error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check for overflow
|
||||
if (value > (double)LLONG_MAX / multiplier) {
|
||||
*error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (long long)(value * multiplier);
|
||||
}
|
||||
|
||||
// Output format functions
|
||||
void output_binary(unsigned char *buffer, int bytes_read, FILE *out) {
|
||||
fwrite(buffer, 1, bytes_read, out);
|
||||
}
|
||||
|
||||
void output_hex(unsigned char *buffer, int bytes_read, FILE *out, int piped) {
|
||||
(void)piped; // Suppress unused parameter warning
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
fprintf(out, "%02x", buffer[i]);
|
||||
}
|
||||
@@ -77,6 +137,7 @@ void output_hex(unsigned char *buffer, int bytes_read, FILE *out, int piped) {
|
||||
}
|
||||
|
||||
void output_decimal(unsigned char *buffer, int bytes_read, FILE *out, int piped) {
|
||||
(void)piped; // Suppress unused parameter warning
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
fprintf(out, "%d", buffer[i]);
|
||||
}
|
||||
@@ -85,6 +146,7 @@ void output_decimal(unsigned char *buffer, int bytes_read, FILE *out, int piped)
|
||||
}
|
||||
|
||||
void output_base64(unsigned char *buffer, int bytes_read, FILE *out, int piped) {
|
||||
(void)piped; // Suppress unused parameter warning
|
||||
static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char encoded[5];
|
||||
for (int i = 0; i < bytes_read; i += 3) {
|
||||
@@ -118,6 +180,7 @@ void print_usage(void) {
|
||||
printf("Usage: truerng [OPTIONS]\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -n, --bytes <N> Number of bytes to generate (default: 1048576)\n");
|
||||
printf(" Supports suffixes: K, MB, GB, TB (e.g., 1K, 2.5MB, 1GB)\n");
|
||||
printf(" -f, --format <FORMAT> Output format: binary, hex, base64, decimal (default: binary when piped, interactive otherwise)\n");
|
||||
printf(" -o, --output <FILE> Output filename (ignored in piped mode)\n");
|
||||
printf(" -q, --quiet Suppress statistics/progress\n");
|
||||
@@ -125,8 +188,10 @@ void print_usage(void) {
|
||||
printf(" -h, --help Show this help message\n");
|
||||
printf("\nExamples:\n");
|
||||
printf(" truerng -n 1024 -f hex # Interactive mode with hex output\n");
|
||||
printf(" truerng -n 1024 | xxd # Piped mode to hex viewer\n");
|
||||
printf(" truerng -o random.dat -q # Save to file quietly\n");
|
||||
printf(" truerng -n 1K -f hex # Same as above using K suffix\n");
|
||||
printf(" truerng -n 2.5MB | xxd # Piped mode with MB suffix\n");
|
||||
printf(" truerng -n 1GB -o random.dat -q # Save 1GB to file quietly\n");
|
||||
printf(" truerng -n 512K -f hex -o output.hex # Save 512KB as hex to file\n");
|
||||
}
|
||||
|
||||
int parse_arguments(int argc, char *argv[]) {
|
||||
@@ -152,13 +217,15 @@ int parse_arguments(int argc, char *argv[]) {
|
||||
int option_index = 0;
|
||||
while ((opt = getopt_long(argc, argv, opt_string, long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
options.bytes = atol(optarg);
|
||||
if (options.bytes <= 0) {
|
||||
fprintf(stderr, "Error: Bytes must be positive\n");
|
||||
case 'n': {
|
||||
int parse_error;
|
||||
options.bytes = parse_byte_size(optarg, &parse_error);
|
||||
if (parse_error || options.bytes <= 0) {
|
||||
fprintf(stderr, "Error: Invalid byte size '%s'. Use a positive number optionally followed by K, MB, GB, or TB\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
if (strcmp(optarg, "binary") == 0) options.format = BINARY;
|
||||
else if (strcmp(optarg, "hex") == 0) options.format = HEX;
|
||||
@@ -199,6 +266,7 @@ int find_truerng_port(char* port_path, int piped, int verbose);
|
||||
int setup_serial_port(const char* port_path);
|
||||
int read_usb_device_info(const char* port_name, char* vid, char* pid);
|
||||
double get_time_diff(struct timeval start, struct timeval end);
|
||||
long long parse_byte_size(const char* size_str, int* error);
|
||||
int parse_arguments(int argc, char *argv[]);
|
||||
void print_usage(void);
|
||||
int is_piped(void);
|
||||
@@ -573,7 +641,9 @@ cleanup:
|
||||
// Reset terminal min setting
|
||||
char stty_cmd[MAX_PATH + 20];
|
||||
snprintf(stty_cmd, sizeof(stty_cmd), "stty -F %s min 1", port_path);
|
||||
system(stty_cmd); // Ignore failure
|
||||
if (system(stty_cmd) != 0) {
|
||||
// Ignore failure - this is just cleanup
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user