src/sbin/fdisk/user.c

224 lines
5.4 KiB
C

/* $OpenBSD: user.c,v 1.85 2023/03/04 21:22:51 krw Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/disklabel.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include "part.h"
#include "mbr.h"
#include "misc.h"
#include "cmd.h"
#include "user.h"
#include "gpt.h"
#include "disk.h"
struct cmd {
char *cmd_name;
int cmd_valid;
int (*cmd_fcn)(const char *, struct mbr *);
char *cmd_help;
};
const struct cmd cmd_table[] = {
{"help", 2, Xhelp, "Display summary of available commands"},
{"manual", 2, Xmanual, "Display fdisk man page"},
{"reinit", 2, Xreinit, "Initialize the partition table"},
{"setpid", 1, Xsetpid, "Set identifier of table entry"},
{"edit", 1, Xedit, "Edit table entry"},
{"flag", 1, Xflag, "Set flag value of table entry"},
{"update", 0, Xupdate, "Update MBR bootcode"},
{"select", 0, Xselect, "Select MBR extended table entry"},
{"swap", 1, Xswap, "Swap two table entries"},
{"print", 2, Xprint, "Print partition table"},
{"write", 1, Xwrite, "Write partition table to disk"},
{"exit", 1, Xexit, "Discard changes and exit edit level"},
{"quit", 1, Xquit, "Save changes and exit edit level"},
{"abort", 2, Xabort, "Discard changes and terminate fdisk"},
};
#define ANY_CMD(_i) (cmd_table[(_i)].cmd_valid > 1)
#define GPT_CMD(_i) (cmd_table[(_i)].cmd_valid > 0)
int modified;
int ask_cmd(const struct mbr *, char **);
void
USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr)
{
struct mbr mbr;
char *args;
int i, st;
static int editlevel;
if (MBR_read(lba_self, lba_firstembr, &mbr))
return;
editlevel += 1;
if (editlevel == 1)
GPT_read(ANYGPT);
printf("Enter 'help' for information\n");
for (;;) {
if (gh.gh_sig == GPTSIGNATURE && editlevel > 1)
break; /* 'reinit gpt'. Unwind recursion! */
printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "",
editlevel);
fflush(stdout);
i = ask_cmd(&mbr, &args);
if (i == -1)
continue;
st = cmd_table[i].cmd_fcn(args ? args : "", &mbr);
if (st == CMD_EXIT) {
if (modified)
printf("Aborting changes to current MBR\n");
break;
}
if (st == CMD_QUIT) {
if (modified && Xwrite(NULL, &mbr) == CMD_CONT)
continue;
break;
}
if (st == CMD_CLEAN)
modified = 0;
if (st == CMD_DIRTY)
modified = 1;
}
editlevel -= 1;
}
void
USER_print_disk(const int verbosity)
{
struct mbr mbr;
uint64_t lba_self, lba_firstembr;
unsigned int i;
lba_self = lba_firstembr = 0;
do {
if (MBR_read(lba_self, lba_firstembr, &mbr))
break;
if (lba_self == DOSBBSECTOR) {
if (MBR_valid_prt(&mbr) == 0) {
DISK_printgeometry("s");
printf("Offset: %d\tSignature: 0x%X.\t"
"No MBR or GPT.\n", DOSBBSECTOR,
(int)mbr.mbr_signature);
return;
}
if (GPT_read(ANYGPT)) {
if (verbosity == VERBOSE) {
printf("Primary GPT:\nNot Found\n");
printf("\nSecondary GPT:\nNot Found\n");
}
} else if (verbosity == TERSE) {
GPT_print("s", verbosity);
return;
} else {
printf("Primary GPT:\n");
GPT_read(PRIMARYGPT);
if (gh.gh_sig == GPTSIGNATURE)
GPT_print("s", verbosity);
else
printf("\tNot Found\n");
printf("\nSecondary GPT:\n");
GPT_read(SECONDARYGPT);
if (gh.gh_sig == GPTSIGNATURE)
GPT_print("s", verbosity);
else
printf("\tNot Found\n");
}
if (verbosity == VERBOSE)
printf("\nMBR:\n");
}
MBR_print(&mbr, "s");
for (lba_self = i = 0; i < nitems(mbr.mbr_prt); i++)
if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND ||
mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) {
lba_self = mbr.mbr_prt[i].prt_bs;
if (lba_firstembr == 0)
lba_firstembr = lba_self;
}
} while (lba_self);
}
void
USER_help(const struct mbr *mbr)
{
unsigned int i;
for (i = 0; i < nitems(cmd_table); i++) {
if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0)
continue;
if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0)
continue;
printf("\t%s\t\t%s\n", cmd_table[i].cmd_name,
cmd_table[i].cmd_help);
}
}
int
ask_cmd(const struct mbr *mbr, char **arg)
{
static char lbuf[LINEBUFSZ];
char *cmd;
unsigned int i;
string_from_line(lbuf, sizeof(lbuf), TRIMMED);
*arg = lbuf;
cmd = strsep(arg, WHITESPACE);
if (*arg != NULL)
*arg += strspn(*arg, WHITESPACE);
if (strlen(cmd) == 0)
return -1;
if (strcmp(cmd, "?") == 0)
cmd = "help";
for (i = 0; i < nitems(cmd_table); i++) {
if (gh.gh_sig == GPTSIGNATURE && GPT_CMD(i) == 0)
continue;
if (MBR_valid_prt(mbr) == 0 && ANY_CMD(i) == 0)
continue;
if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name)
return i;
}
printf("Invalid command '%s", cmd);
if (*arg && strlen(*arg) > 0)
printf(" %s", *arg);
printf("'. Try 'help'.\n");
return -1;
}