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