224 lines
5.4 KiB
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;
|
|
}
|