struct disklabel *readlabel __P((int)); struct disklabel *makebootarea __P((char *, struct disklabel *, int)); void	display __P((FILE *, struct disklabel *)); void	display_partition __P((FILE *, struct disklabel *, int, char, int)); int	width_partition __P((struct disklabel *, int)); int	editor __P((struct disklabel *, int, char *)); int	edit __P((struct disklabel *, int)); int	editit __P((void)); char	*skip __P((char *)); char	*word __P((char *)); int	getasciilabel __P((FILE *, struct disklabel *)); int	checklabel __P((struct disklabel *)); int	cmplabel __P((struct disklabel *, struct disklabel *)); void	setbootflag __P((struct disklabel *)); void	usage __P((void)); u_short	dkcksum __P((struct disklabel *));  int main(argc, argv) int argc; char *argv[]; { int ch, f, writeable, error = 0; struct disklabel *lp; FILE *t;  while ((ch = getopt(argc, argv, "BENRWb:denrs:tvw")) != -1) switch (ch) { #if NUMBOOT > 0 case 'B': ++installboot; break; case 'b': xxboot = optarg; break; #if NUMBOOT > 1 case 's': bootxx = optarg; break; #endif #endif case 'N': if (op != UNSPEC) usage(); writeable = 0; op = SETWRITEABLE; break; case 'R': if (op != UNSPEC) usage(); op = RESTORE; break; case 'W': if (op != UNSPEC) usage(); writeable = 1; op = SETWRITEABLE; break; case 'd': ++dflag; break; case 'e': if (op != UNSPEC) usage(); op = EDIT; break; case 'E': if (op != UNSPEC) usage(); op = EDITOR; break; case 'r': ++rflag; break; case 't': ++tflag; break; case 'w': if (op != UNSPEC) usage(); op = WRITE; break; case 'n': donothing++; break; case 'v': verbose++; break; case '?': default: usage(); } argc -= optind; argv += optind;  #if NUMBOOT > 0 if (installboot) { rflag++; if (op == UNSPEC) op = WRITEBOOT; } else { if (op == UNSPEC) op = READ; } #else if (op == UNSPEC) op = READ; #endif  if (argc < 1 || (rflag && dflag)) usage();  dkname = argv[0]; f = opendev(dkname, (op == READ ? O_RDONLY : O_RDWR), OPENDEV_PART, &specname); if (f < 0) err(4, "%s", specname);  #ifdef DOSLABEL  dosdp = readmbr(f); #endif  switch (op) { case EDIT: if (argc != 1) usage(); if ((lp = readlabel(f)) == NULL) exit(1); error = edit(lp, f); break; case EDITOR: if (argc != 1) usage(); if ((lp = readlabel(f)) == NULL) exit(1); error = editor(lp, f, specname); break; case READ: if (argc != 1) usage(); if ((lp = readlabel(f)) == NULL) exit(1); if (tflag) makedisktab(stdout, lp); else display(stdout, lp); error = checklabel(lp); break; case RESTORE: if (argc < 2 || argc > 3) usage(); #if NUMBOOT > 0 if (installboot && argc == 3) makelabel(argv[2], NULL, &lab); #endif lp = makebootarea(bootarea, &lab, f); if (!(t = fopen(argv[1], "r"))) err(4, "%s", argv[1]); if (getasciilabel(t, lp)) error = writelabel(f, bootarea, lp); break; case SETWRITEABLE: if (!donothing) { if (ioctl(f, DIOCWLABEL, (char *)&writeable) < 0) err(4, "ioctl DIOCWLABEL"); } break; case WRITE: if (argc < 2 || argc > 3) usage(); makelabel(argv[1], argc == 3 ? argv[2] : NULL, &lab); lp = makebootarea(bootarea, &lab, f); *lp = lab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); break; #if NUMBOOT > 0 case WRITEBOOT: { struct disklabel tlab;  if ((lp = readlabel(f)) == NULL) exit(1); tlab = *lp; if (argc == 2) makelabel(argv[1], NULL, &lab); lp = makebootarea(bootarea, &lab, f); *lp = tlab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); break; } #endif } exit(error); }   void makelabel(type, name, lp) char *type, *name; struct disklabel *lp; { struct disklabel *dp;  dp = getdiskbyname(type); if (dp == NULL) errx(1, "unknown disk type: %s", type); *lp = *dp; #if NUMBOOT > 0  if (!xxboot && lp->d_boot0) { if (*lp->d_boot0 != '/') (void)sprintf(boot0, "%s%s", _PATH_BOOTDIR, lp->d_boot0); else (void)strcpy(boot0, lp->d_boot0); xxboot = boot0; } #if NUMBOOT > 1 if (!bootxx && lp->d_boot1) { if (*lp->d_boot1 != '/') (void)sprintf(boot1, "%s%s", _PATH_BOOTDIR, lp->d_boot1); else (void)strcpy(boot1, lp->d_boot1); bootxx = boot1; } #endif #endif  memset(lp->d_packname, 0, sizeof(lp->d_packname)); if (name) (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); }  int writelabel(f, boot, lp) int f; char *boot; struct disklabel *lp; { int writeable; off_t sectoffset = 0;  if (nwflag) { warnx("DANGER! The disklabel was not found at the correct location!"); warnx("To repair this situation, use `disklabel %s > file' to", dkname); warnx("save it, then use `disklabel -R %s file' to replace it.", dkname); warnx("A new disklabel is not being installed now."); return(0);  } #if NUMBOOT > 0 setbootflag(lp); #endif lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if (rflag) { #ifdef DOSLABEL struct partition *pp = &lp->d_partitions[2];   if (dosdp && pp->p_size && (dosdp->dp_typ == DOSPTYP_OPENBSD || dosdp->dp_typ == DOSPTYP_FREEBSD || dosdp->dp_typ == DOSPTYP_NETBSD)) { sectoffset = (off_t)get_le(&dosdp->dp_start) * lp->d_secsize; } else { if (dosdp) { int first, ch;  printf("Erase the previous contents of the disk? [n]: "); fflush(stdout); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (first != 'y' && first != 'Y') exit(0); } sectoffset = 0; }  #if NUMBOOT > 0  if (!installboot) { struct disklabel tlab;  if (lseek(f, sectoffset, SEEK_SET) < 0) { perror("lseek"); return (1); } tlab = *lp; if (read(f, boot, tlab.d_bbsize) != tlab.d_bbsize) { perror("read"); return (1); } *lp =tlab; } #endif #endif   if (!donothing) { if (ioctl(f, DIOCSDINFO, lp) < 0 && errno != ENODEV && errno != ENOTTY) { l_perror("ioctl DIOCSDINFO"); return (1); } } if (verbose) printf("writing label to block %qd (0x%qx)\n", sectoffset/DEV_BSIZE, sectoffset/DEV_BSIZE); if (!donothing) { if (lseek(f, sectoffset, SEEK_SET) < 0) { perror("lseek"); return (1); }  writeable = 1;  if (ioctl(f, DIOCWLABEL, &writeable) < 0) perror("ioctl DIOCWLABEL"); #ifdef __alpha__  { int i; u_int64_t *dp, sum;  dp = (u_int64_t *)boot; sum = 0; for (i = 0; i < 63; i++) sum += dp[i]; dp[63] = sum; } #endif if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) { perror("write"); return (1); } } #if NUMBOOT > 0  if (!donothing && bootbuf && write(f, bootbuf, bootsize) != bootsize) { perror("write"); return(1); } #endif writeable = 0; if (!donothing) if (ioctl(f, DIOCWLABEL, &writeable) < 0) perror("ioctl DIOCWLABEL"); } else { if (!donothing) { if (ioctl(f, DIOCWDINFO, lp) < 0) { l_perror("ioctl DIOCWDINFO"); return (1); } } } #ifdef vax if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { daddr_t alt; int i;  alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { (void)lseek(f, (off_t)((alt + i) * lp->d_secsize), SEEK_SET); if (!donothing) if (write(f, boot, lp->d_secsize) < lp->d_secsize) warn("alternate label %d write", i/2); } } #endif return (0); }  void l_perror(s) char *s; {  switch (errno) { case ESRCH: warnx("%s: No disk label on disk;\n" "use \"disklabel -r\" to install initial label", s); break; case EINVAL: warnx("%s: Label magic number or checksum is wrong!\n" "(disklabel or kernel is out of date?)", s); break; case EBUSY: warnx("%s: Open partition would move or shrink", s); break; case EXDEV: warnx("%s: Labeled partition or 'a' partition must start " "at beginning of disk", s); break; default: warn("%s", s); break; } }  #ifdef DOSLABEL  struct dos_partition * readmbr(f) int f; { static int mbr[DEV_BSIZE / sizeof(int)]; struct dos_partition *dp; int part;   dp = (struct dos_partition *)mbr; if (lseek(f, (off_t)DOSBBSECTOR * DEV_BSIZE, SEEK_SET) < 0 || read(f, mbr, sizeof(mbr)) < sizeof(mbr)) err(4, "can't read master boot record");  bcopy((char *)mbr+DOSPARTOFF, (char *)mbr, sizeof(*dp) * NDOSPART);    for (part = 0; part < NDOSPART; part++) { if ((dp[part].dp_flag & ~0x80) != 0) return (0); }  for (part = 0; part < NDOSPART; part++) { if (get_le(&dp[part].dp_size) && dp[part].dp_typ == DOSPTYP_OPENBSD) { fprintf(stderr, "# using MBR partition %d: " "type %02X off %d (0x%x) size %d (0x%x)\n", part, dp[part].dp_typ, get_le(&dp[part].dp_start), get_le(&dp[part].dp_start), get_le(&dp[part].dp_size), get_le(&dp[part].dp_size)); return (&dp[part]); } } for (part = 0; part < NDOSPART; part++) { if (get_le(&dp[part].dp_size) && dp[part].dp_typ == DOSPTYP_FREEBSD) { fprintf(stderr, "# using MBR partition %d: " "type %02X off %d (0x%x) size %d (0x%x)\n", part, dp[part].dp_typ, get_le(&dp[part].dp_start), get_le(&dp[part].dp_start), get_le(&dp[part].dp_size), get_le(&dp[part].dp_size)); return (&dp[part]); } } for (part = 0; part < NDOSPART; part++) { if (get_le(&dp[part].dp_size) && dp[part].dp_typ == DOSPTYP_NETBSD) { fprintf(stderr, "# using MBR partition %d: " "type %02X off %d (0x%x) size %d (0x%x)\n", part, dp[part].dp_typ, get_le(&dp[part].dp_start), get_le(&dp[part].dp_start), get_le(&dp[part].dp_size), get_le(&dp[part].dp_size)); return (&dp[part]); } }   for (part = 0; part < NDOSPART; part++) { if (get_le(&dp[part].dp_size)) { warnx("warning, DOS partition table with no valid OpenBSD partition"); return (&dp[part]); } }  return (0); } #endif   struct disklabel *
readlabel(f)	int f;{	struct disklabel *lp = NULL;	if (rflag) {		char *msg;		off_t sectoffset = 0;#ifdef DOSLABEL		if (dosdp && get_le(&dosdp->dp_size) &&		    (dosdp->dp_typ == DOSPTYP_OPENBSD ||		    dosdp->dp_typ == DOSPTYP_FREEBSD ||		    dosdp->dp_typ == DOSPTYP_NETBSD))			sectoffset = (off_t)get_le(&dosdp->dp_start) *			    DEV_BSIZE;#endif		if (verbose)			printf("reading label from block %qd, offset %qd\n",			    sectoffset/DEV_BSIZE,			    sectoffset/DEV_BSIZE +			    (LABELSECTOR * DEV_BSIZE) + LABELOFFSET);		if (lseek(f, sectoffset, SEEK_SET) < 0 ||		    read(f, bootarea, BBSIZE) < BBSIZE)			err(4, "%s", specname);		lp = (struct disklabel *)(bootarea +			(LABELSECTOR * DEV_BSIZE) + LABELOFFSET);		if (lp->d_magic == DISKMAGIC &&		    lp->d_magic2 == DISKMAGIC) {			if (lp->d_npartitions <= MAXPARTITIONS &&			    dkcksum(lp) == 0)				return (lp);			msg = "disk label corrupted";		}		else {			warnx("no disklabel found. scanning.");		}		nwflag++;		msg = "no disk label";		for (lp = (struct disklabel *)bootarea;		    lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));		    lp = (struct disklabel *)((char *)lp + sizeof(long))) {			if (lp->d_magic == DISKMAGIC &&			    lp->d_magic2 == DISKMAGIC) {				if (lp->d_npartitions <= MAXPARTITIONS &&				    dkcksum(lp) == 0) {					warnx("found at 0x%x", (char *)lp					    - bootarea);					return (lp);				}				msg = "disk label corrupted";			}		}		warnx(msg);		return(NULL);	} else if (dflag) {		lp = &lab;		if (ioctl(f, DIOCGPDINFO, lp) < 0)			err(4, "ioctl DIOCGPDINFO");	} else {		lp = &lab;		if (ioctl(f, DIOCGDINFO, lp) < 0)			err(4, "ioctl DIOCGDINFO");	}	return (lp);}