Edit

IABSD.fr/src/sbin/fdisk/user.c

Branch :

  • Show log

    Commit

  • Author : krw
    Date : 2025-06-26 13:33:44
    Hash : 887a0d8c
    Message : Consistently apply -v setting to partition displays. Adds GPT verbose info to 'edit #' and 'setpid #' interactive command prompts when -v is specified.

  • sbin/fdisk/user.c
  • /*	$OpenBSD: user.c,v 1.86 2025/06/26 13:33:44 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(void)
    {
    	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");
    				return;
    			} else {
    				printf("Primary GPT:\n");
    				GPT_read(PRIMARYGPT);
    				if (gh.gh_sig == GPTSIGNATURE)
    					GPT_print("s");
    				else
    					printf("\tNot Found\n");
    				printf("\nSecondary GPT:\n");
    				GPT_read(SECONDARYGPT);
    				if (gh.gh_sig == GPTSIGNATURE)
    					GPT_print("s");
    				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;
    }