Home | History | Annotate | Line # | Download | only in mbrlabel
mbrlabel.c revision 1.7.4.1
      1  1.7.4.1       he /*	$NetBSD: mbrlabel.c,v 1.7.4.1 2001/02/26 22:30:25 he Exp $	*/
      2      1.1       ws 
      3      1.1       ws /*
      4      1.1       ws  * Copyright (C) 1998 Wolfgang Solfrank.
      5      1.1       ws  * Copyright (C) 1998 TooLs GmbH.
      6      1.1       ws  * All rights reserved.
      7      1.1       ws  *
      8      1.1       ws  * Redistribution and use in source and binary forms, with or without
      9      1.1       ws  * modification, are permitted provided that the following conditions
     10      1.1       ws  * are met:
     11      1.1       ws  * 1. Redistributions of source code must retain the above copyright
     12      1.1       ws  *    notice, this list of conditions and the following disclaimer.
     13      1.1       ws  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1       ws  *    notice, this list of conditions and the following disclaimer in the
     15      1.1       ws  *    documentation and/or other materials provided with the distribution.
     16      1.1       ws  * 3. All advertising materials mentioning features or use of this software
     17      1.1       ws  *    must display the following acknowledgement:
     18      1.1       ws  *	This product includes software developed by TooLs GmbH.
     19      1.1       ws  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     20      1.1       ws  *    derived from this software without specific prior written permission.
     21      1.1       ws  *
     22      1.1       ws  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     23      1.1       ws  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24      1.1       ws  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25      1.1       ws  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26      1.1       ws  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     27      1.1       ws  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     28      1.1       ws  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     29      1.1       ws  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     30      1.1       ws  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     31      1.1       ws  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32      1.1       ws  */
     33      1.1       ws 
     34      1.1       ws #include <sys/cdefs.h>
     35      1.1       ws #ifndef lint
     36  1.7.4.1       he __RCSID("$NetBSD: mbrlabel.c,v 1.7.4.1 2001/02/26 22:30:25 he Exp $");
     37      1.1       ws #endif /* not lint */
     38      1.1       ws 
     39      1.1       ws #include <stdio.h>
     40      1.1       ws #include <fcntl.h>
     41  1.7.4.1       he #include <stdlib.h>
     42      1.1       ws #include <string.h>
     43      1.1       ws #include <unistd.h>
     44      1.1       ws #include <util.h>
     45      1.1       ws 
     46      1.1       ws #include <sys/param.h>
     47  1.7.4.1       he #define FSTYPENAMES
     48      1.1       ws #include <sys/disklabel.h>
     49      1.3  thorpej #include <sys/disklabel_mbr.h>
     50      1.1       ws #include <sys/ioctl.h>
     51      1.1       ws 
     52      1.1       ws #include "dkcksum.h"
     53  1.7.4.1       he #include "extern.h"
     54      1.1       ws 
     55  1.7.4.1       he int	main(int, char **);
     56  1.7.4.1       he void	usage(void);
     57  1.7.4.1       he void	getlabel(int);
     58  1.7.4.1       he void	setlabel(int, int);
     59  1.7.4.1       he int	getparts(int, u_int32_t, u_int32_t, int);
     60  1.7.4.1       he int	nbsdtype(int);
     61  1.7.4.1       he u_int16_t	getshort(void *);
     62  1.7.4.1       he u_int32_t	getlong(void *);
     63      1.1       ws 
     64      1.1       ws struct disklabel label;
     65  1.7.4.1       he extern char *__progname;
     66      1.1       ws 
     67      1.1       ws void
     68  1.7.4.1       he getlabel(int sd)
     69      1.1       ws {
     70      1.1       ws 
     71      1.1       ws 	if (ioctl(sd, DIOCGDINFO, &label) < 0) {
     72      1.1       ws 		perror("get label");
     73      1.1       ws 		exit(1);
     74      1.1       ws 	}
     75      1.1       ws 	/*
     76      1.1       ws 	 * Some ports seem to not set the number of partitions
     77      1.1       ws 	 * correctly, albeit they seem to set the raw partiton ok!
     78      1.1       ws 	 */
     79      1.1       ws 	if (label.d_npartitions <= RAW_PART)
     80      1.1       ws 		label.d_npartitions = RAW_PART + 1;
     81      1.1       ws }
     82      1.1       ws 
     83      1.1       ws void
     84  1.7.4.1       he setlabel(int sd, int doraw)
     85      1.1       ws {
     86  1.7.4.1       he 
     87      1.1       ws 	label.d_checksum = 0;
     88      1.1       ws 	label.d_checksum = dkcksum(&label);
     89  1.7.4.1       he 	if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) {
     90      1.1       ws 		perror("set label");
     91      1.1       ws 		exit(1);
     92      1.1       ws 	}
     93      1.1       ws }
     94      1.1       ws 
     95      1.1       ws static struct typetab {
     96      1.1       ws 	int mbrtype;
     97      1.1       ws 	int nbsdtype;
     98      1.1       ws } typetable[] = {
     99  1.7.4.1       he 	{ MBR_PTYPE_386BSD,	FS_BSDFFS },
    100  1.7.4.1       he 	{ MBR_PTYPE_FAT12,	FS_MSDOS },
    101  1.7.4.1       he 	{ MBR_PTYPE_FAT16B,	FS_MSDOS },
    102  1.7.4.1       he 	{ MBR_PTYPE_FAT16L,	FS_MSDOS },
    103  1.7.4.1       he 	{ MBR_PTYPE_FAT16S,	FS_MSDOS },
    104  1.7.4.1       he 	{ MBR_PTYPE_FAT32,	FS_MSDOS },
    105  1.7.4.1       he 	{ MBR_PTYPE_FAT32L,	FS_MSDOS },
    106  1.7.4.1       he 	{ MBR_PTYPE_LNXEXT2,	FS_EX2FS },
    107  1.7.4.1       he 	{ MBR_PTYPE_LNXSWAP,	FS_SWAP },
    108  1.7.4.1       he 	{ MBR_PTYPE_NETBSD,	FS_BSDFFS },
    109  1.7.4.1       he 	{ MBR_PTYPE_NTFS,	FS_NTFS },
    110      1.1       ws 	{ 0, 0 }
    111      1.1       ws };
    112      1.1       ws 
    113      1.1       ws int
    114  1.7.4.1       he nbsdtype(int type)
    115      1.1       ws {
    116      1.1       ws 	struct typetab *tt;
    117      1.1       ws 
    118      1.1       ws 	for (tt = typetable; tt->mbrtype; tt++)
    119      1.1       ws 		if (tt->mbrtype == type)
    120  1.7.4.1       he 			return (tt->nbsdtype);
    121  1.7.4.1       he 	return (FS_OTHER);
    122  1.7.4.1       he }
    123  1.7.4.1       he 
    124  1.7.4.1       he u_int16_t
    125  1.7.4.1       he getshort(void *p)
    126  1.7.4.1       he {
    127  1.7.4.1       he 	unsigned char *cp = p;
    128  1.7.4.1       he 
    129  1.7.4.1       he 	return (cp[0] | (cp[1] << 8));
    130      1.1       ws }
    131      1.1       ws 
    132      1.1       ws u_int32_t
    133  1.7.4.1       he getlong(void *p)
    134      1.1       ws {
    135      1.1       ws 	unsigned char *cp = p;
    136      1.1       ws 
    137  1.7.4.1       he 	return (cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24));
    138      1.1       ws }
    139      1.1       ws 
    140      1.1       ws int
    141  1.7.4.1       he getparts(int sd, u_int32_t off, u_int32_t extoff, int verbose)
    142  1.7.4.1       he {
    143  1.7.4.1       he 	unsigned char		buf[DEV_BSIZE];
    144  1.7.4.1       he 	struct mbr_partition	parts[NMBRPART];
    145  1.7.4.1       he 	struct partition	npe;
    146  1.7.4.1       he 	off_t			loff;
    147  1.7.4.1       he 	int			i, j, unused, changed;
    148      1.2     fair 
    149  1.7.4.1       he 	changed = 0;
    150      1.2     fair 	loff = (off_t)off * DEV_BSIZE;
    151      1.1       ws 
    152      1.1       ws 	if (lseek(sd, loff, SEEK_SET) != loff) {
    153      1.1       ws 		perror("seek label");
    154      1.1       ws 		exit(1);
    155      1.1       ws 	}
    156      1.1       ws 	if (read(sd, buf, DEV_BSIZE) != DEV_BSIZE) {
    157      1.1       ws 		perror("read label");
    158      1.1       ws 		exit(1);
    159      1.1       ws 	}
    160  1.7.4.1       he 	if (getshort(buf + MBR_MAGICOFF) != MBR_MAGIC)
    161  1.7.4.1       he 		return (changed);
    162      1.5      cgd 	memcpy(parts, buf + MBR_PARTOFF, sizeof parts);
    163  1.7.4.1       he 
    164  1.7.4.1       he 				/* scan partition table */
    165      1.5      cgd 	for (i = 0; i < NMBRPART; i++) {
    166  1.7.4.1       he 		if (parts[i].mbrp_typ == 0 ||
    167  1.7.4.1       he 				/* extended partitions are handled below */
    168  1.7.4.1       he 		    MBR_IS_EXTENDED(parts[i].mbrp_typ))
    169  1.7.4.1       he 			continue;
    170  1.7.4.1       he 
    171  1.7.4.1       he 		memset((void *)&npe, 0, sizeof(npe));
    172  1.7.4.1       he 		npe.p_size = getlong(&parts[i].mbrp_size);
    173  1.7.4.1       he 		npe.p_offset = getlong(&parts[i].mbrp_start) + off;
    174  1.7.4.1       he 		npe.p_fstype = nbsdtype(parts[i].mbrp_typ);
    175  1.7.4.1       he 
    176  1.7.4.1       he 				/* find existing entry, or first free slot */
    177  1.7.4.1       he 		unused = -1;	/* flag as no free slot */
    178  1.7.4.1       he 		if (verbose)
    179  1.7.4.1       he 			printf(
    180  1.7.4.1       he 			    "Found %s partition; size %u (%u MB), offset %u\n",
    181  1.7.4.1       he 			    fstypenames[npe.p_fstype],
    182  1.7.4.1       he 			    npe.p_size, npe.p_size / 2048, npe.p_offset);
    183  1.7.4.1       he 		for (j = 0; j < label.d_npartitions; j++) {
    184  1.7.4.1       he 			struct partition *lpe;
    185  1.7.4.1       he 
    186  1.7.4.1       he 			if (j == RAW_PART)
    187  1.7.4.1       he 				continue;
    188  1.7.4.1       he 			lpe = &label.d_partitions[j];
    189  1.7.4.1       he 			if (lpe->p_size == npe.p_size &&
    190  1.7.4.1       he 			    lpe->p_offset == npe.p_offset
    191  1.7.4.1       he #ifdef notyet
    192  1.7.4.1       he 			    && (lpe->p_fstype == npe.p_fstype ||
    193  1.7.4.1       he 			     lpe->p_fstype == FS_UNUSED) */
    194      1.1       ws #endif
    195  1.7.4.1       he 			     ) {
    196  1.7.4.1       he 				if (verbose)
    197  1.7.4.1       he 					printf(
    198  1.7.4.1       he 			    "  skipping existing %s partition at slot %c.\n",
    199  1.7.4.1       he 					    fstypenames[lpe->p_fstype],
    200  1.7.4.1       he 					    j + 'a');
    201  1.7.4.1       he 				unused = -2;	/* flag as existing */
    202  1.7.4.1       he 				break;
    203      1.1       ws 			}
    204  1.7.4.1       he 			if (unused == -1 && lpe->p_size == 0 &&
    205  1.7.4.1       he 			    lpe->p_fstype == FS_UNUSED)
    206  1.7.4.1       he 				unused = j;
    207  1.7.4.1       he 		}
    208  1.7.4.1       he 		if (unused == -2)
    209  1.7.4.1       he 			continue;	/* entry exists, skip... */
    210  1.7.4.1       he 		if (unused == -1) {
    211  1.7.4.1       he 			if (label.d_npartitions < MAXPARTITIONS) {
    212  1.7.4.1       he 				unused = label.d_npartitions;
    213  1.7.4.1       he 				label.d_npartitions++;
    214  1.7.4.1       he 			} else {
    215  1.7.4.1       he 				printf(
    216  1.7.4.1       he 				"  WARNING: no slots free for %s partition.\n",
    217  1.7.4.1       he 				    fstypenames[npe.p_fstype]);
    218  1.7.4.1       he 				continue;
    219  1.7.4.1       he 			}
    220  1.7.4.1       he 		}
    221  1.7.4.1       he 
    222  1.7.4.1       he 		if (verbose)
    223  1.7.4.1       he 			printf("  adding %s partition to slot %c.\n",
    224  1.7.4.1       he 			    fstypenames[npe.p_fstype], unused + 'a');
    225  1.7.4.1       he 		switch (npe.p_fstype) {
    226  1.7.4.1       he 		case FS_BSDFFS:
    227  1.7.4.1       he 			npe.p_size = 16384;	/* XXX */
    228  1.7.4.1       he 			npe.p_fsize = 1024;
    229  1.7.4.1       he 			npe.p_frag = 8;
    230  1.7.4.1       he 			npe.p_cpg = 16;
    231  1.7.4.1       he 			break;
    232  1.7.4.1       he #ifdef	__does_not_happen__
    233  1.7.4.1       he 		case FS_BSDLFS:
    234  1.7.4.1       he 			npe.p_size = 16384;	/* XXX */
    235  1.7.4.1       he 			npe.p_fsize = 1024;
    236  1.7.4.1       he 			npe.p_frag = 8;
    237  1.7.4.1       he 			npe.p_sgs = XXX;
    238      1.1       ws 			break;
    239  1.7.4.1       he #endif
    240      1.1       ws 		}
    241  1.7.4.1       he 		changed++;
    242  1.7.4.1       he 		label.d_partitions[unused] = npe;
    243      1.1       ws 	}
    244  1.7.4.1       he 
    245  1.7.4.1       he 				/* recursively scan extended partitions */
    246      1.5      cgd 	for (i = 0; i < NMBRPART; i++) {
    247      1.6       ws 		u_int32_t poff;
    248      1.6       ws 
    249  1.7.4.1       he 		if (MBR_IS_EXTENDED(parts[i].mbrp_typ)) {
    250  1.7.4.1       he 			poff = getlong(&parts[i].mbrp_start) + extoff;
    251  1.7.4.1       he 			changed += getparts(sd, poff,
    252  1.7.4.1       he 			    extoff ? extoff : poff, verbose);
    253      1.1       ws 		}
    254      1.1       ws 	}
    255  1.7.4.1       he 	return (changed);
    256      1.1       ws }
    257      1.1       ws 
    258      1.1       ws void
    259  1.7.4.1       he usage(void)
    260      1.1       ws {
    261  1.7.4.1       he 	fprintf(stderr, "Usage: %s [-fqrw] rawdisk\n", __progname);
    262      1.1       ws 	exit(1);
    263      1.1       ws }
    264      1.1       ws 
    265      1.1       ws 
    266  1.7.4.1       he int
    267  1.7.4.1       he main(int argc, char **argv)
    268  1.7.4.1       he {
    269  1.7.4.1       he 	int	sd, ch, changed;
    270  1.7.4.1       he 	char	name[MAXPATHLEN];
    271  1.7.4.1       he 	int	force;			/* force label update */
    272  1.7.4.1       he 	int	raw;			/* update on-disk label as well */
    273  1.7.4.1       he 	int	verbose;		/* verbose output */
    274  1.7.4.1       he 	int	write_it;		/* update in-core label if changed */
    275  1.7.4.1       he 
    276  1.7.4.1       he 	force = 0;
    277  1.7.4.1       he 	raw = 0;
    278  1.7.4.1       he 	verbose = 1;
    279  1.7.4.1       he 	write_it = 0;
    280  1.7.4.1       he 	while ((ch = getopt(argc, argv, "fqrw")) != -1) {
    281  1.7.4.1       he 		switch (ch) {
    282  1.7.4.1       he 		case 'f':
    283  1.7.4.1       he 			force = 1;
    284  1.7.4.1       he 			break;
    285  1.7.4.1       he 		case 'q':
    286  1.7.4.1       he 			verbose = 0;
    287  1.7.4.1       he 			break;
    288  1.7.4.1       he 		case 'r':
    289  1.7.4.1       he 			raw = 1;
    290  1.7.4.1       he 			break;
    291  1.7.4.1       he 		case 'w':
    292  1.7.4.1       he 			write_it = 1;
    293  1.7.4.1       he 			break;
    294  1.7.4.1       he 		default:
    295  1.7.4.1       he 			usage();
    296  1.7.4.1       he 		}
    297  1.7.4.1       he 	}
    298  1.7.4.1       he 	argc -= optind;
    299  1.7.4.1       he 	argv += optind;
    300  1.7.4.1       he 	if (argc != 1)
    301      1.1       ws 		usage();
    302      1.1       ws 
    303  1.7.4.1       he 	if ((sd = opendisk(argv[0], O_RDWR, name, MAXPATHLEN, 0)) < 0) {
    304  1.7.4.1       he 		perror(argv[0]);
    305      1.1       ws 		exit(1);
    306      1.1       ws 	}
    307      1.1       ws 	getlabel(sd);
    308  1.7.4.1       he 	changed = getparts(sd, MBR_BBSECTOR, 0, verbose);
    309  1.7.4.1       he 
    310  1.7.4.1       he 	if (verbose) {
    311  1.7.4.1       he 		putchar('\n');
    312  1.7.4.1       he 		showpartitions(stdout, &label, 0);
    313  1.7.4.1       he 		putchar('\n');
    314  1.7.4.1       he 	}
    315  1.7.4.1       he 	if (write_it) {
    316  1.7.4.1       he 		if (! changed && ! force)
    317  1.7.4.1       he 			printf("No change; not updating disk label.\n");
    318  1.7.4.1       he 		else {
    319  1.7.4.1       he 			if (verbose)
    320  1.7.4.1       he 				printf("Updating in-core %sdisk label.\n",
    321  1.7.4.1       he 				    raw ? "and on-disk " : "");
    322  1.7.4.1       he 			setlabel(sd, raw);
    323  1.7.4.1       he 		}
    324  1.7.4.1       he 	} else {
    325  1.7.4.1       he 		printf("Not updating disk label.\n");
    326  1.7.4.1       he 	}
    327      1.1       ws 	close(sd);
    328  1.7.4.1       he 	return (0);
    329      1.1       ws }
    330