1 /* $NetBSD: udf_write.c,v 1.8 2013/08/25 14:13:47 reinoud Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 #if HAVE_NBTOOL_CONFIG_H 29 #include "nbtool_config.h" 30 #endif 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: udf_write.c,v 1.8 2013/08/25 14:13:47 reinoud Exp $"); 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <errno.h> 39 #include <time.h> 40 #include <assert.h> 41 #include <err.h> 42 #include <sys/types.h> 43 #include <sys/param.h> 44 45 #if !HAVE_NBTOOL_CONFIG_H 46 #define _EXPOSE_MMC 47 #include <sys/cdio.h> 48 #else 49 #include "udf/cdio_mmc_structs.h" 50 #endif 51 52 #include "udf_create.h" 53 #include "udf_write.h" 54 #include "newfs_udf.h" 55 56 57 union dscrptr *terminator_dscr; 58 59 static int 60 udf_write_phys(void *blob, uint32_t location, uint32_t sects) 61 { 62 uint32_t phys, cnt; 63 uint8_t *bpos; 64 int error; 65 66 for (cnt = 0; cnt < sects; cnt++) { 67 bpos = (uint8_t *) blob; 68 bpos += context.sector_size * cnt; 69 70 phys = location + cnt; 71 error = udf_write_sector(bpos, phys); 72 if (error) 73 return error; 74 } 75 return 0; 76 } 77 78 79 static int 80 udf_write_dscr_phys(union dscrptr *dscr, uint32_t location, 81 uint32_t sects) 82 { 83 dscr->tag.tag_loc = udf_rw32(location); 84 (void) udf_validate_tag_and_crc_sums(dscr); 85 86 return udf_write_phys(dscr, location, sects); 87 } 88 89 90 int 91 udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint32_t vpart, 92 uint32_t sects) 93 { 94 struct file_entry *fe; 95 struct extfile_entry *efe; 96 struct extattrhdr_desc *extattrhdr; 97 uint32_t phys; 98 99 extattrhdr = NULL; 100 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 101 fe = (struct file_entry *) dscr; 102 if (udf_rw32(fe->l_ea) > 0) 103 extattrhdr = (struct extattrhdr_desc *) fe->data; 104 } 105 if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 106 efe = (struct extfile_entry *) dscr; 107 if (udf_rw32(efe->l_ea) > 0) 108 extattrhdr = (struct extattrhdr_desc *) efe->data; 109 } 110 if (extattrhdr) { 111 extattrhdr->tag.tag_loc = udf_rw32(location); 112 udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr); 113 } 114 115 dscr->tag.tag_loc = udf_rw32(location); 116 udf_validate_tag_and_crc_sums(dscr); 117 118 /* determine physical location */ 119 phys = context.vtop_offset[vpart]; 120 if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) { 121 udf_vat_update(location, context.data_alloc_pos); 122 phys += context.data_alloc_pos++; 123 } else { 124 phys += location; 125 } 126 127 return udf_write_phys(dscr, phys, sects); 128 } 129 130 131 void 132 udf_metadata_alloc(int nblk, struct long_ad *pos) 133 { 134 memset(pos, 0, sizeof(*pos)); 135 pos->len = udf_rw32(nblk * context.sector_size); 136 pos->loc.lb_num = udf_rw32(context.metadata_alloc_pos); 137 pos->loc.part_num = udf_rw16(context.metadata_part); 138 139 udf_mark_allocated(context.metadata_alloc_pos, context.metadata_part, 140 nblk); 141 142 context.metadata_alloc_pos += nblk; 143 if (context.metadata_part == context.data_part) 144 context.data_alloc_pos = context.metadata_alloc_pos; 145 } 146 147 148 void 149 udf_data_alloc(int nblk, struct long_ad *pos) 150 { 151 memset(pos, 0, sizeof(*pos)); 152 pos->len = udf_rw32(nblk * context.sector_size); 153 pos->loc.lb_num = udf_rw32(context.data_alloc_pos); 154 pos->loc.part_num = udf_rw16(context.data_part); 155 156 udf_mark_allocated(context.data_alloc_pos, context.data_part, nblk); 157 context.data_alloc_pos += nblk; 158 if (context.metadata_part == context.data_part) 159 context.metadata_alloc_pos = context.data_alloc_pos; 160 } 161 162 163 164 /* --------------------------------------------------------------------- */ 165 166 /* 167 * udf_derive_format derives the format_flags from the disc's mmc_discinfo. 168 * The resulting flags uniquely define a disc format. Note there are at least 169 * 7 distinct format types defined in UDF. 170 */ 171 172 #define UDF_VERSION(a) \ 173 (((a) == 0x100) || ((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \ 174 ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260)) 175 176 int 177 udf_derive_format(int req_enable, int req_disable, int force) 178 { 179 /* disc writability, formatted, appendable */ 180 if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) { 181 (void)printf("Can't newfs readonly device\n"); 182 return EROFS; 183 } 184 if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 185 /* sequentials need sessions appended */ 186 if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) { 187 (void)printf("Can't append session to a closed disc\n"); 188 return EROFS; 189 } 190 if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) && !force) { 191 (void)printf("Disc not empty! Use -F to force " 192 "initialisation\n"); 193 return EROFS; 194 } 195 } else { 196 /* check if disc (being) formatted or has been started on */ 197 if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) { 198 (void)printf("Disc is not formatted\n"); 199 return EROFS; 200 } 201 } 202 203 /* determine UDF format */ 204 format_flags = 0; 205 if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) { 206 /* all rewritable media */ 207 format_flags |= FORMAT_REWRITABLE; 208 if (context.min_udf >= 0x0250) { 209 /* standard dictates meta as default */ 210 format_flags |= FORMAT_META; 211 } 212 213 if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) { 214 /* sparables for defect management */ 215 if (context.min_udf >= 0x150) 216 format_flags |= FORMAT_SPARABLE; 217 } 218 } else { 219 /* all once recordable media */ 220 format_flags |= FORMAT_WRITEONCE; 221 if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) { 222 format_flags |= FORMAT_SEQUENTIAL; 223 224 if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) { 225 /* logical overwritable */ 226 format_flags |= FORMAT_LOW; 227 } else { 228 /* have to use VAT for overwriting */ 229 format_flags |= FORMAT_VAT; 230 } 231 } else { 232 /* rare WORM devices, but BluRay has one, strat4096 */ 233 format_flags |= FORMAT_WORM; 234 } 235 } 236 237 /* enable/disable requests */ 238 if (req_disable & FORMAT_META) { 239 format_flags &= ~(FORMAT_META | FORMAT_LOW); 240 req_disable &= ~FORMAT_META; 241 } 242 if ((format_flags & FORMAT_VAT) & UDF_512_TRACK) 243 format_flags |= FORMAT_TRACK512; 244 245 if (req_enable & FORMAT_READONLY) { 246 format_flags |= FORMAT_READONLY; 247 } 248 249 /* determine partition/media access type */ 250 media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED; 251 if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) { 252 media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE; 253 if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE) 254 media_accesstype = UDF_ACCESSTYPE_REWRITEABLE; 255 } else { 256 /* all once recordable media */ 257 media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE; 258 } 259 if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) 260 media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE; 261 262 /* patch up media accesstype */ 263 if (req_enable & FORMAT_READONLY) { 264 /* better now */ 265 media_accesstype = UDF_ACCESSTYPE_READ_ONLY; 266 } 267 268 /* adjust minimum version limits */ 269 if (format_flags & FORMAT_VAT) 270 context.min_udf = MAX(context.min_udf, 0x0150); 271 if (format_flags & FORMAT_SPARABLE) 272 context.min_udf = MAX(context.min_udf, 0x0150); 273 if (format_flags & FORMAT_META) 274 context.min_udf = MAX(context.min_udf, 0x0250); 275 if (format_flags & FORMAT_LOW) 276 context.min_udf = MAX(context.min_udf, 0x0260); 277 278 /* adjust maximum version limits not to tease or break things */ 279 if (!(format_flags & (FORMAT_META | FORMAT_LOW)) && 280 (context.max_udf > 0x200)) 281 context.max_udf = 0x201; 282 283 if ((format_flags & (FORMAT_VAT | FORMAT_SPARABLE)) == 0) 284 if (context.max_udf <= 0x150) 285 context.min_udf = 0x102; 286 287 /* limit Ecma 167 descriptor if possible/needed */ 288 context.dscrver = 3; 289 if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) { 290 context.dscrver = 2; 291 context.max_udf = 0x150; /* last version < 0x200 */ 292 } 293 294 /* is it possible ? */ 295 if (context.min_udf > context.max_udf) { 296 (void)printf("Initialisation prohibited by specified maximum " 297 "UDF version 0x%04x. Minimum version required 0x%04x\n", 298 context.max_udf, context.min_udf); 299 return EPERM; 300 } 301 302 if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) { 303 printf("Choose UDF version numbers from " 304 "0x102, 0x150, 0x200, 0x201, 0x250 and 0x260\n"); 305 printf("Default version is 0x201\n"); 306 return EPERM; 307 } 308 309 return 0; 310 } 311 312 #undef UDF_VERSION 313 314 315 /* --------------------------------------------------------------------- */ 316 317 int 318 udf_proces_names(void) 319 { 320 uint32_t primary_nr; 321 uint64_t volset_nr; 322 323 if (context.logvol_name == NULL) 324 context.logvol_name = strdup("anonymous"); 325 if (context.primary_name == NULL) { 326 if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) { 327 primary_nr = mmc_discinfo.disc_id; 328 } else { 329 primary_nr = (uint32_t) random(); 330 } 331 context.primary_name = calloc(32, 1); 332 sprintf(context.primary_name, "%08"PRIx32, primary_nr); 333 } 334 if (context.volset_name == NULL) { 335 if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) { 336 volset_nr = mmc_discinfo.disc_barcode; 337 } else { 338 volset_nr = (uint32_t) random(); 339 volset_nr |= ((uint64_t) random()) << 32; 340 } 341 context.volset_name = calloc(128,1); 342 sprintf(context.volset_name, "%016"PRIx64, volset_nr); 343 } 344 if (context.fileset_name == NULL) 345 context.fileset_name = strdup("anonymous"); 346 347 /* check passed/created identifiers */ 348 if (strlen(context.logvol_name) > 128) { 349 (void)printf("Logical volume name too long\n"); 350 return EINVAL; 351 } 352 if (strlen(context.primary_name) > 32) { 353 (void)printf("Primary volume name too long\n"); 354 return EINVAL; 355 } 356 if (strlen(context.volset_name) > 128) { 357 (void)printf("Volume set name too long\n"); 358 return EINVAL; 359 } 360 if (strlen(context.fileset_name) > 32) { 361 (void)printf("Fileset name too long\n"); 362 return EINVAL; 363 } 364 365 /* signal all OK */ 366 return 0; 367 } 368 369 /* --------------------------------------------------------------------- */ 370 371 static int 372 udf_write_iso9660_vrs(void) 373 { 374 struct vrs_desc *iso9660_vrs_desc; 375 uint32_t pos; 376 int error, cnt, dpos; 377 378 /* create ISO/Ecma-167 identification descriptors */ 379 if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL) 380 return ENOMEM; 381 382 /* 383 * All UDF formats should have their ISO/Ecma-167 descriptors written 384 * except when not possible due to track reservation in the case of 385 * VAT 386 */ 387 if ((format_flags & FORMAT_TRACK512) == 0) { 388 dpos = (2048 + context.sector_size - 1) / context.sector_size; 389 390 /* wipe at least 6 times 2048 byte `sectors' */ 391 for (cnt = 0; cnt < 6 *dpos; cnt++) { 392 pos = layout.iso9660_vrs + cnt; 393 if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 394 free(iso9660_vrs_desc); 395 return error; 396 } 397 } 398 399 /* common VRS fields in all written out ISO descriptors */ 400 iso9660_vrs_desc->struct_type = 0; 401 iso9660_vrs_desc->version = 1; 402 pos = layout.iso9660_vrs; 403 404 /* BEA01, NSR[23], TEA01 */ 405 memcpy(iso9660_vrs_desc->identifier, "BEA01", 5); 406 if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 407 free(iso9660_vrs_desc); 408 return error; 409 } 410 pos += dpos; 411 412 if (context.dscrver == 2) 413 memcpy(iso9660_vrs_desc->identifier, "NSR02", 5); 414 else 415 memcpy(iso9660_vrs_desc->identifier, "NSR03", 5); 416 ; 417 if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 418 free(iso9660_vrs_desc); 419 return error; 420 } 421 pos += dpos; 422 423 memcpy(iso9660_vrs_desc->identifier, "TEA01", 5); 424 if ((error = udf_write_sector(iso9660_vrs_desc, pos))) { 425 free(iso9660_vrs_desc); 426 return error; 427 } 428 } 429 430 free(iso9660_vrs_desc); 431 /* return success */ 432 return 0; 433 } 434 435 436 /* --------------------------------------------------------------------- */ 437 438 /* 439 * Main function that creates and writes out disc contents based on the 440 * format_flags's that uniquely define the type of disc to create. 441 */ 442 443 int 444 udf_do_newfs_prefix(void) 445 { 446 union dscrptr *zero_dscr; 447 union dscrptr *dscr; 448 struct mmc_trackinfo ti; 449 uint32_t sparable_blocks; 450 uint32_t sector_size, blockingnr; 451 uint32_t cnt, loc, len; 452 int sectcopy; 453 int error, integrity_type; 454 int data_part, metadata_part; 455 456 /* init */ 457 sector_size = mmc_discinfo.sector_size; 458 459 /* determine span/size */ 460 ti.tracknr = mmc_discinfo.first_track_last_session; 461 error = udf_update_trackinfo(&mmc_discinfo, &ti); 462 if (error) 463 return error; 464 465 if (mmc_discinfo.sector_size < context.sector_size) { 466 fprintf(stderr, "Impossible to format: sectorsize too small\n"); 467 return EIO; 468 } 469 context.sector_size = sector_size; 470 471 /* determine blockingnr */ 472 blockingnr = ti.packet_size; 473 if (blockingnr <= 1) { 474 /* paranoia on blockingnr */ 475 switch (mmc_discinfo.mmc_profile) { 476 case 0x08 : /* CDROM */ 477 case 0x09 : /* CD-R */ 478 case 0x0a : /* CD-RW */ 479 blockingnr = 32; /* UDF requirement */ 480 break; 481 case 0x10 : /* DVDROM */ 482 case 0x11 : /* DVD-R (DL) */ 483 case 0x12 : /* DVD-RAM */ 484 case 0x1b : /* DVD+R */ 485 case 0x2b : /* DVD+R Dual layer */ 486 case 0x13 : /* DVD-RW restricted overwrite */ 487 case 0x14 : /* DVD-RW sequential */ 488 blockingnr = 16; /* SCSI definition */ 489 break; 490 case 0x40 : /* BDROM */ 491 case 0x41 : /* BD-R Sequential recording (SRM) */ 492 case 0x42 : /* BD-R Random recording (RRM) */ 493 case 0x43 : /* BD-RE */ 494 case 0x51 : /* HD DVD-R */ 495 case 0x52 : /* HD DVD-RW */ 496 blockingnr = 32; /* SCSI definition */ 497 break; 498 default: 499 break; 500 } 501 } 502 if (blockingnr <= 0) { 503 printf("Can't fixup blockingnumber for device " 504 "type %d\n", mmc_discinfo.mmc_profile); 505 506 printf("Device is not returning valid blocking" 507 " number and media type is unknown.\n"); 508 509 return EINVAL; 510 } 511 wrtrack_skew = ti.track_start % blockingnr; 512 513 if (mmc_discinfo.mmc_class == MMC_CLASS_CD) { 514 /* not too much for CD-RW, still 20MiB */ 515 sparable_blocks = 32; 516 } else { 517 /* take a value for DVD*RW mainly, BD is `defect free' */ 518 sparable_blocks = 512; 519 } 520 521 /* get layout */ 522 error = udf_calculate_disc_layout(format_flags, context.min_udf, 523 wrtrack_skew, 524 ti.track_start, mmc_discinfo.last_possible_lba, 525 context.sector_size, blockingnr, sparable_blocks, 526 meta_fract); 527 528 /* cache partition for we need it often */ 529 data_part = context.data_part; 530 metadata_part = context.metadata_part; 531 532 /* Create sparing table descriptor if applicable */ 533 if (format_flags & FORMAT_SPARABLE) { 534 if ((error = udf_create_sparing_tabled())) 535 return error; 536 537 if (check_surface) { 538 if ((error = udf_surface_check())) 539 return error; 540 } 541 } 542 543 /* Create a generic terminator descriptor (later reused) */ 544 terminator_dscr = calloc(1, sector_size); 545 if (terminator_dscr == NULL) 546 return ENOMEM; 547 udf_create_terminator(terminator_dscr, 0); 548 549 /* 550 * Start with wipeout of VRS1 upto start of partition. This allows 551 * formatting for sequentials with the track reservation and it 552 * cleans old rubbish on rewritables. For sequentuals without the 553 * track reservation all is wiped from track start. 554 */ 555 if ((zero_dscr = calloc(1, context.sector_size)) == NULL) 556 return ENOMEM; 557 558 loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start; 559 for (; loc < layout.part_start_lba; loc++) { 560 if ((error = udf_write_sector(zero_dscr, loc))) { 561 free(zero_dscr); 562 return error; 563 } 564 } 565 free(zero_dscr); 566 567 /* Create anchors */ 568 for (cnt = 0; cnt < 3; cnt++) { 569 if ((error = udf_create_anchor(cnt))) { 570 return error; 571 } 572 } 573 574 /* 575 * Create the two Volume Descriptor Sets (VDS) each containing the 576 * following descriptors : primary volume, partition space, 577 * unallocated space, logical volume, implementation use and the 578 * terminator 579 */ 580 581 /* start of volume recognision sequence building */ 582 context.vds_seq = 0; 583 584 /* Create primary volume descriptor */ 585 if ((error = udf_create_primaryd())) 586 return error; 587 588 /* Create partition descriptor */ 589 if ((error = udf_create_partitiond(context.data_part, media_accesstype))) 590 return error; 591 592 /* Create unallocated space descriptor */ 593 if ((error = udf_create_unalloc_spaced())) 594 return error; 595 596 /* Create logical volume descriptor */ 597 if ((error = udf_create_logical_dscr(format_flags))) 598 return error; 599 600 /* Create implementation use descriptor */ 601 /* TODO input of fields 1,2,3 and passing them */ 602 if ((error = udf_create_impvold(NULL, NULL, NULL))) 603 return error; 604 605 /* write out what we've created so far */ 606 607 /* writeout iso9660 vrs */ 608 if ((error = udf_write_iso9660_vrs())) 609 return error; 610 611 /* Writeout anchors */ 612 for (cnt = 0; cnt < 3; cnt++) { 613 dscr = (union dscrptr *) context.anchors[cnt]; 614 loc = layout.anchors[cnt]; 615 if ((error = udf_write_dscr_phys(dscr, loc, 1))) 616 return error; 617 618 /* sequential media has only one anchor */ 619 if (format_flags & FORMAT_SEQUENTIAL) 620 break; 621 } 622 623 /* write out main and secondary VRS */ 624 for (sectcopy = 1; sectcopy <= 2; sectcopy++) { 625 loc = (sectcopy == 1) ? layout.vds1 : layout.vds2; 626 627 /* primary volume descriptor */ 628 dscr = (union dscrptr *) context.primary_vol; 629 error = udf_write_dscr_phys(dscr, loc, 1); 630 if (error) 631 return error; 632 loc++; 633 634 /* partition descriptor(s) */ 635 for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) { 636 dscr = (union dscrptr *) context.partitions[cnt]; 637 if (dscr) { 638 error = udf_write_dscr_phys(dscr, loc, 1); 639 if (error) 640 return error; 641 loc++; 642 } 643 } 644 645 /* unallocated space descriptor */ 646 dscr = (union dscrptr *) context.unallocated; 647 error = udf_write_dscr_phys(dscr, loc, 1); 648 if (error) 649 return error; 650 loc++; 651 652 /* logical volume descriptor */ 653 dscr = (union dscrptr *) context.logical_vol; 654 error = udf_write_dscr_phys(dscr, loc, 1); 655 if (error) 656 return error; 657 loc++; 658 659 /* implementation use descriptor */ 660 dscr = (union dscrptr *) context.implementation; 661 error = udf_write_dscr_phys(dscr, loc, 1); 662 if (error) 663 return error; 664 loc++; 665 666 /* terminator descriptor */ 667 error = udf_write_dscr_phys(terminator_dscr, loc, 1); 668 if (error) 669 return error; 670 loc++; 671 } 672 673 /* writeout the two sparable table descriptors (if needed) */ 674 if (format_flags & FORMAT_SPARABLE) { 675 for (sectcopy = 1; sectcopy <= 2; sectcopy++) { 676 loc = (sectcopy == 1) ? layout.spt_1 : layout.spt_2; 677 dscr = (union dscrptr *) context.sparing_table; 678 len = layout.sparing_table_dscr_lbas; 679 680 /* writeout */ 681 error = udf_write_dscr_phys(dscr, loc, len); 682 if (error) 683 return error; 684 } 685 } 686 687 /* 688 * Create unallocated space bitmap descriptor. Sequential recorded 689 * media report their own free/used space; no free/used space tables 690 * should be recorded for these. 691 */ 692 if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) { 693 error = udf_create_space_bitmap( 694 layout.alloc_bitmap_dscr_size, 695 layout.part_size_lba, 696 &context.part_unalloc_bits[data_part]); 697 if (error) 698 return error; 699 /* TODO: freed space bitmap if applicable */ 700 701 /* mark space allocated for the unallocated space bitmap */ 702 udf_mark_allocated(layout.unalloc_space, data_part, 703 layout.alloc_bitmap_dscr_size); 704 } 705 706 /* 707 * Create metadata partition file entries and allocate and init their 708 * space and free space maps. 709 */ 710 if (format_flags & FORMAT_META) { 711 error = udf_create_space_bitmap( 712 layout.meta_bitmap_dscr_size, 713 layout.meta_part_size_lba, 714 &context.part_unalloc_bits[metadata_part]); 715 if (error) 716 return error; 717 718 error = udf_create_meta_files(); 719 if (error) 720 return error; 721 722 /* mark space allocated for meta partition and its bitmap */ 723 udf_mark_allocated(layout.meta_file, data_part, 1); 724 udf_mark_allocated(layout.meta_mirror, data_part, 1); 725 udf_mark_allocated(layout.meta_bitmap, data_part, 1); 726 udf_mark_allocated(layout.meta_part_start_lba, data_part, 727 layout.meta_part_size_lba); 728 729 /* mark space allocated for the unallocated space bitmap */ 730 udf_mark_allocated(layout.meta_bitmap_space, data_part, 731 layout.meta_bitmap_dscr_size); 732 } 733 734 /* create logical volume integrity descriptor */ 735 context.num_files = 0; 736 context.num_directories = 0; 737 integrity_type = UDF_INTEGRITY_OPEN; 738 if ((error = udf_create_lvintd(integrity_type))) 739 return error; 740 741 /* writeout initial open integrity sequence + terminator */ 742 loc = layout.lvis; 743 dscr = (union dscrptr *) context.logvol_integrity; 744 error = udf_write_dscr_phys(dscr, loc, 1); 745 if (error) 746 return error; 747 loc++; 748 error = udf_write_dscr_phys(terminator_dscr, loc, 1); 749 if (error) 750 return error; 751 752 /* create VAT if needed */ 753 if (format_flags & FORMAT_VAT) { 754 context.vat_allocated = context.sector_size; 755 context.vat_contents = malloc(context.vat_allocated); 756 assert(context.vat_contents); 757 758 udf_prepend_VAT_file(); 759 } 760 761 /* create FSD and writeout */ 762 if ((error = udf_create_fsd())) 763 return error; 764 udf_mark_allocated(layout.fsd, metadata_part, 1); 765 766 dscr = (union dscrptr *) context.fileset_desc; 767 error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1); 768 769 return error; 770 } 771 772 773 /* specific routine for newfs to create empty rootdirectory */ 774 int 775 udf_do_rootdir(void) { 776 union dscrptr *root_dscr; 777 int error; 778 779 /* create root directory and write out */ 780 assert(context.unique_id == 0x10); 781 context.unique_id = 0; 782 if ((error = udf_create_new_rootdir(&root_dscr))) 783 return error; 784 udf_mark_allocated(layout.rootdir, context.metadata_part, 1); 785 786 error = udf_write_dscr_virt(root_dscr, 787 layout.rootdir, context.metadata_part, 1); 788 789 free(root_dscr); 790 791 return error; 792 } 793 794 795 int 796 udf_do_newfs_postfix(void) 797 { 798 union dscrptr *vat_dscr; 799 union dscrptr *dscr; 800 struct long_ad vatdata_pos; 801 uint32_t loc, len, phys, sects; 802 int data_part, metadata_part; 803 int error; 804 805 /* cache partition for we need it often */ 806 data_part = context.data_part; 807 metadata_part = context.metadata_part; 808 809 if ((format_flags & FORMAT_SEQUENTIAL) == 0) { 810 /* update lvint and mark it closed */ 811 udf_update_lvintd(UDF_INTEGRITY_CLOSED); 812 813 /* overwrite initial terminator */ 814 loc = layout.lvis+1; 815 dscr = (union dscrptr *) context.logvol_integrity; 816 error = udf_write_dscr_phys(dscr, loc, 1); 817 if (error) 818 return error; 819 loc++; 820 821 /* mark end of integrity desciptor sequence again */ 822 error = udf_write_dscr_phys(terminator_dscr, loc, 1); 823 if (error) 824 return error; 825 } 826 827 /* write out unallocated space bitmap on non sequential media */ 828 if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) { 829 /* writeout unallocated space bitmap */ 830 loc = layout.unalloc_space; 831 dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]); 832 len = layout.alloc_bitmap_dscr_size; 833 error = udf_write_dscr_virt(dscr, loc, data_part, len); 834 if (error) 835 return error; 836 } 837 838 if (format_flags & FORMAT_META) { 839 loc = layout.meta_file; 840 dscr = (union dscrptr *) context.meta_file; 841 error = udf_write_dscr_virt(dscr, loc, data_part, 1); 842 if (error) 843 return error; 844 845 loc = layout.meta_mirror; 846 dscr = (union dscrptr *) context.meta_mirror; 847 error = udf_write_dscr_virt(dscr, loc, data_part, 1); 848 if (error) 849 return error; 850 851 loc = layout.meta_bitmap; 852 dscr = (union dscrptr *) context.meta_bitmap; 853 error = udf_write_dscr_virt(dscr, loc, data_part, 1); 854 if (error) 855 return error; 856 857 /* writeout unallocated space bitmap */ 858 loc = layout.meta_bitmap_space; 859 dscr = (union dscrptr *) 860 (context.part_unalloc_bits[metadata_part]); 861 len = layout.meta_bitmap_dscr_size; 862 error = udf_write_dscr_virt(dscr, loc, data_part, len); 863 if (error) 864 return error; 865 } 866 867 /* create a VAT and account for FSD+root */ 868 vat_dscr = NULL; 869 if (format_flags & FORMAT_VAT) { 870 /* update lvint to reflect the newest values (no writeout) */ 871 udf_update_lvintd(UDF_INTEGRITY_CLOSED); 872 873 error = udf_append_VAT_file(); 874 if (error) 875 return error; 876 877 /* write out VAT data */ 878 sects = UDF_ROUNDUP(context.vat_size, context.sector_size) / 879 context.sector_size; 880 layout.vat = context.data_alloc_pos; 881 udf_data_alloc(sects, &vatdata_pos); 882 883 loc = udf_rw32(vatdata_pos.loc.lb_num); 884 phys = context.vtop_offset[context.data_part] + loc; 885 886 error = udf_write_phys(context.vat_contents, phys, sects); 887 if (error) 888 return error; 889 loc += sects; 890 891 /* create new VAT descriptor */ 892 error = udf_create_VAT(&vat_dscr); 893 if (error) 894 return error; 895 context.data_alloc_pos++; 896 loc++; 897 898 error = udf_write_dscr_virt(vat_dscr, loc, metadata_part, 1); 899 free(vat_dscr); 900 if (error) 901 return error; 902 } 903 904 /* done */ 905 return 0; 906 } 907