[feature] Add command handling and usage functions for aaruformattool using argtable3

This commit is contained in:
2025-08-01 16:07:33 +01:00
parent 788c7a2bc7
commit 56ebb9f6af
7 changed files with 318 additions and 225 deletions

View File

@@ -1,8 +1,14 @@
project(aaruformattool)
find_package(ICU COMPONENTS uc REQUIRED)
find_package(Argtable3 CONFIG REQUIRED)
include_directories(${ICU_INCLUDE_DIRS})
add_executable(aaruformattool main.c main.h aaruformattool.h identify.c info.c helpers.c read.c printhex.c verify.c ecc_cd.c)
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)
target_link_libraries(aaruformattool "aaruformat" argtable3::argtable3)
target_link_libraries(aaruformattool "aaruformat" ICU::uc)

123
tool/commands.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 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 "commands.h"
#include <argtable3.h>
#include <stdbool.h>
#include <stdio.h>
#include "aaruformattool.h"
#include "usage.h"
int cmd_identify(int argc, char *argv[])
{
struct arg_str *filename = arg_str1(NULL, NULL, "<filename>", "Image to identify");
struct arg_end *end = arg_end(10);
void *argtable[] = {filename, end};
if(arg_parse(argc, argv, argtable) > 0)
{
arg_print_errors(stderr, end, "identify");
usage_identify();
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return -1;
}
int result = identify(filename->sval[0]);
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return result;
}
int cmd_info(int argc, char *argv[])
{
struct arg_str *filename = arg_str1(NULL, NULL, "<filename>", "Image to inspect");
struct arg_end *end = arg_end(10);
void *argtable[] = {filename, end};
if(arg_parse(argc, argv, argtable) > 0)
{
arg_print_errors(stderr, end, "info");
usage_info();
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return -1;
}
int result = info(filename->sval[0]);
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return result;
}
int cmd_read_common(int argc, char *argv[], bool long_mode)
{
struct arg_int *sector = arg_int1(NULL, NULL, "<sector>", "Sector number");
struct arg_str *filename = arg_str1(NULL, NULL, "<filename>", "Image file");
struct arg_end *end = arg_end(10);
void *argtable[] = {sector, filename, end};
if(arg_parse(argc, argv, argtable) > 0 || sector->ival[0] < 0)
{
arg_print_errors(stderr, end, long_mode ? "read_long" : "read");
long_mode ? usage_read_long() : usage_read();
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return -1;
}
int result = long_mode ? read_long(sector->ival[0], filename->sval[0]) : read(sector->ival[0], filename->sval[0]);
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return result;
}
int cmd_read(int argc, char *argv[]) { return cmd_read_common(argc, argv, false); }
int cmd_read_long(int argc, char *argv[]) { return cmd_read_common(argc, argv, true); }
int cmd_verify_common(int argc, char *argv[], bool sectors_mode)
{
struct arg_str *filename = arg_str1(NULL, NULL, "<filename>", "Image file");
struct arg_end *end = arg_end(10);
void *argtable[] = {filename, end};
if(arg_parse(argc, argv, argtable) > 0)
{
arg_print_errors(stderr, end, sectors_mode ? "verify_sectors" : "verify");
sectors_mode ? usage_verify_sectors() : usage_verify();
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return -1;
}
int result = sectors_mode ? verify_sectors(filename->sval[0]) : verify(filename->sval[0]);
arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0]));
return result;
}
int cmd_verify(int argc, char *argv[]) { return cmd_verify_common(argc, argv, false); }
int cmd_verify_sectors(int argc, char *argv[]) { return cmd_verify_common(argc, argv, true); }
Command commands[] = {
{ "identify", cmd_identify},
{ "info", cmd_info},
{ "read", cmd_read},
{ "read_long", cmd_read_long},
{ "verify", cmd_verify},
{"verify_sectors", cmd_verify_sectors},
};
const size_t num_commands = sizeof(commands) / sizeof(commands[0]);

42
tool/commands.h Normal file
View File

