This commit is contained in:
cfif 2026-06-02 10:44:45 +03:00
parent 87fa30640f
commit c337f34aaf
1 changed files with 93 additions and 83 deletions

View File

@ -2,7 +2,13 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
// Кроссплатформенная совместимость
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#define strdup _strdup
#pragma warning(disable: 4996)
#endif
// Таблица CRC32 для полинома 0xEDB88320 (IEEE 802.3)
static const uint32_t crc32_table[256] = {
@ -126,12 +132,14 @@ uint32_t calculate_file_crc32_without_last4(const char *filename, int verbose) {
}
// Выделяем память под данные
if (data_size > 0) {
buffer = (uint8_t*)malloc(data_size);
if (buffer == NULL && data_size > 0) {
if (buffer == NULL) {
perror("Failed to allocate memory");
fclose(file);
return 0;
}
}
// Возвращаемся в начало
if (fseek(file, 0, SEEK_SET) != 0) {
@ -144,7 +152,7 @@ uint32_t calculate_file_crc32_without_last4(const char *filename, int verbose) {
// Читаем данные (все, кроме последних 4 байт)
if (data_size > 0) {
size_t bytes_read = fread(buffer, 1, data_size, file);
if (bytes_read != data_size) {
if (bytes_read != (size_t)data_size) {
fprintf(stderr, "Failed to read file data. Read %zu bytes, expected %ld bytes\n",
bytes_read, data_size);
free(buffer);
@ -155,7 +163,7 @@ uint32_t calculate_file_crc32_without_last4(const char *filename, int verbose) {
// Вычисляем CRC
if (data_size > 0) {
crc = calculate_crc32(buffer, data_size);
crc = calculate_crc32(buffer, (uint32_t)data_size);
} else {
crc = calculate_crc32(NULL, 0);
}
@ -214,14 +222,14 @@ uint32_t calculate_file_crc32_full(const char *filename, int verbose) {
}
size_t bytes_read = fread(buffer, 1, file_size, file);
if (bytes_read != file_size) {
if (bytes_read != (size_t)file_size) {
fprintf(stderr, "Failed to read entire file\n");
free(buffer);
fclose(file);
return 0;
}
crc = calculate_crc32(buffer, file_size);
crc = calculate_crc32(buffer, (uint32_t)file_size);
free(buffer);
fclose(file);
@ -349,12 +357,9 @@ int verify_crc32(const char *filename, int verbose) {
}
// Всегда выводим значения CRC при проверке
printf("\n╔════════════════════════════════════════╗\n");
printf("║ CRC32 Verification ║\n");
printf("╠════════════════════════════════════════╣\n");
printf("║ Stored CRC : 0x%08X (%10u) ║\n", stored_crc, stored_crc);
printf("║ Calculated CRC : 0x%08X (%10u) ║\n", calculated_crc, calculated_crc);
printf("╚════════════════════════════════════════╝\n");
printf("\nCRC32 Verification:\n");
printf("Stored CRC : 0x%08X (%u)\n", stored_crc, stored_crc);
printf("Calculated CRC : 0x%08X (%u)\n", calculated_crc, calculated_crc);
if (calculated_crc == stored_crc) {
printf("\n✓ VERIFIED: CRC matches! File integrity check passed.\n");
@ -460,7 +465,7 @@ int split_bin_file(const char *input_file, long offset, const char *output1, con
long next_progress = progress_step;
while (remaining > 0) {
size_t to_read = (remaining < buffer_size) ? remaining : buffer_size;
size_t to_read = (remaining < (long)buffer_size) ? (size_t)remaining : buffer_size;
bytes_read = fread(buffer, 1, to_read, fin);
if (bytes_read != to_read) {
fprintf(stderr, "Error reading input file (first part)\n");
@ -475,7 +480,7 @@ int split_bin_file(const char *input_file, long offset, const char *output1, con
goto cleanup;
}
remaining -= bytes_read;
remaining -= (long)bytes_read;
if (verbose && progress_step > 0 && remaining <= next_progress) {
int percent = (int)((bytes_to_copy1 - remaining) * 100 / bytes_to_copy1);
@ -494,7 +499,7 @@ int split_bin_file(const char *input_file, long offset, const char *output1, con
next_progress = bytes_to_copy2 - progress_step;
while (remaining > 0) {
size_t to_read = (remaining < buffer_size) ? remaining : buffer_size;
size_t to_read = (remaining < (long)buffer_size) ? (size_t)remaining : buffer_size;
bytes_read = fread(buffer, 1, to_read, fin);
if (bytes_read != to_read) {
fprintf(stderr, "Error reading input file (second part)\n");
@ -509,7 +514,7 @@ int split_bin_file(const char *input_file, long offset, const char *output1, con
goto cleanup;
}
remaining -= bytes_read;
remaining -= (long)bytes_read;
if (verbose && progress_step > 0 && remaining <= next_progress) {
int percent = (int)((bytes_to_copy2 - remaining) * 100 / bytes_to_copy2);
@ -576,20 +581,7 @@ void print_usage(const char *program_name) {
* @brief Разбирает аргументы командной строки
*/
int parse_arguments(int argc, char *argv[], ProgramOptions *options) {
int option_index = 0;
int c;
static struct option long_options[] = {
{"write", no_argument, 0, 'w'},
{"check", no_argument, 0, 'c'},
{"show-only", no_argument, 0, 's'},
{"split", required_argument, 0, 1000},
{"output1", required_argument, 0, 1001},
{"output2", required_argument, 0, 1002},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
int i;
memset(options, 0, sizeof(ProgramOptions));
@ -598,58 +590,79 @@ int parse_arguments(int argc, char *argv[], ProgramOptions *options) {
options->output2 = NULL;
options->split_offset = 0;
// Поддержка коротких опций: -1 и -2 для output1/output2
while ((c = getopt_long(argc, argv, "wcsvh1:2:", long_options, &option_index)) != -1) {
switch (c) {
case 'w':
// Ручной разбор аргументов
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--write") == 0) {
options->write_crc = 1;
break;
case 'c':
}
else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--check") == 0) {
options->verify_crc = 1;
break;
case 's':
}
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--show-only") == 0) {
options->show_only = 1;
break;
case 'v':
}
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
options->verbose = 1;
break;
case 'h':
}
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return -1;
case '1': // Короткая опция -1 для output1
options->output1 = strdup(optarg);
break;
case '2': // Короткая опция -2 для output2
options->output2 = strdup(optarg);
break;
case 1000: // --split
options->split = 1;
// Поддержка шестнадцатеричных чисел
if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X')) {
options->split_offset = strtol(optarg, NULL, 16);
} else {
options->split_offset = strtol(optarg, NULL, 10);
}
break;
case 1001: // --output1
options->output1 = strdup(optarg);
break;
case 1002: // --output2
options->output2 = strdup(optarg);
break;
case '?':
else if (strcmp(argv[i], "--split") == 0) {
options->split = 1;
i++;
if (i >= argc) {
fprintf(stderr, "Error: --split requires an offset argument\n");
return -1;
}
// Поддержка шестнадцатеричных чисел
if (argv[i][0] == '0' && (argv[i][1] == 'x' || argv[i][1] == 'X')) {
options->split_offset = strtol(argv[i], NULL, 16);
}
else {
options->split_offset = strtol(argv[i], NULL, 10);
}
}
else if (strcmp(argv[i], "-1") == 0 || strcmp(argv[i], "--output1") == 0) {
i++;
if (i >= argc) {
fprintf(stderr, "Error: -1/--output1 requires a filename argument\n");
return -1;
}
options->output1 = strdup(argv[i]);
}
else if (strcmp(argv[i], "-2") == 0 || strcmp(argv[i], "--output2") == 0) {
i++;
if (i >= argc) {
fprintf(stderr, "Error: -2/--output2 requires a filename argument\n");
return -1;
}
options->output2 = strdup(argv[i]);
}
else if (argv[i][0] == '-') {
fprintf(stderr, "Error: Unknown option %s\n", argv[i]);
print_usage(argv[0]);
return -1;
}
else {
// Это должно быть имя файла
if (options->filename == NULL) {
options->filename = argv[i];
}
else {
fprintf(stderr, "Error: Multiple filenames specified\n");
return -1;
}
}
}
if (optind >= argc) {
// Проверяем, что имя файла указано
if (options->filename == NULL) {
fprintf(stderr, "Error: No filename specified.\n");
print_usage(argv[0]);
return -1;
}
options->filename = argv[optind];
// Подсчет количества выбранных режимов
int mode_count = options->write_crc + options->verify_crc + options->show_only + options->split;
if (mode_count > 1) {
@ -671,13 +684,13 @@ int parse_arguments(int argc, char *argv[], ProgramOptions *options) {
// Генерация имен выходных файлов, если не указаны
if (options->output1 == NULL) {
char *default_name = malloc(strlen(options->filename) + 10);
char *default_name = (char*)malloc(strlen(options->filename) + 10);
sprintf(default_name, "%s_part1.bin", options->filename);
options->output1 = default_name;
}
if (options->output2 == NULL) {
char *default_name = malloc(strlen(options->filename) + 10);
char *default_name = (char*)malloc(strlen(options->filename) + 10);
sprintf(default_name, "%s_part2.bin", options->filename);
options->output2 = default_name;
}
@ -724,11 +737,8 @@ int main(int argc, char *argv[]) {
}
// Всегда выводим вычисленное CRC при записи
printf("\n╔════════════════════════════════════════╗\n");
printf("║ CRC32 Calculation ║\n");
printf("╠════════════════════════════════════════╣\n");
printf("║ Calculated CRC : 0x%08X (%10u) ║\n", crc_value, crc_value);
printf("╚════════════════════════════════════════╝\n");
printf("\nCRC32 Calculation:\n");
printf("Calculated CRC : 0x%08X (%u)\n", crc_value, crc_value);
if (options.verbose) {
printf("\nStep 2: Writing CRC to last 4 bytes...\n");