int main(int argc, char *argv[]) { FILE *t; int ch, error, fd; const char *name; error = 0; name = NULL; while ((ch = getopt(argc, argv, "ABb:efm:nRrw")) != -1) switch (ch) { case 'A': allfields = 1; break; case 'B': ++installboot; break; case 'b': xxboot = optarg; break; case 'f': is_file=1; break; case 'm': if (!strcmp(optarg, "i386") || !strcmp(optarg, "amd64") || !strcmp(optarg, "ia64") || !strcmp(optarg, "pc98")) { labelsoffset = 1; labeloffset = 0; bbsize = 8192; } else { errx(1, "Unsupported architecture"); } break; case 'n': disable_write = 1; break; case 'R': if (op != UNSPEC) usage(); op = RESTORE; break; case 'e': if (op != UNSPEC) usage(); op = EDIT; break; case 'r': /* * We accept and ignore -r for compatibility with * historical disklabel usage. */ break; case 'w': if (op != UNSPEC) usage(); op = WRITE; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc < 1) usage(); if (labelsoffset < 0 || labeloffset < 0) errx(1, "a -m <architecture> option must be specified"); /* Figure out the names of the thing we're working on */ if (is_file) { specname = argv[0]; } else { specname = g_device_path(argv[0]); if (specname == NULL) { warn("unable to get correct path for %s", argv[0]); return(1); } fd = open(specname, O_RDONLY); if (fd < 0) { warn("error opening %s", specname); return(1); } pname = g_providername(fd); if (pname == NULL) { warn("error getting providername for %s", specname); close(fd); return(1); } close(fd); } if (installboot && op == UNSPEC) op = WRITEBOOT; else if (op == UNSPEC) op = READ; switch(op) { case UNSPEC: break; case EDIT: if (argc != 1) usage(); readlabel(1); fixlabel(&lab); error = edit(); break; case READ: if (argc != 1) usage(); readlabel(1); display(stdout, NULL); error = checklabel(NULL); break; case RESTORE: if (argc != 2) usage(); if (!(t = fopen(argv[1], "r"))) err(4, "fopen %s", argv[1]); readlabel(0); if (!getasciilabel(t, &lab)) exit(1); error = writelabel(); break; case WRITE: if (argc == 2) name = argv[1]; else if (argc == 1) name = "auto"; else usage(); readlabel(0); makelabel(name, &lab); fixlabel(&lab); if (checklabel(NULL) == 0) error = writelabel(); break; case WRITEBOOT: readlabel(1); fixlabel(&lab); if (argc == 2) makelabel(argv[1], &lab); if (checklabel(NULL) == 0) error = writelabel(); break; } exit(error); }
/* * Write out the mbr to the specified file. */ static void write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size) { struct gctl_req *grq; const char *errmsg; char *pname; ssize_t n; int fd; fd = open(fname, O_WRONLY | flags, 0666); if (fd != -1) { n = write(fd, mbr, mbr_size); close(fd); if (n != mbr_size) errx(1, "%s: short write", fname); return; } /* * If we're called to write to a backup file, don't try to * write through GEOM. */ if (flags != 0) err(1, "can't open file %s to write backup", fname); /* Try open it read only. */ fd = open(fname, O_RDONLY); if (fd == -1) { warn("error opening %s", fname); return; } pname = g_providername(fd); if (pname == NULL) { warn("error getting providername for %s", fname); return; } /* First check that GEOM_PART is available */ if (geom_class_available("PART") != 0) { grq = gctl_get_handle(); gctl_ro_param(grq, "class", -1, "PART"); gctl_ro_param(grq, "arg0", -1, pname); gctl_ro_param(grq, "verb", -1, "bootcode"); gctl_ro_param(grq, "bootcode", mbr_size, mbr); gctl_ro_param(grq, "flags", -1, "C"); errmsg = gctl_issue(grq); if (errmsg != NULL && errmsg[0] != '\0') errx(1, "GEOM_PART: write bootcode to %s failed: %s", fname, errmsg); gctl_free(grq); } else if (geom_class_available("MBR") != 0) { grq = gctl_get_handle(); gctl_ro_param(grq, "verb", -1, "write MBR"); gctl_ro_param(grq, "class", -1, "MBR"); gctl_ro_param(grq, "geom", -1, pname); gctl_ro_param(grq, "data", mbr_size, mbr); errmsg = gctl_issue(grq); if (errmsg != NULL) err(1, "GEOM_MBR: write MBR to %s failed", fname); gctl_free(grq); } else errx(1, "can't write MBR to %s", fname); free(pname); }