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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * Portions of this source code were derived from Berkeley 4.3 BSD 31 * under license from the Regents of the University of California. 32 */ 33 34 /* 35 * make file system for udfs (UDF - ISO13346) 36 * 37 * usage: 38 * 39 * mkfs [-F FSType] [-V] [-m] [options] 40 * [-o specific_options] special size 41 * 42 * where specific_options are: 43 * N - no create 44 * label - volume label 45 * psize - physical block size 46 */ 47 48 #include <stdio.h> 49 #include <strings.h> 50 #include <string.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 #include <time.h> 54 #include <locale.h> 55 #include <fcntl.h> 56 #include <errno.h> 57 #include <limits.h> 58 #include <sys/mnttab.h> 59 #include <sys/param.h> 60 #include <sys/types.h> 61 #include <sys/sysmacros.h> 62 #include <sys/vnode.h> 63 #include <sys/mntent.h> 64 #include <sys/filio.h> 65 #include <sys/stat.h> 66 #include <ustat.h> 67 #include <sys/isa_defs.h> /* for ENDIAN defines */ 68 #include <sys/dkio.h> 69 #include <sys/fdio.h> 70 #include <sys/vtoc.h> 71 #include <sys/fs/udf_volume.h> 72 73 extern char *getfullrawname(char *); 74 extern char *getfullblkname(char *); 75 extern struct tm *localtime_r(const time_t *, struct tm *); 76 extern void maketag(struct tag *, struct tag *); 77 extern int verifytag(struct tag *, uint32_t, struct tag *, int); 78 extern void setcharspec(struct charspec *, int32_t, uint8_t *); 79 80 81 #define UMASK 0755 82 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 83 #define MB (1024*1024) 84 85 /* 86 * Forward declarations 87 */ 88 static void rdfs(daddr_t bno, int size, char *bf); 89 static void wtfs(daddr_t bno, int size, char *bf); 90 static void dump_fscmd(char *fsys, int fsi); 91 static int32_t number(long big, char *param); 92 static void usage(); 93 static int match(char *s); 94 static int readvolseq(); 95 static uint32_t get_last_block(); 96 97 /* 98 * variables set up by front end. 99 */ 100 static int Nflag = 0; /* run mkfs without writing */ 101 /* file system */ 102 static int mflag = 0; /* return the command line used */ 103 /* to create this FS */ 104 static int fssize; /* file system size */ 105 static uint32_t disk_size; /* partition size from VTOC */ 106 static uint32_t unused; /* unused sectors in partition */ 107 static int sectorsize = 2048; /* bytes/sector default */ 108 /* If nothing specified */ 109 110 static char *fsys; 111 static int fsi; 112 static int fso; 113 114 #define BIG LONG_MAX 115 static uint32_t number_flags = 0; 116 117 static char *string; 118 119 static void setstamp(tstamp_t *); 120 static void setextad(extent_ad_t *, uint32_t, uint32_t); 121 static void setdstring(dstring_t *, char *, int32_t); 122 static void wtvolseq(tag_t *, daddr_t, daddr_t); 123 static void volseqinit(); 124 static void setstamp(tstamp_t *); 125 static uint32_t get_bsize(); 126 127 128 #define VOLRECSTART (32 * 1024) 129 130 #define VOLSEQSTART 128 131 #define VOLSEQLEN 16 132 #define INTSEQSTART 192 133 #define INTSEQLEN 8192 134 #define FIRSTAVDP 256 135 #define AVDPLEN 1 136 137 138 #define FILESETLEN 2 139 140 #define SPACEMAP_OFF 24 141 #define MAXID 16 142 143 static time_t mkfstime; 144 static struct tm res; 145 static long tzone; 146 static char vsibuf[128]; 147 148 static regid_t sunmicro = { 0, "*SUN SOLARIS UDF", 4, 2 }; 149 static regid_t lvinfo = { 0, "*UDF LV Info", 0x50, 0x1, 4, 2 }; 150 static regid_t partid = { 0, "+NSR02", 0 }; 151 static regid_t udf_compliant = { 0, "*OSTA UDF Compliant", 0x50, 0x1, 0 }; 152 static uint8_t osta_unicode[] = "OSTA Compressed Unicode"; 153 154 static int bdevismounted; 155 static int ismounted; 156 static int directory; 157 static char buf[MAXBSIZE]; 158 static char buf2[MAXBSIZE]; 159 static char lvid[MAXBSIZE]; 160 161 uint32_t ecma_version = 2; 162 163 static int serialnum = 1; /* Tag serial number */ 164 static char udfs_label[128] = "*NoLabel*"; 165 static int acctype = PART_ACC_OW; 166 static uint32_t part_start; 167 static uint32_t part_len; 168 static uint32_t part_bmp_bytes; 169 static uint32_t part_bmp_sectors; 170 static int32_t part_unalloc = -1; 171 static uint32_t filesetblock; 172 173 /* Set by readvolseq for -m option */ 174 static uint32_t oldfssize; 175 static char *oldlabel; 176 177 int 178 main(int32_t argc, int8_t *argv[]) 179 { 180 long i; 181 FILE *mnttab; 182 struct mnttab mntp; 183 char *special, *raw_special; 184 struct stat statarea; 185 struct ustat ustatarea; 186 int32_t c; 187 uint32_t temp_secsz; 188 int isfs; 189 190 (void) setlocale(LC_ALL, ""); 191 192 #if !defined(TEXT_DOMAIN) 193 #define TEXT_DOMAIN "SYS_TEST" 194 #endif 195 (void) textdomain(TEXT_DOMAIN); 196 197 while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) { 198 switch (c) { 199 200 case 'F': 201 string = optarg; 202 if (strcmp(string, "udfs") != 0) { 203 usage(); 204 } 205 break; 206 207 case 'V': 208 { 209 char *opt_text; 210 int opt_count; 211 212 (void) fprintf(stdout, 213 gettext("mkfs -F udfs ")); 214 for (opt_count = 1; opt_count < argc; 215 opt_count++) { 216 opt_text = argv[opt_count]; 217 if (opt_text) { 218 (void) fprintf(stdout, 219 " %s ", opt_text); 220 } 221 } 222 (void) fprintf(stdout, "\n"); 223 } 224 break; 225 226 case 'm': 227 /* 228 * return command line used 229 * to create this FS 230 */ 231 mflag++; 232 break; 233 234 case 'o': 235 /* 236 * udfs specific options. 237 */ 238 string = optarg; 239 while (*string != '\0') { 240 if (match("N")) { 241 Nflag++; 242 } else if (match("psize=")) { 243 number_flags = 0; 244 sectorsize = number(BIG, 245 "psize"); 246 } else if (match("label=")) { 247 for (i = 0; i < 31; i++) { 248 if (*string == '\0') { 249 break; 250 } 251 udfs_label[i] = 252 *string++; 253 } 254 udfs_label[i] = '\0'; 255 } else if (*string == '\0') { 256 break; 257 } else { 258 (void) fprintf(stdout, 259 gettext("illegal " 260 "option: %s\n"), 261 string); 262 usage(); 263 } 264 if (*string == ',') { 265 string++; 266 } 267 if (*string == ' ') { 268 string++; 269 } 270 } 271 break; 272 273 case '?': 274 usage(); 275 break; 276 } 277 } 278 279 (void) time(&mkfstime); 280 if (optind > (argc - 1)) { 281 usage(); 282 } 283 284 argc -= optind; 285 argv = &argv[optind]; 286 fsys = argv[0]; 287 raw_special = getfullrawname(fsys); 288 fsi = open(raw_special, 0); 289 if (fsi < 0) { 290 (void) fprintf(stdout, 291 gettext("%s: cannot open\n"), fsys); 292 exit(32); 293 } 294 fso = fsi; 295 296 if ((temp_secsz = get_bsize()) != 0) { 297 sectorsize = temp_secsz; 298 } 299 300 /* Get old file system information */ 301 isfs = readvolseq(); 302 303 if (mflag) { 304 /* 305 * Figure out the block size and 306 * file system size and print the information 307 */ 308 if (isfs) 309 dump_fscmd(fsys, fsi); 310 else 311 (void) printf(gettext( 312 "[not currently a valid file system]\n")); 313 exit(0); 314 } 315 316 /* 317 * Get the disk size from the drive or VTOC for the N and N-256 318 * AVDPs and to make sure we don't want to create a file system 319 * bigger than the partition. 320 */ 321 disk_size = get_last_block(); 322 323 if (argc < 2 && disk_size == 0 || argc < 1) { 324 usage(); 325 } 326 327 if (argc < 2) { 328 (void) printf(gettext("No size specified, entire partition " 329 "of %u sectors used\n"), disk_size); 330 fssize = disk_size; 331 } else { 332 string = argv[1]; 333 number_flags = 0; 334 fssize = number(BIG, "size"); 335 } 336 337 if (fssize < 0) { 338 (void) fprintf(stderr, 339 gettext("Negative number of sectors(%d) not allowed\n"), 340 fssize); 341 exit(32); 342 } 343 344 if (fssize < (512 * sectorsize / DEV_BSIZE)) { 345 (void) fprintf(stdout, 346 gettext("size should be at least %d sectors\n"), 347 (512 * sectorsize / DEV_BSIZE)); 348 exit(32); 349 } 350 351 if (disk_size != 0) { 352 if (fssize > disk_size) { 353 (void) fprintf(stderr, gettext("Invalid size: %d " 354 "larger than the partition size\n"), fssize); 355 exit(32); 356 } else if (fssize < disk_size) { 357 unused = disk_size - fssize; 358 (void) printf( 359 gettext("File system size %d smaller than " 360 "partition, %u sectors unused\n"), 361 fssize, unused); 362 } 363 } else { 364 /* Use passed-in size */ 365 disk_size = fssize; 366 } 367 368 if (!Nflag) { 369 special = getfullblkname(fsys); 370 371 /* 372 * If we found the block device name, 373 * then check the mount table. 374 * if mounted, write lock the file system 375 * 376 */ 377 if ((special != NULL) && (*special != '\0')) { 378 mnttab = fopen(MNTTAB, "r"); 379 while ((getmntent(mnttab, &mntp)) == 0) { 380 if (strcmp(special, mntp.mnt_special) == 0) { 381 (void) fprintf(stdout, 382 gettext("%s is mounted," 383 " can't mkfs\n"), special); 384 exit(32); 385 } 386 } 387 (void) fclose(mnttab); 388 } 389 if ((bdevismounted) && (ismounted == 0)) { 390 (void) fprintf(stdout, 391 gettext("can't check mount point; ")); 392 (void) fprintf(stdout, 393 gettext("%s is mounted but not in mnttab(4)\n"), 394 special); 395 exit(32); 396 } 397 if (directory) { 398 if (ismounted == 0) { 399 (void) fprintf(stdout, 400 gettext("%s is not mounted\n"), 401 special); 402 exit(32); 403 } 404 } 405 fso = creat(fsys, 0666); 406 if (fso < 0) { 407 (void) fprintf(stdout, 408 gettext("%s: cannot create\n"), fsys); 409 exit(32); 410 } 411 if (stat(fsys, &statarea) < 0) { 412 (void) fprintf(stderr, 413 gettext("%s: %s: cannot stat\n"), 414 argv[0], fsys); 415 exit(32); 416 } 417 if (ustat(statarea.st_rdev, &ustatarea) >= 0) { 418 (void) fprintf(stderr, 419 gettext("%s is mounted, can't mkfs\n"), fsys); 420 exit(32); 421 } 422 } else { 423 /* 424 * For the -N case, a file descriptor is needed for the llseek() 425 * in wtfs(). See the comment in wtfs() for more information. 426 * 427 * Get a file descriptor that's read-only so that this code 428 * doesn't accidentally write to the file. 429 */ 430 fso = open(fsys, O_RDONLY); 431 if (fso < 0) { 432 (void) fprintf(stderr, gettext("%s: cannot open\n"), 433 fsys); 434 exit(32); 435 } 436 } 437 438 439 /* 440 * Validate the given file system size. 441 * Verify that its last block can actually be accessed. 442 */ 443 fssize = fssize / (sectorsize / DEV_BSIZE); 444 if (fssize <= 0) { 445 (void) fprintf(stdout, 446 gettext("preposterous size %d. sectors\n"), fssize); 447 exit(32); 448 } 449 fssize --; 450 451 /* 452 * verify device size 453 */ 454 rdfs(fssize - 1, sectorsize, buf); 455 456 if ((sectorsize < DEV_BSIZE) || 457 (sectorsize > MAXBSIZE)) { 458 (void) fprintf(stdout, 459 gettext("sector size must be" 460 " between 512, 8192 bytes\n")); 461 } 462 if (!POWEROF2(sectorsize)) { 463 (void) fprintf(stdout, 464 gettext("sector size must be a power of 2, not %d\n"), 465 sectorsize); 466 exit(32); 467 } 468 if (Nflag) { 469 exit(0); 470 } 471 472 (void) printf(gettext("Creating file system with sector size of " 473 "%d bytes\n"), sectorsize); 474 475 /* 476 * Set up time stamp values 477 */ 478 mkfstime = time(0); 479 (void) localtime_r(&mkfstime, &res); 480 if (res.tm_isdst > 0) { 481 tzone = altzone / 60; 482 } else if (res.tm_isdst == 0) { 483 tzone = tzone / 60; 484 } else { 485 tzone = 2047; /* Unknown */ 486 } 487 488 /* 489 * Initialize the volume recognition sequence, the volume descriptor 490 * sequences and the anchor pointer. 491 */ 492 volseqinit(); 493 494 (void) fsync(fso); 495 (void) close(fsi); 496 (void) close(fso); 497 498 return (0); 499 } 500 501 static void 502 setstamp(tstamp_t *tp) 503 { 504 tp->ts_usec = 0; 505 tp->ts_husec = 0; 506 tp->ts_csec = 0; 507 508 tp->ts_sec = res.tm_sec; 509 tp->ts_min = res.tm_min; 510 tp->ts_hour = res.tm_hour; 511 tp->ts_day = res.tm_mday; 512 tp->ts_month = res.tm_mon + 1; 513 tp->ts_year = 1900 + res.tm_year; 514 515 tp->ts_tzone = 0x1000 + (-tzone & 0xFFF); 516 } 517 518 static void 519 setextad(extent_ad_t *eap, uint32_t len, uint32_t loc) 520 { 521 eap->ext_len = len; 522 eap->ext_loc = loc; 523 } 524 525 static void 526 setdstring(dstring_t *dp, char *cp, int len) 527 { 528 int32_t length; 529 530 bzero(dp, len); 531 length = strlen(cp); 532 if (length > len - 3) { 533 length = len - 3; 534 } 535 dp[len - 1] = length + 1; 536 *dp++ = 8; 537 (void) strncpy(dp, cp, len-2); 538 } 539 540 static void 541 wtvolseq(tag_t *tp, daddr_t blk1, daddr_t blk2) 542 { 543 static uint32_t vdsn = 0; 544 545 tp->tag_loc = blk1; 546 switch (tp->tag_id) { 547 case UD_PRI_VOL_DESC : 548 ((struct pri_vol_desc *)tp)->pvd_vdsn = vdsn++; 549 break; 550 case UD_VOL_DESC_PTR : 551 ((struct vol_desc_ptr *)tp)->vdp_vdsn = vdsn++; 552 break; 553 case UD_IMPL_USE_DESC : 554 ((struct iuvd_desc *)tp)->iuvd_vdsn = vdsn++; 555 break; 556 case UD_PART_DESC : 557 ((struct part_desc *)tp)->pd_vdsn = vdsn++; 558 break; 559 case UD_LOG_VOL_DESC : 560 ((struct log_vol_desc *)tp)->lvd_vdsn = vdsn++; 561 break; 562 case UD_UNALL_SPA_DESC : 563 ((struct unall_spc_desc *)tp)->ua_vdsn = vdsn++; 564 break; 565 } 566 567 bzero(buf2, sectorsize); 568 /* LINTED */ 569 maketag(tp, (struct tag *)buf2); 570 571 /* 572 * Write at Main Volume Descriptor Sequence 573 */ 574 wtfs(blk1, sectorsize, buf2); 575 576 tp->tag_loc = blk2; 577 switch (tp->tag_id) { 578 case UD_PRI_VOL_DESC : 579 ((struct pri_vol_desc *)tp)->pvd_vdsn = vdsn++; 580 break; 581 case UD_VOL_DESC_PTR : 582 ((struct vol_desc_ptr *)tp)->vdp_vdsn = vdsn++; 583 break; 584 case UD_IMPL_USE_DESC : 585 ((struct iuvd_desc *)tp)->iuvd_vdsn = vdsn++; 586 break; 587 case UD_PART_DESC : 588 ((struct part_desc *)tp)->pd_vdsn = vdsn++; 589 break; 590 case UD_LOG_VOL_DESC : 591 ((struct log_vol_desc *)tp)->lvd_vdsn = vdsn++; 592 break; 593 case UD_UNALL_SPA_DESC : 594 ((struct unall_spc_desc *)tp)->ua_vdsn = vdsn++; 595 break; 596 } 597 maketag(tp, tp); 598 /* 599 * Write at Reserve Volume Descriptor Sequence 600 */ 601 wtfs(blk2, sectorsize, buf); 602 } 603 604 static void 605 volseqinit() 606 { 607 struct tag *tp; 608 struct nsr_desc *nsp; 609 struct pri_vol_desc *pvdp; 610 struct iuvd_desc *iudp; 611 struct part_desc *pp; 612 struct phdr_desc *php; 613 struct log_vol_desc *lvp; 614 long_ad_t *lap; 615 struct pmap_typ1 *pmp; 616 struct unall_spc_desc *uap; 617 struct log_vol_int_desc *lvip; 618 struct term_desc *tdp; 619 struct anch_vol_desc_ptr *avp; 620 struct lvid_iu *lviup; 621 struct file_set_desc *fsp; 622 struct file_entry *fp; 623 struct icb_tag *icb; 624 struct short_ad *sap; 625 struct file_id *fip; 626 struct space_bmap_desc *sbp; 627 uint8_t *cp; 628 daddr_t nextblock, endblock; 629 int32_t volseq_sectors, nextlogblock, rootfelen, i; 630 uint32_t mvds_loc, rvds_loc; 631 632 bzero(buf, MAXBSIZE); 633 634 /* 635 * Starting from MAXBSIZE, clear out till 256 sectors. 636 */ 637 for (i = MAXBSIZE / sectorsize; i < FIRSTAVDP; i++) { 638 wtfs(i, sectorsize, buf); 639 } 640 641 /* Zero out the avdp at N - 257 */ 642 wtfs(fssize - 256, sectorsize, buf); 643 644 /* 645 * Leave 1st 32K for O.S. 646 */ 647 nextblock = VOLRECSTART / sectorsize; 648 649 /* 650 * Write BEA01/NSR02/TEA01 sequence. 651 * Each one must be 2K bytes in length. 652 */ 653 nsp = (struct nsr_desc *)buf; 654 nsp->nsr_str_type = 0; 655 nsp->nsr_ver = 1; 656 (void) strncpy((int8_t *)nsp->nsr_id, "BEA01", 5); 657 658 nsp = (struct nsr_desc *)&buf[2048]; 659 nsp->nsr_str_type = 0; 660 nsp->nsr_ver = 1; 661 (void) strncpy((int8_t *)nsp->nsr_id, "NSR02", 5); 662 663 nsp = (struct nsr_desc *)&buf[4096]; 664 nsp->nsr_str_type = 0; 665 nsp->nsr_ver = 1; 666 (void) strncpy((int8_t *)nsp->nsr_id, "TEA01", 5); 667 668 wtfs(nextblock, 8192, buf); 669 bzero(buf, MAXBSIZE); 670 671 /* 672 * Minimum length of volume sequences 673 */ 674 volseq_sectors = 16; 675 676 /* 677 * Round up to next 32K boundary for 678 * volume descriptor sequences 679 */ 680 nextblock = VOLSEQSTART; 681 bzero(buf, sectorsize); 682 mvds_loc = VOLSEQSTART; 683 rvds_loc = mvds_loc + volseq_sectors; 684 685 /* 686 * Primary Volume Descriptor 687 */ 688 /* LINTED */ 689 pvdp = (struct pri_vol_desc *)buf; 690 tp = &pvdp->pvd_tag; 691 tp->tag_id = UD_PRI_VOL_DESC; 692 tp->tag_desc_ver = ecma_version; 693 tp->tag_sno = serialnum; 694 tp->tag_crc_len = sizeof (struct pri_vol_desc) - 695 sizeof (struct tag); 696 pvdp->pvd_vdsn = 0; 697 pvdp->pvd_pvdn = 0; 698 setdstring(pvdp->pvd_vol_id, udfs_label, 32); 699 pvdp->pvd_vsn = 1; 700 pvdp->pvd_mvsn = 1; 701 pvdp->pvd_il = 2; /* Single-volume */ 702 pvdp->pvd_mil = 3; /* Multi-volume */ 703 pvdp->pvd_csl = 1; /* CS0 */ 704 pvdp->pvd_mcsl = 1; /* CS0 */ 705 (void) sprintf(vsibuf, "%08X", SWAP_32((uint32_t)mkfstime)); 706 setdstring(pvdp->pvd_vsi, vsibuf, 128); 707 (void) strncpy(pvdp->pvd_vsi + 17, udfs_label, 128 - 17); 708 setcharspec(&pvdp->pvd_desc_cs, 0, osta_unicode); 709 setcharspec(&pvdp->pvd_exp_cs, 0, osta_unicode); 710 setextad(&pvdp->pvd_vol_abs, 0, 0); 711 setextad(&pvdp->pvd_vcn, 0, 0); 712 bzero(&pvdp->pvd_appl_id, sizeof (regid_t)); 713 setstamp(&pvdp->pvd_time); 714 bcopy(&sunmicro, &pvdp->pvd_ii, sizeof (regid_t)); 715 pvdp->pvd_flags = 0; 716 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 717 nextblock++; 718 719 /* 720 * Implementation Use Descriptor 721 */ 722 bzero(buf, sectorsize); 723 /* LINTED */ 724 iudp = (struct iuvd_desc *)buf; 725 tp = &iudp->iuvd_tag; 726 tp->tag_id = UD_IMPL_USE_DESC; 727 tp->tag_desc_ver = ecma_version; 728 tp->tag_sno = serialnum; 729 tp->tag_crc_len = sizeof (struct iuvd_desc) - 730 sizeof (struct tag); 731 iudp->iuvd_vdsn = 0; 732 bcopy(&lvinfo, &iudp->iuvd_ii, sizeof (regid_t)); 733 setcharspec(&iudp->iuvd_cset, 0, osta_unicode); 734 setdstring(iudp->iuvd_lvi, udfs_label, 128); 735 736 setdstring(iudp->iuvd_ifo1, "", 36); 737 setdstring(iudp->iuvd_ifo2, "", 36); 738 setdstring(iudp->iuvd_ifo3, "", 36); 739 740 741 /* 742 * info1,2,3 = user specified 743 */ 744 bcopy(&sunmicro, &iudp->iuvd_iid, sizeof (regid_t)); 745 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 746 nextblock++; 747 748 /* 749 * Partition Descriptor 750 */ 751 bzero(buf, sectorsize); 752 /* LINTED */ 753 pp = (struct part_desc *)buf; 754 tp = &pp->pd_tag; 755 tp->tag_id = UD_PART_DESC; 756 tp->tag_desc_ver = ecma_version; 757 tp->tag_sno = serialnum; 758 tp->tag_crc_len = sizeof (struct part_desc) - 759 sizeof (struct tag); 760 pp->pd_vdsn = 0; 761 pp->pd_pflags = 1; /* Allocated */ 762 pp->pd_pnum = 0; 763 bcopy(&partid, &pp->pd_pcontents, sizeof (regid_t)); 764 765 part_start = FIRSTAVDP + AVDPLEN; 766 part_len = fssize - part_start; 767 part_bmp_bytes = (part_len + NBBY - 1) / NBBY; 768 part_bmp_sectors = (part_bmp_bytes + SPACEMAP_OFF + sectorsize - 1) / 769 sectorsize; 770 771 pp->pd_part_start = part_start; 772 pp->pd_part_length = part_len; 773 774 pp->pd_acc_type = acctype; 775 nextlogblock = 0; 776 777 /* 778 * Do the partition header 779 */ 780 /* LINTED */ 781 php = (struct phdr_desc *)&pp->pd_pc_use; 782 783 /* 784 * Set up unallocated space bitmap 785 */ 786 if (acctype == PART_ACC_RW || acctype == PART_ACC_OW) { 787 php->phdr_usb.sad_ext_len = 788 (part_bmp_bytes + SPACEMAP_OFF + sectorsize - 1) & 789 (~(sectorsize - 1)); 790 php->phdr_usb.sad_ext_loc = nextlogblock; 791 part_unalloc = nextlogblock; 792 nextlogblock += part_bmp_sectors; 793 } 794 795 bcopy(&sunmicro, &pp->pd_ii, sizeof (regid_t)); 796 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 797 nextblock++; 798 799 /* 800 * Logical Volume Descriptor 801 */ 802 bzero(buf, sectorsize); 803 /* LINTED */ 804 lvp = (struct log_vol_desc *)buf; 805 tp = &lvp->lvd_tag; 806 tp->tag_id = UD_LOG_VOL_DESC; 807 tp->tag_desc_ver = ecma_version; 808 tp->tag_sno = serialnum; 809 tp->tag_crc_len = sizeof (struct log_vol_desc) - 810 sizeof (struct tag); 811 lvp->lvd_vdsn = 0; 812 setcharspec(&lvp->lvd_desc_cs, 0, osta_unicode); 813 setdstring(lvp->lvd_lvid, udfs_label, 128); 814 lvp->lvd_log_bsize = sectorsize; 815 bcopy(&udf_compliant, &lvp->lvd_dom_id, sizeof (regid_t)); 816 lap = (long_ad_t *)&lvp->lvd_lvcu; 817 lap->lad_ext_len = FILESETLEN * sectorsize; 818 filesetblock = nextlogblock; 819 lap->lad_ext_loc = nextlogblock; 820 lap->lad_ext_prn = 0; 821 lvp->lvd_mtbl_len = 6; 822 lvp->lvd_num_pmaps = 1; 823 bcopy(&sunmicro, &lvp->lvd_ii, sizeof (regid_t)); 824 /* LINTED */ 825 pmp = (struct pmap_typ1 *)&lvp->lvd_pmaps; 826 pmp->map1_type = 1; 827 pmp->map1_length = 6; 828 pmp->map1_vsn = SWAP_16(1); 829 pmp->map1_pn = 0; 830 tp->tag_crc_len = (char *)(pmp + 1) - buf - sizeof (struct tag); 831 setextad(&lvp->lvd_int_seq_ext, INTSEQLEN, INTSEQSTART); 832 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 833 nextblock++; 834 835 /* 836 * Unallocated Space Descriptor 837 */ 838 bzero(buf, sectorsize); 839 /* LINTED */ 840 uap = (struct unall_spc_desc *)buf; 841 tp = &uap->ua_tag; 842 tp->tag_id = UD_UNALL_SPA_DESC; 843 tp->tag_desc_ver = ecma_version; 844 tp->tag_sno = serialnum; 845 uap->ua_vdsn = 0; 846 uap->ua_nad = 0; 847 tp->tag_crc_len = (char *)uap->ua_al_dsc - buf - sizeof (struct tag); 848 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 849 nextblock++; 850 851 /* 852 * Terminating Descriptor 853 */ 854 bzero(buf, sectorsize); 855 /* LINTED */ 856 tdp = (struct term_desc *)buf; 857 tp = &tdp->td_tag; 858 tp->tag_id = UD_TERM_DESC; 859 tp->tag_desc_ver = ecma_version; 860 tp->tag_sno = serialnum; 861 tp->tag_crc_len = sizeof (struct term_desc) - 862 sizeof (struct tag); 863 tp->tag_loc = nextblock; 864 wtvolseq(tp, nextblock, nextblock + volseq_sectors); 865 nextblock++; 866 867 /* 868 * Do the anchor volume descriptor 869 */ 870 if (nextblock > FIRSTAVDP) { 871 (void) fprintf(stdout, 872 gettext("Volume integrity sequence" 873 " descriptors too long\n")); 874 exit(32); 875 } 876 877 nextblock = FIRSTAVDP; 878 bzero(buf, sectorsize); 879 /* LINTED */ 880 avp = (struct anch_vol_desc_ptr *)buf; 881 tp = &avp->avd_tag; 882 tp->tag_id = UD_ANCH_VOL_DESC; 883 tp->tag_desc_ver = ecma_version; 884 tp->tag_sno = serialnum; 885 tp->tag_crc_len = sizeof (struct anch_vol_desc_ptr) - 886 sizeof (struct tag); 887 tp->tag_loc = nextblock; 888 setextad(&avp->avd_main_vdse, 889 volseq_sectors * sectorsize, mvds_loc); 890 setextad(&avp->avd_res_vdse, 891 volseq_sectors * sectorsize, rvds_loc); 892 bzero(buf2, sectorsize); 893 /* LINTED */ 894 maketag(tp, (struct tag *)buf2); 895 wtfs(nextblock, sectorsize, buf2); 896 nextblock++; 897 898 tp->tag_loc = fssize; 899 /* LINTED */ 900 maketag(tp, (struct tag *)buf2); 901 wtfs(fssize, sectorsize, buf2); 902 903 /* 904 * File Set Descriptor 905 */ 906 bzero(buf, sectorsize); 907 /* LINTED */ 908 fsp = (struct file_set_desc *)&buf; 909 tp = &fsp->fsd_tag; 910 tp->tag_id = UD_FILE_SET_DESC; 911 tp->tag_desc_ver = ecma_version; 912 tp->tag_sno = serialnum; 913 tp->tag_crc_len = sizeof (struct file_set_desc) - 914 sizeof (struct tag); 915 tp->tag_loc = nextlogblock; 916 setstamp(&fsp->fsd_time); 917 fsp->fsd_ilevel = 3; 918 fsp->fsd_mi_level = 3; 919 fsp->fsd_cs_list = 1; 920 fsp->fsd_mcs_list = 1; 921 fsp->fsd_fs_no = 0; 922 fsp->fsd_fsd_no = 0; 923 setcharspec(&fsp->fsd_lvidcs, 0, osta_unicode); 924 setdstring(fsp->fsd_lvid, udfs_label, 128); 925 setcharspec(&fsp->fsd_fscs, 0, osta_unicode); 926 setdstring(fsp->fsd_fsi, udfs_label, 32); 927 setdstring(fsp->fsd_cfi, "", 32); 928 setdstring(fsp->fsd_afi, "", 32); 929 lap = (long_ad_t *)&fsp->fsd_root_icb; 930 lap->lad_ext_len = sectorsize; 931 lap->lad_ext_loc = filesetblock + FILESETLEN; 932 lap->lad_ext_prn = 0; 933 bcopy(&udf_compliant, &fsp->fsd_did, sizeof (regid_t)); 934 maketag(tp, tp); 935 wtfs(nextlogblock + part_start, sectorsize, (char *)tp); 936 nextlogblock++; 937 938 /* 939 * Terminating Descriptor 940 */ 941 bzero(buf, sectorsize); 942 /* LINTED */ 943 tdp = (struct term_desc *)buf; 944 tp = &tdp->td_tag; 945 tp->tag_id = UD_TERM_DESC; 946 tp->tag_desc_ver = ecma_version; 947 tp->tag_sno = serialnum; 948 tp->tag_crc_len = sizeof (struct term_desc) - 949 sizeof (struct tag); 950 tp->tag_loc = nextlogblock; 951 maketag(tp, tp); 952 wtfs(nextlogblock + part_start, sectorsize, (char *)tp); 953 nextlogblock++; 954 955 if (nextlogblock > filesetblock + FILESETLEN) { 956 (void) fprintf(stdout, 957 gettext("File set descriptor too long\n")); 958 exit(32); 959 } 960 nextlogblock = filesetblock + FILESETLEN; 961 962 /* 963 * Root File Entry 964 */ 965 bzero(buf, sectorsize); 966 /* LINTED */ 967 fp = (struct file_entry *)&buf; 968 tp = &fp->fe_tag; 969 tp->tag_id = UD_FILE_ENTRY; 970 tp->tag_desc_ver = ecma_version; 971 tp->tag_sno = serialnum; 972 tp->tag_loc = nextlogblock; 973 icb = &fp->fe_icb_tag; 974 icb->itag_prnde = 0; 975 icb->itag_strategy = STRAT_TYPE4; 976 icb->itag_param = 0; /* what does this mean? */ 977 icb->itag_max_ent = 1; 978 icb->itag_ftype = FTYPE_DIRECTORY; 979 icb->itag_lb_loc = 0; 980 icb->itag_lb_prn = 0; 981 icb->itag_flags = ICB_FLAG_ARCHIVE; 982 fp->fe_uid = getuid(); 983 fp->fe_gid = getgid(); 984 fp->fe_perms = (0x1f << 10) | (0x5 << 5) | 0x5; 985 fp->fe_lcount = 1; 986 fp->fe_rec_for = 0; 987 fp->fe_rec_dis = 0; 988 fp->fe_rec_len = 0; 989 fp->fe_info_len = sizeof (struct file_id); 990 fp->fe_lbr = 1; 991 setstamp(&fp->fe_acc_time); 992 setstamp(&fp->fe_mod_time); 993 setstamp(&fp->fe_attr_time); 994 fp->fe_ckpoint = 1; 995 bcopy(&sunmicro, &fp->fe_impl_id, sizeof (regid_t)); 996 fp->fe_uniq_id = 0; 997 fp->fe_len_ear = 0; 998 fp->fe_len_adesc = sizeof (short_ad_t); 999 1000 /* LINTED */ 1001 sap = (short_ad_t *)(fp->fe_spec + fp->fe_len_ear); 1002 sap->sad_ext_len = sizeof (struct file_id); 1003 sap->sad_ext_loc = nextlogblock + 1; 1004 rootfelen = (char *)(sap + 1) - buf; 1005 tp->tag_crc_len = rootfelen - sizeof (struct tag); 1006 maketag(tp, tp); 1007 wtfs(nextlogblock + part_start, sectorsize, (char *)tp); 1008 nextlogblock++; 1009 1010 /* 1011 * Root Directory 1012 */ 1013 bzero(buf, sectorsize); 1014 /* LINTED */ 1015 fip = (struct file_id *)&buf; 1016 tp = &fip->fid_tag; 1017 tp->tag_id = UD_FILE_ID_DESC; 1018 tp->tag_desc_ver = ecma_version; 1019 tp->tag_sno = serialnum; 1020 tp->tag_crc_len = sizeof (struct file_id) - 1021 sizeof (struct tag); 1022 tp->tag_loc = nextlogblock; 1023 fip->fid_ver = 1; 1024 fip->fid_flags = FID_DIR | FID_PARENT; 1025 fip->fid_idlen = 0; 1026 fip->fid_iulen = 0; 1027 fip->fid_icb.lad_ext_len = sectorsize; /* rootfelen; */ 1028 fip->fid_icb.lad_ext_loc = nextlogblock - 1; 1029 fip->fid_icb.lad_ext_prn = 0; 1030 maketag(tp, tp); 1031 wtfs(nextlogblock + part_start, sectorsize, (char *)tp); 1032 nextlogblock++; 1033 1034 /* 1035 * Now do the space bitmaps 1036 */ 1037 if (part_unalloc >= 0) { 1038 int size = sectorsize * part_bmp_sectors; 1039 1040 sbp = (struct space_bmap_desc *)malloc(size); 1041 if (!sbp) { 1042 (void) fprintf(stdout, 1043 gettext("Can't allocate bitmap space\n")); 1044 exit(32); 1045 } 1046 bzero((char *)sbp, sectorsize * part_bmp_sectors); 1047 tp = &sbp->sbd_tag; 1048 tp->tag_id = UD_SPA_BMAP_DESC; 1049 tp->tag_desc_ver = ecma_version; 1050 tp->tag_sno = serialnum; 1051 tp->tag_crc_len = 0; /* Don't do CRCs on bitmaps */ 1052 tp->tag_loc = part_unalloc; 1053 sbp->sbd_nbits = part_len; 1054 sbp->sbd_nbytes = part_bmp_bytes; 1055 maketag(tp, tp); 1056 if (part_unalloc >= 0) { 1057 int32_t i; 1058 1059 cp = (uint8_t *)sbp + SPACEMAP_OFF; 1060 i = nextlogblock / NBBY; 1061 cp[i++] = (0xff << (nextlogblock % NBBY)) & 0xff; 1062 while (i < part_bmp_bytes) 1063 cp[i++] = 0xff; 1064 if (part_len % NBBY) 1065 cp[--i] = (unsigned)0xff >> 1066 (NBBY - part_len % NBBY); 1067 1068 wtfs(part_unalloc + part_start, size, (char *)tp); 1069 } 1070 free((char *)sbp); 1071 } 1072 1073 /* 1074 * Volume Integrity Descriptor 1075 */ 1076 nextblock = INTSEQSTART; 1077 endblock = nextblock + INTSEQLEN / sectorsize; 1078 /* LINTED */ 1079 lvip = (struct log_vol_int_desc *)&lvid; 1080 tp = &lvip->lvid_tag; 1081 tp->tag_id = UD_LOG_VOL_INT; 1082 tp->tag_desc_ver = ecma_version; 1083 tp->tag_sno = serialnum; 1084 tp->tag_loc = nextblock; 1085 setstamp(&lvip->lvid_tstamp); 1086 lvip->lvid_int_type = LOG_VOL_CLOSE_INT; 1087 setextad(&lvip->lvid_nie, 0, 0); 1088 lvip->lvid_npart = 1; 1089 lvip->lvid_liu = 0x2e; 1090 lvip->lvid_uniqid = MAXID + 1; 1091 lvip->lvid_fst[0] = part_len - nextlogblock; /* Free space */ 1092 lvip->lvid_fst[1] = part_len; /* Size */ 1093 lviup = (struct lvid_iu *)&lvip->lvid_fst[2]; 1094 bcopy(&sunmicro, &lviup->lvidiu_regid, sizeof (regid_t)); 1095 lviup->lvidiu_nfiles = 0; 1096 lviup->lvidiu_ndirs = 1; 1097 lviup->lvidiu_mread = 0x102; 1098 lviup->lvidiu_mwrite = 0x102; 1099 lviup->lvidiu_maxwr = 0x150; 1100 tp->tag_crc_len = sizeof (struct log_vol_int_desc) + lvip->lvid_liu - 1101 sizeof (struct tag); 1102 maketag(tp, tp); 1103 wtfs(nextblock, sectorsize, (char *)tp); 1104 nextblock++; 1105 1106 /* 1107 * Terminating Descriptor 1108 */ 1109 bzero(buf, sectorsize); 1110 /* LINTED */ 1111 tdp = (struct term_desc *)buf; 1112 tp = &tdp->td_tag; 1113 tp->tag_id = UD_TERM_DESC; 1114 tp->tag_desc_ver = ecma_version; 1115 tp->tag_sno = serialnum; 1116 tp->tag_crc_len = sizeof (struct term_desc) - sizeof (struct tag); 1117 tp->tag_loc = nextblock; 1118 maketag(tp, tp); 1119 wtfs(nextblock, sectorsize, (char *)tp); 1120 nextblock++; 1121 1122 /* Zero out the rest of the LVI extent */ 1123 bzero(buf, sectorsize); 1124 while (nextblock < endblock) 1125 wtfs(nextblock++, sectorsize, buf); 1126 } 1127 1128 /* 1129 * read a block from the file system 1130 */ 1131 static void 1132 rdfs(daddr_t bno, int size, char *bf) 1133 { 1134 int n, saverr; 1135 1136 if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) { 1137 saverr = errno; 1138 (void) fprintf(stderr, 1139 gettext("seek error on sector %ld: %s\n"), 1140 bno, strerror(saverr)); 1141 exit(32); 1142 } 1143 n = read(fsi, bf, size); 1144 if (n != size) { 1145 saverr = errno; 1146 (void) fprintf(stderr, 1147 gettext("read error on sector %ld: %s\n"), 1148 bno, strerror(saverr)); 1149 exit(32); 1150 } 1151 } 1152 1153 /* 1154 * write a block to the file system 1155 */ 1156 static void 1157 wtfs(daddr_t bno, int size, char *bf) 1158 { 1159 int n, saverr; 1160 1161 if (fso == -1) 1162 return; 1163 1164 if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) { 1165 saverr = errno; 1166 (void) fprintf(stderr, 1167 gettext("seek error on sector %ld: %s\n"), 1168 bno, strerror(saverr)); 1169 exit(32); 1170 } 1171 if (Nflag) 1172 return; 1173 n = write(fso, bf, size); 1174 if (n != size) { 1175 saverr = errno; 1176 (void) fprintf(stderr, 1177 gettext("write error on sector %ld: %s\n"), 1178 bno, strerror(saverr)); 1179 exit(32); 1180 } 1181 } 1182 1183 static void 1184 usage() 1185 { 1186 (void) fprintf(stderr, 1187 gettext("udfs usage: mkfs [-F FSType] [-V]" 1188 " [-m] [-o options] special size(sectors)\n")); 1189 (void) fprintf(stderr, 1190 gettext(" -m : dump fs cmd line used to make" 1191 " this partition\n")); 1192 (void) fprintf(stderr, 1193 gettext(" -V : print this command line and return\n")); 1194 (void) fprintf(stderr, 1195 gettext(" -o : udfs options: :psize=%d:label=%s\n"), 1196 sectorsize, udfs_label); 1197 (void) fprintf(stderr, 1198 gettext("NOTE that all -o suboptions: must" 1199 " be separated only by commas so as to\n")); 1200 (void) fprintf(stderr, 1201 gettext("be parsed as a single argument\n")); 1202 exit(32); 1203 } 1204 1205 /*ARGSUSED*/ 1206 static void 1207 dump_fscmd(char *fsys, int fsi) 1208 { 1209 (void) printf(gettext("mkfs -F udfs -o ")); 1210 (void) printf("psize=%d,label=\"%s\" %s %d\n", 1211 sectorsize, oldlabel, fsys, oldfssize); 1212 } 1213 1214 /* number ************************************************************* */ 1215 /* */ 1216 /* Convert a numeric arg to binary */ 1217 /* */ 1218 /* Arg: big - maximum valid input number */ 1219 /* Global arg: string - pointer to command arg */ 1220 /* */ 1221 /* Valid forms: 123 | 123k | 123*123 | 123x123 */ 1222 /* */ 1223 /* Return: converted number */ 1224 /* */ 1225 /* ******************************************************************** */ 1226 1227 static int32_t 1228 number(long big, char *param) 1229 { 1230 char *cs; 1231 int64_t n = 0; 1232 int64_t cut = BIG; 1233 int32_t minus = 0; 1234 1235 #define FOUND_MULT 0x1 1236 #define FOUND_K 0x2 1237 1238 cs = string; 1239 if (*cs == '-') { 1240 minus = 1; 1241 cs++; 1242 } 1243 n = 0; 1244 while ((*cs != ' ') && (*cs != '\0') && (*cs != ',')) { 1245 if ((*cs >= '0') && (*cs <= '9')) { 1246 n = n * 10 + *cs - '0'; 1247 cs++; 1248 } else if ((*cs == '*') || (*cs == 'x')) { 1249 if (number_flags & FOUND_MULT) { 1250 (void) fprintf(stderr, 1251 gettext("mkfs: only one \"*\" " 1252 "or \"x\" allowed\n")); 1253 exit(2); 1254 } 1255 number_flags |= FOUND_MULT; 1256 cs++; 1257 string = cs; 1258 n = n * number(big, param); 1259 cs = string; 1260 continue; 1261 } else if (*cs == 'k') { 1262 if (number_flags & FOUND_K) { 1263 (void) fprintf(stderr, 1264 gettext("mkfs: only one \"k\" allowed\n")); 1265 exit(2); 1266 } 1267 number_flags |= FOUND_K; 1268 n = n * 1024; 1269 cs++; 1270 continue; 1271 } else { 1272 (void) fprintf(stderr, 1273 gettext("mkfs: bad numeric arg: \"%s\"\n"), 1274 string); 1275 exit(2); 1276 } 1277 } 1278 1279 if (n > cut) { 1280 (void) fprintf(stderr, 1281 gettext("mkfs: value for %s overflowed\n"), param); 1282 exit(2); 1283 } 1284 1285 if (minus) { 1286 n = -n; 1287 } 1288 1289 if ((n > big) || (n < 0)) { 1290 (void) fprintf(stderr, 1291 gettext("mkfs: argument %s out of range\n"), param); 1292 exit(2); 1293 } 1294 1295 string = cs; 1296 return ((int32_t)n); 1297 } 1298 1299 /* match ************************************************************** */ 1300 /* */ 1301 /* Compare two text strings for equality */ 1302 /* */ 1303 /* Arg: s - pointer to string to match with a command arg */ 1304 /* Global arg: string - pointer to command arg */ 1305 /* */ 1306 /* Return: 1 if match, 0 if no match */ 1307 /* If match, also reset `string' to point to the text */ 1308 /* that follows the matching text. */ 1309 /* */ 1310 /* ******************************************************************** */ 1311 1312 static int 1313 match(char *s) 1314 { 1315 char *cs; 1316 1317 cs = string; 1318 while (*cs++ == *s) { 1319 if (*s++ == '\0') { 1320 goto true; 1321 } 1322 } 1323 if (*s != '\0') { 1324 return (0); 1325 } 1326 1327 true: 1328 cs--; 1329 string = cs; 1330 return (1); 1331 } 1332 1333 static uint32_t 1334 get_bsize() 1335 { 1336 struct dk_cinfo info; 1337 struct fd_char fd_char; 1338 struct dk_minfo dkminfo; 1339 1340 if (ioctl(fso, DKIOCINFO, &info) < 0) { 1341 perror("mkfs DKIOCINFO "); 1342 (void) fprintf(stdout, 1343 gettext("DKIOCINFO failed using psize = 2048" 1344 " for creating file-system\n")); 1345 return (0); 1346 } 1347 1348 switch (info.dki_ctype) { 1349 case DKC_CDROM : 1350 return (2048); 1351 case DKC_SCSI_CCS : 1352 if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) { 1353 if (dkminfo.dki_lbsize != 0 && 1354 POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) && 1355 dkminfo.dki_lbsize != DEV_BSIZE) { 1356 fprintf(stderr, 1357 gettext("The device sector size " 1358 "%u is not supported by udfs!\n"), 1359 dkminfo.dki_lbsize); 1360 (void) close(fso); 1361 exit(1); 1362 } 1363 } 1364 /* FALLTHROUGH */ 1365 case DKC_INTEL82072 : 1366 /* FALLTHROUGH */ 1367 case DKC_INTEL82077 : 1368 /* FALLTHROUGH */ 1369 case DKC_DIRECT : 1370 if (ioctl(fso, FDIOGCHAR, &fd_char) >= 0) { 1371 return (fd_char.fdc_sec_size); 1372 } 1373 /* FALLTHROUGH */ 1374 case DKC_PCMCIA_ATA : 1375 return (512); 1376 default : 1377 return (0); 1378 } 1379 } 1380 1381 /* 1382 * Read in the volume sequences descriptors. 1383 */ 1384 static int 1385 readvolseq() 1386 { 1387 struct tag *tp; 1388 uint8_t *cp, *end; 1389 int err; 1390 struct pri_vol_desc *pvolp; 1391 struct part_desc *partp; 1392 struct log_vol_desc *logvp; 1393 struct anch_vol_desc_ptr *avp; 1394 char *main_vdbuf; 1395 uint32_t nextblock; 1396 1397 avp = (struct anch_vol_desc_ptr *)malloc(sectorsize); 1398 rdfs(FIRSTAVDP, sectorsize, (char *)avp); 1399 tp = (struct tag *)avp; 1400 err = verifytag(tp, FIRSTAVDP, tp, UD_ANCH_VOL_DESC); 1401 if (err) 1402 return (0); 1403 main_vdbuf = malloc(avp->avd_main_vdse.ext_len); 1404 if (main_vdbuf == NULL) { 1405 (void) fprintf(stderr, gettext("Cannot allocate space for " 1406 "volume sequences\n")); 1407 exit(32); 1408 } 1409 rdfs(avp->avd_main_vdse.ext_loc, avp->avd_main_vdse.ext_len, 1410 main_vdbuf); 1411 end = (uint8_t *)main_vdbuf + avp->avd_main_vdse.ext_len; 1412 1413 nextblock = avp->avd_main_vdse.ext_loc; 1414 for (cp = (uint8_t *)main_vdbuf; cp < end; cp += sectorsize, 1415 nextblock++) { 1416 /* LINTED */ 1417 tp = (struct tag *)cp; 1418 err = verifytag(tp, nextblock, tp, 0); 1419 if (err) 1420 continue; 1421 1422 switch (tp->tag_id) { 1423 case UD_PRI_VOL_DESC: 1424 /* Bump serial number, according to spec. */ 1425 serialnum = tp->tag_sno + 1; 1426 pvolp = (struct pri_vol_desc *)tp; 1427 oldlabel = pvolp->pvd_vol_id + 1; 1428 break; 1429 case UD_ANCH_VOL_DESC: 1430 avp = (struct anch_vol_desc_ptr *)tp; 1431 break; 1432 case UD_VOL_DESC_PTR: 1433 break; 1434 case UD_IMPL_USE_DESC: 1435 break; 1436 case UD_PART_DESC: 1437 partp = (struct part_desc *)tp; 1438 part_start = partp->pd_part_start; 1439 part_len = partp->pd_part_length; 1440 oldfssize = part_start + part_len; 1441 break; 1442 case UD_LOG_VOL_DESC: 1443 logvp = (struct log_vol_desc *)tp; 1444 break; 1445 case UD_UNALL_SPA_DESC: 1446 break; 1447 case UD_TERM_DESC: 1448 goto done; 1449 break; 1450 case UD_LOG_VOL_INT: 1451 break; 1452 default: 1453 break; 1454 } 1455 } 1456 done: 1457 if (!partp || !logvp) { 1458 return (0); 1459 } 1460 return (1); 1461 } 1462 1463 uint32_t 1464 get_last_block() 1465 { 1466 struct vtoc vtoc; 1467 struct dk_cinfo dki_info; 1468 1469 if (ioctl(fsi, DKIOCGVTOC, (intptr_t)&vtoc) != 0) { 1470 (void) fprintf(stderr, gettext("Unable to read VTOC\n")); 1471 return (0); 1472 } 1473 1474 if (vtoc.v_sanity != VTOC_SANE) { 1475 (void) fprintf(stderr, gettext("Vtoc.v_sanity != VTOC_SANE\n")); 1476 return (0); 1477 } 1478 1479 if (ioctl(fsi, DKIOCINFO, (intptr_t)&dki_info) != 0) { 1480 (void) fprintf(stderr, 1481 gettext("Could not get the slice information\n")); 1482 return (0); 1483 } 1484 1485 if (dki_info.dki_partition > V_NUMPAR) { 1486 (void) fprintf(stderr, 1487 gettext("dki_info.dki_partition > V_NUMPAR\n")); 1488 return (0); 1489 } 1490 1491 return ((uint32_t)vtoc.v_part[dki_info.dki_partition].p_size); 1492 } 1493