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 #include <sys/cdefs.h> 28 #ifdef __FBSDID 29 __FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $"); 30 #endif 31 #ifdef __RCSID 32 __RCSID("$NetBSD: backup.c,v 1.3 2014/09/10 10:49:44 jnemeth Exp $"); 33 #endif 34 35 #include <sys/bootblock.h> 36 #include <sys/types.h> 37 38 #include <err.h> 39 #include <stddef.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 #include <prop/proplib.h> 45 46 #include "map.h" 47 #include "gpt.h" 48 49 50 const char backupmsg[] = "backup device ..."; 51 52 __dead static void 53 usage_backup(void) 54 { 55 56 fprintf(stderr, 57 "usage: %s %s\n", getprogname(), backupmsg); 58 exit(1); 59 } 60 61 #define PROP_ERR(x) if (!(x)) { \ 62 warn("proplib failure"); \ 63 return; \ 64 } 65 66 static void 67 backup(void) 68 { 69 uuid_t u; 70 map_t *m; 71 struct mbr *mbr; 72 struct gpt_ent *ent; 73 struct gpt_hdr *hdr; 74 unsigned int i; 75 prop_dictionary_t props, mbr_dict, gpt_dict, type_dict; 76 prop_array_t mbr_array, gpt_array; 77 prop_data_t propdata; 78 prop_number_t propnum; 79 prop_string_t propstr; 80 char *propext, *s; 81 bool rc; 82 83 props = prop_dictionary_create(); 84 PROP_ERR(props); 85 propnum = prop_number_create_integer(secsz); 86 PROP_ERR(propnum); 87 rc = prop_dictionary_set(props, "sector_size", propnum); 88 PROP_ERR(rc); 89 m = map_first(); 90 while (m != NULL) { 91 switch (m->map_type) { 92 case MAP_TYPE_MBR: 93 case MAP_TYPE_PMBR: 94 type_dict = prop_dictionary_create(); 95 PROP_ERR(type_dict); 96 mbr = m->map_data; 97 propdata = prop_data_create_data_nocopy(mbr->mbr_code, 98 sizeof(mbr->mbr_code)); 99 PROP_ERR(propdata); 100 rc = prop_dictionary_set(type_dict, "code", propdata); 101 PROP_ERR(rc); 102 mbr_array = NULL; 103 for (i = 0; i < 4; i++) { 104 if (mbr->mbr_part[i].part_typ != 105 MBR_PTYPE_UNUSED) { 106 mbr_dict = prop_dictionary_create(); 107 PROP_ERR(mbr_dict); 108 propnum = prop_number_create_integer(i); 109 PROP_ERR(propnum); 110 rc = prop_dictionary_set(mbr_dict, 111 "index", propnum); 112 PROP_ERR(rc); 113 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_flag); 114 PROP_ERR(propnum); 115 rc = prop_dictionary_set(mbr_dict, 116 "flag", propnum); 117 PROP_ERR(rc); 118 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_shd); 119 PROP_ERR(propnum); 120 rc = prop_dictionary_set(mbr_dict, 121 "start_head", propnum); 122 PROP_ERR(rc); 123 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_ssect); 124 PROP_ERR(propnum); 125 rc = prop_dictionary_set(mbr_dict, 126 "start_sector", propnum); 127 PROP_ERR(rc); 128 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_scyl); 129 PROP_ERR(propnum); 130 rc = prop_dictionary_set(mbr_dict, 131 "start_cylinder", propnum); 132 PROP_ERR(rc); 133 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_typ); 134 PROP_ERR(propnum); 135 rc = prop_dictionary_set(mbr_dict, 136 "type", propnum); 137 PROP_ERR(rc); 138 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_ehd); 139 PROP_ERR(propnum); 140 rc = prop_dictionary_set(mbr_dict, 141 "end_head", propnum); 142 PROP_ERR(rc); 143 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_esect); 144 PROP_ERR(propnum); 145 rc = prop_dictionary_set(mbr_dict, 146 "end_sector", propnum); 147 PROP_ERR(rc); 148 propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_ecyl); 149 PROP_ERR(propnum); 150 rc = prop_dictionary_set(mbr_dict, 151 "end_cylinder", propnum); 152 PROP_ERR(rc); 153 propnum = prop_number_create_unsigned_integer(le16toh(mbr->mbr_part[i].part_start_lo)); 154 PROP_ERR(propnum); 155 rc = prop_dictionary_set(mbr_dict, 156 "lba_start_low", propnum); 157 PROP_ERR(rc); 158 propnum = prop_number_create_unsigned_integer(le16toh(mbr->mbr_part[i].part_start_hi)); 159 PROP_ERR(propnum); 160 rc = prop_dictionary_set(mbr_dict, 161 "lba_start_high", propnum); 162 PROP_ERR(rc); 163 propnum = prop_number_create_unsigned_integer(le16toh(mbr->mbr_part[i].part_size_lo)); 164 PROP_ERR(propnum); 165 rc = prop_dictionary_set(mbr_dict, 166 "lba_size_low", propnum); 167 PROP_ERR(rc); 168 propnum = prop_number_create_unsigned_integer(le16toh(mbr->mbr_part[i].part_size_hi)); 169 PROP_ERR(propnum); 170 rc = prop_dictionary_set(mbr_dict, 171 "lba_size_high", propnum); 172 if (mbr_array == NULL) { 173 mbr_array = prop_array_create(); 174 PROP_ERR(mbr_array); 175 } 176 rc = prop_array_add(mbr_array, 177 mbr_dict); 178 PROP_ERR(rc); 179 } 180 } 181 if (mbr_array != NULL) { 182 rc = prop_dictionary_set(type_dict, 183 "mbr_array", mbr_array); 184 PROP_ERR(rc); 185 prop_object_release(mbr_array); 186 } 187 rc = prop_dictionary_set(props, "MBR", type_dict); 188 PROP_ERR(rc); 189 prop_object_release(type_dict); 190 break; 191 case MAP_TYPE_PRI_GPT_HDR: 192 type_dict = prop_dictionary_create(); 193 PROP_ERR(type_dict); 194 hdr = m->map_data; 195 propnum = prop_number_create_unsigned_integer(le32toh(hdr->hdr_revision)); 196 PROP_ERR(propnum); 197 rc = prop_dictionary_set(type_dict, "revision", 198 propnum); 199 PROP_ERR(rc); 200 le_uuid_dec(hdr->hdr_guid, &u); 201 uuid_to_string(&u, &s, NULL); 202 propstr = prop_string_create_cstring(s); 203 free(s); 204 PROP_ERR(propstr); 205 rc = prop_dictionary_set(type_dict, "guid", propstr); 206 PROP_ERR(rc); 207 propnum = prop_number_create_integer(le32toh(hdr->hdr_entries)); 208 PROP_ERR(propnum); 209 rc = prop_dictionary_set(type_dict, "entries", propnum); 210 PROP_ERR(rc); 211 rc = prop_dictionary_set(props, "GPT_HDR", type_dict); 212 PROP_ERR(rc); 213 prop_object_release(type_dict); 214 break; 215 case MAP_TYPE_PRI_GPT_TBL: 216 type_dict = prop_dictionary_create(); 217 PROP_ERR(type_dict); 218 ent = m->map_data; 219 gpt_array = prop_array_create(); 220 PROP_ERR(gpt_array); 221 for (i = 1, ent = m->map_data; 222 (char *)ent < (char *)(m->map_data) + 223 m->map_size * secsz; i++, ent++) { 224 gpt_dict = prop_dictionary_create(); 225 PROP_ERR(gpt_dict); 226 propnum = prop_number_create_integer(i); 227 PROP_ERR(propnum); 228 rc = prop_dictionary_set(gpt_dict, "index", 229 propnum); 230 PROP_ERR(propnum); 231 le_uuid_dec(ent->ent_type, &u); 232 uuid_to_string(&u, &s, NULL); 233 propstr = prop_string_create_cstring(s); 234 free(s); 235 PROP_ERR(propstr); 236 rc = prop_dictionary_set(gpt_dict, "type", 237 propstr); 238 le_uuid_dec(ent->ent_guid, &u); 239 uuid_to_string(&u, &s, NULL); 240 propstr = prop_string_create_cstring(s); 241 free(s); 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 305 backup(); 306 307 gpt_close(fd); 308 } 309 310 return (0); 311 } 312