1 1.5 riastrad /* $NetBSD: gptsubr.c,v 1.5 2025/03/02 01:07:11 riastradh Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Redistribution and use in source and binary forms, with or without 5 1.1 christos * modification, are permitted provided that the following conditions 6 1.1 christos * are met: 7 1.1 christos * 1. Redistributions of source code must retain the above copyright 8 1.1 christos * notice, this list of conditions and the following disclaimer. 9 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 10 1.1 christos * notice, this list of conditions and the following disclaimer in the 11 1.1 christos * documentation and/or other materials provided with the distribution. 12 1.1 christos * 13 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 14 1.1 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 1.1 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 1.1 christos * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 1.1 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 1.1 christos * SUCH DAMAGE. 24 1.1 christos */ 25 1.1 christos 26 1.1 christos #include <sys/cdefs.h> 27 1.1 christos #ifndef lint 28 1.5 riastrad __RCSID("$NetBSD: gptsubr.c,v 1.5 2025/03/02 01:07:11 riastradh Exp $"); 29 1.1 christos #endif /* not lint */ 30 1.1 christos 31 1.1 christos #include <sys/param.h> 32 1.1 christos 33 1.1 christos #include <sys/disk.h> 34 1.1 christos #include <sys/disklabel.h> 35 1.1 christos #include <sys/disklabel_gpt.h> 36 1.1 christos #include <sys/dkio.h> 37 1.1 christos #include <sys/ioctl.h> 38 1.1 christos #include <sys/stat.h> 39 1.1 christos #include <sys/statvfs.h> 40 1.1 christos 41 1.1 christos #include <err.h> 42 1.1 christos #include <fcntl.h> 43 1.1 christos #include <libgen.h> 44 1.1 christos #include <paths.h> 45 1.1 christos #include <stdbool.h> 46 1.1 christos #include <stdio.h> 47 1.1 christos #include <stdlib.h> 48 1.1 christos #include <unistd.h> 49 1.1 christos #include <uuid.h> 50 1.1 christos 51 1.1 christos #include "defs.h" 52 1.1 christos #include "gpt.h" 53 1.1 christos #include "gptsubr.h" 54 1.1 christos #include "map.h" 55 1.1 christos 56 1.1 christos #define DEBUG 57 1.1 christos 58 1.1 christos #ifdef DEBUG 59 1.1 christos #define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) 60 1.1 christos #else 61 1.1 christos #define DPRINTF(fmt, ...) do { } while (/*CONSTCOND*/0) 62 1.1 christos #endif 63 1.1 christos 64 1.1 christos static const char * 65 1.1 christos map_type_name(int map_type) 66 1.1 christos { 67 1.1 christos const char *xtbl[] = { 68 1.1 christos "UNUSED", // 0 69 1.1 christos "MBR", // 1 70 1.1 christos "MBR_PART", // 2 71 1.1 christos "PRI_GPT_HDR", // 3 72 1.1 christos "SEC_GPT_HDR", // 4 73 1.1 christos "PRI_GPT_TBL", // 5 74 1.1 christos "SEC_GPT_TBL", // 6 75 1.1 christos "GPT_PART", // 7 76 1.1 christos "PMBR", // 8 77 1.1 christos }; 78 1.1 christos 79 1.1 christos if (map_type >= (int)__arraycount(xtbl)) 80 1.1 christos return "UNKNOWN"; 81 1.1 christos 82 1.1 christos return xtbl[map_type]; 83 1.1 christos } 84 1.1 christos 85 1.1 christos #if 0 86 1.1 christos struct map { 87 1.1 christos off_t map_start; 88 1.1 christos off_t map_size; 89 1.1 christos struct map *map_next; 90 1.1 christos struct map *map_prev; 91 1.1 christos int map_type; 92 1.1 christos #define MAP_TYPE_UNUSED 0 93 1.1 christos #define MAP_TYPE_MBR 1 94 1.1 christos #define MAP_TYPE_MBR_PART 2 95 1.1 christos #define MAP_TYPE_PRI_GPT_HDR 3 96 1.1 christos #define MAP_TYPE_SEC_GPT_HDR 4 97 1.1 christos #define MAP_TYPE_PRI_GPT_TBL 5 98 1.1 christos #define MAP_TYPE_SEC_GPT_TBL 6 99 1.1 christos #define MAP_TYPE_GPT_PART 7 100 1.1 christos #define MAP_TYPE_PMBR 8 101 1.1 christos unsigned int map_index; 102 1.1 christos void *map_data; 103 1.1 christos int map_alloc; 104 1.1 christos }; 105 1.1 christos 106 1.1 christos struct gpt_ent { 107 1.1 christos uint8_t ent_type[16]; /* partition type GUID */ 108 1.1 christos uint8_t ent_guid[16]; /* unique partition GUID */ 109 1.1 christos uint64_t ent_lba_start; /* start of partition */ 110 1.1 christos uint64_t ent_lba_end; /* end of partition */ 111 1.1 christos uint64_t ent_attr; /* partition attributes */ 112 1.1 christos uint16_t ent_name[36]; /* partition name in UCS-2 */ 113 1.1 christos }; 114 1.1 christos 115 1.1 christos struct gpt_hdr { 116 1.1 christos int8_t hdr_sig[8]; /* identifies GUID Partition Table */ 117 1.1 christos uint32_t hdr_revision; /* GPT specification revision */ 118 1.1 christos uint32_t hdr_size; /* size of GPT Header */ 119 1.1 christos uint32_t hdr_crc_self; /* CRC32 of GPT Header */ 120 1.1 christos uint32_t hdr__rsvd0; /* must be zero */ 121 1.1 christos uint64_t hdr_lba_self; /* LBA that contains this Header */ 122 1.1 christos uint64_t hdr_lba_alt; /* LBA of backup GPT Header */ 123 1.1 christos uint64_t hdr_lba_start; /* first LBA usable for partitions */ 124 1.1 christos uint64_t hdr_lba_end; /* last LBA usable for partitions */ 125 1.1 christos uint8_t hdr_guid[16]; /* GUID to identify the disk */ 126 1.1 christos uint64_t hdr_lba_table; /* first LBA of GPE array */ 127 1.1 christos uint32_t hdr_entries; /* number of entries in GPE array */ 128 1.1 christos uint32_t hdr_entsz; /* size of each GPE */ 129 1.1 christos uint32_t hdr_crc_table; /* CRC32 of GPE array */ 130 1.1 christos /* 131 1.1 christos * The remainder of the block that contains the GPT Header 132 1.1 christos * is reserved by EFI for future GPT Header expansion, and 133 1.1 christos * must be zero. 134 1.1 christos */ 135 1.1 christos }; 136 1.1 christos #endif 137 1.1 christos 138 1.1 christos struct map_widths { 139 1.1 christos uint start; 140 1.1 christos uint size; 141 1.1 christos uint type_name; 142 1.1 christos }; 143 1.1 christos 144 1.1 christos static struct map_widths 145 1.1 christos get_map_widths(gpt_t gpt) 146 1.1 christos { 147 1.1 christos struct map_widths w; 148 1.1 christos off_t max_start = 0; 149 1.1 christos off_t max_size = 0; 150 1.1 christos map_t m; 151 1.1 christos 152 1.1 christos w.type_name = 0; 153 1.1 christos for (m = map_first(gpt); m != NULL; m = m->map_next) { 154 1.1 christos uint n; 155 1.1 christos 156 1.1 christos if (max_start < m->map_start) 157 1.1 christos max_start = m->map_start; 158 1.1 christos if (max_size < m->map_size) 159 1.1 christos max_size = m->map_size; 160 1.1 christos if (m->map_type == MAP_TYPE_GPT_PART) { 161 1.1 christos struct gpt_ent *ent = m->map_data; 162 1.1 christos gpt_uuid_t gpt_uuid; 163 1.1 christos char ent_type[128]; 164 1.1 christos 165 1.1 christos memcpy(&gpt_uuid, ent->ent_type, sizeof(gpt_uuid)); 166 1.5 riastrad n = (uint)gpt_uuid_snprintf(ent_type, sizeof(ent_type), 167 1.5 riastrad "%s", gpt_uuid); 168 1.1 christos if (w.type_name < n) 169 1.1 christos w.type_name = n; 170 1.1 christos } 171 1.1 christos 172 1.1 christos } 173 1.2 martin w.start = (uint)snprintf(NULL, 0, "%" PRIx64, max_start); 174 1.2 martin w.size = (uint)snprintf(NULL, 0, "%" PRIx64, max_size); 175 1.1 christos 176 1.1 christos #define MIN_WIDTH_OF(s) (sizeof(s) - 1) 177 1.1 christos if (w.type_name < MIN_WIDTH_OF("TYPE_NAME")) 178 1.1 christos w.type_name = MIN_WIDTH_OF("TYPE_NAME"); 179 1.1 christos if (w.start < MIN_WIDTH_OF("START")) 180 1.1 christos w.start = MIN_WIDTH_OF("START"); 181 1.1 christos if (w.size < MIN_WIDTH_OF("SIZE")) 182 1.1 christos w.size = MIN_WIDTH_OF("SIZE"); 183 1.1 christos #undef MIN_WIDTH_OF 184 1.1 christos 185 1.1 christos return w; 186 1.1 christos } 187 1.1 christos 188 1.1 christos static void 189 1.1 christos show_map_banner(struct map_widths w) 190 1.1 christos { 191 1.1 christos 192 1.1 christos printf("IDX %*s %*s ATTR PARTITION_GUID" 193 1.1 christos " TYPE_UUID %*s " 194 1.1 christos "TYPE_NAME ENTRY_NAME DESCRIPTION\n", 195 1.1 christos w.start, "START", 196 1.1 christos w.size, "SIZE", 197 1.1 christos w.type_name, ""); 198 1.1 christos } 199 1.1 christos 200 1.1 christos static void 201 1.1 christos show_map(map_t m, struct map_widths w) 202 1.1 christos { 203 1.1 christos struct gpt_ent *ent; 204 1.1 christos struct gpt_hdr *hdr; 205 1.1 christos gpt_uuid_t gpt_uuid; 206 1.1 christos uuid_t uuid; 207 1.1 christos uint32_t status; 208 1.1 christos char *type_uuid; 209 1.1 christos char *part_guid; 210 1.1 christos uint64_t ent_attr; 211 1.1 christos uint8_t ent_desc[128]; 212 1.1 christos char ent_type[128]; 213 1.1 christos 214 1.1 christos ent_desc[0] = '\0'; 215 1.1 christos ent_type[0] = '\0'; 216 1.1 christos ent_attr = 0; 217 1.1 christos 218 1.1 christos switch (m->map_type) { 219 1.1 christos case MAP_TYPE_PRI_GPT_HDR: 220 1.1 christos case MAP_TYPE_SEC_GPT_HDR: 221 1.1 christos hdr = m->map_data; 222 1.1 christos memcpy(&uuid, hdr->hdr_guid, sizeof(uuid)); 223 1.1 christos uuid_to_string(&uuid, &part_guid, &status); 224 1.1 christos type_uuid = estrdup(""); 225 1.1 christos break; 226 1.3 riastrad 227 1.1 christos case MAP_TYPE_GPT_PART: 228 1.1 christos ent = m->map_data; 229 1.1 christos 230 1.1 christos memcpy(&uuid, ent->ent_type, sizeof(uuid)); 231 1.1 christos uuid_to_string(&uuid, &type_uuid, &status); 232 1.3 riastrad 233 1.1 christos memcpy(&uuid, ent->ent_guid, sizeof(uuid)); 234 1.1 christos uuid_to_string(&uuid, &part_guid, &status); 235 1.3 riastrad 236 1.1 christos ent_attr = ent->ent_attr; 237 1.1 christos 238 1.1 christos memcpy(&gpt_uuid, ent->ent_type, sizeof(uuid)); 239 1.1 christos gpt_uuid_snprintf(ent_type, sizeof(ent_type), "%s", gpt_uuid); 240 1.3 riastrad 241 1.1 christos /* 242 1.1 christos * Use the gpt.c code here rather than our 243 1.1 christos * ucs2_to_utf8() as we are in their world. 244 1.1 christos */ 245 1.1 christos utf16_to_utf8(ent->ent_name, sizeof(ent->ent_name), 246 1.1 christos ent_desc, sizeof(ent_desc)); 247 1.1 christos 248 1.1 christos break; 249 1.3 riastrad 250 1.1 christos case MAP_TYPE_MBR_PART: 251 1.1 christos part_guid = estrdup(""); 252 1.1 christos type_uuid = estrdup(""); 253 1.1 christos break; 254 1.1 christos 255 1.1 christos case MAP_TYPE_MBR: { 256 1.1 christos struct mbr *mbr = m->map_data; 257 1.1 christos 258 1.5 riastrad easprintf(&part_guid, 259 1.5 riastrad "%02x%02x%02x%02x-0000-0000-0000-000000000000", 260 1.1 christos mbr->mbr_code[440], 261 1.1 christos mbr->mbr_code[441], 262 1.1 christos mbr->mbr_code[442], 263 1.1 christos mbr->mbr_code[443]); 264 1.1 christos uuid_to_string(&(uuid_t)GPT_ENT_TYPE_MBR, &type_uuid, &status); 265 1.1 christos break; 266 1.1 christos } 267 1.1 christos default: 268 1.1 christos part_guid = estrdup(""); 269 1.1 christos type_uuid = estrdup(""); 270 1.1 christos break; 271 1.1 christos } 272 1.1 christos 273 1.2 martin printf("%2u: %*" PRIx64 " %*" PRIx64 " %08" PRIx64 274 1.2 martin " %36s %36s %*s %-11s %s\n", 275 1.1 christos m->map_index, 276 1.1 christos w.start, 277 1.1 christos m->map_start, 278 1.1 christos w.size, 279 1.1 christos m->map_size, 280 1.1 christos ent_attr, 281 1.1 christos part_guid, 282 1.1 christos type_uuid, 283 1.1 christos w.type_name, 284 1.1 christos ent_type, 285 1.1 christos map_type_name(m->map_type), 286 1.1 christos ent_desc); 287 1.3 riastrad 288 1.1 christos free(part_guid); 289 1.1 christos free(type_uuid); 290 1.1 christos } 291 1.1 christos 292 1.1 christos PUBLIC map_t 293 1.1 christos find_gpt_map(const char *dev, uint idx) 294 1.1 christos { 295 1.1 christos gpt_t gpt; 296 1.1 christos map_t m; 297 1.1 christos 298 1.1 christos gpt = gpt_open(dev, GPT_READONLY, 0, 0, 0, 0); 299 1.1 christos 300 1.1 christos if (gpt == NULL) 301 1.1 christos err(EXIT_FAILURE, "gpt_open"); 302 1.1 christos 303 1.1 christos if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) == NULL) 304 1.1 christos printf("GPT not found, displaying data from MBR.\n"); 305 1.1 christos 306 1.1 christos for (m = map_first(gpt); m != NULL; m = m->map_next) { 307 1.1 christos if (m->map_index == idx) 308 1.1 christos break; 309 1.1 christos } 310 1.1 christos gpt_close(gpt); 311 1.1 christos return m; 312 1.1 christos } 313 1.1 christos 314 1.1 christos PUBLIC char * 315 1.1 christos parent_of_fname(const char *fname) 316 1.1 christos { 317 1.1 christos struct dkwedge_info dkinfo; 318 1.1 christos struct statvfs vfsb; 319 1.1 christos struct stat sb; 320 1.1 christos const char *d, *b; 321 1.1 christos char *p; 322 1.1 christos size_t n; 323 1.1 christos int fd, rv; 324 1.1 christos 325 1.1 christos rv = stat(fname, &sb); 326 1.1 christos if (rv == -1) 327 1.1 christos err(EXIT_FAILURE, "stat: %s", fname); 328 1.1 christos 329 1.1 christos if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) 330 1.1 christos return estrdup(fname); 331 1.1 christos 332 1.1 christos rv = statvfs(fname, &vfsb); 333 1.1 christos if (rv == -1) 334 1.1 christos err(EXIT_FAILURE, "statvfs: %s", fname); 335 1.1 christos 336 1.1 christos b = basename(vfsb.f_mntfromname); 337 1.1 christos d = dirname(vfsb.f_mntfromname); 338 1.1 christos easprintf(&p, "%s/r%s", d, b); 339 1.3 riastrad 340 1.1 christos fd = open(p, O_RDONLY); 341 1.1 christos if (fd == -1) 342 1.1 christos err(EXIT_FAILURE, "open"); 343 1.3 riastrad 344 1.1 christos rv = ioctl(fd, DIOCGWEDGEINFO, &dkinfo); 345 1.1 christos close(fd); 346 1.1 christos 347 1.1 christos if (rv != -1) { 348 1.1 christos free(p); 349 1.1 christos return estrdup(dkinfo.dkw_parent); 350 1.1 christos } 351 1.1 christos 352 1.1 christos warn("ioctl: DIOCGWEDGEINFO"); 353 1.3 riastrad 354 1.1 christos /* 355 1.1 christos * Hum. No wedges? Assume we have the old disklabel 356 1.1 christos * "/dev/rwd0x" syntax. Convert it to "/dev/rwd0d". 357 1.1 christos * XXX: this probably won't work. 358 1.1 christos */ 359 1.1 christos n = strlen(p); 360 1.1 christos p[n - 1] = 'd'; 361 1.1 christos 362 1.1 christos return p; 363 1.1 christos } 364 1.1 christos 365 1.1 christos PUBLIC int 366 1.1 christos mbr_sig_write(const char *fname, uint32_t new_sig, bool force, int verbose) 367 1.1 christos { 368 1.1 christos gpt_t gpt; 369 1.1 christos map_t m; 370 1.1 christos struct mbr *mbr; 371 1.1 christos const char *dev; 372 1.1 christos uint32_t old_sig; 373 1.1 christos 374 1.1 christos if (fname == NULL) 375 1.1 christos errx(EXIT_FAILURE, "please specify a device"); 376 1.1 christos 377 1.1 christos dev = parent_of_fname(fname); 378 1.1 christos if (dev == NULL) { 379 1.1 christos warnx("unable to find parent device of %s\n", fname); 380 1.1 christos return -1; 381 1.1 christos } 382 1.1 christos 383 1.1 christos gpt = gpt_open(dev, GPT_MODIFIED, verbose, 0, 0, 0); 384 1.1 christos 385 1.1 christos if (gpt == NULL) 386 1.1 christos err(EXIT_FAILURE, "gpt_open"); 387 1.1 christos 388 1.1 christos m = map_find(gpt, MAP_TYPE_MBR); 389 1.1 christos if (m == NULL) 390 1.1 christos printf("No MBR partition found!\n"); 391 1.1 christos else { 392 1.1 christos mbr = m->map_data; 393 1.1 christos 394 1.1 christos memcpy(&old_sig, &mbr->mbr_code[440], 4); 395 1.1 christos 396 1.1 christos if (old_sig == 0) 397 1.1 christos force = true; 398 1.1 christos 399 1.1 christos if (force) { 400 1.1 christos memcpy(&mbr->mbr_code[440], &new_sig, 4); 401 1.1 christos if (gpt_write(gpt, m) == -1) 402 1.1 christos warn("gpt_write"); 403 1.1 christos else if (verbose) 404 1.1 christos printf("sig: 0x%08x -> 0x%08x\n", 405 1.1 christos old_sig, new_sig); 406 1.1 christos } 407 1.1 christos else if (verbose) 408 1.1 christos printf("sig: 0x%08x (unchanged)\n", old_sig); 409 1.1 christos } 410 1.1 christos 411 1.1 christos gpt_close(gpt); 412 1.1 christos return 0; 413 1.1 christos } 414 1.1 christos 415 1.1 christos PUBLIC int 416 1.1 christos show_gpt(const char *fname, int verbose) 417 1.1 christos { 418 1.1 christos gpt_t gpt; 419 1.1 christos map_t m; 420 1.1 christos struct map_widths w; 421 1.1 christos const char *dev; 422 1.1 christos 423 1.1 christos dev = parent_of_fname(fname); 424 1.1 christos if (dev == NULL) 425 1.1 christos return -1; 426 1.1 christos 427 1.1 christos gpt = gpt_open(dev, GPT_READONLY, verbose, 0, 0, 0); 428 1.1 christos 429 1.1 christos if (gpt == NULL) 430 1.1 christos err(EXIT_FAILURE, "gpt_open"); 431 1.1 christos 432 1.1 christos if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) == NULL) 433 1.1 christos warnx("GPT not found, displaying data from MBR."); 434 1.1 christos 435 1.1 christos w = get_map_widths(gpt); 436 1.1 christos show_map_banner(w); 437 1.1 christos 438 1.1 christos for (m = map_first(gpt); m != NULL; m = m->map_next) 439 1.1 christos show_map(m, w); 440 1.1 christos 441 1.1 christos gpt_close(gpt); 442 1.1 christos return 0; 443 1.1 christos } 444 1.1 christos 445 1.1 christos #if 0 /* UNUSED */ 446 1.1 christos 447 1.1 christos PUBLIC char * 448 1.1 christos wedge_of_fname(const char *fname) 449 1.1 christos { 450 1.1 christos struct statvfs vfsbuf; 451 1.1 christos int rv; 452 1.1 christos 453 1.1 christos rv = statvfs(fname, &vfsbuf); 454 1.1 christos if (rv) { 455 1.1 christos warn("statvfs: %s", fname); 456 1.1 christos return NULL; 457 1.1 christos } 458 1.1 christos 459 1.1 christos return estrdup(vfsbuf.f_mntfromname); 460 1.1 christos } 461 1.1 christos 462 1.1 christos PUBLIC int 463 1.1 christos find_partition_idx(const char *fname, int verbose) 464 1.1 christos { 465 1.1 christos struct dkwedge_info dkinfo; 466 1.1 christos struct stat sb; 467 1.1 christos struct statvfs vfsbuf; 468 1.1 christos gpt_t gpt; 469 1.1 christos map_t m; 470 1.1 christos off_t offset; 471 1.1 christos size_t size; 472 1.1 christos const char *parent; 473 1.1 christos char *b, *d; 474 1.1 christos int rv; 475 1.1 christos 476 1.1 christos /* the following are for gpt_open() */ 477 1.1 christos off_t mediasz = 0; 478 1.1 christos u_int secsz = 0; 479 1.1 christos time_t timestamp = 0; 480 1.1 christos 481 1.1 christos rv = stat(fname, &sb); 482 1.1 christos if (rv == -1) 483 1.1 christos err(EXIT_FAILURE, "stat: %s", fname); 484 1.1 christos 485 1.1 christos if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { 486 1.1 christos parent = fname; 487 1.1 christos offset = 0; 488 1.1 christos size = 0; 489 1.1 christos goto doit; 490 1.1 christos } 491 1.1 christos 492 1.1 christos rv = statvfs(fname, &vfsbuf); 493 1.1 christos if (rv == -1) 494 1.1 christos err(EXIT_FAILURE, "statvfs: %s", fname); 495 1.1 christos 496 1.1 christos b = basename(vfsbuf.f_mntfromname); 497 1.1 christos d = dirname(vfsbuf.f_mntfromname); 498 1.1 christos 499 1.1 christos { 500 1.1 christos char *p; 501 1.1 christos 502 1.1 christos easprintf(&p, "%s/r%s", d, b); 503 1.1 christos 504 1.1 christos int fd = open(p, O_RDONLY); 505 1.1 christos if (fd == -1) 506 1.1 christos err(EXIT_FAILURE, "open"); 507 1.3 riastrad 508 1.1 christos rv = ioctl(fd, DIOCGWEDGEINFO, &dkinfo); 509 1.1 christos if (rv != -1) { 510 1.1 christos parent = dkinfo.dkw_parent; 511 1.1 christos offset = dkinfo.dkw_offset; 512 1.1 christos size = dkinfo.dkw_size; 513 1.1 christos } 514 1.1 christos else { 515 1.1 christos struct disklabel dl; 516 1.3 riastrad 517 1.1 christos warn("ioctl: DIOCGWEDGEINFO"); 518 1.3 riastrad 519 1.1 christos rv = ioctl(fd, DIOCGDINFO, &dl); 520 1.1 christos if (rv == -1) 521 1.1 christos err(EXIT_FAILURE, "ioctl: DIOCGDINFO"); 522 1.3 riastrad 523 1.1 christos size_t n = strlen(p); 524 1.3 riastrad 525 1.1 christos int pnum = p[n - 1] - 'a'; 526 1.1 christos p[n - 1] = 'd'; 527 1.3 riastrad 528 1.1 christos printf("num_parts: %u\n", dl.d_npartitions); 529 1.1 christos printf("partition %d\n", pnum); 530 1.4 riastrad printf(" offset = %u (%#x)\n", 531 1.4 riastrad dl.d_partitions[pnum].p_offset, 532 1.4 riastrad dl.d_partitions[pnum].p_offset); 533 1.4 riastrad printf(" size = %u (%#x)\n", 534 1.4 riastrad dl.d_partitions[pnum].p_size, 535 1.4 riastrad dl.d_partitions[pnum].p_size); 536 1.3 riastrad 537 1.1 christos parent = p; // vfsbuf.f_mntfromname; 538 1.1 christos offset = dl.d_partitions[pnum].p_offset; 539 1.1 christos size = dl.d_partitions[pnum].p_size; 540 1.1 christos } 541 1.3 riastrad 542 1.1 christos close(fd); 543 1.1 christos free(p); 544 1.1 christos } 545 1.1 christos 546 1.1 christos doit: 547 1.1 christos DPRINTF("parent: %s\n", parent); 548 1.1 christos DPRINTF("offset: 0x%lx\n", offset); 549 1.1 christos DPRINTF("size: 0x%lx\n", size); 550 1.1 christos 551 1.1 christos gpt = gpt_open(parent, GPT_READONLY, 552 1.1 christos verbose, mediasz, secsz, timestamp); 553 1.1 christos 554 1.1 christos if (gpt == NULL) 555 1.1 christos err(EXIT_FAILURE, "gpt_open"); 556 1.1 christos 557 1.1 christos if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) == NULL) 558 1.1 christos printf("GPT not found, displaying data from MBR.\n"); 559 1.1 christos 560 1.1 christos int index = -1; 561 1.1 christos struct map_widths w; 562 1.1 christos if (verbose) { 563 1.1 christos w = get_map_widths(gpt); 564 1.1 christos show_map_banner(w); 565 1.1 christos } 566 1.1 christos for (m = map_first(gpt); m != NULL; m = m->map_next) { 567 1.1 christos if (verbose) 568 1.1 christos show_map(m, w); 569 1.1 christos 570 1.1 christos if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1) { 571 1.1 christos continue; 572 1.1 christos } 573 1.1 christos 574 1.1 christos if ((off_t)offset == m->map_start && 575 1.1 christos (off_t)size == m->map_size) { 576 1.1 christos if (index != -1) 577 1.1 christos printf("match: %u\n", index); 578 1.1 christos index = (int)m->map_index; 579 1.1 christos } 580 1.1 christos } 581 1.1 christos return index; 582 1.1 christos } 583 1.1 christos 584 1.1 christos PUBLIC char * 585 1.1 christos find_partition_pathname(const char *fname) 586 1.1 christos { 587 1.1 christos char *pname; /* partition name */ 588 1.1 christos char *rname; /* real name */ 589 1.1 christos struct statvfs vfsbuf; 590 1.1 christos int i, rv; 591 1.1 christos 592 1.1 christos rname = realpath(fname, NULL); 593 1.1 christos 594 1.1 christos DPRINTF("fname: %s\n", fname); 595 1.1 christos DPRINTF("rname: %s\n", rname); 596 1.1 christos 597 1.1 christos rv = statvfs(rname, &vfsbuf); 598 1.1 christos if (rv) { 599 1.1 christos warn("statvfs: %s", rname); 600 1.1 christos free(rname); 601 1.1 christos return NULL; 602 1.1 christos } 603 1.1 christos 604 1.1 christos DPRINTF("mount: %s\n", vfsbuf.f_mntonname); 605 1.1 christos 606 1.1 christos i = 0; 607 1.5 riastrad while (vfsbuf.f_mntonname[i] == rname[i] && 608 1.5 riastrad vfsbuf.f_mntonname[i] != '\0') 609 1.1 christos i++; 610 1.1 christos 611 1.1 christos if (vfsbuf.f_mntonname[i] != '\0') 612 1.1 christos errx(EXIT_FAILURE, "mntonname mismatch: %s", 613 1.1 christos vfsbuf.f_mntonname + i); 614 1.3 riastrad 615 1.1 christos pname = estrdup(rname + i); 616 1.1 christos free(rname); 617 1.1 christos 618 1.1 christos return pname; 619 1.1 christos } 620 1.1 christos 621 1.1 christos #endif 622