/* * Fetch disklabel for disk. * Use ioctl to get label unless -r flag is given. */ struct disklabel32 * readlabel(int f) { const char *msg; struct disklabel32 *lp; int r; if (rflag) { r = read(f, bootarea, BBSIZE); if (r < BBSIZE) err(4, "%s", specname); for (lp = (struct disklabel32 *)bootarea; lp <= (struct disklabel32 *)(bootarea + BBSIZE - sizeof(*lp)); lp = (struct disklabel32 *)((char *)lp + 16)) { if (lp->d_magic == DISKMAGIC32 && lp->d_magic2 == DISKMAGIC32) break; } if (lp > (struct disklabel32 *)(bootarea+BBSIZE-sizeof(*lp)) || lp->d_magic != DISKMAGIC32 || lp->d_magic2 != DISKMAGIC32 || dkcksum32(lp) != 0) { errx(1, "bad pack magic number (label is damaged, " "or pack is unlabeled)"); } if ((msg = fixlabel(f, lp, 0)) != NULL) errx(1, msg); } else { lp = &lab; if (ioctl(f, DIOCGDINFO32, lp) < 0) { l_perror("ioctl DIOCGDINFO32"); exit(4); } } return (lp); }
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); }
int writelabel(int f, const char *boot, struct disklabel32 *lp) { const char *msg; int flag; int r; if (disable_write) { Warning("write to disk label suppressed - label was as follows:"); display(stdout, lp); return (0); } else { /* make sure we are not overwriting our boot code */ if (checkoldboot(f, boot)) errx(4, "Will not overwrite old bootblocks w/ label, install new boot blocks first!"); setbootflag(lp); lp->d_magic = DISKMAGIC32; lp->d_magic2 = DISKMAGIC32; lp->d_checksum = 0; lp->d_checksum = dkcksum32(lp); if (rflag) { /* * First set the kernel disk label, * then write a label to the raw disk. * If the SDINFO ioctl fails because it is unimplemented, * keep going; otherwise, the kernel consistency checks * may prevent us from changing the current (in-core) * label. */ if (ioctl(f, DIOCSDINFO32, lp) < 0 && errno != ENODEV && errno != ENOTTY) { l_perror("ioctl DIOCSDINFO32"); return (1); } lseek(f, (off_t)0, SEEK_SET); /* * write enable label sector before write * (if necessary), disable after writing. */ flag = 1; if (ioctl(f, DIOCWLABEL, &flag) < 0) warn("ioctl DIOCWLABEL"); msg = fixlabel(f, lp, 1); if (msg) { warn(msg); return (1); } r = write(f, boot, lp->d_bbsize); fixlabel(f, lp, 0); if (r != ((ssize_t)lp->d_bbsize)) { warn("write"); return (1); } #if NUMBOOT > 0 /* * Output the remainder of the disklabel */ if (bootbuf) { fixlabel(f, lp, 1); r = write(f, bootbuf, bootsize); fixlabel(f, lp, 0); if (r != bootsize) { warn("write"); return(1); } } #endif flag = 0; ioctl(f, DIOCWLABEL, &flag); } else if (ioctl(f, DIOCWDINFO32, lp) < 0) { l_perror("ioctl DIOCWDINFO32"); return (1); } } return (0); }