@@ -0,0 +1,42 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 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.
*/
#ifndef LIBAARUFORMAT_COMMANDS_H
#define LIBAARUFORMAT_COMMANDS_H
typedef int (*command_func)(int argc, char *argv[]);
typedef struct
{
const char *verb;
command_func handler;
} Command;
extern Command commands[];
extern const size_t num_commands;
// Command wrappers
int cmd_identify(int argc, char *argv[]);
int cmd_info(int argc, char *argv[]);
int cmd_read(int argc, char *argv[]);
int cmd_read_long(int argc, char *argv[]);
int cmd_verify(int argc, char *argv[]);
int cmd_verify_sectors(int argc, char *argv[]);
#endif // LIBAARUFORMAT_COMMANDS_H

View File

@@ -17,108 +17,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <aaruformat.h>
#include "aaruformattool.h"
#include "main.h"
void usage()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool <verb> [arguments]\n");
printf("\n");
printf("Available verbs:\n");
printf("\tidentify\tIdentifies if the indicated file is a supported AaruFormat image.\n");
printf("\tinfo\tPrints information about a given AaruFormat image.\n");
printf("\tread\tReads a sector and prints it out on screen.\n");
printf("\tread_long\tReads a sector with all its prefixes and suffixes and prints it out on screen.\n");
printf("\tverify\tVerifies the integrity of all blocks in a AaruFormat image.\n");
printf("\tverify_sectors\tVerifies the integrity of all sectors in a AaruFormat image.\n");
printf("\n");
printf("For help on the verb invoke the tool with the verb and no arguments.\n");
}
void usage_identify()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool identify <filename>\n");
printf("Identifies if the indicated file is a support AaruFormat image.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<filename>\tPath to file to identify if it is a supported AaruFormat image.\n");
}
void usage_info()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool info <filename>\n");
printf("Prints information about a given AaruFormat image.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<filename>\tPath to AaruFormat image to print information from.\n");
}
void usage_read()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool read <sector_number> <filename>\n");
printf("Reads a sector and prints it out on screen.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<sector_number>\tSector number to read and print out.\n");
printf("\t<filename>\tPath to AaruFormat image to print information from.\n");
}
void usage_read_long()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool read_long <sector_number> <filename>\n");
printf("Reads a sector with all its prefixes and suffixes and prints it out on screen.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<sector_number>\tSector number to read and print out.\n");
printf("\t<filename>\tPath to AaruFormat image to print information from.\n");
}
void usage_verify()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool verify <filename>\n");
printf("Verifies the integrity of all blocks in a AaruFormat image.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<filename>\tPath to AaruFormat image to verify.\n");
}
void usage_verify_sectors()
{
printf("\n");
printf("Usage:\n");
printf("aaruformattool verify_sectors <filename>\n");
printf("Verifies the integrity of all sectors in a AaruFormat image.\n");
printf("\n");
printf("Arguments:\n");
printf("\t<filename>\tPath to AaruFormat image to verify.\n");
}
#include <string.h>
#include "commands.h"
#include "usage.h"
int main(int argc, char *argv[])
{
uint64_t sector_no = 0;
printf("AaruFormat Tool version %d.%d\n", AARUFORMAT_TOOL_MAJOR_VERSION, AARUFORMAT_TOOL_MINOR_VERSION);
printf("Copyright (C) 2019-2022 Natalia Portillo\n");
printf("libaaruformat version %d.%d\n", LIBAARUFORMAT_MAJOR_VERSION, LIBAARUFORMAT_MINOR_VERSION);
printf("\n");
print_banner();
if(argc < 2)
{
@@ -126,133 +32,16 @@ int main(int argc, char *argv[])
return -1;
}
if(strncmp(argv[1], "identify", strlen("identify")) == 0)
const char *verb = argv[1];
argc--;
argv++; // Shift to pass only args to verb handlers
for(size_t i = 0; i < num_commands; ++i)
{
if(argc == 2)
{
usage_identify();
return -1;
}
if(argc > 3)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_identify();
return -1;
}
return identify(argv[2]);
if(strcmp(commands[i].verb, verb) == 0) { return commands[i].handler(argc, argv); }
}
if(strncmp(argv[1], "info", strlen("info")) == 0)
{
if(argc == 2)
{
usage_info();
return -1;
}
if(argc > 3)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_info();
return -1;
}
return info(argv[2]);
}
if(strncmp(argv[1], "read_long", strlen("read_long")) == 0)
{
if(argc < 4)
{
usage_read_long();
return -1;
}
if(argc > 5)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_read_long();
return -1;
}
errno = 0;
sector_no = strtoll(argv[2], NULL, 10);
if(errno != 0)
{
fprintf(stderr, "Invalid sector number\n");
usage_read_long();
return -1;
}
return read_long(sector_no, argv[3]);
}
else if(strncmp(argv[1], "read", strlen("read")) == 0)
{
if(argc < 4)
{
usage_read();
return -1;
}
if(argc > 5)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_read();
return -1;
}
errno = 0;
sector_no = strtoll(argv[2], NULL, 10);
if(errno != 0)
{
fprintf(stderr, "Invalid sector number\n");
usage_read();
return -1;
}
return read(sector_no, argv[3]);
}
if(strncmp(argv[1], "verify_sectors", strlen("verify_sectors")) == 0)
{
if(argc == 2)
{
usage_verify_sectors();
return -1;
}
if(argc > 3)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_verify_sectors();
return -1;
}
return verify_sectors(argv[2]);
}
else if(strncmp(argv[1], "verify", strlen("verify")) == 0)
{
if(argc == 2)
{
usage_verify();
return -1;
}
if(argc > 3)
{
fprintf(stderr, "Invalid number of arguments\n");
usage_verify();
return -1;
}
return verify(argv[2]);
}
return 0;
fprintf(stderr, "Unknown verb: %s\n", verb);
usage();
return -1;
}

