#include <err.h>
#include <util.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <machine/param.h>
#include "user.h"
#include "disk.h"
#include "misc.h"
#include "mbr.h"
#include "cmd.h"
static cmd_table_t cmd_table[] = {
{"help", Xhelp, "Command help list"},
{"manual", Xmanual, "Show entire man page for fdisk"},
{"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"},
{"auto", Xauto, "Auto-partition the disk with a partition style"},
{"setpid", Xsetpid, "Set the identifier of a given table entry"},
{"disk", Xdisk, "Edit current drive stats"},
{"edit", Xedit, "Edit given table entry"},
{"erase", Xerase, "Erase current MBR"},
{"flag", Xflag, "Flag given table entry as bootable"},
{"update", Xupdate, "Update machine code in loaded MBR"},
{"select", Xselect, "Select extended partition table entry MBR"},
{"print", Xprint, "Print loaded MBR partition table"},
{"write", Xwrite, "Write loaded MBR to disk"},
{"exit", Xexit, "Exit edit of current MBR, without saving changes"},
{"quit", Xquit, "Quit edit of current MBR, saving current changes"},
{"abort", Xabort, "Abort program without saving current changes"},
{NULL, NULL, NULL}
};
int
USER_write(disk, tt, preserve, force)
disk_t *disk;
mbr_t *tt;
int preserve;
int force;
{
int fd, yn;
char *msgp = "\nDo you wish to write new MBR?";
char *msgk = "\nDo you wish to write new MBR and partition table?";
if (force) {
yn = 1;
} else {
printf("\a\n"
"\t-----------------------------------------------------\n"
"\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n"
"\t-----------------------------------------------------\n");
if (preserve)
yn = ask_yn(msgp, 0);
else
yn = ask_yn(msgk, 0);
}
if (yn) {
if (preserve) {
int shared;
fd = DISK_openshared(disk->name, O_RDWR, &shared);
MBR_make(tt);
MBR_write(disk, fd, tt);
DISK_close(fd);
} else {
MBR_write_all(disk, tt);
}
} else {
printf("MBR is unchanged\n");
}
return (0);
}
int
USER_modify(disk, tt, offset, reloff)
disk_t *disk;
mbr_t *tt;
off_t offset;
off_t reloff;
{
static int editlevel;
mbr_t *mbr;
cmd_t cmd;
int i, st, fd;
int modified = 0;
editlevel += 1;
cmd.table = cmd_table;
mbr = MBR_alloc(NULL);
fd = DISK_open(disk->name, O_RDONLY);
MBR_read(disk, fd, offset, mbr);
DISK_close(fd);
MBR_parse(disk, offset, reloff, mbr);
if (mbr->signature != MBR_SIGNATURE) {
int yn = ask_yn("The signature for this MBR is invalid.\nWould you like to initialize the partition table?", 1);
if (yn) {
strlcpy(cmd.cmd, "erase", sizeof(cmd.cmd));
cmd.args[0] = '\0';
st = Xerase(&cmd, disk, mbr, tt, offset);
modified = 1;
}
}
printf("Enter 'help' for information\n");
do {
again:
printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel);
fflush(stdout);
ask_cmd(&cmd);
if (cmd.cmd[0] == '\0')
goto again;
for (i = 0; cmd_table[i].cmd != NULL; i++)
if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd)
break;
if (!strcmp(cmd.cmd, "?"))
i = 0;
if (cmd_table[i].cmd == NULL) {
printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd);
continue;
} else
strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof(cmd.cmd));
st = cmd_table[i].fcn(&cmd, disk, mbr, tt, offset);
if (st == CMD_EXIT)
break;
if (st == CMD_SAVE)
break;
if (st == CMD_CLEAN)
modified = 0;
if (st == CMD_DIRTY)
modified = 1;
} while (1);
if (modified) {
if (st == CMD_SAVE) {
int shared = 0;
printf("Writing current MBR to disk.\n");
fd = DISK_openshared(disk->name, O_RDWR, &shared);
if(shared) {
if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) {
close(fd);
goto again;
}
}
MBR_make(mbr);
MBR_write(disk, fd, mbr);
close(fd);
} else {
int yn = ask_yn("MBR was modified; really quit without saving?", 0);
if (yn) {
printf("Aborting changes to current MBR.\n");
} else {
goto again;
}
}
}
editlevel -= 1;
MBR_free(mbr);
return (0);
}
int
USER_print_disk(disk, do_dump)
disk_t *disk;
int do_dump;
{
int fd, offset, firstoff;
mbr_t *mbr;
fd = DISK_open(disk->name, O_RDONLY);
offset = firstoff = 0;
if (!do_dump)
DISK_printmetrics(disk);
mbr = MBR_read_all(disk);
if (do_dump)
MBR_dump_all(mbr);
else
MBR_print_all(mbr);
MBR_free(mbr);
return (DISK_close(fd));
}