Home | History | Annotate | Line # | Download | only in mbrlabel
mbrlabel.c revision 1.8
      1 /*	$NetBSD: mbrlabel.c,v 1.8 2000/07/03 03:37:59 matt Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1998 Wolfgang Solfrank.
      5  * Copyright (C) 1998 TooLs GmbH.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by TooLs GmbH.
     19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 #ifndef lint
     36 __RCSID("$NetBSD: mbrlabel.c,v 1.8 2000/07/03 03:37:59 matt Exp $");
     37 #endif /* not lint */
     38 
     39 #include <stdio.h>
     40 #include <fcntl.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <unistd.h>
     44 #include <util.h>
     45 
     46 #include <sys/param.h>
     47 #include <sys/disklabel.h>
     48 #include <sys/disklabel_mbr.h>
     49 #include <sys/ioctl.h>
     50 
     51 #include "dkcksum.h"
     52 
     53 #define	FIRSTPART	0
     54 
     55 int main __P((int, char **));
     56 void usage __P((void));
     57 void getlabel __P((int));
     58 void setlabel __P((int));
     59 int getparts __P((int, int, u_int32_t, u_int32_t));
     60 int nbsdtype __P((int));
     61 u_int32_t getlong __P((void *p));
     62 
     63 struct disklabel label;
     64 
     65 void
     66 getlabel(sd)
     67 	int sd;
     68 {
     69 	struct partition save;
     70 
     71 	if (ioctl(sd, DIOCGDINFO, &label) < 0) {
     72 		perror("get label");
     73 		exit(1);
     74 	}
     75 	save = label.d_partitions[RAW_PART];
     76 	memset(label.d_partitions, 0, sizeof label.d_partitions);
     77 	label.d_partitions[RAW_PART] = save;
     78 	/*
     79 	 * Some ports seem to not set the number of partitions
     80 	 * correctly, albeit they seem to set the raw partiton ok!
     81 	 */
     82 	if (label.d_npartitions <= RAW_PART)
     83 		label.d_npartitions = RAW_PART + 1;
     84 }
     85 
     86 void
     87 setlabel(sd)
     88 	int sd;
     89 {
     90 	label.d_checksum = 0;
     91 	label.d_checksum = dkcksum(&label);
     92 	if (ioctl(sd, DIOCSDINFO, &label) < 0) {
     93 		perror("set label");
     94 		exit(1);
     95 	}
     96 }
     97 
     98 static struct typetab {
     99 	int mbrtype;
    100 	int nbsdtype;
    101 } typetable[] = {
    102 	{ MBR_PTYPE_NETBSD, FS_BSDFFS },
    103 	{ MBR_PTYPE_386BSD, FS_BSDFFS },
    104 	{ MBR_PTYPE_FAT12, FS_MSDOS },
    105 	{ MBR_PTYPE_FAT16S, FS_MSDOS },
    106 	{ MBR_PTYPE_FAT16B, FS_MSDOS },
    107 	{ MBR_PTYPE_FAT32, FS_MSDOS },
    108 	{ MBR_PTYPE_FAT32L, FS_MSDOS },
    109 	{ MBR_PTYPE_FAT16L, FS_MSDOS },
    110 	{ MBR_PTYPE_LNXEXT2, FS_EX2FS },
    111 	{ 0, 0 }
    112 };
    113 
    114 int
    115 nbsdtype(type)
    116 	int type;
    117 {
    118 	struct typetab *tt;
    119 
    120 	for (tt = typetable; tt->mbrtype; tt++)
    121 		if (tt->mbrtype == type)
    122 			return tt->nbsdtype;
    123 	return FS_OTHER;
    124 }
    125 
    126 u_int32_t
    127 getlong(p)
    128 	void *p;
    129 {
    130 	unsigned char *cp = p;
    131 
    132 	return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
    133 }
    134 
    135 int
    136 getparts(sd, np, off, eoff)
    137 	int sd;
    138 	int np;
    139 	u_int32_t off;
    140 	u_int32_t eoff;
    141 {
    142 	unsigned char buf[DEV_BSIZE];
    143 	struct mbr_partition parts[NMBRPART];
    144 	off_t loff = 0;	/* XXX this nonsense shuts up GCC 2.7.2.2 */
    145 	int i;
    146 
    147 	loff = (off_t)off * DEV_BSIZE;
    148 
    149 	if (lseek(sd, loff, SEEK_SET) != loff) {
    150 		perror("seek label");
    151 		exit(1);
    152 	}
    153 	if (read(sd, buf, DEV_BSIZE) != DEV_BSIZE) {
    154 		perror("read label");
    155 		exit(1);
    156 	}
    157 	if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa)
    158 		return np;
    159 	memcpy(parts, buf + MBR_PARTOFF, sizeof parts);
    160 	for (i = 0; i < NMBRPART; i++) {
    161 		switch (parts[i].mbrp_typ) {
    162 		case 0:
    163 			/* Nothing to do */
    164 			break;
    165 		case MBR_PTYPE_EXT:
    166 		case MBR_PTYPE_EXT_LBA:
    167 		case MBR_PTYPE_EXT_LNX:
    168 			/* Will be handled below */
    169 			break;
    170 		default:
    171 			label.d_partitions[np].p_size = getlong(&parts[i].mbrp_size);
    172 			label.d_partitions[np].p_offset = getlong(&parts[i].mbrp_start) + off;
    173 			label.d_partitions[np].p_fstype = nbsdtype(parts[i].mbrp_typ);
    174 			switch (label.d_partitions[np].p_fstype) {
    175 			case FS_BSDFFS:
    176 				label.d_partitions[np].p_size = 16384;
    177 				label.d_partitions[np].p_fsize = 1024;
    178 				label.d_partitions[np].p_frag = 8;
    179 				label.d_partitions[np].p_cpg = 16;
    180 				break;
    181 #ifdef	__does_not_happen__
    182 			case FS_BSDLFS:
    183 				label.d_partitions[np].p_size = 16384;
    184 				label.d_partitions[np].p_fsize = 1024;
    185 				label.d_partitions[np].p_frag = 8;
    186 				label.d_partitions[np].p_sgs = XXX;
    187 				break;
    188 #endif
    189 			}
    190 			np++;
    191 			break;
    192 		}
    193 		if (np >MAXPARTITIONS)
    194 			return np;
    195 		if (np == RAW_PART)
    196 			np++;
    197 	}
    198 	for (i = 0; i < NMBRPART; i++) {
    199 		u_int32_t poff;
    200 
    201 		switch (parts[i].mbrp_typ) {
    202 		case MBR_PTYPE_EXT:
    203 		case MBR_PTYPE_EXT_LBA:
    204 		case MBR_PTYPE_EXT_LNX:
    205 			poff = getlong(&parts[i].mbrp_start) + eoff;
    206 			np = getparts(sd, np, poff, eoff ? eoff : poff);
    207 			break;
    208 		default:
    209 			break;
    210 		}
    211 		if (np >MAXPARTITIONS)
    212 			return np;
    213 	}
    214 	return np;
    215 }
    216 
    217 void
    218 usage()
    219 {
    220 	fprintf(stderr, "usage: mbrlabel rawdisk\n");
    221 	exit(1);
    222 }
    223 
    224 int
    225 main(argc, argv)
    226 	int argc;
    227 	char **argv;
    228 {
    229 	int sd;
    230 	int np;
    231 	char name[MAXPATHLEN];
    232 
    233 	if (argc != 2)
    234 		usage();
    235 
    236 	if ((sd = opendisk(*++argv, O_RDWR, name, MAXPATHLEN, 0)) < 0) {
    237 		perror(*argv);
    238 		exit(1);
    239 	}
    240 	getlabel(sd);
    241 	np = getparts(sd, FIRSTPART, MBR_BBSECTOR, 0);
    242 	if (np > label.d_npartitions)
    243 		label.d_npartitions = np;
    244 	setlabel(sd);
    245 	close(sd);
    246 	return 0;
    247 }
    248