Home | History | Annotate | Line # | Download | only in gpt
backup.c revision 1.15
      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.15 2015/12/03 04:39:41 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 *backuphelp[] = {
     55 	"[-o outfile]",
     56 };
     57 
     58 static int cmd_backup(gpt_t, int, char *[]);
     59 
     60 struct gpt_cmd c_backup = {
     61 	"backup",
     62 	cmd_backup,
     63 	backuphelp, __arraycount(backuphelp),
     64 	GPT_READONLY,
     65 };
     66 
     67 #define usage() gpt_usage(NULL, &c_backup)
     68 
     69 #define PROP_ERR(x)	if (!(x)) {			\
     70 		gpt_warnx(gpt, "proplib failure");	\
     71 		return -1;				\
     72 	}
     73 
     74 #define prop_uint(a) prop_number_create_unsigned_integer(a)
     75 
     76 static int
     77 store_mbr(gpt_t gpt, unsigned int i, const struct mbr *mbr,
     78     prop_array_t *mbr_array)
     79 {
     80 	prop_dictionary_t mbr_dict;
     81 	prop_number_t propnum;
     82 	const struct mbr_part *par = &mbr->mbr_part[i];
     83 	bool rc;
     84 
     85 	if (mbr->mbr_part[i].part_typ == MBR_PTYPE_UNUSED)
     86 		return 0;
     87 
     88 	mbr_dict = prop_dictionary_create();
     89 	PROP_ERR(mbr_dict);
     90 	propnum = prop_number_create_integer(i);
     91 	PROP_ERR(propnum);
     92 	rc = prop_dictionary_set(mbr_dict, "index", propnum);
     93 	PROP_ERR(rc);
     94 	propnum = prop_uint(par->part_flag);
     95 	PROP_ERR(propnum);
     96 	rc = prop_dictionary_set(mbr_dict, "flag", propnum);
     97 	PROP_ERR(rc);
     98 	propnum = prop_uint(par->part_shd);
     99 	PROP_ERR(propnum);
    100 	rc = prop_dictionary_set(mbr_dict, "start_head", propnum);
    101 	PROP_ERR(rc);
    102 	propnum = prop_uint(par->part_ssect);
    103 	PROP_ERR(propnum);
    104 	rc = prop_dictionary_set(mbr_dict, "start_sector", propnum);
    105 	PROP_ERR(rc);
    106 	propnum = prop_uint(par->part_scyl);
    107 	PROP_ERR(propnum);
    108 	rc = prop_dictionary_set(mbr_dict, "start_cylinder", propnum);
    109 	PROP_ERR(rc);
    110 	propnum = prop_uint(par->part_typ);
    111 	PROP_ERR(propnum);
    112 	rc = prop_dictionary_set(mbr_dict, "type", propnum);
    113 	PROP_ERR(rc);
    114 	propnum = prop_uint(par->part_ehd);
    115 	PROP_ERR(propnum);
    116 	rc = prop_dictionary_set(mbr_dict, "end_head", propnum);
    117 	PROP_ERR(rc);
    118 	propnum = prop_uint(par->part_esect);
    119 	PROP_ERR(propnum);
    120 	rc = prop_dictionary_set(mbr_dict, "end_sector", propnum);
    121 	PROP_ERR(rc);
    122 	propnum = prop_uint(par->part_ecyl);
    123 	PROP_ERR(propnum);
    124 	rc = prop_dictionary_set(mbr_dict, "end_cylinder", propnum);
    125 	PROP_ERR(rc);
    126 	propnum = prop_uint(le16toh(par->part_start_lo));
    127 	PROP_ERR(propnum);
    128 	rc = prop_dictionary_set(mbr_dict, "lba_start_low", propnum);
    129 	PROP_ERR(rc);
    130 	propnum = prop_uint(le16toh(par->part_start_hi));
    131 	PROP_ERR(propnum);
    132 	rc = prop_dictionary_set(mbr_dict, "lba_start_high", propnum);
    133 	PROP_ERR(rc);
    134 	propnum = prop_uint(le16toh(par->part_size_lo));
    135 	PROP_ERR(propnum);
    136 	rc = prop_dictionary_set(mbr_dict, "lba_size_low", propnum);
    137 	PROP_ERR(rc);
    138 	propnum = prop_uint(le16toh(par->part_size_hi));
    139 	PROP_ERR(propnum);
    140 	rc = prop_dictionary_set(mbr_dict, "lba_size_high", propnum);
    141 	if (*mbr_array == NULL) {
    142 		*mbr_array = prop_array_create();
    143 		PROP_ERR(*mbr_array);
    144 	}
    145 	rc = prop_array_add(*mbr_array, mbr_dict);
    146 	PROP_ERR(rc);
    147 	return 0;
    148 }
    149 
    150 static int
    151 store_gpt(gpt_t gpt, const struct gpt_hdr *hdr, prop_dictionary_t *type_dict)
    152 {
    153 	prop_number_t propnum;
    154 	prop_string_t propstr;
    155 	char buf[128];
    156 	bool rc;
    157 
    158 	*type_dict = prop_dictionary_create();
    159 	PROP_ERR(type_dict);
    160 	propnum = prop_uint(le32toh(hdr->hdr_revision));
    161 	PROP_ERR(propnum);
    162 	rc = prop_dictionary_set(*type_dict, "revision", propnum);
    163 	PROP_ERR(rc);
    164 	gpt_uuid_snprintf(buf, sizeof(buf), "%d", hdr->hdr_guid);
    165 	propstr = prop_string_create_cstring(buf);
    166 	PROP_ERR(propstr);
    167 	rc = prop_dictionary_set(*type_dict, "guid", propstr);
    168 	PROP_ERR(rc);
    169 	propnum = prop_number_create_integer(le32toh(hdr->hdr_entries));
    170 	PROP_ERR(propnum);
    171 	rc = prop_dictionary_set(*type_dict, "entries", propnum);
    172 	PROP_ERR(rc);
    173 	return 0;
    174 }
    175 
    176 static int
    177 store_tbl(gpt_t gpt, const map_t m, prop_dictionary_t *type_dict)
    178 {
    179 	const struct gpt_ent *ent;
    180 	unsigned int i;
    181 	prop_dictionary_t gpt_dict;
    182 	prop_array_t gpt_array;
    183 	prop_number_t propnum;
    184 	prop_string_t propstr;
    185 	char buf[128];
    186 	uint8_t utfbuf[__arraycount(ent->ent_name) * 3 + 1];
    187 	bool rc;
    188 
    189 	*type_dict = prop_dictionary_create();
    190 	PROP_ERR(*type_dict);
    191 
    192 	ent = m->map_data;
    193 	gpt_array = prop_array_create();
    194 	PROP_ERR(gpt_array);
    195 	for (i = 1, ent = m->map_data;
    196 	    (const char *)ent < (const char *)(m->map_data) +
    197 	    m->map_size * gpt->secsz; i++, ent++) {
    198 		gpt_dict = prop_dictionary_create();
    199 		PROP_ERR(gpt_dict);
    200 		propnum = prop_number_create_integer(i);
    201 		PROP_ERR(propnum);
    202 		rc = prop_dictionary_set(gpt_dict, "index", propnum);
    203 		PROP_ERR(propnum);
    204 		gpt_uuid_snprintf(buf, sizeof(buf), "%d", ent->ent_type);
    205 		propstr = prop_string_create_cstring(buf);
    206 		PROP_ERR(propstr);
    207 		rc = prop_dictionary_set(gpt_dict, "type", propstr);
    208 		gpt_uuid_snprintf(buf, sizeof(buf), "%d", ent->ent_guid);
    209 		propstr = prop_string_create_cstring(buf);
    210 		PROP_ERR(propstr);
    211 		rc = prop_dictionary_set(gpt_dict, "guid", propstr);
    212 		PROP_ERR(propstr);
    213 		propnum = prop_uint(le64toh(ent->ent_lba_start));
    214 		PROP_ERR(propnum);
    215 		rc = prop_dictionary_set(gpt_dict, "start", propnum);
    216 		PROP_ERR(rc);
    217 		propnum = prop_uint(le64toh(ent->ent_lba_end));
    218 		PROP_ERR(rc);
    219 		rc = prop_dictionary_set(gpt_dict, "end", propnum);
    220 		PROP_ERR(rc);
    221 		propnum = prop_uint(le64toh(ent->ent_attr));
    222 		PROP_ERR(propnum);
    223 		rc = prop_dictionary_set(gpt_dict, "attributes", propnum);
    224 		PROP_ERR(rc);
    225 		utf16_to_utf8(ent->ent_name, utfbuf, sizeof(utfbuf));
    226 		if (utfbuf[0] != '\0') {
    227 			propstr = prop_string_create_cstring((char *)utfbuf);
    228 			PROP_ERR(propstr);
    229 			rc = prop_dictionary_set(gpt_dict, "name", propstr);
    230 			PROP_ERR(rc);
    231 		}
    232 		rc = prop_array_add(gpt_array, gpt_dict);
    233 		PROP_ERR(rc);
    234 	}
    235 	rc = prop_dictionary_set(*type_dict, "gpt_array", gpt_array);
    236 	PROP_ERR(rc);
    237 	prop_object_release(gpt_array);
    238 	return 0;
    239 }
    240 
    241 static int
    242 backup(gpt_t gpt, const char *outfile)
    243 {
    244 	map_t m;
    245 	struct mbr *mbr;
    246 	unsigned int i;
    247 	prop_dictionary_t props, type_dict;
    248 	prop_array_t mbr_array;
    249 	prop_data_t propdata;
    250 	prop_number_t propnum;
    251 	char *propext;
    252 	bool rc;
    253 	FILE *fp;
    254 
    255 	props = prop_dictionary_create();
    256 	PROP_ERR(props);
    257 	propnum = prop_number_create_integer(gpt->secsz);
    258 	PROP_ERR(propnum);
    259 	rc = prop_dictionary_set(props, "sector_size", propnum);
    260 	PROP_ERR(rc);
    261 	m = map_first(gpt);
    262 	while (m != NULL) {
    263 		switch (m->map_type) {
    264 		case MAP_TYPE_MBR:
    265 		case MAP_TYPE_PMBR:
    266 			type_dict = prop_dictionary_create();
    267 			PROP_ERR(type_dict);
    268 			mbr = m->map_data;
    269 			propdata = prop_data_create_data_nocopy(mbr->mbr_code,
    270 			    sizeof(mbr->mbr_code));
    271 			PROP_ERR(propdata);
    272 			rc = prop_dictionary_set(type_dict, "code", propdata);
    273 			PROP_ERR(rc);
    274 			mbr_array = NULL;
    275 			for (i = 0; i < 4; i++) {
    276 				if (store_mbr(gpt, i, mbr, &mbr_array) == -1)
    277 					return -1;
    278 			}
    279 			if (mbr_array != NULL) {
    280 				rc = prop_dictionary_set(type_dict,
    281 				    "mbr_array", mbr_array);
    282 				PROP_ERR(rc);
    283 				prop_object_release(mbr_array);
    284 			}
    285 			rc = prop_dictionary_set(props, "MBR", type_dict);
    286 			PROP_ERR(rc);
    287 			prop_object_release(type_dict);
    288 			break;
    289 		case MAP_TYPE_PRI_GPT_HDR:
    290 			if (store_gpt(gpt, m->map_data, &type_dict) == -1)
    291 				return -1;
    292 
    293 			rc = prop_dictionary_set(props, "GPT_HDR", type_dict);
    294 			PROP_ERR(rc);
    295 			prop_object_release(type_dict);
    296 			break;
    297 		case MAP_TYPE_PRI_GPT_TBL:
    298 			if (store_tbl(gpt, m, &type_dict) == -1)
    299 				return -1;
    300 			rc = prop_dictionary_set(props, "GPT_TBL", type_dict);
    301 			PROP_ERR(rc);
    302 			prop_object_release(type_dict);
    303 			break;
    304 		}
    305 		m = m->map_next;
    306 	}
    307 	propext = prop_dictionary_externalize(props);
    308 	PROP_ERR(propext);
    309 	prop_object_release(props);
    310 	fp = strcmp(outfile, "-") == 0 ? stdout : fopen(outfile, "w");
    311 	if (fp == NULL) {
    312 		gpt_warn(gpt, "Can't open `%s'", outfile);
    313 		return -1;
    314 	}
    315 	fputs(propext, fp);
    316 	if (fp != stdout)
    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 	const char *outfile = "-";
    327 
    328 	while ((ch = getopt(argc, argv, "o:")) != -1) {
    329 		switch(ch) {
    330 		case 'o':
    331 			outfile = optarg;
    332 			break;
    333 		default:
    334 			return usage();
    335 		}
    336 	}
    337 	if (argc != optind)
    338 		return usage();
    339 
    340 	return backup(gpt, outfile);
    341 }
    342