Home | History | Annotate | Line # | Download | only in gpt
backup.c revision 1.13
      1 /*-
      2  * Copyright (c) 2002 Marcel Moolenaar
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #if HAVE_NBTOOL_CONFIG_H
     28 #include "nbtool_config.h"
     29 #endif
     30 
     31 #include <sys/cdefs.h>
     32 #ifdef __FBSDID
     33 __FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
     34 #endif
     35 #ifdef __RCSID
     36 __RCSID("$NetBSD: backup.c,v 1.13 2015/12/02 12:36:53 christos Exp $");
     37 #endif
     38 
     39 #include <sys/bootblock.h>
     40 #include <sys/types.h>
     41 
     42 #include <err.h>
     43 #include <stddef.h>
     44 #include <stdio.h>
     45 #include <stdlib.h>
     46 #include <string.h>
     47 #include <unistd.h>
     48 #include <prop/proplib.h>
     49 
     50 #include "map.h"
     51 #include "gpt.h"
     52 #include "gpt_private.h"
     53 
     54 static const char *outfile = "/dev/stdout";
     55 
     56 static const char *backuphelp[] = {
     57     "[-o outfile]",
     58 };
     59 
     60 static int cmd_backup(gpt_t, int, char *[]);
     61 
     62 struct gpt_cmd c_backup = {
     63 	"backup",
     64 	cmd_backup,
     65 	backuphelp, __arraycount(backuphelp),
     66 	GPT_READONLY,
     67 };
     68 
     69 #define usage() gpt_usage(NULL, &c_backup)
     70 
     71 #define PROP_ERR(x)	if (!(x)) {			\
     72 		gpt_warnx(gpt, "proplib failure");	\
     73 		return -1;				\
     74 	}
     75 
     76 #define prop_uint(a) prop_number_create_unsigned_integer(a)
     77 
     78 static int
     79 store_mbr(gpt_t gpt, unsigned int i, const struct mbr *mbr,
     80     prop_array_t *mbr_array)
     81 {
     82 	prop_dictionary_t mbr_dict;
     83 	prop_number_t propnum;
     84 	const struct mbr_part *par = &mbr->mbr_part[i];
     85 	bool rc;
     86 
     87 	if (mbr->mbr_part[i].part_typ == MBR_PTYPE_UNUSED)
     88 		return 0;
     89 
     90 	mbr_dict = prop_dictionary_create();
     91 	PROP_ERR(mbr_dict);
     92 	propnum = prop_number_create_integer(i);
     93 	PROP_ERR(propnum);
     94 	rc = prop_dictionary_set(mbr_dict, "index", propnum);
     95 	PROP_ERR(rc);
     96 	propnum = prop_uint(par->part_flag);
     97 	PROP_ERR(propnum);
     98 	rc = prop_dictionary_set(mbr_dict, "flag", propnum);
     99 	PROP_ERR(rc);
    100 	propnum = prop_uint(par->part_shd);
    101 	PROP_ERR(propnum);
    102 	rc = prop_dictionary_set(mbr_dict, "start_head", propnum);
    103 	PROP_ERR(rc);
    104 	propnum = prop_uint(par->part_ssect);
    105 	PROP_ERR(propnum);
    106 	rc = prop_dictionary_set(mbr_dict, "start_sector", propnum);
    107 	PROP_ERR(rc);
    108 	propnum = prop_uint(par->part_scyl);
    109 	PROP_ERR(propnum);
    110 	rc = prop_dictionary_set(mbr_dict, "start_cylinder", propnum);
    111 	PROP_ERR(rc);
    112 	propnum = prop_uint(par->part_typ);
    113 	PROP_ERR(propnum);
    114 	rc = prop_dictionary_set(mbr_dict, "type", propnum);
    115 	PROP_ERR(rc);
    116 	propnum = prop_uint(par->part_ehd);
    117 	PROP_ERR(propnum);
    118 	rc = prop_dictionary_set(mbr_dict, "end_head", propnum);
    119 	PROP_ERR(rc);
    120 	propnum = prop_uint(par->part_esect);
    121 	PROP_ERR(propnum);
    122 	rc = prop_dictionary_set(mbr_dict, "end_sector", propnum);
    123 	PROP_ERR(rc);
    124 	propnum = prop_uint(par->part_ecyl);
    125 	PROP_ERR(propnum);
    126 	rc = prop_dictionary_set(mbr_dict, "end_cylinder", propnum);
    127 	PROP_ERR(rc);
    128 	propnum = prop_uint(le16toh(par->part_start_lo));
    129 	PROP_ERR(propnum);
    130 	rc = prop_dictionary_set(mbr_dict, "lba_start_low", propnum);
    131 	PROP_ERR(rc);
    132 	propnum = prop_uint(le16toh(par->part_start_hi));
    133 	PROP_ERR(propnum);
    134 	rc = prop_dictionary_set(mbr_dict, "lba_start_high", propnum);
    135 	PROP_ERR(rc);
    136 	propnum = prop_uint(le16toh(par->part_size_lo));
    137 	PROP_ERR(propnum);
    138 	rc = prop_dictionary_set(mbr_dict, "lba_size_low", propnum);
    139 	PROP_ERR(rc);
    140 	propnum = prop_uint(le16toh(par->part_size_hi));
    141 	PROP_ERR(propnum);
    142 	rc = prop_dictionary_set(mbr_dict, "lba_size_high", propnum);
    143 	if (*mbr_array == NULL) {
    144 		*mbr_array = prop_array_create();
    145 		PROP_ERR(*mbr_array);
    146 	}
    147 	rc = prop_array_add(*mbr_array, mbr_dict);
    148 	PROP_ERR(rc);
    149 	return 0;
    150 }
    151 
    152 static int
    153 store_gpt(gpt_t gpt, const struct gpt_hdr *hdr, prop_dictionary_t *type_dict)
    154 {
    155 	prop_number_t propnum;
    156 	prop_string_t propstr;
    157 	char buf[128];
    158 	bool rc;
    159 
    160 	*type_dict = prop_dictionary_create();
    161 	PROP_ERR(type_dict);
    162 	propnum = prop_uint(le32toh(hdr->hdr_revision));
    163 	PROP_ERR(propnum);
    164 	rc = prop_dictionary_set(*type_dict, "revision", propnum);
    165 	PROP_ERR(rc);
    166 	gpt_uuid_snprintf(buf, sizeof(buf), "%d", hdr->hdr_guid);
    167 	propstr = prop_string_create_cstring(buf);
    168 	PROP_ERR(propstr);
    169 	rc = prop_dictionary_set(*type_dict, "guid", propstr);
    170 	PROP_ERR(rc);
    171 	propnum = prop_number_create_integer(le32toh(hdr->hdr_entries));
    172 	PROP_ERR(propnum);
    173 	rc = prop_dictionary_set(*type_dict, "entries", propnum);
    174 	PROP_ERR(rc);
    175 	return 0;
    176 }
    177 
    178 static int
    179 store_tbl(gpt_t gpt, const map_t m, prop_dictionary_t *type_dict)
    180 {
    181 	const struct gpt_ent *ent;
    182 	unsigned int i;
    183 	prop_dictionary_t gpt_dict;
    184 	prop_array_t gpt_array;
    185 	prop_number_t propnum;
    186 	prop_string_t propstr;
    187 	char buf[128];
    188 	uint8_t utfbuf[__arraycount(ent->ent_name) * 3 + 1];
    189 	bool rc;
    190 
    191 	*type_dict = prop_dictionary_create();
    192 	PROP_ERR(*type_dict);
    193 
    194 	ent = m->map_data;
    195 	gpt_array = prop_array_create();
    196 	PROP_ERR(gpt_array);
    197 	for (i = 1, ent = m->map_data;
    198 	    (const char *)ent < (const char *)(m->map_data) +
    199 	    m->map_size * gpt->secsz; i++, ent++) {
    200 		gpt_dict = prop_dictionary_create();
    201 		PROP_ERR(gpt_dict);
    202 		propnum = prop_number_create_integer(i);
    203 		PROP_ERR(propnum);
    204 		rc = prop_dictionary_set(gpt_dict, "index", propnum);
    205 		PROP_ERR(propnum);
    206 		gpt_uuid_snprintf(buf, sizeof(buf), "%d", ent->ent_type);
    207 		propstr = prop_string_create_cstring(buf);
    208 		PROP_ERR(propstr);
    209 		rc = prop_dictionary_set(gpt_dict, "type", propstr);
    210 		gpt_uuid_snprintf(buf, sizeof(buf), "%d", ent->ent_guid);
    211 		propstr = prop_string_create_cstring(buf);
    212 		PROP_ERR(propstr);
    213 		rc = prop_dictionary_set(gpt_dict, "guid", propstr);
    214 		PROP_ERR(propstr);
    215 		propnum = prop_uint(le64toh(ent->ent_lba_start));
    216 		PROP_ERR(propnum);
    217 		rc = prop_dictionary_set(gpt_dict, "start", propnum);
    218 		PROP_ERR(rc);
    219 		propnum = prop_uint(le64toh(ent->ent_lba_end));
    220 		PROP_ERR(rc);
    221 		rc = prop_dictionary_set(gpt_dict, "end", propnum);
    222 		PROP_ERR(rc);
    223 		propnum = prop_uint(le64toh(ent->ent_attr));
    224 		PROP_ERR(propnum);
    225 		rc = prop_dictionary_set(gpt_dict, "attributes", propnum);
    226 		PROP_ERR(rc);
    227 		utf16_to_utf8(ent->ent_name, utfbuf, sizeof(utfbuf));
    228 		if (utfbuf[0] != '\0') {
    229 			propstr = prop_string_create_cstring((char *)utfbuf);
    230 			PROP_ERR(propstr);
    231 			rc = prop_dictionary_set(gpt_dict, "name", propstr);
    232 			PROP_ERR(rc);
    233 		}
    234 		rc = prop_array_add(gpt_array, gpt_dict);
    235 		PROP_ERR(rc);
    236 	}
    237 	rc = prop_dictionary_set(*type_dict, "gpt_array", gpt_array);
    238 	PROP_ERR(rc);
    239 	prop_object_release(gpt_array);
    240 	return 0;
    241 }
    242 
    243 static int
    244 backup(gpt_t gpt)
    245 {
    246 	map_t m;
    247 	struct mbr *mbr;
    248 	unsigned int i;
    249 	prop_dictionary_t props, type_dict;
    250 	prop_array_t mbr_array;
    251 	prop_data_t propdata;
    252 	prop_number_t propnum;
    253 	char *propext;
    254 	bool rc;
    255 	FILE *fp;
    256 
    257 	props = prop_dictionary_create();
    258 	PROP_ERR(props);
    259 	propnum = prop_number_create_integer(gpt->secsz);
    260 	PROP_ERR(propnum);
    261 	rc = prop_dictionary_set(props, "sector_size", propnum);
    262 	PROP_ERR(rc);
    263 	m = map_first(gpt);
    264 	while (m != NULL) {
    265 		switch (m->map_type) {
    266 		case MAP_TYPE_MBR:
    267 		case MAP_TYPE_PMBR:
    268 			type_dict = prop_dictionary_create();
    269 			PROP_ERR(type_dict);
    270 			mbr = m->map_data;
    271 			propdata = prop_data_create_data_nocopy(mbr->mbr_code,
    272 			    sizeof(mbr->mbr_code));
    273 			PROP_ERR(propdata);
    274 			rc = prop_dictionary_set(type_dict, "code", propdata);
    275 			PROP_ERR(rc);
    276 			mbr_array = NULL;
    277 			for (i = 0; i < 4; i++) {
    278 				if (store_mbr(gpt, i, mbr, &mbr_array) == -1)
    279 					return -1;
    280 			}
    281 			if (mbr_array != NULL) {
    282 				rc = prop_dictionary_set(type_dict,
    283 				    "mbr_array", mbr_array);
    284 				PROP_ERR(rc);
    285 				prop_object_release(mbr_array);
    286 			}
    287 			rc = prop_dictionary_set(props, "MBR", type_dict);
    288 			PROP_ERR(rc);
    289 			prop_object_release(type_dict);
    290 			break;
    291 		case MAP_TYPE_PRI_GPT_HDR:
    292 			if (store_gpt(gpt, m->map_data, &type_dict) == -1)
    293 				return -1;
    294 
    295 			rc = prop_dictionary_set(props, "GPT_HDR", type_dict);
    296 			PROP_ERR(rc);
    297 			prop_object_release(type_dict);
    298 			break;
    299 		case MAP_TYPE_PRI_GPT_TBL:
    300 			if (store_tbl(gpt, m, &type_dict) == -1)
    301 				return -1;
    302 			rc = prop_dictionary_set(props, "GPT_TBL", type_dict);
    303 			PROP_ERR(rc);
    304 			prop_object_release(type_dict);
    305 			break;
    306 		}
    307 		m = m->map_next;
    308 	}
    309 	propext = prop_dictionary_externalize(props);
    310 	PROP_ERR(propext);
    311 	prop_object_release(props);
    312 	if ((fp = fopen(outfile, "w")) == NULL) {
    313 		gpt_warn(gpt, "Can't open `%s'", outfile);
    314 		return -1;
    315 	}
    316 	fputs(propext, fp);
    317 	fclose(fp);
    318 	free(propext);
    319 	return 0;
    320 }
    321 
    322 static int
    323 cmd_backup(gpt_t gpt, int argc, char *argv[])
    324 {
    325 	int ch;
    326 
    327 	while ((ch = getopt(argc, argv, "o:")) != -1) {
    328 		switch(ch) {
    329 		case 'o':
    330 			outfile = optarg;
    331 			break;
    332 		default:
    333 			return usage();
    334 		}
    335 	}
    336 	if (argc != optind)
    337 		return usage();
    338 
    339 	return backup(gpt);
    340 }
    341