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