int Xwrite(char *args, struct disk *disk, struct mbr *mbr, struct mbr *tt, int offset) { struct dos_mbr dos_mbr; int fd, i, n; for (i = 0, n = 0; i < NDOSPART; i++) if (mbr->part[i].id == 0xA6) n++; if (n >= 2) { warnx("MBR contains more than one OpenBSD partition!"); if (!ask_yn("Write MBR anyway?")) return (CMD_CONT); } fd = DISK_open(disk->name, O_RDWR); MBR_make(mbr, &dos_mbr); printf("Writing MBR at offset %d.\n", offset); if (MBR_write(fd, offset, &dos_mbr) == -1) { int saved_errno = errno; warn("error writing MBR"); close(fd); errno = saved_errno; return (CMD_CONT); } close(fd); /* Refresh in memory copy to reflect what was just written. */ MBR_parse(disk, &dos_mbr, mbr->offset, mbr->reloffset, mbr); return (CMD_CLEAN); }
int USER_print_disk(disk_t *disk) { off_t offset, firstoff; int fd, i, error; char gpt_buf[DEV_BSIZE]; gpt_t gpt; fd = DISK_open(disk->name, O_RDONLY); offset = firstoff = 1; DISK_printmetrics(disk, NULL); error = GPT_load(fd, disk, &gpt, 0); if (error == -1) { printf("Master header not clean, trying backup header\n"); error = GPT_load(fd, disk, &gpt, 1); } if (error == -1) { printf("Backup header not clean, exiting.\n"); return (close(fd)); } printf("Offset: %lld\t", offset); GPT_print(&gpt, NULL); GPT_free(&gpt); return (close(fd)); }
/* * Parse the MBR partition table into 'mbr', leaving the rest of 'mbr' * untouched. */ void MBR_pcopy(struct disk *disk, struct mbr *mbr) { int i, fd, error; struct dos_mbr dos_mbr; fd = DISK_open(disk->name, O_RDONLY); error = MBR_read(fd, 0, &dos_mbr); close(fd); if (error == -1) return; for (i = 0; i < NDOSPART; i++) PRT_parse(disk, &dos_mbr.dmbr_parts[i], 0, 0, &mbr->part[i]); }
/* Routine to go after the disklabel for geometry * information. This should work everywhere, but * in the land of PC, things are not always what * they seem. */ DISK_metrics * DISK_getlabelmetrics(char *name) { DISK_metrics *lm = NULL; u_int64_t sz, spc; int fd; /* Get label metrics */ if ((fd = DISK_open(name, O_RDONLY)) != -1) { lm = malloc(sizeof(DISK_metrics)); if (lm == NULL) err(1, NULL); if (ioctl(fd, DIOCGPDINFO, &dl) == -1) { warn("DIOCGPDINFO"); free(lm); lm = NULL; } else { lm->cylinders = dl.d_ncylinders; lm->heads = dl.d_ntracks; lm->sectors = dl.d_nsectors; /* MBR handles only first UINT32_MAX sectors. */ spc = (u_int64_t)lm->heads * lm->sectors; sz = DL_GETDSIZE(&dl); if (sz > UINT32_MAX) { lm->cylinders = UINT32_MAX / spc; lm->size = lm->cylinders * spc; warnx("disk too large (%llu sectors)." " size truncated.", sz); } else lm->size = sz; unit_types[SECTORS].conversion = dl.d_secsize; } close(fd); } return (lm); }
int USER_modify(disk_t *disk, gpt_t *tt, off_t offset, off_t reloff) { char gpt_buf[DEV_BSIZE]; gpt_t gpt; cmd_t cmd; int i, st, fd, error; /* Set up command table pointer */ cmd.table = cmd_table; /* Read GPT & partition */ fd = DISK_open(disk->name, O_RDONLY); error = GPT_load(fd, disk, &gpt, 0); if (error == -1) { printf("Master header not clean, trying backup header\n"); error = GPT_load(fd, disk, &gpt, 1); } close(fd); if (error == -1) { printf("Backup header not clean, exiting.\n"); goto done; } printf("Enter 'help' for information\n"); /* Edit cycle */ do { again: printf("gdisk:%c> ", (modified)?'*':' '); 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; /* Quick hack to put in '?' == 'help' */ if (!strcmp(cmd.cmd, "?")) i = 0; /* Check for valid command */ 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); /* Call function */ st = cmd_table[i].fcn(&cmd, disk, &gpt, tt, offset); /* Update status */ if (st == CMD_EXIT) break; if (st == CMD_SAVE) break; if (st == CMD_CLEAN) modified = 0; if (st == CMD_DIRTY) modified = 1; } while (1); /* Write out GPT */ if (modified) { if (st == CMD_SAVE) { if (Xwrite(NULL, disk, &gpt, NULL, offset) == CMD_CONT) goto again; close(fd); } else printf("Aborting changes to current GPT.\n"); } GPT_free(&gpt); done: return (0); }