f3fix: add proper support to parameters

This commit is contained in:
Michel Machado 2014-12-24 09:54:01 -03:00
parent 5df999a767
commit 3f02ab9ac6
2 changed files with 219 additions and 34 deletions

View File

@ -19,7 +19,7 @@ f3probe: libutils.o libdevs.o libprobe.o utils.o f3probe.o
f3brew: libutils.o libdevs.o f3brew.o
$(CC) -o $@ $^ -lm -ludev
f3fix: f3fix.o
f3fix: utils.o f3fix.o
$(CC) -o $@ $^ -lparted
-include *.d

255
f3fix.c
View File

@ -1,24 +1,197 @@
#include <error.h>
#include <assert.h>
#include <stdbool.h>
#include <argp.h>
#include <parted/parted.h>
#include "version.h"
/* XXX Refactor utils library since f3probe barely uses it. */
#include "utils.h"
/* TODO Modify f3probe to suggest using f3fix when the drive is fake.
* Wait until f3fix is stable to implement this.
*/
/* TODO Add parameters. */
/* Argp's global variables. */
const char *argp_program_version = "F3 Fix " F3_STR_VERSION;
/* TODO List types of the partition table. */
/* Arguments. */
static char adoc[] = "<DISK_DEV>";
static char doc[] = "F3 Fix -- edit the partition table of "
"a fake flash drive to have a single partition that fully covers "
"the real capacity of the drive";
static struct argp_option options[] = {
{"disk-type", 'd', "TYPE", 0,
"Disk type of the partition table", 2},
{"fs-type", 'f', "TYPE", 0,
"Type of the file system of the partition", 0},
{"boot", 'b', NULL, 0,
"Mark the partition for boot", 0},
{"no-boot", 'n', NULL, 0,
"Do not mark the partition for boot", 0},
{"first-sec", 'a', "SEC-NUM", 0,
"Sector where the partition starts", 0},
{"last-sec", 'l', "SEC-NUM", 0,
"Sector where the partition ends", 0},
{"list-disk-types", 'k', NULL, 0,
"List all supported disk types", 3},
{"list-fs-types", 's', NULL, 0,
"List all supported types of file systems", 0},
{ 0 }
};
struct args {
bool list_disk_types;
bool list_fs_types;
bool boot;
/* 29 free bytes. */
const char *dev_filename;
PedDiskType *disk_type;
PedFileSystemType *fs_type;
PedSector first_sec;
PedSector last_sec;
};
static long long arg_to_long_long(const struct argp_state *state,
const char *arg)
{
char *end;
long long ll = strtoll(arg, &end, 0);
if (!arg)
argp_error(state, "An integer must be provided");
if (!*arg || *end)
argp_error(state, "`%s' is not an integer", arg);
return ll;
}
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct args *args = state->input;
long long ll;
switch (key) {
case 'd':
args->disk_type = ped_disk_type_get(arg);
if (!args->disk_type)
argp_error(state,
"Disk type `%s' is not supported; use --list-disk-types to see the supported types");
break;
case 'f':
args->fs_type = ped_file_system_type_get(arg);
if (!args->fs_type)
argp_error(state,
"File system type `%s' is not supported; use --list-fs-types to see the supported types");
break;
case 'b':
args->boot = true;
break;
case 'n':
args->boot = false;
break;
case 'a':
ll = arg_to_long_long(state, arg);
if (ll < 0)
argp_error(state,
"First sector must be greater or equal to 0");
args->first_sec = ll;
break;
case 'l':
ll = arg_to_long_long(state, arg);
if (ll < 0)
argp_error(state,
"Last sector must be greater or equal to 0");
args->last_sec = ll;
break;
case 'k':
args->list_disk_types = true;
break;
case 's':
args->list_fs_types = true;
break;
case ARGP_KEY_INIT:
args->dev_filename = NULL;
args->last_sec = -1;
break;
case ARGP_KEY_ARG:
if (args->dev_filename)
argp_error(state,
"Wrong number of arguments; only one is allowed");
args->dev_filename = arg;
break;
case ARGP_KEY_END:
if (args->list_disk_types || args->list_fs_types)
break;
if (!args->dev_filename)
argp_error(state,
"The disk device was not specified");
if (args->last_sec < 0)
argp_error(state,
"Option --last-sec is required");
if (args->first_sec > args->last_sec)
argp_error(state,
"Option --fist_sec must be less or equal to option --last_sec");
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {options, parse_opt, adoc, doc, NULL, NULL, NULL};
static void list_disk_types(void)
{
PedDiskType *type;
int i = 0;
printf("Disk types:\n");
for (type = ped_disk_type_get_next(NULL); type;
type = ped_disk_type_get_next(type)) {
printf("%s\t", type->name);
i++;
if (i == 5) {
printf("\n");
i = 0;
}
}
if (i > 0)
printf("\n");
printf("\n");
}
/* TODO List types of file systems (function below).
* One still needs a calling option to list the types.
*/
static void list_fs_types(void)
{
PedFileSystemType *fs_type;
int i = 0;
printf("File system types:\n");
for (fs_type = ped_file_system_type_get_next(NULL); fs_type;
fs_type = ped_file_system_type_get_next(fs_type))
puts(fs_type->name);
fs_type = ped_file_system_type_get_next(fs_type)) {
printf("%s\t", fs_type->name);
i++;
if (i == 5) {
printf("\n");
i = 0;
}
}
if (i > 0)
printf("\n");
printf("\n");
}
/* 0 on failure, 1 otherwise. */
@ -67,37 +240,49 @@ out:
return ret;
}
/* Use example: sudo ./f3fix /dev/sdb msdos 2048 15010455 */
int main (int argc, char *argv[])
{
struct args args = {
/* Defaults. */
.list_disk_types = false,
.list_fs_types = false,
.boot = true,
.disk_type = ped_disk_type_get("msdos"),
.fs_type = ped_file_system_type_get("fat32"),
.first_sec = 2048, /* Skip first 1MB. */
};
PedDevice *dev;
PedDiskType *type;
PedFileSystemType *fs_type;
PedSector start = atoi(argv[3]);
PedSector end = atoi(argv[4]);
int ret = 1;
int ret;
if (argc != 5)
error(EXIT_FAILURE, 0, "wrong number of arguments");
/* Read parameters. */
argp_parse(&argp, argc, argv, 0, NULL, &args);
print_header(stdout, "fix");
dev = ped_device_get(argv[1]);
if (!dev)
goto out;
if (args.list_disk_types)
list_disk_types();
type = ped_disk_type_get(argv[2]);
if (!type)
goto device;
fs_type = ped_file_system_type_get("fat32");
if (!fs_type)
goto device;
ret = !fix_disk(dev, type, fs_type, true, start, end);
device:
ped_device_destroy(dev);
out:
return ret;
if (args.list_fs_types)
list_fs_types();
if (args.list_disk_types || args.list_fs_types) {
/* If the user has asked for the types,
* so she doesn't want to fix the drive yet.
*/
return 0;
}
/* XXX If @dev is a partition, refer the user to
* the disk of this partition.
*/
dev = ped_device_get(args.dev_filename);
if (!dev)
return 1;
ret = !fix_disk(dev, args.disk_type, args.fs_type, args.boot,
args.first_sec, args.last_sec);
ped_device_destroy(dev);
return ret;
}