101
tool/usage.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 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 "usage.h"
#include <stdio.h>
#include "aaruformat.h"
#include "version.h" // Optional if you want a central place for version macros
void print_banner()
{
printf("AaruFormat Tool version %d.%d\n", AARUFORMAT_TOOL_MAJOR_VERSION, AARUFORMAT_TOOL_MINOR_VERSION);
printf("Copyright (C) 2019-2022 Natalia Portillo\n");
printf("libaaruformat version %d.%d\n\n", LIBAARUFORMAT_MAJOR_VERSION, LIBAARUFORMAT_MINOR_VERSION);
}
void usage()
{
printf("\nUsage:\n");
printf(" aaruformattool <verb> [arguments]\n\n");
printf("Available verbs:\n");
printf(" identify Identifies if the indicated file is a supported AaruFormat image.\n");
printf(" info Prints information about a given AaruFormat image.\n");
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("For help with any verb, run:\n");
printf(" aaruformattool <verb> --help\n");
}
void usage_identify()
{
printf("\nUsage:\n");
printf(" aaruformattool identify <filename>\n\n");
printf("Identifies if the file is a supported AaruFormat image.\n");
printf("Arguments:\n");
printf(" <filename> Path to the image file.\n");
}
void usage_info()
{
printf("\nUsage:\n");
printf(" aaruformattool info <filename>\n\n");
printf("Prints metadata about the image.\n");
printf("Arguments:\n");
printf(" <filename> Path to AaruFormat image.\n");
}
void usage_read()
{
printf("\nUsage:\n");
printf(" aaruformattool read <sector_number> <filename>\n\n");
printf("Reads a sector and prints it out.\n");
printf("Arguments:\n");
printf(" <sector_number> Sector number to read.\n");
printf(" <filename> Path to image file.\n");
}
void usage_read_long()
{
printf("\nUsage:\n");
printf(" aaruformattool read_long <sector_number> <filename>\n\n");
printf("Reads sector with all metadata and prints it out.\n");
printf("Arguments:\n");
printf(" <sector_number> Sector number to read.\n");
printf(" <filename> Path to image file.\n");
}
void usage_verify()
{
printf("\nUsage:\n");
printf(" aaruformattool verify <filename>\n\n");
printf("Checks block-level integrity.\n");
printf("Arguments:\n");
printf(" <filename> Path to image file.\n");
}
void usage_verify_sectors()
{
printf("\nUsage:\n");
printf(" aaruformattool verify_sectors <filename>\n\n");
printf("Checks sector-level integrity.\n");
printf("Arguments:\n");
printf(" <filename> Path to image file.\n");
}

32
tool/usage.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* This file is part of the Aaru Data Preservation Suite.
* Copyright (c) 2019-2022 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.
*/
#ifndef LIBAARUFORMAT_USAGE_H
#define LIBAARUFORMAT_USAGE_H
void print_banner();
void usage();
void usage_identify();
void usage_info();
void usage_read();
void usage_read_long();
void usage_verify();
void usage_verify_sectors();
#endif // LIBAARUFORMAT_USAGE_H