This commit is contained in:
cfif 2026-05-28 14:31:57 +03:00
parent f161bcdfab
commit 87fa30640f
1 changed files with 23 additions and 162 deletions

View File

@ -230,15 +230,11 @@ uint32_t calculate_file_crc32_full(const char *filename, int verbose) {
} }
/** /**
* @brief Записывает размер данных и CRC32 в файл * @brief Записывает CRC32 в последние 4 байта файла
* Размер данных (file_size - 4) записывается по смещению 256 байт от конца файла
* CRC32 записывается в последние 4 байта файла
*/ */
int write_crc32_to_file(const char *filename, uint32_t crc_value, int verbose) { int write_crc32_to_file(const char *filename, uint32_t crc_value, int verbose) {
FILE *file = NULL; FILE *file = NULL;
long file_size; long file_size;
long data_size;
int result = 0;
file = fopen(filename, "rb+"); file = fopen(filename, "rb+");
if (file == NULL) { if (file == NULL) {
@ -246,7 +242,6 @@ int write_crc32_to_file(const char *filename, uint32_t crc_value, int verbose) {
return -1; return -1;
} }
// Получаем размер файла
if (fseek(file, 0, SEEK_END) != 0) { if (fseek(file, 0, SEEK_END) != 0) {
perror("Failed to seek to end"); perror("Failed to seek to end");
fclose(file); fclose(file);
@ -260,70 +255,11 @@ int write_crc32_to_file(const char *filename, uint32_t crc_value, int verbose) {
return -1; return -1;
} }
data_size = file_size - 4; // Размер данных без CRC // Перемещаемся на позицию последних 4 байт
if (verbose) {
printf("File size: %ld bytes\n", file_size);
printf("Data size (without CRC): %ld bytes (0x%lX)\n", data_size, data_size);
printf("CRC value: 0x%08X (%u)\n", crc_value, crc_value);
}
// ==============================================
// 1. Записываем размер данных по смещению 256 байт от конца файла
// ==============================================
long data_size_offset = file_size - 256; // Позиция для размера данных (ровно 256 байт от конца)
// Проверяем, что позиция не отрицательная и не перекрывается с CRC
if (data_size_offset < 0) {
fprintf(stderr, "Warning: File too small, cannot write data size at offset 256 from end\n");
fprintf(stderr, "File size: %ld bytes, need at least 256 bytes\n", file_size);
if (verbose) {
printf("Skipping data size write (file too small)\n");
}
} else if (data_size_offset + 4 > file_size - 4) {
fprintf(stderr, "Warning: Data size position overlaps with CRC area\n");
fprintf(stderr, "Data size would be at %ld, CRC at %ld\n", data_size_offset, file_size - 4);
if (verbose) {
printf("Skipping data size write (overlap detected)\n");
}
} else {
// Перемещаемся на позицию для записи размера данных
if (fseek(file, data_size_offset, SEEK_SET) != 0) {
perror("Failed to seek to data size position");
result = -1;
goto cleanup;
}
// Записываем размер данных в little-endian порядке (4 байта для 32-битного размера)
uint8_t size_bytes[4];
size_bytes[0] = (data_size >> 0) & 0xFF;
size_bytes[1] = (data_size >> 8) & 0xFF;
size_bytes[2] = (data_size >> 16) & 0xFF;
size_bytes[3] = (data_size >> 24) & 0xFF;
size_t bytes_written = fwrite(size_bytes, 1, 4, file);
if (bytes_written != 4) {
fprintf(stderr, "Failed to write data size to file\n");
result = -1;
goto cleanup;
}
if (verbose) {
printf("\nData size written: %ld bytes (0x%lX)\n", data_size, data_size);
printf(" Position: %ld (0x%lX) bytes from start\n", data_size_offset, data_size_offset);
printf(" Distance from end: %ld bytes (exactly 256 bytes)\n", file_size - data_size_offset);
printf(" Bytes written (LE 32-bit): %02X %02X %02X %02X\n",
size_bytes[0], size_bytes[1], size_bytes[2], size_bytes[3]);
}
}
// ==============================================
// 2. Записываем CRC в последние 4 байта файла
// ==============================================
if (fseek(file, file_size - 4, SEEK_SET) != 0) { if (fseek(file, file_size - 4, SEEK_SET) != 0) {
perror("Failed to seek to CRC position"); perror("Failed to seek to CRC position");
result = -1; fclose(file);
goto cleanup; return -1;
} }
// Записываем CRC в little-endian порядке // Записываем CRC в little-endian порядке
@ -336,34 +272,29 @@ int write_crc32_to_file(const char *filename, uint32_t crc_value, int verbose) {
size_t bytes_written = fwrite(crc_bytes, 1, 4, file); size_t bytes_written = fwrite(crc_bytes, 1, 4, file);
if (bytes_written != 4) { if (bytes_written != 4) {
fprintf(stderr, "Failed to write CRC to file\n"); fprintf(stderr, "Failed to write CRC to file\n");
result = -1; fclose(file);
goto cleanup; return -1;
} }
fclose(file);
if (verbose) { if (verbose) {
printf("\nCRC32 value written: 0x%08X (%u)\n", crc_value, crc_value); printf("CRC32 value written: 0x%08X (%u)\n", crc_value, crc_value);
printf(" Position: %ld-%ld (last 4 bytes)\n", file_size - 4, file_size - 1); printf("Written to bytes: %ld-%ld (last 4 bytes)\n", file_size - 4, file_size - 1);
printf(" Bytes written (LE): %02X %02X %02X %02X\n",
crc_bytes[0], crc_bytes[1], crc_bytes[2], crc_bytes[3]);
printf("Byte order: little-endian (LSB first)\n"); printf("Byte order: little-endian (LSB first)\n");
} }
cleanup: return 0;
fclose(file);
return result;
} }
/** /**
* @brief Проверяет CRC32, сравнивая вычисленное значение с сохраненным * @brief Проверяет CRC32, сравнивая вычисленное значение с сохраненным
* Также опционально проверяет сохраненный размер данных
*/ */
int verify_crc32(const char *filename, int verbose) { int verify_crc32(const char *filename, int verbose) {
FILE *file = NULL; FILE *file = NULL;
long file_size; long file_size;
long stored_data_size = 0;
uint32_t calculated_crc = 0; uint32_t calculated_crc = 0;
uint32_t stored_crc = 0; uint32_t stored_crc = 0;
int verify_size = 1; // Флаг проверки размера
file = fopen(filename, "rb"); file = fopen(filename, "rb");
if (file == NULL) { if (file == NULL) {
@ -388,48 +319,7 @@ int verify_crc32(const char *filename, int verbose) {
printf("File size: %ld bytes\n", file_size); printf("File size: %ld bytes\n", file_size);
} }
// ============================================== // Читаем сохраненный CRC из последних 4 байт
// 1. Читаем сохраненный размер данных (опционально)
// ==============================================
long data_size_offset = file_size - 256; // Позиция размера данных (256 байт от конца)
if (data_size_offset >= 0 && data_size_offset + 4 <= file_size - 4) {
if (fseek(file, data_size_offset, SEEK_SET) != 0) {
perror("Failed to seek to stored data size");
verify_size = 0;
} else {
uint8_t size_bytes[4];
size_t bytes_read = fread(size_bytes, 1, 4, file);
if (bytes_read == 4) {
stored_data_size = (long)size_bytes[0] << 0 |
(long)size_bytes[1] << 8 |
(long)size_bytes[2] << 16 |
(long)size_bytes[3] << 24;
if (verbose) {
printf("\nStored data size: %ld bytes (0x%lX) at offset %ld\n",
stored_data_size, stored_data_size, data_size_offset);
printf(" Distance from end: %ld bytes (exactly 256 bytes)\n", file_size - data_size_offset);
printf(" Bytes read (LE 32-bit): %02X %02X %02X %02X\n",
size_bytes[0], size_bytes[1], size_bytes[2], size_bytes[3]);
}
} else {
verify_size = 0;
if (verbose) {
printf("Failed to read stored data size (expected 4 bytes, got %zu)\n", bytes_read);
}
}
}
} else {
verify_size = 0;
if (verbose) {
printf("\nNo valid data size stored at offset 256 bytes from end\n");
printf(" File size: %ld, would need at least %ld bytes\n", file_size, 256 + 4);
}
}
// ==============================================
// 2. Читаем сохраненный CRC из последних 4 байт
// ==============================================
if (fseek(file, file_size - 4, SEEK_SET) != 0) { if (fseek(file, file_size - 4, SEEK_SET) != 0) {
perror("Failed to seek to stored CRC"); perror("Failed to seek to stored CRC");
fclose(file); fclose(file);
@ -458,48 +348,20 @@ int verify_crc32(const char *filename, int verbose) {
return -1; return -1;
} }
long actual_data_size = file_size - 4;
// Всегда выводим значения CRC при проверке // Всегда выводим значения CRC при проверке
printf("\n╔════════════════════════════════════════════════════════════╗\n"); printf("\n╔════════════════════════════════════════╗\n");
printf("║ CRC32 Verification ║\n"); printf("║ CRC32 Verification ║\n");
printf("╠════════════════════════════════════════════════════════════╣\n"); printf("╠════════════════════════════════════════╣\n");
printf("║ Stored CRC : 0x%08X (%10u) ║\n", stored_crc, stored_crc); printf("║ Stored CRC : 0x%08X (%10u) ║\n", stored_crc, stored_crc);
printf("║ Calculated CRC : 0x%08X (%10u) ║\n", calculated_crc, calculated_crc); printf("║ Calculated CRC : 0x%08X (%10u) ║\n", calculated_crc, calculated_crc);
printf("╚════════════════════════════════════════╝\n");
if (verify_size && stored_data_size > 0) { if (calculated_crc == stored_crc) {
printf("╠════════════════════════════════════════════════════════════╣\n"); printf("\n✓ VERIFIED: CRC matches! File integrity check passed.\n");
printf("║ Stored data size : %12ld bytes (0x%lX) ║\n", stored_data_size, stored_data_size);
printf("║ Actual data size : %12ld bytes (0x%lX) ║\n", actual_data_size, actual_data_size);
}
printf("╚════════════════════════════════════════════════════════════╝\n");
int crc_valid = (calculated_crc == stored_crc);
int size_valid = 1;
if (verify_size && stored_data_size > 0) {
size_valid = (actual_data_size == stored_data_size);
}
if (crc_valid && size_valid) {
printf("\n✓ VERIFIED: CRC matches and data size is correct! File integrity check passed.\n");
return 0; return 0;
} else if (crc_valid && !size_valid) {
printf("\n⚠ WARNING: CRC matches but data size mismatch!\n");
printf(" Stored size: %ld, Actual size: %ld, Difference: %ld\n",
stored_data_size, actual_data_size, actual_data_size - stored_data_size);
return 1;
} else if (!crc_valid && size_valid) {
printf("\n✗ MISMATCH: File is corrupted! CRC does not match (data size OK).\n");
printf(" Difference: 0x%08X\n", calculated_crc ^ stored_crc);
return 1;
} else { } else {
printf("\n✗ MISMATCH: File is corrupted! Both CRC and data size are incorrect!\n"); printf("\n✗ MISMATCH: File is corrupted or CRC was not written correctly!\n");
printf(" CRC difference: 0x%08X\n", calculated_crc ^ stored_crc); printf(" Difference: 0x%08X\n", calculated_crc ^ stored_crc);
if (verify_size && stored_data_size > 0) {
printf(" Size difference: %ld bytes\n", actual_data_size - stored_data_size);
}
return 1; return 1;
} }
} }
@ -704,7 +566,6 @@ void print_usage(const char *program_name) {
printf("\nNote:\n"); printf("\nNote:\n");
printf(" For -w and -c operations, CRC is calculated from the first\n"); printf(" For -w and -c operations, CRC is calculated from the first\n");
printf(" (file_size - 4) bytes, ignoring the last 4 bytes.\n"); printf(" (file_size - 4) bytes, ignoring the last 4 bytes.\n");
printf(" Data size (file_size - 4) is written at offset 256 bytes from end.\n");
printf(" For split operation, offset can be specified in decimal or hex (0x prefix).\n"); printf(" For split operation, offset can be specified in decimal or hex (0x prefix).\n");
printf(" If output filenames are not specified, default names will be used:\n"); printf(" If output filenames are not specified, default names will be used:\n");
printf(" <input>_part1.bin and <input>_part2.bin\n"); printf(" <input>_part1.bin and <input>_part2.bin\n");
@ -870,7 +731,7 @@ int main(int argc, char *argv[]) {
printf("╚════════════════════════════════════════╝\n"); printf("╚════════════════════════════════════════╝\n");
if (options.verbose) { if (options.verbose) {
printf("\nStep 2: Writing CRC and data size to file...\n"); printf("\nStep 2: Writing CRC to last 4 bytes...\n");
} }
result = write_crc32_to_file(options.filename, crc_value, options.verbose); result = write_crc32_to_file(options.filename, crc_value, options.verbose);