Submit #2873 ยป 0001-sbin-fdisk.patch
| sbin/fdisk/fdisk.c | ||
|---|---|---|
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
int iotest;
|
||
|
#define LBUF 100
|
||
|
static char lbuf[LBUF];
|
||
|
#define MBRSIGOFF 510
|
||
|
/*
|
||
|
*
|
||
|
* Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992
|
||
| ... | ... | |
|
*/
|
||
|
#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
|
||
|
#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
|
||
|
#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
|
||
|
#define RoundCyl(x) roundup(x, cylsecs)
|
||
|
#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */
|
||
|
#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */
|
||
|
int secsize = 0; /* the sensed sector size */
|
||
|
const char *disk;
|
||
|
const char *disks[] =
|
||
|
#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */
|
||
|
#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */
|
||
|
#define MAX_SECTORS_PER_TRACK 0x3f /* maximum number of sectors per track */
|
||
|
#define MIN_SECTORS_PER_TRACK 0x1 /* minimum number of sectors per track */
|
||
|
#define MAX_HEADS 0xff /* maximum number of head */
|
||
|
static int secsize = 0; /* the sensed sector size */
|
||
|
static int fd; /* file descriptor of the given disk */
|
||
|
static const char *disk;
|
||
|
static const char *disks[] =
|
||
|
{
|
||
|
"/dev/ad0", "/dev/da0", "/dev/vkd0", 0
|
||
|
};
|
||
|
int cyls, sectors, heads, cylsecs;
|
||
|
int64_t disksecs;
|
||
|
static int cyls, sectors, heads, cylsecs;
|
||
|
static int64_t disksecs;
|
||
|
struct mboot
|
||
|
{
|
||
| ... | ... | |
|
off_t bootinst_size;
|
||
|
struct dos_partition parts[4];
|
||
|
};
|
||
|
struct mboot mboot;
|
||
|
static struct mboot mboot;
|
||
|
#define ACTIVE 0x80
|
||
|
#define BOOT_MAGIC 0xAA55
|
||
| ... | ... | |
|
int dos_sectors;
|
||
|
int dos_cylsecs;
|
||
|
#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
|
||
|
#define DOSSECT(s,c) ((s & MAX_SECTORS_PER_TRACK) | ((c >> 2) & 0xc0))
|
||
|
#define DOSCYL(c) (c & 0xff)
|
||
|
#define MAXCYL 1023
|
||
|
static int partition = -1;
|
||
|
#define MAX_ARGS 10
|
||
|
static int current_line_number;
|
||
|
static int geom_processed = 0;
|
||
|
static int part_processed = 0;
|
||
|
static int active_processed = 0;
|
||
|
typedef struct cmd {
|
||
|
char cmd;
|
||
|
int n_args;
|
||
| ... | ... | |
|
} args[MAX_ARGS];
|
||
|
} CMD;
|
||
|
static int B_flag = 0; /* replace boot code */
|
||
|
static int C_flag = 0; /* use wrapped values for CHS */
|
||
|
static int E_flag = 0; /* Erase through TRIM */
|
||
| ... | ... | |
|
static void reset_boot(void);
|
||
|
static int sanitize_partition(struct dos_partition *);
|
||
|
static void usage(void);
|
||
|
#if 0
|
||
|
static int hex(char *str, int *num, int deflt);
|
||
|
static int string(char *str, char **ans);
|
||
|
#endif
|
||
|
int
|
||
|
main(int argc, char *argv[])
|
||
| ... | ... | |
|
{
|
||
|
disk = disks[i];
|
||
|
rv = open_disk();
|
||
|
if(rv != -2) break;
|
||
|
if (rv != -2) break;
|
||
|
}
|
||
|
if(rv < 0)
|
||
|
if (rv < 0)
|
||
|
err(1, "cannot open any disk");
|
||
|
} else {
|
||
|
if (open_disk() < 0)
|
||
| ... | ... | |
|
}
|
||
|
else
|
||
|
{
|
||
|
if(u_flag)
|
||
|
if (u_flag)
|
||
|
{
|
||
|
get_params_to_use();
|
||
|
}
|
||
| ... | ... | |
|
init_boot(void)
|
||
|
{
|
||
|
const char *fname;
|
||
|
int fd, n;
|
||
|
int boot_fd, n;
|
||
|
struct stat sb;
|
||
|
fname = b_flag ? b_flag : "/boot/mbr";
|
||
|
if ((fd = open(fname, O_RDONLY)) == -1 ||
|
||
|
fstat(fd, &sb) == -1)
|
||
|
if ((boot_fd = open(fname, O_RDONLY)) == -1 ||
|
||
|
fstat(boot_fd, &sb) == -1)
|
||
|
err(1, "%s", fname);
|
||
|
if ((mboot.bootinst_size = sb.st_size) % secsize != 0)
|
||
|
errx(1, "%s: length must be a multiple of sector size", fname);
|
||
| ... | ... | |
|
free(mboot.bootinst);
|
||
|
if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL)
|
||
|
errx(1, "%s: unable to allocate read buffer", fname);
|
||
|
if ((n = read(fd, mboot.bootinst, mboot.bootinst_size)) == -1 ||
|
||
|
close(fd))
|
||
|
if ((n = read(boot_fd, mboot.bootinst, mboot.bootinst_size)) == -1 ||
|
||
|
close(boot_fd))
|
||
|
err(1, "%s", fname);
|
||
|
if (n != mboot.bootinst_size)
|
||
|
errx(1, "%s: short read", fname);
|
||
| ... | ... | |
|
partp->dp_typ = DOSPTYP_386BSD;
|
||
|
partp->dp_flag = ACTIVE;
|
||
|
start = roundup(start, dos_sectors);
|
||
|
if(start == 0)
|
||
|
if (start == 0)
|
||
|
start = dos_sectors;
|
||
|
partp->dp_start = start;
|
||
|
if (disksecs - start > 0xFFFFFFFFU) {
|
||
| ... | ... | |
|
printf("parameters extracted from device are:\n");
|
||
|
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
|
||
|
,cyls,heads,sectors,cylsecs);
|
||
|
if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
|
||
|
if ((dos_sectors > MAX_SECTORS_PER_TRACK) || (dos_cyls > MAXCYL) || (dos_heads > MAX_HEADS))
|
||
|
printf("Figures below won't work with BIOS for partitions not in cyl 1\n");
|
||
|
printf("parameters to be used for BIOS calculations are:\n");
|
||
|
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
int fd;
|
||
|
static void
|
||
|
erase_partition(int i)
|
||
|
{
|
||
| ... | ... | |
|
dev_name = strtok(dev_name + strlen("/dev/da"),"s");
|
||
|
sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", dev_name);
|
||
|
sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0);
|
||
|
if(errno == ENOENT) {
|
||
|
if (errno == ENOENT) {
|
||
|
printf("Device:%s does not support the TRIM command\n", disk);
|
||
|
usage();
|
||
|
}
|
||
|
if(!trim_enabled) {
|
||
|
if (!trim_enabled) {
|
||
|
printf("Erase device option selected, but sysctl (%s) "
|
||
|
"is not enabled\n",sysctl_name);
|
||
|
usage();
|
||
| ... | ... | |
|
warnx("device %s is not character special", disk);
|
||
|
if ((fd = open(disk,
|
||
|
a_flag || I_flag || B_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
|
||
|
if(errno == ENXIO)
|
||
|
if (errno == ENXIO)
|
||
|
return -2;
|
||
|
warnx("can't open device %s", disk);
|
||
|
return -1;
|
||
| ... | ... | |
|
read_disk(off_t sector, void *buf)
|
||
|
{
|
||
|
lseek(fd,(sector * 512), 0);
|
||
|
if( secsize == 0 )
|
||
|
if ( secsize == 0 )
|
||
|
for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 )
|
||
|
{
|
||
|
/* try the read */
|
||
|
int size = read(fd, buf, secsize);
|
||
|
if( size == secsize )
|
||
|
if ( size == secsize )
|
||
|
/* it worked so return */
|
||
|
return secsize;
|
||
|
}
|
||
| ... | ... | |
|
*/
|
||
|
if (ioctl(fd, DIOCGPART, &partinfo) == -1) {
|
||
|
if (p_flag && fstat(fd, &st) == 0 && st.st_size) {
|
||
|
sectors = 63;
|
||
|
heads = 255;
|
||
|
sectors = MAX_SECTORS_PER_TRACK;
|
||
|
heads = MAX_HEADS;
|
||
|
cylsecs = heads * sectors;
|
||
|
cyls = st.st_size / 512 / cylsecs;
|
||
|
} else {
|
||
| ... | ... | |
|
warnx("can't read fdisk partition table");
|
||
|
return -1;
|
||
|
}
|
||
|
if (*(uint16_t *)&mboot.bootinst[MBRSIGOFF] != BOOT_MAGIC) {
|
||
|
if (*(uint16_t *)&mboot.bootinst[DOSMAGICOFFSET] != BOOT_MAGIC) {
|
||
|
warnx("invalid fdisk partition table found");
|
||
|
/* So should we initialize things */
|
||
|
return -1;
|
||
| ... | ... | |
|
write_s0(void)
|
||
|
{
|
||
|
#ifdef NOT_NOW
|
||
|
int flag;
|
||
|
int flag = 1;
|
||
|
#endif
|
||
|
int sector;
|
||
|
if (iotest) {
|
||
|
print_s0(-1);
|
||
|
return 0;
|
||
|
}
|
||
|
memcpy(&mboot.bootinst[DOSPARTOFF], mboot.parts, sizeof(mboot.parts));
|
||
|
/*
|
||
|
* write enable label sector before write (if necessary),
|
||
| ... | ... | |
|
* sector 0. (e.g. empty disk)
|
||
|
*/
|
||
|
#ifdef NOT_NOW
|
||
|
flag = 1;
|
||
|
if (ioctl(fd, DIOCWLABEL, &flag) < 0)
|
||
|
warn("ioctl DIOCWLABEL");
|
||
|
#endif
|
||
| ... | ... | |
|
if (write_disk(sector,
|
||
|
&mboot.bootinst[sector * secsize]) == -1) {
|
||
|
warn("can't write fdisk partition table");
|
||
|
return -1;
|
||
|
#ifdef NOT_NOW
|
||
|
flag = 0;
|
||
|
ioctl(fd, DIOCWLABEL, &flag);
|
||
|
#endif
|
||
|
return -1;
|
||
|
}
|
||
|
#ifdef NOT_NOW
|
||
|
flag = 0;
|
||
| ... | ... | |
|
static int
|
||
|
decimal(const char *str, int *num, int deflt)
|
||
|
{
|
||
|
int acc = 0, c;
|
||
|
char *cp;
|
||
|
int acc = 0, c;
|
||
|
char *cp;
|
||
|
while (1) {
|
||
|
printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
|
||
| ... | ... | |
|
}
|
||
|
#if 0
|
||
|
static int
|
||
|
hex(char *str, int *num, int deflt)
|
||
|
{
|
||
|
int acc = 0, c;
|
||
|
char *cp;
|
||
|
while (1) {
|
||
|
printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
|
||
|
fgets(lbuf, LBUF, stdin);
|
||
|
lbuf[strlen(lbuf)-1] = 0;
|
||
|
if (!*lbuf)
|
||
|
return 0;
|
||
|
cp = lbuf;
|
||
|
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
|
||
|
if (!c)
|
||
|
return 0;
|
||
|
while ((c = *cp++)) {
|
||
|
if (c <= '9' && c >= '0')
|
||
|
acc = (acc << 4) + c - '0';
|
||
|
else if (c <= 'f' && c >= 'a')
|
||
|
acc = (acc << 4) + c - 'a' + 10;
|
||
|
else if (c <= 'F' && c >= 'A')
|
||
|
acc = (acc << 4) + c - 'A' + 10;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
if (c == ' ' || c == '\t')
|
||
|
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
|
||
|
if (!c) {
|
||
|
*num = acc;
|
||
|
return 1;
|
||
|
} else
|
||
|
printf("%s is an invalid hex number. Try again.\n",
|
||
|
lbuf);
|
||
|
}
|
||
|
}
|
||
|
static int
|
||
|
string(char *str, char **ans)
|
||
|
{
|
||
|
int c;
|
||
|
char *cp = lbuf;
|
||
|
while (1) {
|
||
|
printf("Supply a string value for \"%s\" [%s] ", str, *ans);
|
||
|
fgets(lbuf, LBUF, stdin);
|
||
|
lbuf[strlen(lbuf)-1] = 0;
|
||
|
if (!*lbuf)
|
||
|
return 0;
|
||
|
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
|
||
|
if (c == '"') {
|
||
|
c = *++cp;
|
||
|
*ans = cp;
|
||
|
while ((c = *cp) && c != '"') cp++;
|
||
|
} else {
|
||
|
*ans = cp;
|
||
|
while ((c = *cp) && c != ' ' && c != '\t') cp++;
|
||
|
}
|
||
|
if (c)
|
||
|
*cp = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
static const char *
|
||
|
get_type(int type)
|
||
|
{
|
||
| ... | ... | |
|
while(counter < numentries)
|
||
|
{
|
||
|
if(ptr->type == type)
|
||
|
if (ptr->type == type)
|
||
|
{
|
||
|
return(ptr->name);
|
||
|
}
|
||
| ... | ... | |
|
current_line_number);
|
||
|
status = 0;
|
||
|
}
|
||
|
else if (dos_sectors < 1 || dos_sectors > 63)
|
||
|
else if (dos_sectors < MIN_SECTORS_PER_TRACK || dos_sectors > MAX_SECTORS_PER_TRACK)
|
||
|
{
|
||
|
warnx("ERROR line %d: number of sectors must be within (1-63)",
|
||
|
current_line_number);
|
||