1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * rmf_slice.c : 30 * This file contains the functions for parsing a slice file 31 * for rmformat. 32 */ 33 34 #include <sys/types.h> 35 #include <ctype.h> 36 #include <sys/vtoc.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <string.h> 40 #include <fcntl.h> 41 #include <errno.h> 42 #include <memory.h> 43 #include <dirent.h> 44 #include <sys/fcntl.h> 45 #include <sys/param.h> 46 #include <sys/stat.h> 47 #include <stdio.h> 48 #include <sys/dkio.h> 49 #include <priv_utils.h> 50 #include "rmformat.h" 51 52 extern void my_perror(char *err_string); 53 54 static int32_t last_token_type = 0; 55 #define spc() (last_token_type) 56 57 58 /* 59 * This global is used to store the current line # in the 60 * data file. It must be global because the I/O routines 61 * are allowed to side effect it to keep track of backslashed 62 * newlines. 63 */ 64 65 static int32_t data_lineno; /* current line # in data file */ 66 67 #define CHG_MODE_UNDEFINED (-1) /* undefined value */ 68 #define CHG_MODE_SET 0 /* set bits by or'ing */ 69 #define CHG_MODE_CLR 1 /* clr bits by and'ing */ 70 #define CHG_MODE_ABS 2 /* set absolute value */ 71 72 73 #define TOKEN_SIZE 36 /* max length of a token */ 74 typedef char TOKEN[TOKEN_SIZE+1]; /* token type */ 75 #define DATA_INPUT 0 /* 2 modes of input */ 76 #define CMD_INPUT 1 77 #define WILD_STRING "$" /* wildcard character */ 78 #define COMMENT_CHAR '#' /* comment character */ 79 80 /* 81 * List of strings with arbitrary matching values 82 */ 83 typedef struct slist { 84 char *str; 85 char *help; 86 int32_t value; 87 } slist_t; 88 89 static slist_t ptag_choices[] = { 90 { "unassigned", "", V_UNASSIGNED }, 91 { "boot", "", V_BOOT }, 92 { "root", "", V_ROOT }, 93 { "swap", "", V_SWAP }, 94 { "usr", "", V_USR }, 95 { "backup", "", V_BACKUP }, 96 { "stand", "", V_STAND }, 97 { "var", "", V_VAR }, 98 { "home", "", V_HOME }, 99 { "alternates", "", V_ALTSCTR }, 100 { NULL } 101 }; 102 103 104 /* 105 * Choices for the p_flag vtoc field 106 */ 107 static slist_t pflag_choices[] = { 108 { "wm", "read-write, mountable", 0 }, 109 { "wu", "read-write, unmountable", V_UNMNT }, 110 { "rm", "read-only, mountable", V_RONLY }, 111 { "ru", "read-only, unmountable", V_RONLY|V_UNMNT }, 112 { NULL } 113 }; 114 115 /* 116 * The definitions are the token types that the data file parser recognizes. 117 */ 118 #define SUP_EOF -1 /* eof token */ 119 #define SUP_STRING 0 /* string token */ 120 #define SUP_EQL 1 /* equals token */ 121 #define SUP_COMMA 2 /* comma token */ 122 #define SUP_COLON 3 /* colon token */ 123 #define SUP_EOL 4 /* newline token */ 124 #define SUP_OR 5 /* vertical bar */ 125 #define SUP_AND 6 /* ampersand */ 126 #define SUP_TILDE 7 /* tilde */ 127 128 129 /* 130 * Prototypes for ANSI C compilers 131 */ 132 static int32_t sup_prxfile(char *file_name, struct vtoc *vt); 133 static int32_t sup_setpart(struct vtoc *vt); 134 static void sup_pushchar(int32_t c); 135 static void clean_token(char *cleantoken, char *token); 136 static void clean_token(char *cleantoken, char *token); 137 static int32_t sup_inputchar(); 138 static int32_t sup_gettoken(char *buf); 139 static int32_t sup_get_token(char *buf); 140 static int32_t find_value(slist_t *slist, char *str, int32_t *value); 141 static int32_t check_vtoc_sanity(smedia_handle_t, int32_t fd, struct vtoc *vt); 142 static int32_t str2sector(char *str); 143 static int32_t strcnt(char *s1, char *s2); 144 static int32_t get_fdisk(smedia_handle_t, int32_t fd, int32_t offset, 145 struct fdisk_info *fdisk); 146 static void erase(smedia_handle_t handle, uint32_t offset, uint32_t size); 147 148 extern char *myname; 149 extern int64_t my_atoll(char *ptr); 150 extern smmedium_prop_t med_info; 151 152 static FILE *data_file; 153 154 static int32_t 155 sup_prxfile(char *file_name, struct vtoc *vt) 156 { 157 int32_t status, ret_val; 158 TOKEN token; 159 TOKEN cleaned; 160 161 /* 162 * Open the data file. Return 0 if unable to do so. 163 */ 164 data_file = fopen(file_name, "r"); 165 if (data_file == NULL) { 166 PERROR("Open failed"); 167 return (-1); 168 } 169 /* 170 * Step through the data file a meta-line at a time. There are 171 * typically several backslashed newlines in each meta-line, 172 * so data_lineno will be getting side effected along the way. 173 */ 174 data_lineno = 1; 175 for (;;) { 176 177 /* 178 * Get the keyword. 179 */ 180 status = sup_gettoken(token); 181 /* 182 * If we hit the end of the data file, we're done. 183 */ 184 if (status == SUP_EOF) 185 break; 186 /* 187 * If the line starts with some key character, it's an error. 188 */ 189 if (status != SUP_STRING) { 190 (void) fprintf(stderr, 191 gettext("Expecting keyword, found '%s'"), 192 token); 193 (void) fprintf(stderr, 194 gettext("Line no %d\n"), data_lineno); 195 continue; 196 } 197 /* 198 * Clean up the token and see which keyword it is. Call 199 * the appropriate routine to process the rest of the line. 200 */ 201 clean_token(cleaned, token); 202 if (strcmp(cleaned, "slices") == 0) { 203 ret_val = sup_setpart(vt); 204 (void) fclose(data_file); 205 return (ret_val); 206 } else { 207 (void) fprintf(stderr, gettext("Unknown keyword '%s'"), 208 cleaned); 209 (void) fprintf(stderr, 210 gettext("Line no %d\n"), data_lineno); 211 (void) fclose(data_file); 212 return (-1); 213 } 214 } 215 /* 216 * Close the data file. 217 */ 218 (void) fclose(data_file); 219 220 (void) fprintf(stderr, 221 gettext("Unexpected end of file (line no %d)\n"), data_lineno); 222 return (-1); 223 } 224 225 static int32_t 226 sup_gettoken(char *buf) 227 { 228 /* 229 * Skip end of lines and blank lines. 230 */ 231 while ((last_token_type = sup_get_token(buf)) == SUP_EOL) 232 ; 233 return (last_token_type); 234 } 235 236 static int32_t 237 sup_get_token(char *buf) 238 { 239 char *ptr = buf; 240 int32_t c, quoted = 0; 241 242 /* 243 * Was an end of file detected last try? 244 */ 245 246 if (feof(data_file)) { 247 return (SUP_EOF); 248 } 249 250 /* 251 * Zero out the returned token buffer 252 */ 253 254 bzero(buf, TOKEN_SIZE + 1); 255 256 /* 257 * Strip off leading white-space. 258 */ 259 while (isspace(c = sup_inputchar())) 260 ; 261 262 /* 263 * Only white spaces and then end of file? 264 */ 265 266 if (feof(data_file)) { 267 return (SUP_EOF); 268 } 269 270 /* 271 * Read in characters until we hit unquoted white-space. 272 */ 273 for (; !isspace(c) || quoted; c = sup_inputchar()) { 274 275 /* 276 * If we hit eof, check if we have anything in buffer. 277 * if we have, return STRING, next time we will return EOF 278 * else, return EOF here...should not happen. 279 */ 280 if (feof(data_file)) { 281 if (ptr - buf > 0) { 282 return (SUP_STRING); 283 } else { 284 return (SUP_EOF); 285 } 286 } 287 288 /* 289 * If we hit a double quote, change the state of quoting. 290 */ 291 if (c == '"') { 292 quoted = !quoted; 293 continue; 294 } 295 /* 296 * If we hit a newline, that delimits a token. 297 */ 298 if (c == '\n') 299 break; 300 /* 301 * If we hit any nonquoted special delimiters, that delimits 302 * a token. 303 */ 304 if (!quoted && (c == '=' || c == ',' || c == ':' || 305 c == '#' || c == '|' || c == '&' || c == '~')) 306 break; 307 /* 308 * Store the character if there's room left. 309 */ 310 if (ptr - buf < TOKEN_SIZE) 311 *ptr++ = (char)c; 312 } 313 /* 314 * If we stored characters in the buffer, then we inputted a string. 315 * Push the delimiter back into the pipe and return the string. 316 */ 317 if (ptr - buf > 0) { 318 sup_pushchar(c); 319 return (SUP_STRING); 320 } 321 /* 322 * We didn't input a string, so we must have inputted a known delimiter. 323 * store the delimiter in the buffer, so it will get returned. 324 */ 325 buf[0] = c; 326 /* 327 * Switch on the delimiter. Return the appropriate value for each one. 328 */ 329 switch (c) { 330 case '=': 331 return (SUP_EQL); 332 case ':': 333 return (SUP_COLON); 334 case ',': 335 return (SUP_COMMA); 336 case '\n': 337 return (SUP_EOL); 338 case '|': 339 return (SUP_OR); 340 case '&': 341 return (SUP_AND); 342 case '~': 343 return (SUP_TILDE); 344 case '#': 345 /* 346 * For comments, we flush out the rest of the line and return 347 * an eol. 348 */ 349 while ((c = sup_inputchar()) != '\n' && !feof(data_file)) 350 ; 351 if (feof(data_file)) 352 return (SUP_EOF); 353 else 354 return (SUP_EOL); 355 /* 356 * Shouldn't ever get here. 357 */ 358 default: 359 return (SUP_STRING); 360 } 361 } 362 static int32_t 363 sup_inputchar() 364 { 365 int32_t c; 366 367 /* 368 * Input the character. 369 */ 370 c = getc(data_file); 371 /* 372 * If it's not a backslash, return it. 373 */ 374 375 /* 376 * It was a backslash. Get the next character. 377 */ 378 379 if (c == '\\') 380 c = getc(data_file); 381 382 /* 383 * If it was a newline, update the line counter and get the next 384 * character. 385 */ 386 if (c == '\n') { 387 data_lineno++; 388 } 389 /* 390 * Return the character. 391 */ 392 return (c); 393 } 394 395 static void 396 sup_pushchar(int32_t c) 397 { 398 399 (void) ungetc(c, data_file); 400 if (c == '\n') 401 data_lineno--; 402 } 403 404 static void 405 clean_token(char *cleantoken, char *token) 406 { 407 char *ptr; 408 409 /* 410 * Strip off leading white-space. 411 */ 412 for (ptr = token; isspace(*ptr) && (ptr <= 413 (token + strlen(token) - 1)); ptr++); 414 415 /* 416 * Copy it into the clean buffer. 417 */ 418 (void) strcpy(cleantoken, ptr); 419 /* 420 * Strip off trailing white-space. 421 */ 422 for (ptr = cleantoken + strlen(cleantoken) - 1; 423 isspace(*ptr) && (ptr >= cleantoken); ptr--) { 424 *ptr = '\0'; 425 } 426 } 427 428 static int32_t 429 sup_setpart(struct vtoc *vt) 430 { 431 TOKEN token, cleaned, ident; 432 int32_t i, index, status, val1, val2; 433 ushort_t vtoc_tag = 0xFFFF; 434 ushort_t vtoc_flag = 0xFFFF; 435 436 /* 437 * Pull in some grammar. 438 */ 439 440 status = sup_gettoken(token); 441 442 if (status != SUP_COLON) { 443 (void) fprintf(stderr, 444 gettext("Expecting ':', found '%s'"), token); 445 (void) fprintf(stderr, 446 gettext("Line no %d\n"), data_lineno); 447 return (-1); 448 } 449 450 for (;;) { 451 status = sup_gettoken(token); 452 if (status != SUP_STRING) { 453 (void) fprintf(stderr, 454 gettext("Expecting string, found '%s'"), token); 455 (void) fprintf(stderr, 456 gettext("Line no %d\n"), data_lineno); 457 return (-1); 458 } 459 clean_token(ident, token); 460 /* 461 * Also make sure it is within the legal range of letters. 462 */ 463 /* 464 * Here's the index of the partition we're dealing with 465 */ 466 index = (int32_t)my_atoll(ident); 467 if ((index < 0) || (index > NDKMAP)) { 468 (void) fprintf(stderr, 469 gettext("Unknown partition '%s'"), index); 470 (void) fprintf(stderr, 471 gettext("Line no %d\n"), data_lineno); 472 return (-1); 473 } 474 /* 475 * Check for floppy and PCMCIA_MEM cards. 476 * for floppy, the partition no. can be 0 1 2. 477 * for PCMCIA, the partition no. can be 2 478 */ 479 if (med_info.sm_media_type == SM_FLOPPY) { 480 if ((index < 0) || (index > 2)) { 481 (void) fprintf(stderr, gettext( 482 "Floppy can have partitions 0 1 and 2\n")); 483 return (-1); 484 } 485 } 486 if (med_info.sm_media_type == SM_PCMCIA_MEM) { 487 if (index != 2) { 488 (void) fprintf(stderr, gettext( 489 "PCMCIA Memory cards can have partition 2 only.\n")); 490 return (-1); 491 } 492 } 493 494 DPRINTF1("\n Partition %d: ", index); 495 496 status = sup_gettoken(token); 497 if (status != SUP_EQL) { 498 (void) fprintf(stderr, 499 gettext("Expecting '=', found '%s'"), token); 500 (void) fprintf(stderr, 501 gettext("Line no %d\n"), data_lineno); 502 return (-1); 503 504 } 505 506 507 status = sup_gettoken(token); 508 /* 509 * If we hit a key character, it's an error. 510 */ 511 if (status != SUP_STRING) { 512 (void) fprintf(stderr, 513 gettext("Expecting value, found '%s'"), token); 514 (void) fprintf(stderr, 515 gettext("Line no %d\n"), data_lineno); 516 return (-1); 517 } 518 clean_token(cleaned, token); 519 /* 520 * <tag> may be one of: boot, root, swap, etc. 521 * <flag> consists of two characters: 522 * W (writable) or R (read-only) 523 * M (mountable) or U (unmountable) 524 * 525 * Start with the defaults assigned above: 526 */ 527 528 /* 529 * All other attributes have a pair of numeric values. 530 * Convert the first value to a number. This value 531 * is the starting cylinder number of the partition. 532 */ 533 534 /* Check for valid partition, e.g. > 8 or 16 */ 535 val1 = str2sector(cleaned); 536 if (val1 == -1) { 537 (void) fprintf(stderr, 538 gettext("Invalid partition beggining %s \n"), 539 cleaned); 540 (void) fprintf(stderr, 541 gettext("Line no %d\n"), data_lineno); 542 } 543 544 DPRINTF1(" begins %s", cleaned); 545 /* 546 * Pull in some grammar. 547 */ 548 status = sup_gettoken(token); 549 if (status != SUP_COMMA) { 550 (void) fprintf(stderr, 551 gettext("Expecting ', ', found '%s'"), token); 552 (void) fprintf(stderr, 553 gettext("Line no %d\n"), data_lineno); 554 return (-1); 555 } 556 /* 557 * Pull in the second value. 558 */ 559 status = sup_gettoken(token); 560 if (status != SUP_STRING) { 561 (void) fprintf(stderr, 562 gettext("Expecting value, found '%s'"), token); 563 (void) fprintf(stderr, 564 gettext("Line no %d\n"), data_lineno); 565 return (-1); 566 } 567 clean_token(cleaned, token); 568 569 val2 = str2sector(cleaned); 570 if (val2 == -1) { 571 (void) fprintf(stderr, 572 gettext("Invalid partition size %s \n"), 573 cleaned); 574 (void) fprintf(stderr, 575 gettext("Line no %d\n"), data_lineno); 576 } 577 DPRINTF1(" ends %s ", cleaned); 578 579 /* 580 * Pull in some grammar. 581 */ 582 status = sup_gettoken(token); 583 584 if (status == SUP_COMMA) { 585 /* tags and flags */ 586 status = sup_gettoken(token); 587 if (status != SUP_STRING) { 588 (void) fprintf(stderr, 589 gettext("Expecting value, found '%s'"), 590 token); 591 (void) fprintf(stderr, 592 gettext("Line no %d\n"), data_lineno); 593 return (-1); 594 } 595 clean_token(cleaned, token); 596 if (find_value(pflag_choices, cleaned, &i) == 1) { 597 /* 598 * Found valid tag. Use it and advance parser 599 */ 600 DPRINTF1(" flag = %s", cleaned); 601 vtoc_flag = (ushort_t)i; 602 status = sup_gettoken(token); 603 } else if (find_value(ptag_choices, cleaned, &i) == 1) { 604 DPRINTF1(" tag = %s", cleaned); 605 vtoc_tag = (ushort_t)i; 606 status = sup_gettoken(token); 607 if (status == SUP_COMMA) { 608 (void) fprintf(stderr, 609 gettext("Expecting : got %s\n"), 610 token); 611 (void) fprintf(stderr, 612 gettext("Line no %d\n"), 613 data_lineno); 614 return (-1); 615 } 616 } else { 617 (void) fprintf(stderr, 618 gettext("Invalid flag or tag\n")); 619 (void) fprintf(stderr, 620 gettext("Line no %d\n"), data_lineno); 621 return (-1); 622 } 623 624 625 if (status == SUP_COMMA) { 626 /* Can be tag only */ 627 628 status = sup_gettoken(token); 629 if (status != SUP_STRING) { 630 (void) fprintf(stderr, 631 gettext( 632 "Expecting value, found '%s'"), 633 token); 634 (void) fprintf(stderr, 635 gettext("Line no %d\n"), 636 data_lineno); 637 return (-1); 638 } 639 640 clean_token(cleaned, token); 641 if (find_value(ptag_choices, 642 cleaned, &i) == 1) { 643 DPRINTF1(" tag = %s", cleaned); 644 vtoc_tag = (ushort_t)i; 645 } 646 status = sup_gettoken(token); 647 } 648 } 649 650 /* 651 * Fill in the appropriate map entry with the values. 652 */ 653 vt->v_part[index].p_start = val1; 654 vt->v_part[index].p_size = val2; 655 if (vtoc_tag != 0xFFFF) { 656 vt->v_part[index].p_tag = vtoc_tag; 657 vtoc_tag = 0xFFFF; 658 } 659 if (vtoc_flag != 0xFFFF) { 660 vt->v_part[index].p_flag = vtoc_flag; 661 vtoc_flag = 0xFFFF; 662 } 663 if (status == SUP_EOF) { 664 DPRINTF("\nEnd of file\n"); 665 break; 666 } 667 if (status != SUP_COLON) { 668 (void) fprintf(stderr, 669 gettext("Expecting ':', found '%s'"), token); 670 (void) fprintf(stderr, 671 gettext("Line no %d\n"), data_lineno); 672 return (-1); 673 } 674 675 } 676 return (0); 677 } 678 679 static int32_t 680 find_value(slist_t *slist, char *match_str, int32_t *match_value) 681 { 682 int32_t i; 683 int32_t nmatches; 684 int32_t length; 685 int32_t match_length; 686 687 nmatches = 0; 688 length = 0; 689 690 match_length = strlen(match_str); 691 692 for (; slist->str != NULL; slist++) { 693 /* 694 * See how many characters of the token match 695 */ 696 i = strcnt(match_str, slist->str); 697 /* 698 * If it's not the whole token, then it's not a match. 699 */ 700 if (i < match_length) { 701 continue; 702 } 703 /* 704 * If it ties with another input, remember that. 705 */ 706 if (i == length) 707 nmatches++; 708 /* 709 * If it matches the most so far, record that. 710 */ 711 if (i > length) { 712 *match_value = slist->value; 713 nmatches = 1; 714 length = i; 715 } 716 } 717 718 return (nmatches); 719 } 720 721 static int32_t 722 strcnt(char *s1, char *s2) 723 { 724 int32_t i = 0; 725 726 while ((*s1 != '\0') && (*s1++ == *s2++)) 727 i++; 728 return (i); 729 } 730 731 static int32_t 732 str2sector(char *str) 733 { 734 int32_t mul_factor = 1; 735 char *s1, *s2, *base; 736 int32_t num_sectors; 737 int64_t size; 738 739 base = s2 = (char *)malloc(strlen(str) + 1); 740 if (s2 == NULL) { 741 PERROR("Malloc failed"); 742 return (-1); 743 } 744 *s2 = '\0'; 745 746 747 748 s1 = str; 749 while (*s1) { 750 if ((*s1 != 'x') && ((*s1 < 'A') || (*s1 > 'F')) && 751 ((*s1 < 'a') || (*s1 > 'f')) && ((*s1 < '0') || 752 (*s1 > '9'))) { 753 if (*s1 == 'G') { 754 mul_factor = 1024*1024*1024; 755 s1++; 756 } else if (*s1 == 'M') { 757 mul_factor = 1024*1024; 758 s1++; 759 } else if (*s1 == 'K') { 760 mul_factor = 1024; 761 s1++; 762 } 763 if ((*s1 != 'B') || (*(++s1) != NULL)) { 764 (void) fprintf(stderr, 765 gettext("Extra chars at the end\n")); 766 free(base); 767 return (-1); 768 } 769 break; 770 } else { 771 *s2++ = *s1++; 772 *s2 = '\0'; 773 } 774 } 775 *s2 = NULL; 776 777 size = my_atoll(base); 778 if ((!mul_factor) || (size == -1)) { 779 free(base); 780 return (-1); 781 } 782 num_sectors = (uint64_t)size * (uint64_t)mul_factor /512; 783 784 free(base); 785 return (num_sectors); 786 } 787 788 789 int32_t 790 valid_slice_file(smedia_handle_t handle, int32_t fd, char *file_name, 791 struct vtoc *vt) 792 { 793 struct stat status; 794 int32_t ret_val; 795 if (stat(file_name, &status)) { 796 PERROR(file_name); 797 return (-1); 798 } 799 (void) memset(vt, 0, sizeof (*vt)); 800 /* Set default tag and flag */ 801 #ifdef sparc 802 vt->v_part[0].p_tag = V_ROOT; 803 vt->v_part[1].p_tag = V_SWAP; 804 vt->v_part[2].p_tag = V_BACKUP; 805 vt->v_part[6].p_tag = V_USR; 806 807 vt->v_part[1].p_flag = V_UNMNT; /* Unmountable */ 808 vt->v_part[2].p_flag = V_UNMNT; /* Unmountable */ 809 #endif 810 811 ret_val = sup_prxfile(file_name, vt); 812 if (ret_val < 0) 813 return (-1); 814 815 #ifdef DEBUG 816 { 817 int32_t i; 818 for (i = 0; i < 8; i++) { 819 DPRINTF1("\npart %d\n", i); 820 DPRINTF1("\t start %d", (int32_t)vt->v_part[i].p_start); 821 DPRINTF1("\t size %d ", (int32_t)vt->v_part[i].p_size); 822 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 823 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 824 } 825 } 826 #endif /* DEBUG */ 827 if (check_vtoc_sanity(handle, fd, vt) < 0) { 828 return (-1); 829 } 830 #ifdef DEBUG 831 { 832 int32_t i; 833 for (i = 0; i < 8; i++) { 834 DPRINTF1("\npart %d\n", i); 835 DPRINTF1("\t start %d", (int32_t)vt->v_part[i].p_start); 836 DPRINTF1("\t size %d ", (int32_t)vt->v_part[i].p_size); 837 DPRINTF1("\t tag %d", vt->v_part[i].p_tag); 838 DPRINTF1("\t flag %d", vt->v_part[i].p_flag); 839 } 840 } 841 #endif /* DEBUG */ 842 return (0); 843 } 844 845 #define SWAP(a, b) {int32_t tmp; tmp = (a); (a) = (b); (b) = tmp; } 846 847 /* 848 * On x86 Solaris, the partitioning is done in two levels, fdisk and Solaris 849 * VTOC. Where as, on sparc solaris, it is only VTOC. On floppy and PCMCIA 850 * also it is assumed to be only VTOC, no fdisk. 851 * 852 * On sparc, the back up slice can cover the whole medium. But on x86 853 * (SCSI/ATAPI disks), the backup slice can cover the solaris partition 854 * in fdisk table. 855 * Following table describes how is it handled 856 * SPARC: 857 * SCSI/ATAPI, floppy, pcmcia : don't check for fdisk. 858 * DKIOCGGEOM is sufficient. 859 * x86 : floppy, pcmcia : Don't check for fdisk. DKIOCGGEOM is sufficient. 860 * SCSI/ATAPI : Check for fdisk. 861 * if not present, assume that the solaris 862 * partition covers 100% of the medium 863 * (minus one cylinder). 864 * 865 * if present : 866 * check for active solaris partition. 867 * if not found, take the first solaris 868 * partition. 869 * If there are no solaris partitions, its an error, stop. 870 */ 871 872 static int32_t 873 check_vtoc_sanity(smedia_handle_t handle, int32_t fd, struct vtoc *vt) 874 { 875 876 int32_t i, j; 877 struct dk_geom dkg; 878 int32_t num_backup = 0; 879 long backup_size = 0; 880 struct part_struct { 881 long start; 882 long end; 883 int32_t num; 884 } part[NDKMAP]; 885 long min_val, min_slice, num_slices; 886 long media_size; 887 int32_t cyl_size; 888 int sparc_style = 0; /* sparc_style handling ? */ 889 struct fdisk_info fdisk; 890 int sol_part; 891 int total_parts = 0; 892 893 #ifdef sparc 894 sparc_style = 1; 895 #endif /* sparc */ 896 897 if ((med_info.sm_media_type == SM_FLOPPY) || 898 (med_info.sm_media_type == SM_PCMCIA_MEM) || 899 (med_info.sm_media_type == SM_PCMCIA_ATA) || 900 (med_info.sm_media_type == SM_SCSI_FLOPPY)) { 901 sparc_style = 1; 902 } 903 904 if (sparc_style) { 905 DPRINTF("sparc style true\n"); 906 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) { 907 PERROR("DKIOCGGEOM Failed"); 908 return (-1); 909 } 910 media_size = dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect; 911 cyl_size = dkg.dkg_nhead * dkg.dkg_nsect; 912 } 913 914 if (!sparc_style) { 915 /* 916 * Try to get the fdisk information if available. 917 */ 918 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 919 /* fdisk table on disk */ 920 sol_part = 0xFF; 921 for (i = 0; i < FD_NUMPART; i++) { 922 if (fdisk.part[i].systid == SUNIXOS || 923 fdisk.part[i].systid == SUNIXOS2) { 924 if (sol_part == 0xFF) 925 sol_part = i; 926 total_parts++; 927 if (fdisk.part[i].bootid == ACTIVE) 928 sol_part = i; 929 } 930 } 931 if (sol_part == 0xFF) { 932 /* No Solaris partition */ 933 934 (void) fprintf(stderr, gettext("No FDISK \ 935 Solaris partition found!\n")); 936 return (-1); 937 } 938 if (total_parts > 1) 939 (void) fprintf(stderr, gettext("Multiple FDISK \ 940 Solaris partitions found.\n")); 941 media_size = fdisk.part[sol_part].numsect; 942 943 DPRINTF1("sol_part %d\n", sol_part); 944 DPRINTF1("media_size %d\n", (int)media_size); 945 } else { 946 DPRINTF("Didn't get fdisk\n"); 947 /* 948 * No fdisk partition available. Assume a 100% Solaris. 949 * partition. 950 * Try getting disk geometry. 951 */ 952 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 953 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 954 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 955 return (-1); 956 } 957 /* On x86 platform 1 cylinder is used for fdisk table */ 958 dkg.dkg_ncyl = dkg.dkg_ncyl - 1; 959 media_size = dkg.dkg_ncyl * dkg.dkg_nhead * 960 dkg.dkg_nsect; 961 } 962 } 963 964 #ifdef DEBUG 965 DPRINTF1("Ncyl %d\n", dkg.dkg_ncyl); 966 DPRINTF1("nhead %d\n", dkg.dkg_nhead); 967 DPRINTF1("nsect %d\n", dkg.dkg_nsect); 968 #endif /* DEBUG */ 969 970 if (media_size == 0) { 971 media_size = med_info.sm_capacity; 972 } 973 974 (void) memset(&part, 0, sizeof (part)); 975 for (i = 0, j = 0; i < NDKMAP; i++) { 976 if (vt->v_part[i].p_tag == V_BACKUP) { 977 if (vt->v_part[i].p_start != 0) { 978 (void) fprintf(stderr, 979 gettext( 980 "Backup slice should start at sector 0\n")); 981 return (-1); 982 } 983 backup_size = vt->v_part[i].p_size; 984 num_backup++; 985 continue; 986 } 987 if (vt->v_part[i].p_size) { 988 989 if (sparc_style) { 990 if (vt->v_part[i].p_start % cyl_size) { 991 (void) fprintf(stderr, 992 gettext( 993 "Slice %d does not start on cylinder boundary\n"), i); 994 (void) fprintf(stderr, 995 gettext( 996 "Cylinder size %d 512 byte sectors\n"), cyl_size); 997 return (-1); 998 } 999 } 1000 part[j].start = vt->v_part[i].p_start; 1001 part[j].end = vt->v_part[i].p_start + 1002 vt->v_part[i].p_size -1; 1003 part[j].num = i; 1004 j++; 1005 } 1006 } 1007 if (num_backup > 1) { 1008 (void) fprintf(stderr, 1009 gettext("Maximum one backup slice is allowed\n")); 1010 (void) smedia_release_handle(handle); 1011 (void) close(fd); 1012 exit(1); 1013 } 1014 num_slices = j; 1015 1016 for (i = 0; i < num_slices; i++) { 1017 min_val = part[i].start; 1018 min_slice = i; 1019 for (j = i+1; j < num_slices; j++) { 1020 if (part[j].start < min_val) { 1021 min_val = part[j].start; 1022 min_slice = j; 1023 } 1024 } 1025 if (min_slice != i) { 1026 SWAP(part[i].start, part[min_slice].start) 1027 SWAP(part[i].end, part[min_slice].end) 1028 SWAP(part[i].num, part[min_slice].num) 1029 } 1030 } 1031 1032 #ifdef DEBUG 1033 for (i = 0; i < num_slices; i++) { 1034 DPRINTF4("\n %d (%d) : %d, %d", i, part[i].num, 1035 part[i].start, part[i].end); 1036 } 1037 #endif /* DEBUG */ 1038 1039 if (backup_size > media_size) { 1040 if (sparc_style) { 1041 (void) fprintf(stderr, 1042 gettext( 1043 "Backup slice extends beyond size of media\n")); 1044 (void) fprintf(stderr, 1045 gettext("media size : %d sectors \n"), media_size); 1046 } else { 1047 1048 (void) fprintf(stderr, 1049 gettext("Backup slice extends beyond size of FDISK \ 1050 Solaris partition\n")); 1051 (void) fprintf(stderr, 1052 gettext( 1053 "FDISK Solaris partition size : %d sectors \n"), 1054 media_size); 1055 } 1056 return (-1); 1057 } 1058 1059 /* 1060 * If we have only backup slice return success here. 1061 */ 1062 if (num_slices == 0) 1063 return (0); 1064 1065 if (backup_size) { 1066 if (part[num_slices - 1].end > backup_size) { 1067 (void) fprintf(stderr, 1068 gettext("Slice %d extends beyond backup slice.\n"), 1069 part[num_slices -1].num); 1070 return (-1); 1071 } 1072 } else { 1073 if (part[num_slices - 1].end > media_size) { 1074 if (sparc_style) { 1075 (void) fprintf(stderr, 1076 gettext( 1077 "Slice %d extends beyond media size\n"), 1078 part[num_slices -1].num); 1079 (void) fprintf(stderr, 1080 gettext("media size : %d sectors \n"), 1081 media_size); 1082 } else { 1083 (void) fprintf(stderr, 1084 gettext( 1085 "Slice %d extends beyond FDISK Solaris partition size\n"), 1086 part[num_slices -1].num); 1087 (void) fprintf(stderr, 1088 gettext("FDISK Solaris partition size : %d \ 1089 sectors \n"), media_size); 1090 } 1091 return (-1); 1092 } 1093 } 1094 1095 1096 1097 for (i = 0; i < num_slices; i++) { 1098 if (i == 0) 1099 continue; 1100 if (part[i].start <= part[i-1].end) { 1101 (void) fprintf(stderr, 1102 gettext("Overlap between slices %d and %d\n"), 1103 part[i-1].num, part[i].num); 1104 (void) smedia_release_handle(handle); 1105 (void) close(fd); 1106 exit(1); 1107 } 1108 } 1109 1110 return (0); 1111 } 1112 1113 1114 static int32_t 1115 get_fdisk(smedia_handle_t handle, int32_t fd, int32_t offset, 1116 struct fdisk_info *fdisk) 1117 { 1118 struct mboot *boot_sec; 1119 struct ipart *part; 1120 char *buf; 1121 int32_t i, ret; 1122 int save_errno; 1123 1124 /* Read the master boot program */ 1125 1126 buf = (char *)malloc(med_info.sm_blocksize); 1127 if (buf == NULL) { 1128 PERROR("malloc failed"); 1129 exit(1); 1130 } 1131 errno = 0; 1132 ret = ioctl(fd, DKIOCGMBOOT, buf); 1133 if (ret < 0) { 1134 if (errno != ENOTTY) { 1135 PERROR("DKIOCGMBOOT ioctl failed"); 1136 return (-1); 1137 } 1138 1139 /* Turn on privileges. */ 1140 (void) __priv_bracket(PRIV_ON); 1141 1142 ret = smedia_raw_read(handle, offset/med_info.sm_blocksize, 1143 buf, med_info.sm_blocksize); 1144 1145 /* Turn off privileges. */ 1146 (void) __priv_bracket(PRIV_OFF); 1147 1148 save_errno = errno; 1149 errno = save_errno; 1150 if (ret != med_info.sm_blocksize) { 1151 if (errno == ENOTSUP) { 1152 errno = 0; 1153 if (lseek(fd, offset, SEEK_SET)) { 1154 PERROR("Seek failed:"); 1155 free(buf); 1156 return (-1); 1157 } 1158 1159 /* Turn on privileges. */ 1160 (void) __priv_bracket(PRIV_ON); 1161 1162 ret = read(fd, buf, sizeof (struct mboot)); 1163 1164 /* Turn off privileges. */ 1165 (void) __priv_bracket(PRIV_OFF); 1166 1167 if (ret != sizeof (struct mboot)) { 1168 PERROR("Could not read master boot record"); 1169 free(buf); 1170 return (-1); 1171 } 1172 } else { 1173 PERROR("Could not read master boot record"); 1174 free(buf); 1175 return (-1); 1176 } 1177 } 1178 } 1179 /* LINTED pointer cast may result in improper alignment */ 1180 boot_sec = (struct mboot *)buf; 1181 1182 /* Is this really a master boot record? */ 1183 if (les(boot_sec->signature) != MBB_MAGIC) { 1184 DPRINTF("fdisk: Invalid master boot file \n"); 1185 DPRINTF2("Bad magic number: is %x, should be %x.\n", 1186 les(boot_sec->signature), MBB_MAGIC); 1187 free(buf); 1188 return (-1); 1189 } 1190 1191 for (i = 0; i < FD_NUMPART; i++) { 1192 DPRINTF1("part %d\n", i); 1193 /* LINTED pointer cast may result in improper alignment */ 1194 part = (struct ipart *)&boot_sec->parts[i * 1195 sizeof (struct ipart)]; 1196 fdisk->part[i].bootid = part->bootid; 1197 if (part->bootid && (part->bootid != ACTIVE)) { 1198 /* Hmmm...not a valid fdisk! */ 1199 return (-1); 1200 } 1201 fdisk->part[i].systid = part->systid; 1202 1203 /* To avoid the misalign access in sparc */ 1204 1205 fdisk->part[i].relsect = lel(GET_32(&(part->relsect))); 1206 fdisk->part[i].numsect = lel(GET_32(&(part->numsect))); 1207 1208 DPRINTF1("\tboot id 0x%x\n", part->bootid); 1209 DPRINTF1("\tsystem id 0x%x\n", part->systid); 1210 DPRINTF1("\trel sector 0x%x\n", fdisk->part[i].relsect); 1211 DPRINTF1("\tnum sector 0x%x\n", fdisk->part[i].numsect); 1212 } 1213 free(buf); 1214 return (0); 1215 } 1216 1217 1218 /* 1219 * wrrite_defualt_label(int32_t fd) 1220 * fd = file descriptor for the device. 1221 * 1222 * For sparc solaris 1223 * Create a vtoc partition with 1224 * slice 0 = slice 2 = medium capacity. 1225 * The cyl, head, sect (CHS) values are computed as done in sd 1226 * capacity <= 1GB, 1227 * nhead = 64, nsect = 32 1228 * capacity > 1gb, 1229 * nhead = 255, nsect = 63 1230 * 1231 * For x86 solaris 1232 * Create a fdisk partition, 1233 * partition 0 covers the full medium, the partition 1234 * type is set to Solaris. 1235 * Then create solaris vtoc. The algorithm is same as sparc solaris. 1236 * But the capacity is reduced by 1 cyl, to leave space for fdisk table. 1237 */ 1238 1239 #ifdef sparc 1240 /*ARGSUSED*/ 1241 void 1242 write_default_label(smedia_handle_t handle, int32_t fd) 1243 { 1244 1245 struct vtoc v_toc; 1246 int32_t nhead, numcyl, nsect, capacity; 1247 int32_t ret; 1248 char asciilabel[LEN_DKL_ASCII]; 1249 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1250 int32_t acyl = 2; 1251 1252 1253 DPRINTF("Writing default vtoc\n"); 1254 (void) memset(&v_toc, 0, sizeof (v_toc)); 1255 1256 1257 v_toc.v_nparts = V_NUMPAR; 1258 v_toc.v_sanity = VTOC_SANE; 1259 v_toc.v_version = V_VERSION; 1260 v_toc.v_sectorsz = DEV_BSIZE; 1261 1262 /* 1263 * For the head, cyl and number of sector per track, 1264 * if the capacity <= 1GB, head = 64, sect = 32. 1265 * else head = 255, sect 63 1266 * NOTE: the capacity should be equal to C*H*S values. 1267 * This will cause some truncation of size due to 1268 * round off errors. 1269 */ 1270 if (med_info.sm_capacity <= 0x200000) { 1271 nhead = 64; 1272 nsect = 32; 1273 } else { 1274 nhead = 255; 1275 nsect = 63; 1276 } 1277 1278 numcyl = med_info.sm_capacity / (nhead * nsect); 1279 capacity = nhead * nsect * numcyl; 1280 1281 v_toc.v_part[0].p_start = 0; 1282 v_toc.v_part[0].p_size = capacity; 1283 v_toc.v_part[0].p_tag = V_ROOT; 1284 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1285 1286 v_toc.v_part[2].p_start = 0; 1287 v_toc.v_part[2].p_size = capacity; 1288 v_toc.v_part[2].p_tag = V_BACKUP; 1289 v_toc.v_part[2].p_flag = V_UNMNT; 1290 1291 /* Create asciilabel for compatibility with format utility */ 1292 (void) snprintf(asciilabel, sizeof (asciilabel), 1293 "%s cyl %d alt %d hd %d sec %d", 1294 asciilabel2, numcyl, acyl, nhead, nsect); 1295 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1296 LEN_DKL_ASCII); 1297 1298 errno = 0; 1299 1300 /* Turn on privileges. */ 1301 (void) __priv_bracket(PRIV_ON); 1302 1303 ret = write_vtoc(fd, &v_toc); 1304 1305 /* Turn off privileges. */ 1306 (void) __priv_bracket(PRIV_OFF); 1307 1308 if (ret < 0) { 1309 PERROR("write VTOC failed"); 1310 DPRINTF1("Errno = %d\n", errno); 1311 } 1312 } 1313 1314 #else /* !sparc */ 1315 #ifdef i386 1316 1317 void 1318 write_default_label(smedia_handle_t handle, int32_t fd) 1319 { 1320 1321 int32_t i, ret; 1322 struct dk_geom dkg; 1323 struct vtoc v_toc; 1324 int tmp_fd; 1325 char *fdisk_buf; 1326 struct mboot boot_code; /* Buffer for master boot record */ 1327 struct ipart parts[FD_NUMPART]; 1328 int32_t numcyl, nhead, nsect; 1329 int32_t unixend; 1330 int32_t blocksize; 1331 int32_t capacity; 1332 int save_errno; 1333 size_t bytes_written; 1334 char asciilabel[LEN_DKL_ASCII]; 1335 char asciilabel2[LEN_DKL_ASCII] = "DEFAULT\0"; 1336 int32_t acyl = 2; 1337 1338 DPRINTF("Writing default fdisk table and vtoc\n"); 1339 (void) memset(&v_toc, 0, sizeof (v_toc)); 1340 /* 1341 * Try getting disk geometry. 1342 */ 1343 if (ioctl(fd, DKIOCGGEOM, &dkg) < 0) 1344 if (ioctl(fd, DKIOCG_PHYGEOM, &dkg) < 0) { 1345 1346 DPRINTF("DKIOCG_PHYGEOM ioctl failed"); 1347 return; 1348 } 1349 1350 tmp_fd = open("/usr/lib/fs/ufs/mboot", O_RDONLY); 1351 if (tmp_fd <= 0) { 1352 return; 1353 } 1354 1355 if (read(tmp_fd, &boot_code, sizeof (struct mboot)) 1356 != sizeof (struct mboot)) { 1357 (void) close(tmp_fd); 1358 return; 1359 } 1360 1361 blocksize = med_info.sm_blocksize; 1362 fdisk_buf = (char *)malloc(blocksize); 1363 if (fdisk_buf == NULL) { 1364 DPRINTF("malloc for fdisk_buf failed\n"); 1365 return; 1366 } 1367 1368 (void) memset(&parts, 0, sizeof (parts)); 1369 1370 for (i = 0; i < FD_NUMPART; i++) { 1371 parts[i].systid = UNUSED; 1372 parts[i].numsect = lel(UNUSED); 1373 parts[i].relsect = lel(UNUSED); 1374 parts[i].bootid = 0; 1375 } 1376 1377 numcyl = dkg.dkg_ncyl; 1378 nhead = dkg.dkg_nhead; 1379 nsect = dkg.dkg_nsect; 1380 1381 parts[0].bootid = ACTIVE; 1382 parts[0].begsect = 1; 1383 1384 unixend = numcyl; 1385 1386 parts[0].relsect = lel(nhead * nsect); 1387 parts[0].numsect = lel((long)((numcyl) * nhead * nsect)); 1388 parts[0].systid = SUNIXOS2; /* Solaris */ 1389 parts[0].beghead = 0; 1390 parts[0].begcyl = 1; 1391 parts[0].endhead = nhead - 1; 1392 parts[0].endsect = (nsect & 0x3f) | 1393 (char)((unixend >> 2) & 0x00c0); 1394 parts[0].endcyl = (char)(unixend & 0x00ff); 1395 1396 (void) memcpy(&(boot_code.parts), parts, sizeof (parts)); 1397 (void) memcpy(fdisk_buf, &boot_code, sizeof (boot_code)); 1398 1399 /* Turn on privileges. */ 1400 (void) __priv_bracket(PRIV_ON); 1401 1402 ret = ioctl(fd, DKIOCSMBOOT, fdisk_buf); 1403 1404 /* Turn off privileges. */ 1405 (void) __priv_bracket(PRIV_OFF); 1406 1407 if (ret == -1) { 1408 if (errno != ENOTTY) { 1409 PERROR("DKIOCSMBOOT ioctl Failed"); 1410 return; 1411 } 1412 1413 /* Turn on privileges. */ 1414 (void) __priv_bracket(PRIV_ON); 1415 1416 bytes_written = smedia_raw_write(handle, 0, fdisk_buf, 1417 blocksize); 1418 1419 /* Turn off privileges. */ 1420 (void) __priv_bracket(PRIV_OFF); 1421 1422 save_errno = errno; 1423 errno = save_errno; 1424 if (bytes_written != blocksize) { 1425 if (errno == ENOTSUP) { 1426 1427 /* Turn on privileges. */ 1428 (void) __priv_bracket(PRIV_ON); 1429 1430 ret = write(fd, fdisk_buf, blocksize); 1431 1432 /* Turn off privileges. */ 1433 (void) __priv_bracket(PRIV_OFF); 1434 1435 if (ret != blocksize) { 1436 return; 1437 } 1438 } else { 1439 return; 1440 } 1441 } 1442 } 1443 capacity = (numcyl - 1) * nhead * nsect; 1444 1445 v_toc.v_nparts = V_NUMPAR; 1446 v_toc.v_sanity = VTOC_SANE; 1447 v_toc.v_version = V_VERSION; 1448 v_toc.v_sectorsz = DEV_BSIZE; 1449 1450 v_toc.v_part[0].p_start = 0; 1451 v_toc.v_part[0].p_size = capacity; 1452 v_toc.v_part[0].p_tag = V_ROOT; 1453 v_toc.v_part[0].p_flag = 0; /* Mountable */ 1454 1455 v_toc.v_part[2].p_start = 0; 1456 v_toc.v_part[2].p_size = capacity; 1457 v_toc.v_part[2].p_tag = V_BACKUP; 1458 v_toc.v_part[2].p_flag = V_UNMNT; 1459 1460 /* Create asciilabel for compatibility with format utility */ 1461 (void) snprintf(asciilabel, sizeof (asciilabel), 1462 "%s cyl %d alt %d hd %d sec %d", 1463 asciilabel2, numcyl, acyl, nhead, nsect); 1464 (void) memcpy(v_toc.v_asciilabel, asciilabel, 1465 LEN_DKL_ASCII); 1466 1467 errno = 0; 1468 1469 1470 /* Turn on privileges. */ 1471 (void) __priv_bracket(PRIV_ON); 1472 1473 ret = write_vtoc(fd, &v_toc); 1474 1475 /* Turn off privileges. */ 1476 (void) __priv_bracket(PRIV_OFF); 1477 1478 if (ret < 0) { 1479 PERROR("write VTOC failed"); 1480 DPRINTF1("Errno = %d\n", errno); 1481 } 1482 } 1483 1484 #else /* !i386 */ 1485 1486 #error One of sparc or i386 must be defined! 1487 1488 #endif /* i386 */ 1489 #endif /* sparc */ 1490 1491 /* 1492 * void overwrite_metadata(int32_t fd, smedia_handle_t handle) 1493 * 1494 * purpose : quick format does not erase the data on Iomega 1495 * zip/jaz media. So, the meta data on the disk should be erased. 1496 * 1497 * If there is a valid fdisk table, 1498 * erase first 64K of each partition. 1499 * If there is a valid vtoc, 1500 * erase first 64k of each slice. 1501 * Then erase the 0th sector (the home for vtoc and fdisk) of the disk. 1502 * Note that teh vtoc on x86 resides in one of the fdisk partition. 1503 * So delay the erasing of the solaris partition until the vtoc is read. 1504 */ 1505 1506 void 1507 overwrite_metadata(int32_t fd, smedia_handle_t handle) 1508 { 1509 1510 struct fdisk_info fdisk; 1511 uint32_t sol_offset = 0; 1512 int i, ret; 1513 struct vtoc t_vtoc; 1514 #ifdef i386 1515 uint32_t sol_size = 0; 1516 int32_t active = 0; 1517 #endif /* i386 */ 1518 1519 /* Get fdisk info. */ 1520 if (get_fdisk(handle, fd, 0, &fdisk) >= 0) { 1521 /* Got a valid fdisk */ 1522 for (i = 0; i < FD_NUMPART; i++) { 1523 1524 if (fdisk.part[i].numsect == 0) 1525 continue; 1526 if ((fdisk.part[i].systid == UNUSED) || 1527 (fdisk.part[i].systid == 0)) 1528 continue; 1529 #ifdef i386 1530 if (fdisk.part[i].systid == SUNIXOS || 1531 fdisk.part[i].systid == SUNIXOS2) { 1532 if (!sol_offset) { 1533 sol_offset = fdisk.part[i].relsect; 1534 sol_size = fdisk.part[i].numsect; 1535 if (fdisk.part[i].bootid == ACTIVE) 1536 active = 1; 1537 continue; 1538 } else if ((fdisk.part[i].bootid == ACTIVE) && 1539 (!active)) { 1540 erase(handle, sol_offset, sol_size); 1541 sol_offset = fdisk.part[i].relsect; 1542 sol_size = fdisk.part[i].numsect; 1543 active = 1; 1544 continue; 1545 } 1546 } 1547 #endif /* i386 */ 1548 erase(handle, fdisk.part[i].relsect, 1549 fdisk.part[i].numsect); 1550 } 1551 } 1552 1553 (void) memset(&t_vtoc, 0, sizeof (t_vtoc)); 1554 1555 if (sol_offset) { 1556 /* fdisk x86 Solaris partition */ 1557 /* VTOC location in solaris partition is DK_LABEL_LOC */ 1558 1559 /* Turn on privileges. */ 1560 (void) __priv_bracket(PRIV_ON); 1561 1562 ret = read_vtoc(fd, &t_vtoc); 1563 1564 /* Turn off privileges. */ 1565 (void) __priv_bracket(PRIV_OFF); 1566 1567 if (ret < 0) { 1568 /* No valid vtoc, erase fdisk table. */ 1569 erase(handle, 0, 1); 1570 return; 1571 } 1572 } else { 1573 /* Sparc Solaris or x86 solaris with faked fdisk */ 1574 1575 /* Turn on privileges */ 1576 (void) __priv_bracket(PRIV_ON); 1577 1578 ret = read_vtoc(fd, &t_vtoc); 1579 1580 /* Turn off privileges. */ 1581 (void) __priv_bracket(PRIV_OFF); 1582 1583 if (ret < 0) { 1584 /* No valid vtoc, erase from 0th sector */ 1585 erase(handle, 0, med_info.sm_capacity); 1586 return; 1587 } 1588 } 1589 1590 for (i = 0; i < V_NUMPAR; i++) { 1591 if (t_vtoc.v_part[i].p_size != 0) { 1592 erase(handle, sol_offset + t_vtoc.v_part[i].p_start, 1593 t_vtoc.v_part[i].p_size); 1594 /* 1595 * To make the udfs not recognise the partition we will 1596 * erase sectors 256, (p_size-256) and psize. 1597 */ 1598 erase(handle, 1599 sol_offset + t_vtoc.v_part[i].p_start + 256, 1600 1); 1601 erase(handle, 1602 (sol_offset + t_vtoc.v_part[i].p_start + 1603 t_vtoc.v_part[i].p_size - 256), 1604 1); 1605 erase(handle, 1606 (sol_offset + t_vtoc.v_part[i].p_start + 1607 t_vtoc.v_part[i].p_size - 1), 1608 1); 1609 } 1610 } 1611 1612 /* 1613 * If x86 fdisk solaris partition, erase the vtoc also. 1614 * for sparc, the erasing 0the sector erases vtoc. 1615 */ 1616 if (sol_offset) { 1617 erase(handle, sol_offset, DK_LABEL_LOC + 2); 1618 } 1619 1620 /* 1621 * erase the 0th sector, it is not guaranteed to be 1622 * erased in the above sequence. 1623 */ 1624 1625 erase(handle, 0, 1); 1626 } 1627 1628 /* 1629 * void erase(smedia_handle_t handle, uint32_t offset, uint32_t size) 1630 * 1631 * Initialize the media with '0' from offset 'offset' upto 'size' 1632 * or 128 blocks(64k), whichever is smaller. 1633 */ 1634 1635 static void 1636 erase(smedia_handle_t handle, uint32_t offset, uint32_t size) 1637 { 1638 char *buf; 1639 int32_t nblocks = size; 1640 int32_t ret; 1641 1642 1643 nblocks = (nblocks < 128) ? nblocks : 128; 1644 buf = (char *)malloc(nblocks * med_info.sm_blocksize); 1645 if (buf == NULL) { 1646 PERROR("malloc failed"); 1647 return; 1648 } 1649 (void) memset(buf, 0, nblocks * med_info.sm_blocksize); 1650 1651 /* Turn on privileges. */ 1652 (void) __priv_bracket(PRIV_ON); 1653 1654 ret = smedia_raw_write(handle, offset, buf, 1655 nblocks * med_info.sm_blocksize); 1656 1657 /* Turn off privileges. */ 1658 (void) __priv_bracket(PRIV_OFF); 1659 1660 if (ret != (nblocks * med_info.sm_blocksize)) 1661 PERROR("error in writing\n"); 1662 1663 free(buf); 1664 1665 } 1666