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