Add convert command to AaruFormat tool for image conversion

This commit is contained in:
2025-09-28 17:22:19 +01:00
parent 90ca1ee872
commit 99b432cab6
7 changed files with 163 additions and 2 deletions

View File

@@ -6,6 +6,6 @@ find_package(Argtable3 CONFIG REQUIRED)
include_directories(${ICU_INCLUDE_DIRS})
add_executable(aaruformattool main.c version.h aaruformattool.h identify.c info.c helpers.c read.c printhex.c verify.c ecc_cd.c
commands.h commands.c usage.h usage.c compare.c termbox2.h)
commands.h commands.c usage.h usage.c compare.c convert.c termbox2.h)
target_link_libraries(aaruformattool "aaruformat" argtable3::argtable3)
target_link_libraries(aaruformattool "aaruformat" ICU::uc)

View File

@@ -34,5 +34,6 @@ int verify_sectors(const char *path);
bool check_cd_sector_channel(CdEccContext *context, uint8_t *sector, bool *unknown, bool *has_edc, bool *edc_correct,
bool *has_ecc_p, bool *ecc_p_correct, bool *has_ecc_q, bool *ecc_q_correct);
int compare(char *path1, char *path2);
int convert(char *input_path, char *output_path);
#endif // LIBAARUFORMAT_TOOL_AARUFORMATTOOL_H_

View File

@@ -132,6 +132,26 @@ int cmd_verify(int argc, char *argv[]) { return cmd_verify_common(argc, argv, fa
int cmd_verify_sectors(int argc, char *argv[]) { return cmd_verify_common(argc, argv, true); }
int cmd_convert(int argc, char *argv[])
{
struct arg_str *input_filename = arg_str1(NULL, NULL, "<input>", "Input image file");
struct arg_str *output_filename = arg_str1(NULL, NULL, "<output>", "Output image file");
struct arg_end *end = arg_end(10);
void *argtable[] = {input_filename, output_filename, end};
if(arg_parse(argc, argv, argtable) > 0)
{
arg_print_errors(stderr, end, "convert");
usage_convert();
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return -1;
}
int result = convert(input_filename->sval[0], output_filename->sval[0]);
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return result;
}
Command commands[] = {
{ "identify", cmd_identify},
{ "info", cmd_info},
@@ -140,6 +160,7 @@ Command commands[] = {
{ "verify", cmd_verify},
{"verify_sectors", cmd_verify_sectors},
{ "compare", cmd_compare},
{ "convert", cmd_convert},
};
const size_t num_commands = sizeof(commands) / sizeof(commands[0]);

View File

@@ -39,5 +39,6 @@ int cmd_read_long(int argc, char *argv[]);
int cmd_verify(int argc, char *argv[]);
int cmd_verify_sectors(int argc, char *argv[]);
int cmd_compare(int argc, char *argv[]);
int cmd_convert(int argc, char *argv[]);
#endif // LIBAARUFORMAT_COMMANDS_H

125
tool/convert.c Normal file
View File

@@ -0,0 +1,125 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2025 Natalia Portillo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <aaruformat.h>
#include "aaruformattool.h"
int convert(char *input_path, char *output_path)
{
aaruformatContext *input_ctx = NULL;
aaruformatContext *output_ctx = NULL;
int32_t res = 0;
uint32_t sector_size = 0;
uint64_t total_sectors = 0;
uint8_t *sector_data = NULL;
printf("Converting image from %s to %s...\n", input_path, output_path);
// Open input image
input_ctx = aaruf_open(input_path);
if(input_ctx == NULL)
{
printf("Error %d when opening input AaruFormat image.\n", errno);
return errno;
}
// Get image information from input
total_sectors = input_ctx->imageInfo.Sectors;
sector_size = input_ctx->imageInfo.SectorSize;
printf("Input image has %llu sectors of %u bytes each.\n", (unsigned long long)total_sectors, sector_size);
// Create output image
output_ctx = aaruf_create(output_path, input_ctx->imageInfo.MediaType, sector_size, total_sectors,
0, // negative sectors
0, // overflow sectors
NULL, // options
(const uint8_t *)"aaruformattool",
14, // application name length
1, // major version
0 // minor version
);
if(output_ctx == NULL)
{
printf("Error %d when creating output AaruFormat image.\n", errno);
aaruf_close(input_ctx);
return errno;
}
// Allocate buffer for sector data
sector_data = malloc(sector_size);
if(sector_data == NULL)
{
printf("Error allocating memory for sector buffer.\n");
aaruf_close(input_ctx);
aaruf_close(output_ctx);
return AARUF_ERROR_NOT_ENOUGH_MEMORY;
}
// Copy sectors from input to output
for(uint64_t sector = 0; sector < total_sectors; sector++)
{
uint32_t read_length = sector_size;
// Show progress every 1000 sectors
if(sector % 1000 == 0 || sector == total_sectors - 1)
{
printf("\rProgress: %llu/%llu sectors (%.1f%%)", (unsigned long long)sector + 1,
(unsigned long long)total_sectors, ((double)(sector + 1) / total_sectors) * 100.0);
fflush(stdout);
}
// Read sector from input
res = aaruf_read_sector(input_ctx, sector, sector_data, &read_length);
if(res != AARUF_STATUS_OK)
{
printf("\nError %d when reading sector %llu from input image.\n", res, (unsigned long long)sector);
break;
}
// Write sector to output
res = aaruf_write_sector(output_ctx, sector, sector_data, 0, read_length);
if(res != AARUF_STATUS_OK)
{
printf("\nError %d when writing sector %llu to output image.\n", res, (unsigned long long)sector);
break;
}
}
printf("\n");
// Clean up
free(sector_data);
aaruf_close(input_ctx);
res = aaruf_close(output_ctx);
if(res == AARUF_STATUS_OK)
printf("Conversion completed successfully.\n");
else
printf("Conversion failed with error %d.\n", res);
return res;
}

View File

@@ -39,7 +39,9 @@ void usage()
printf(" read Reads a sector and prints it out on screen.\n");
printf(" read_long Reads a sector with all its prefixes and suffixes.\n");
printf(" verify Verifies the integrity of blocks in an image.\n");
printf(" verify_sectors Verifies the integrity of all sectors in an image.\n\n");
printf(" verify_sectors Verifies the integrity of all sectors in an image.\n");
printf(" compare Compares two AaruFormat images.\n");
printf(" convert Converts an AaruFormat image to another AaruFormat image.\n\n");
printf("For help with any verb, run:\n");
printf(" aaruformattool <verb> --help\n");
}
@@ -109,3 +111,13 @@ void usage_compare()
printf(" <filename1> Path to first image file.\n");
printf(" <filename2> Path to second image file.\n");
}
void usage_convert()
{
printf("\nUsage:\n");
printf(" aaruformattool convert <input> <output>\n\n");
printf("Converts an AaruFormat image by reading all sectors from input and writing them to output.\n");
printf("Arguments:\n");
printf(" <input> Path to input image file.\n");
printf(" <output> Path to output image file.\n");
}

View File

@@ -29,5 +29,6 @@ void usage_read_long();
void usage_verify();
void usage_verify_sectors();
void usage_compare();
void usage_convert();
#endif // LIBAARUFORMAT_USAGE_H