1/* $NetBSD: udf_create.c,v 1.16 2009/05/19 12:13:02 reinoud Exp $ */ 2 3/* 4 * Copyright (c) 2006, 2008 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 29#include <sys/cdefs.h> 30#ifndef lint 31__RCSID("$NetBSD: udf_create.c,v 1.16 2009/05/19 12:13:02 reinoud Exp $"); 32#endif /* not lint */ 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <errno.h> 38#include <time.h> 39#include <assert.h> 40#include <err.h> 41#include <sys/types.h> 42#include <sys/param.h> 43#include "udf_create.h" 44 45 46#if 0 47# ifndef DEBUG 48# define DEBUG 49# endif 50#endif 51 52 53void 54udf_init_create_context(void) 55{ 56 /* clear */ 57 memset(&context, 0, sizeof(struct udf_create_context)); 58 59 /* fill with defaults currently known */ 60 context.dscrver = 3; 61 context.min_udf = 0x0102; 62 context.max_udf = 0x0260; 63 context.serialnum = 1; /* default */ 64 65 context.gmtoff = 0; 66 context.sector_size = 512; /* minimum for UDF */ 67 68 context.logvol_name = NULL; 69 context.primary_name = NULL; 70 context.volset_name = NULL; 71 context.fileset_name = NULL; 72 73 context.app_name = "*NetBSD newfs"; 74 context.app_version_main = __NetBSD_Version__ / 100000000; 75 context.app_version_sub = (__NetBSD_Version__ / 1000000) % 100; 76 context.impl_name = "*NetBSD kernel UDF"; 77 78 context.vds_seq = 0; /* first one starts with zero */ 79 80 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */ 81 context.unique_id = 0x10; 82 83 context.num_files = 0; 84 context.num_directories = 0; 85} 86 87 88static uint32_t 89udf_space_bitmap_len(uint32_t part_size) 90{ 91 return sizeof(struct space_bitmap_desc)-1 + 92 part_size/8; 93} 94 95 96static uint32_t 97udf_bytes_to_sectors(uint64_t bytes) 98{ 99 uint32_t sector_size = layout.sector_size; 100 return (bytes + sector_size -1) / sector_size; 101} 102 103 104int 105udf_calculate_disc_layout(int format_flags, int min_udf, 106 uint32_t wrtrack_skew, 107 uint32_t first_lba, uint32_t last_lba, 108 uint32_t sector_size, uint32_t blockingnr, 109 uint32_t sparable_blocks, float meta_fract) 110{ 111 uint64_t kbsize, bytes; 112 uint32_t sparable_blockingnr; 113 uint32_t align_blockingnr; 114 uint32_t pos, mpos; 115 116 /* clear */ 117 bzero(&layout, sizeof(struct udf_disclayout)); 118 119 /* fill with parameters */ 120 layout.wrtrack_skew = wrtrack_skew; 121 layout.first_lba = first_lba; 122 layout.last_lba = last_lba; 123 layout.sector_size = sector_size; 124 layout.blockingnr = blockingnr; 125 layout.sparable_blocks = sparable_blocks; 126 127 /* start disc layouting */ 128 129 /* 130 * location of iso9660 vrs is defined as first sector AFTER 32kb, 131 * minimum `sector size' 2048 132 */ 133 layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size) 134 + first_lba; 135 136 /* anchor starts at specified offset in sectors */ 137 layout.anchors[0] = first_lba + 256; 138 if (format_flags & FORMAT_TRACK512) 139 layout.anchors[0] = first_lba + 512; 140 layout.anchors[1] = last_lba - 256; 141 layout.anchors[2] = last_lba; 142 143 /* update workable space */ 144 first_lba = layout.anchors[0] + blockingnr; 145 last_lba = layout.anchors[1] - 1; 146 147 /* XXX rest of anchor packet can be added to unallocated space descr */ 148 149 /* reserve space for VRS and VRS copy and associated tables */ 150 layout.vds_size = MAX(16, blockingnr); /* UDF 2.2.3.1+2 */ 151 layout.vds1 = first_lba; 152 first_lba += layout.vds_size; /* next packet */ 153 154 if (format_flags & FORMAT_SEQUENTIAL) { 155 /* for sequential, append them ASAP */ 156 layout.vds2 = first_lba; 157 first_lba += layout.vds_size; 158 } else { 159 layout.vds2 = layout.anchors[1] - layout.vds_size; 160 last_lba = layout.vds2 - 1; /* XXX -1 ?? */ 161 } 162 163 /* reserve space for logvol integrity sequence */ 164 layout.lvis_size = MAX(8192/sector_size, 2 * blockingnr); 165 if (format_flags & FORMAT_VAT) 166 layout.lvis_size = 2; 167 if (format_flags & FORMAT_WORM) 168 layout.lvis_size = 64 * blockingnr; 169 170 /* TODO skip bad blocks in LVID sequence; for now use f.e. */ 171//first_lba+=128; 172 layout.lvis = first_lba; 173 first_lba += layout.lvis_size; 174 175 /* initial guess of UDF partition size */ 176 layout.part_start_lba = first_lba; 177 layout.part_size_lba = last_lba - layout.part_start_lba; 178 179 /* all non sequential media needs an unallocated space bitmap */ 180 layout.alloc_bitmap_dscr_size = 0; 181 if ((format_flags & FORMAT_SEQUENTIAL) == 0) { 182 bytes = udf_space_bitmap_len(layout.part_size_lba); 183 layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes); 184 185 /* XXX freed space map when applicable */ 186 } 187 188 /* 189 * Note that for (bug) compatibility with version UDF 2.00 (fixed in 190 * 2.01 and higher) the blocking size needs to be 32 sectors otherwise 191 * the drive's blockingnr. 192 */ 193 194 sparable_blockingnr = blockingnr; 195 if (min_udf <= 0x200) 196 sparable_blockingnr = 32; 197 198 align_blockingnr = blockingnr; 199 if (format_flags & (FORMAT_SPARABLE | FORMAT_META)) 200 align_blockingnr = sparable_blockingnr; 201 202 layout.align_blockingnr = align_blockingnr; 203 layout.sparable_blockingnr = sparable_blockingnr; 204 205 /* 206 * Align partition LBA space to blocking granularity. Not strickly 207 * nessisary for non sparables but safer for the VRS data since it is 208 * not updated sporadically 209 */ 210 211 if ((format_flags & FORMAT_SEQUENTIAL) == 0) { 212#ifdef DEBUG 213 printf("Lost %d slack sectors at start\n", UDF_ROUNDUP( 214 first_lba - wrtrack_skew, align_blockingnr) - 215 (first_lba - wrtrack_skew)); 216 printf("Lost %d slack sectors at end\n", 217 (first_lba - wrtrack_skew) - UDF_ROUNDDOWN( 218 first_lba - wrtrack_skew, align_blockingnr)); 219#endif 220 221 first_lba = UDF_ROUNDUP( first_lba - wrtrack_skew, align_blockingnr); 222 last_lba = UDF_ROUNDDOWN(last_lba - wrtrack_skew, align_blockingnr); 223 } 224 225 if ((format_flags & FORMAT_SPARABLE) == 0) 226 layout.sparable_blocks = 0; 227 228 if (format_flags & FORMAT_SPARABLE) { 229 layout.sparable_area_size = 230 layout.sparable_blocks * sparable_blockingnr; 231 232 /* a sparing table descriptor is a whole blockingnr sectors */ 233 layout.sparing_table_dscr_lbas = sparable_blockingnr; 234 235 /* place the descriptors at the start and end of the area */ 236 layout.spt_1 = first_lba; 237 first_lba += layout.sparing_table_dscr_lbas; 238 239 layout.spt_2 = last_lba - layout.sparing_table_dscr_lbas; 240 last_lba -= layout.sparing_table_dscr_lbas; 241 242 /* allocate sparable section */ 243 layout.sparable_area = first_lba; 244 first_lba += layout.sparable_area_size; 245 } 246 247 /* update guess of UDF partition size */ 248 layout.part_start_lba = first_lba; 249 layout.part_size_lba = last_lba - layout.part_start_lba; 250 251 /* determine partition selection for data and metadata */ 252 context.data_part = 0; 253 context.metadata_part = context.data_part; 254 if ((format_flags & FORMAT_VAT) || (format_flags & FORMAT_META)) 255 context.metadata_part = context.data_part + 1; 256 257 /* 258 * Pick fixed logical space sector numbers for main FSD, rootdir and 259 * unallocated space. The reason for this pre-allocation is that they 260 * are referenced in the volume descriptor sequence and hence can't be 261 * allocated later. 262 */ 263 pos = 0; 264 layout.unalloc_space = pos; 265 pos += layout.alloc_bitmap_dscr_size; 266 267 /* claim metadata descriptors and partition space [UDF 2.2.10] */ 268 if (format_flags & FORMAT_META) { 269 /* note: all in backing partition space */ 270 layout.meta_file = pos++; 271 layout.meta_bitmap = pos++;; 272 layout.meta_mirror = layout.part_size_lba-1; 273 layout.meta_alignment = MAX(blockingnr, sparable_blockingnr); 274 layout.meta_blockingnr = MAX(layout.meta_alignment, 32); 275 276 /* calculate our partition length and store in sectors */ 277 layout.meta_part_size_lba = layout.part_size_lba * meta_fract; 278 layout.meta_part_size_lba = MAX(layout.meta_part_size_lba, 32); 279 layout.meta_part_size_lba = 280 UDF_ROUNDDOWN(layout.meta_part_size_lba, layout.meta_blockingnr); 281 282 /* calculate positions */ 283 bytes = udf_space_bitmap_len(layout.meta_part_size_lba); 284 layout.meta_bitmap_dscr_size = udf_bytes_to_sectors(bytes); 285 286 layout.meta_bitmap_space = pos; 287 pos += layout.meta_bitmap_dscr_size; 288 289 layout.meta_part_start_lba = UDF_ROUNDUP(pos, layout.meta_alignment); 290 } 291 292 mpos = (context.metadata_part == context.data_part) ? pos : 0; 293 layout.fsd = mpos; mpos += 1; 294 layout.rootdir = mpos; mpos += 1; 295 layout.vat = mpos; mpos += 1; /* if present */ 296 297#if 0 298 printf("Summary so far\n"); 299 printf("\tiso9660_vrs\t\t%d\n", layout.iso9660_vrs); 300 printf("\tanchor0\t\t\t%d\n", layout.anchors[0]); 301 printf("\tanchor1\t\t\t%d\n", layout.anchors[1]); 302 printf("\tanchor2\t\t\t%d\n", layout.anchors[2]); 303 printf("\tvds_size\t\t%d\n", layout.vds_size); 304 printf("\tvds1\t\t\t%d\n", layout.vds1); 305 printf("\tvds2\t\t\t%d\n", layout.vds2); 306 printf("\tlvis_size\t\t%d\n", layout.lvis_size); 307 printf("\tlvis\t\t\t%d\n", layout.lvis); 308 if (format_flags & FORMAT_SPARABLE) { 309 printf("\tsparable size\t\t%d\n", layout.sparable_area_size); 310 printf("\tsparable\t\t%d\n", layout.sparable_area); 311 } 312 printf("\tpartition start lba\t%d\n", layout.part_start_lba); 313 printf("\tpartition size\t\t%d KiB, %d MiB\n", 314 (layout.part_size_lba * sector_size) / 1024, 315 (layout.part_size_lba * sector_size) / (1024*1024)); 316 if ((format_flags & FORMAT_SEQUENTIAL) == 0) { 317 printf("\tpart bitmap start\t%d\n", layout.unalloc_space); 318 printf("\t\tfor %d lba\n", layout.alloc_bitmap_dscr_size); 319 } 320 if (format_flags & FORMAT_META) { 321 printf("\tmeta blockingnr\t\t%d\n", layout.meta_blockingnr); 322 printf("\tmeta alignment\t\t%d\n", layout.meta_alignment); 323 printf("\tmeta size\t\t%d KiB, %d MiB\n", 324 (layout.meta_part_size_lba * sector_size) / 1024, 325 (layout.meta_part_size_lba * sector_size) / (1024*1024)); 326 printf("\tmeta file\t\t%d\n", layout.meta_file); 327 printf("\tmeta mirror\t\t%d\n", layout.meta_mirror); 328 printf("\tmeta bitmap\t\t%d\n", layout.meta_bitmap); 329 printf("\tmeta bitmap start\t%d\n", layout.meta_bitmap_space); 330 printf("\t\tfor %d lba\n", layout.meta_bitmap_dscr_size); 331 printf("\tmeta space start\t%d\n", layout.meta_part_start_lba); 332 printf("\t\tfor %d lba\n", layout.meta_part_size_lba); 333 } 334 printf("\n"); 335#endif 336 337 kbsize = (uint64_t) last_lba * sector_size; 338 printf("Total space on this medium approx. %"PRIu64" KiB, %"PRIu64" MiB\n", 339 kbsize/1024, kbsize/(1024*1024)); 340 kbsize = (uint64_t) (layout.part_size_lba - layout.alloc_bitmap_dscr_size 341 - layout.meta_bitmap_dscr_size) * sector_size; 342 printf("Free space on this volume approx. %"PRIu64" KiB, %"PRIu64" MiB\n\n", 343 kbsize/1024, kbsize/(1024*1024)); 344 345 return 0; 346} 347 348 349int 350udf_validate_tag_sum(union dscrptr *dscr) 351{ 352 struct desc_tag *tag = &dscr->tag; 353 uint8_t *pos, sum, cnt; 354 355 /* calculate TAG header checksum */ 356 pos = (uint8_t *) tag; 357 sum = 0; 358 359 for(cnt = 0; cnt < 16; cnt++) { 360 if (cnt != 4) sum += *pos; 361 pos++; 362 }; 363 tag->cksum = sum; /* 8 bit */ 364 365 return 0; 366} 367 368 369/* assumes sector number of descriptor to be allready present */ 370int 371udf_validate_tag_and_crc_sums(union dscrptr *dscr) 372{ 373 struct desc_tag *tag = &dscr->tag; 374 uint16_t crc; 375 376 /* check payload CRC if applicable */ 377 if (udf_rw16(tag->desc_crc_len) > 0) { 378 crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, 379 udf_rw16(tag->desc_crc_len)); 380 tag->desc_crc = udf_rw16(crc); 381 }; 382 383 /* calculate TAG header checksum */ 384 return udf_validate_tag_sum(dscr); 385} 386 387 388void 389udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc) 390{ 391 tag->id = udf_rw16(tagid); 392 tag->descriptor_ver = udf_rw16(context.dscrver); 393 tag->cksum = 0; 394 tag->reserved = 0; 395 tag->serial_num = udf_rw16(context.serialnum); 396 tag->tag_loc = udf_rw32(loc); 397} 398 399 400int 401udf_create_anchor(int num) 402{ 403 struct anchor_vdp *avdp; 404 uint32_t vds_extent_len = layout.vds_size * context.sector_size; 405 406 if ((avdp = calloc(1, context.sector_size)) == NULL) 407 return ENOMEM; 408 409 udf_inittag(&avdp->tag, TAGID_ANCHOR, layout.anchors[num]); 410 411 avdp->main_vds_ex.loc = udf_rw32(layout.vds1); 412 avdp->main_vds_ex.len = udf_rw32(vds_extent_len); 413 414 avdp->reserve_vds_ex.loc = udf_rw32(layout.vds2); 415 avdp->reserve_vds_ex.len = udf_rw32(vds_extent_len); 416 417 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */ 418 avdp->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH); 419 420 context.anchors[num] = avdp; 421 return 0; 422} 423 424 425void 426udf_create_terminator(union dscrptr *dscr, uint32_t loc) 427{ 428 bzero(dscr, context.sector_size); 429 udf_inittag(&dscr->tag, TAGID_TERM, loc); 430 431 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */ 432 dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH); 433} 434 435 436void 437udf_osta_charset(struct charspec *charspec) 438{ 439 bzero(charspec, sizeof(struct charspec)); 440 charspec->type = 0; 441 strcpy((char *) charspec->inf, "OSTA Compressed Unicode"); 442} 443 444 445void 446udf_encode_osta_id(char *osta_id, uint16_t len, char *text) 447{ 448 uint16_t u16_name[1024]; 449 uint8_t *pos; 450 uint16_t *pos16; 451 452 bzero(osta_id, len); 453 if (!text || (strlen(text) == 0)) return; 454 455 bzero(u16_name, sizeof(uint16_t) * 1023); 456 457 /* convert ascii to 16 bits unicode */ 458 pos = (uint8_t *) text; 459 pos16 = u16_name; 460 while (*pos) { 461 *pos16 = *pos; 462 pos++; pos16++; 463 }; 464 *pos16 = 0; 465 466 udf_CompressUnicode(len, 8, (unicode_t *) u16_name, (byte *) osta_id); 467 468 /* Ecma 167/7.2.13 states that length is recorded in the last byte */ 469 osta_id[len-1] = strlen(text)+1; 470} 471 472 473/* first call udf_set_regid and then the suffix */ 474void 475udf_set_regid(struct regid *regid, char const *name) 476{ 477 bzero(regid, sizeof(struct regid)); 478 regid->flags = 0; /* not dirty and not protected */ 479 strcpy((char *) regid->id, name); 480} 481 482 483void 484udf_add_domain_regid(struct regid *regid) 485{ 486 uint16_t *ver; 487 488 ver = (uint16_t *) regid->id_suffix; 489 *ver = udf_rw16(context.min_udf); 490} 491 492 493void 494udf_add_udf_regid(struct regid *regid) 495{ 496 uint16_t *ver; 497 498 ver = (uint16_t *) regid->id_suffix; 499 *ver = udf_rw16(context.min_udf); 500 501 regid->id_suffix[2] = 4; /* unix */ 502 regid->id_suffix[3] = 8; /* NetBSD */ 503} 504 505 506void 507udf_add_impl_regid(struct regid *regid) 508{ 509 regid->id_suffix[0] = 4; /* unix */ 510 regid->id_suffix[1] = 8; /* NetBSD */ 511} 512 513 514void 515udf_add_app_regid(struct regid *regid) 516{ 517 regid->id_suffix[0] = context.app_version_main; 518 regid->id_suffix[1] = context.app_version_sub; 519} 520 521 522/* 523 * Fill in timestamp structure based on clock_gettime(). Time is reported back as a time_t 524 * accompanied with a nano second field. 525 * 526 * The husec, usec and csec could be relaxed in type. 527 */ 528static void 529udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp) 530{ 531 struct tm tm; 532 uint64_t husec, usec, csec; 533 534 bzero(timestamp, sizeof(struct timestamp)); 535 gmtime_r(×pec->tv_sec, &tm); 536 537 /* 538 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1. 539 * 540 * Lower 12 bits are two complement signed timezone offset if bit 12 541 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone 542 * offset to -2047 i.e. unsigned `zero' 543 */ 544 545 /* set method 1 for CUT/GMT */ 546 timestamp->type_tz = udf_rw16((1<<12) + 0); 547 timestamp->year = udf_rw16(tm.tm_year + 1900); 548 timestamp->month = tm.tm_mon + 1; /* `tm' uses 0..11 for months */ 549 timestamp->day = tm.tm_mday; 550 timestamp->hour = tm.tm_hour; 551 timestamp->minute = tm.tm_min; 552 timestamp->second = tm.tm_sec; 553 554 usec = (timespec->tv_nsec + 500) / 1000; /* round */ 555 husec = usec / 100; 556 usec -= husec * 100; /* only 0-99 in usec */ 557 csec = husec / 100; /* only 0-99 in csec */ 558 husec -= csec * 100; /* only 0-99 in husec */ 559 560 timestamp->centisec = csec; 561 timestamp->hund_usec = husec; 562 timestamp->usec = usec; 563} 564 565 566 567void 568udf_set_timestamp_now(struct timestamp *timestamp) 569{ 570 struct timespec now; 571 572 clock_gettime(CLOCK_REALTIME, &now); 573 udf_timespec_to_timestamp(&now, timestamp); 574} 575 576 577int 578udf_create_primaryd(void) 579{ 580 struct pri_vol_desc *pri; 581 uint16_t crclen; 582 583 pri = calloc(1, context.sector_size); 584 if (pri == NULL) 585 return ENOMEM; 586 587 bzero(pri, context.sector_size); 588 udf_inittag(&pri->tag, TAGID_PRI_VOL, /* loc */ 0); 589 pri->seq_num = udf_rw32(context.vds_seq); context.vds_seq++; 590 591 pri->pvd_num = udf_rw32(0); /* default serial */ 592 udf_encode_osta_id(pri->vol_id, 32, context.primary_name); 593 594 /* set defaults for single disc volumes as UDF prescribes */ 595 pri->vds_num = udf_rw16(1); 596 pri->max_vol_seq = udf_rw16(1); 597 pri->ichg_lvl = udf_rw16(2); 598 pri->max_ichg_lvl = udf_rw16(3); 599 pri->flags = udf_rw16(0); 600 601 pri->charset_list = udf_rw32(1); /* only CS0 */ 602 pri->max_charset_list = udf_rw32(1); /* only CS0 */ 603 604 udf_encode_osta_id(pri->volset_id, 128, context.volset_name); 605 udf_osta_charset(&pri->desc_charset); 606 udf_osta_charset(&pri->explanatory_charset); 607 608 udf_set_regid(&pri->app_id, context.app_name); 609 udf_add_app_regid(&pri->app_id); 610 611 udf_set_regid(&pri->imp_id, context.impl_name); 612 udf_add_impl_regid(&pri->imp_id); 613 614 udf_set_timestamp_now(&pri->time); 615 616 crclen = sizeof(struct pri_vol_desc) - UDF_DESC_TAG_LENGTH; 617 pri->tag.desc_crc_len = udf_rw16(crclen); 618 619 context.primary_vol = pri; 620 621 return 0; 622} 623 624 625/* XXX no support for unallocated or freed space tables yet (!) */ 626int 627udf_create_partitiond(int part_num, int part_accesstype) 628{ 629 struct part_desc *pd; 630 struct part_hdr_desc *phd; 631 uint32_t sector_size, bitmap_bytes; 632 uint16_t crclen; 633 634 sector_size = context.sector_size; 635 bitmap_bytes = layout.alloc_bitmap_dscr_size * sector_size; 636 637 if (context.partitions[part_num]) { 638 printf("Internal error: partition %d allready defined\n", 639 part_num); 640 return EINVAL; 641 } 642 643 pd = calloc(1, context.sector_size); 644 if (pd == NULL) 645 return ENOMEM; 646 phd = &pd->_impl_use.part_hdr; 647 648 udf_inittag(&pd->tag, TAGID_PARTITION, /* loc */ 0); 649 pd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++; 650 651 pd->flags = udf_rw16(1); /* allocated */ 652 pd->part_num = udf_rw16(part_num); /* only one physical partition */ 653 654 if (context.dscrver == 2) { 655 udf_set_regid(&pd->contents, "+NSR02"); 656 } else { 657 udf_set_regid(&pd->contents, "+NSR03"); 658 } 659 udf_add_app_regid(&pd->contents); 660 661 phd->unalloc_space_bitmap.len = udf_rw32(bitmap_bytes); 662 phd->unalloc_space_bitmap.lb_num = udf_rw32(layout.unalloc_space); 663 664 if (layout.freed_space) { 665 phd->freed_space_bitmap.len = udf_rw32(bitmap_bytes); 666 phd->freed_space_bitmap.lb_num = udf_rw32(layout.freed_space); 667 } 668 669 pd->access_type = udf_rw32(part_accesstype); 670 pd->start_loc = udf_rw32(layout.part_start_lba); 671 pd->part_len = udf_rw32(layout.part_size_lba); 672 673 udf_set_regid(&pd->imp_id, context.impl_name); 674 udf_add_impl_regid(&pd->imp_id); 675 676 crclen = sizeof(struct part_desc) - UDF_DESC_TAG_LENGTH; 677 pd->tag.desc_crc_len = udf_rw16(crclen); 678 679 context.partitions[part_num] = pd; 680 681 return 0; 682} 683 684 685int 686udf_create_unalloc_spaced(void) 687{ 688 struct unalloc_sp_desc *usd; 689 uint16_t crclen; 690 691 usd = calloc(1, context.sector_size); 692 if (usd == NULL) 693 return ENOMEM; 694 695 udf_inittag(&usd->tag, TAGID_UNALLOC_SPACE, /* loc */ 0); 696 usd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++; 697 698 /* no default entries */ 699 usd->alloc_desc_num = udf_rw32(0); /* no entries */ 700 701 crclen = sizeof(struct unalloc_sp_desc) - sizeof(struct extent_ad); 702 crclen -= UDF_DESC_TAG_LENGTH; 703 usd->tag.desc_crc_len = udf_rw16(crclen); 704 705 context.unallocated = usd; 706 707 return 0; 708} 709 710 711static int 712udf_create_base_logical_dscr(void) 713{ 714 struct logvol_desc *lvd; 715 uint32_t sector_size; 716 uint16_t crclen; 717 718 sector_size = context.sector_size; 719 720 lvd = calloc(1, sector_size); 721 if (lvd == NULL) 722 return ENOMEM; 723 724 udf_inittag(&lvd->tag, TAGID_LOGVOL, /* loc */ 0); 725 lvd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++; 726 727 udf_osta_charset(&lvd->desc_charset); 728 udf_encode_osta_id(lvd->logvol_id, 128, context.logvol_name); 729 lvd->lb_size = udf_rw32(context.sector_size); 730 731 udf_set_regid(&lvd->domain_id, "*OSTA UDF Compliant"); 732 udf_add_domain_regid(&lvd->domain_id); 733 734 /* no partition mappings/entries yet */ 735 lvd->mt_l = udf_rw32(0); 736 lvd->n_pm = udf_rw32(0); 737 738 udf_set_regid(&lvd->imp_id, context.impl_name); 739 udf_add_impl_regid(&lvd->imp_id); 740 741 lvd->integrity_seq_loc.loc = udf_rw32(layout.lvis); 742 lvd->integrity_seq_loc.len = udf_rw32(layout.lvis_size * sector_size); 743 744 /* just one fsd for now */ 745 lvd->lv_fsd_loc.len = udf_rw32(sector_size); 746 lvd->lv_fsd_loc.loc.part_num = udf_rw32(context.metadata_part); 747 lvd->lv_fsd_loc.loc.lb_num = udf_rw32(layout.fsd); 748 749 crclen = sizeof(struct logvol_desc) - 1 - UDF_DESC_TAG_LENGTH; 750 lvd->tag.desc_crc_len = udf_rw16(crclen); 751 752 context.logical_vol = lvd; 753 context.vtop_tp[UDF_VTOP_RAWPART] = UDF_VTOP_TYPE_RAW; 754 context.vtop_offset[UDF_VTOP_RAWPART] = 0; 755 756 return 0; 757} 758 759 760static void 761udf_add_logvol_part_physical(uint16_t phys_part) 762{ 763 struct logvol_desc *logvol = context.logical_vol; 764 union udf_pmap *pmap; 765 uint8_t *pmap_pos; 766 uint16_t crclen; 767 uint32_t pmap1_size, log_part; 768 769 log_part = udf_rw32(logvol->n_pm); 770 pmap_pos = logvol->maps + udf_rw32(logvol->mt_l); 771 pmap1_size = sizeof(struct part_map_1); 772 773 pmap = (union udf_pmap *) pmap_pos; 774 pmap->pm1.type = 1; 775 pmap->pm1.len = sizeof(struct part_map_1); 776 pmap->pm1.vol_seq_num = udf_rw16(1); /* no multi-volume */ 777 pmap->pm1.part_num = udf_rw16(phys_part); 778 779 context.vtop [log_part] = phys_part; 780 context.vtop_tp [log_part] = UDF_VTOP_TYPE_PHYS; 781 context.vtop_offset[log_part] = layout.part_start_lba; 782 context.part_size[log_part] = layout.part_size_lba; 783 context.part_free[log_part] = layout.part_size_lba; 784 785 /* increment number of partitions and length */ 786 logvol->n_pm = udf_rw32(log_part + 1); 787 logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmap1_size); 788 789 crclen = udf_rw16(logvol->tag.desc_crc_len) + pmap1_size; 790 logvol->tag.desc_crc_len = udf_rw16(crclen); 791} 792 793 794static void 795udf_add_logvol_part_virtual(uint16_t phys_part) 796{ 797 union udf_pmap *pmap; 798 struct logvol_desc *logvol = context.logical_vol; 799 uint8_t *pmap_pos; 800 uint16_t crclen; 801 uint32_t pmapv_size, log_part; 802 803 log_part = udf_rw32(logvol->n_pm); 804 pmap_pos = logvol->maps + udf_rw32(logvol->mt_l); 805 pmapv_size = sizeof(struct part_map_2); 806 807 pmap = (union udf_pmap *) pmap_pos; 808 pmap->pmv.type = 2; 809 pmap->pmv.len = pmapv_size; 810 811 udf_set_regid(&pmap->pmv.id, "*UDF Virtual Partition"); 812 udf_add_udf_regid(&pmap->pmv.id); 813 814 pmap->pmv.vol_seq_num = udf_rw16(1); /* no multi-volume */ 815 pmap->pmv.part_num = udf_rw16(phys_part); 816 817 context.vtop [log_part] = phys_part; 818 context.vtop_tp [log_part] = UDF_VTOP_TYPE_VIRT; 819 context.vtop_offset[log_part] = context.vtop_offset[phys_part]; 820 context.part_size[log_part] = 0xffffffff; 821 context.part_free[log_part] = 0xffffffff; 822 823 /* increment number of partitions and length */ 824 logvol->n_pm = udf_rw32(log_part + 1); 825 logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size); 826 827 crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size; 828 logvol->tag.desc_crc_len = udf_rw16(crclen); 829} 830 831 832/* sparing table size is in bytes */ 833static void 834udf_add_logvol_part_sparable(uint16_t phys_part) 835{ 836 union udf_pmap *pmap; 837 struct logvol_desc *logvol = context.logical_vol; 838 uint32_t *st_pos, sparable_bytes, pmaps_size; 839 uint8_t *pmap_pos, num; 840 uint16_t crclen; 841 uint32_t log_part; 842 843 log_part = udf_rw32(logvol->n_pm); 844 pmap_pos = logvol->maps + udf_rw32(logvol->mt_l); 845 pmaps_size = sizeof(struct part_map_2); 846 sparable_bytes = layout.sparable_area_size * context.sector_size; 847 848 pmap = (union udf_pmap *) pmap_pos; 849 pmap->pms.type = 2; 850 pmap->pms.len = pmaps_size; 851 852 udf_set_regid(&pmap->pmv.id, "*UDF Sparable Partition"); 853 udf_add_udf_regid(&pmap->pmv.id); 854 855 pmap->pms.vol_seq_num = udf_rw16(1); /* no multi-volume */ 856 pmap->pms.part_num = udf_rw16(phys_part); 857 858 pmap->pms.packet_len = udf_rw16(layout.sparable_blockingnr); 859 pmap->pms.st_size = udf_rw32(sparable_bytes); 860 861 /* enter spare tables */ 862 st_pos = &pmap->pms.st_loc[0]; 863 *st_pos++ = udf_rw32(layout.spt_1); 864 *st_pos++ = udf_rw32(layout.spt_2); 865 866 num = 2; 867 if (layout.spt_2 == 0) num--; 868 if (layout.spt_1 == 0) num--; 869 pmap->pms.n_st = num; /* 8 bit */ 870 871 /* the vtop_offset needs to explicitly set since there is no phys. */ 872 context.vtop [log_part] = phys_part; 873 context.vtop_tp [log_part] = UDF_VTOP_TYPE_SPARABLE; 874 context.vtop_offset[log_part] = layout.part_start_lba; 875 context.part_size[log_part] = layout.part_size_lba; 876 context.part_free[log_part] = layout.part_size_lba; 877 878 /* increment number of partitions and length */ 879 logvol->n_pm = udf_rw32(log_part + 1); 880 logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmaps_size); 881 882 crclen = udf_rw16(logvol->tag.desc_crc_len) + pmaps_size; 883 logvol->tag.desc_crc_len = udf_rw16(crclen); 884} 885 886 887int 888udf_create_sparing_tabled(void) 889{ 890 struct udf_sparing_table *spt; 891 struct spare_map_entry *sme; 892 uint32_t loc, cnt; 893 uint32_t crclen; /* XXX: should be 16; need to detect overflow */ 894 895 spt = calloc(context.sector_size, layout.sparing_table_dscr_lbas); 896 if (spt == NULL) 897 return ENOMEM; 898 899 /* a sparing table descriptor is a whole sparable_blockingnr sectors */ 900 udf_inittag(&spt->tag, TAGID_SPARING_TABLE, /* loc */ 0); 901 902 udf_set_regid(&spt->id, "*UDF Sparing Table"); 903 udf_add_udf_regid(&spt->id); 904 905 spt->rt_l = udf_rw16(layout.sparable_blocks); 906 spt->seq_num = udf_rw32(0); /* first generation */ 907 908 for (cnt = 0; cnt < layout.sparable_blocks; cnt++) { 909 sme = &spt->entries[cnt]; 910 loc = layout.sparable_area + cnt * layout.sparable_blockingnr; 911 sme->org = udf_rw32(0xffffffff); /* open for reloc */ 912 sme->map = udf_rw32(loc); 913 } 914 915 /* calculate crc len for actual size */ 916 crclen = sizeof(struct udf_sparing_table) - UDF_DESC_TAG_LENGTH; 917 crclen += (layout.sparable_blocks-1) * sizeof(struct spare_map_entry); 918/* XXX ensure crclen doesn't exceed UINT16_MAX ? */ 919 spt->tag.desc_crc_len = udf_rw16((uint16_t)crclen); 920 921 context.sparing_table = spt; 922 923 return 0; 924} 925 926 927static void 928udf_add_logvol_part_meta(uint16_t phys_part) 929{ 930 union udf_pmap *pmap; 931 struct logvol_desc *logvol = context.logical_vol; 932 uint8_t *pmap_pos; 933 uint32_t pmapv_size, log_part; 934 uint16_t crclen; 935 936 log_part = udf_rw32(logvol->n_pm); 937 pmap_pos = logvol->maps + udf_rw32(logvol->mt_l); 938 pmapv_size = sizeof(struct part_map_2); 939 940 pmap = (union udf_pmap *) pmap_pos; 941 pmap->pmm.type = 2; 942 pmap->pmm.len = pmapv_size; 943 944 udf_set_regid(&pmap->pmm.id, "*UDF Metadata Partition"); 945 udf_add_udf_regid(&pmap->pmm.id); 946 947 pmap->pmm.vol_seq_num = udf_rw16(1); /* no multi-volume */ 948 pmap->pmm.part_num = udf_rw16(phys_part); 949 950 /* fill in meta data file(s) and alloc/alignment unit sizes */ 951 pmap->pmm.meta_file_lbn = udf_rw32(layout.meta_file); 952 pmap->pmm.meta_mirror_file_lbn = udf_rw32(layout.meta_mirror); 953 pmap->pmm.meta_bitmap_file_lbn = udf_rw32(layout.meta_bitmap); 954 pmap->pmm.alloc_unit_size = udf_rw32(layout.meta_blockingnr); 955 pmap->pmm.alignment_unit_size = udf_rw16(layout.meta_alignment); 956 pmap->pmm.flags = 0; /* METADATA_DUPLICATED */ 957 958 context.vtop [log_part] = phys_part; 959 context.vtop_tp [log_part] = UDF_VTOP_TYPE_META; 960 context.vtop_offset[log_part] = 961 context.vtop_offset[phys_part] + layout.meta_part_start_lba; 962 context.part_size[log_part] = layout.meta_part_size_lba; 963 context.part_free[log_part] = layout.meta_part_size_lba; 964 965 /* increment number of partitions and length */ 966 logvol->n_pm = udf_rw32(log_part + 1); 967 logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size); 968 969 crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size; 970 logvol->tag.desc_crc_len = udf_rw16(crclen); 971} 972 973 974int 975udf_create_logical_dscr(int format_flags) 976{ 977 int error; 978 979 if ((error = udf_create_base_logical_dscr())) 980 return error; 981 982 /* we pass data_part for there might be a read-only part one day */ 983 if (format_flags & FORMAT_SPARABLE) { 984 /* sparable partition mapping has no physical mapping */ 985 udf_add_logvol_part_sparable(context.data_part); 986 } else { 987 udf_add_logvol_part_physical(context.data_part); 988 } 989 990 if (format_flags & FORMAT_VAT) { 991 /* add VAT virtual mapping; reflects on datapart */ 992 udf_add_logvol_part_virtual(context.data_part); 993 } 994 if (format_flags & FORMAT_META) { 995 /* add META data mapping; reflects on datapart */ 996 udf_add_logvol_part_meta(context.data_part); 997 } 998 999 return 0; 1000} 1001 1002 1003int 1004udf_create_impvold(char *field1, char *field2, char *field3) 1005{ 1006 struct impvol_desc *ivd; 1007 struct udf_lv_info *lvi; 1008 uint16_t crclen; 1009 1010 ivd = calloc(1, context.sector_size); 1011 if (ivd == NULL) 1012 return ENOMEM; 1013 lvi = &ivd->_impl_use.lv_info; 1014 1015 udf_inittag(&ivd->tag, TAGID_IMP_VOL, /* loc */ 0); 1016 ivd->seq_num = udf_rw32(context.vds_seq); context.vds_seq++; 1017 1018 udf_set_regid(&ivd->impl_id, "*UDF LV Info"); 1019 udf_add_udf_regid(&ivd->impl_id); 1020 1021 /* fill in UDF specific part */ 1022 udf_osta_charset(&lvi->lvi_charset); 1023 udf_encode_osta_id(lvi->logvol_id, 128, context.logvol_name); 1024 1025 udf_encode_osta_id(lvi->lvinfo1, 36, field1); 1026 udf_encode_osta_id(lvi->lvinfo2, 36, field2); 1027 udf_encode_osta_id(lvi->lvinfo3, 36, field3); 1028 1029 udf_set_regid(&lvi->impl_id, context.impl_name); 1030 udf_add_impl_regid(&lvi->impl_id); 1031 1032 crclen = sizeof(struct impvol_desc) - UDF_DESC_TAG_LENGTH; 1033 ivd->tag.desc_crc_len = udf_rw16(crclen); 1034 1035 context.implementation = ivd; 1036 1037 return 0; 1038} 1039 1040 1041/* XXX might need to be sanitised a bit later */ 1042void 1043udf_update_lvintd(int type) 1044{ 1045 struct logvol_int_desc *lvid; 1046 struct udf_logvol_info *lvinfo; 1047 struct logvol_desc *logvol; 1048 uint32_t *pos; 1049 uint32_t cnt, l_iu, num_partmappings; 1050 uint32_t crclen; /* XXX: should be 16; need to detect overflow */ 1051 1052 lvid = context.logvol_integrity; 1053 logvol = context.logical_vol; 1054 1055 assert(lvid); 1056 assert(logvol); 1057 1058 lvid->integrity_type = udf_rw32(type); 1059 1060 num_partmappings = udf_rw32(logvol->n_pm); 1061 1062 udf_set_timestamp_now(&lvid->time); 1063 1064 lvinfo = (struct udf_logvol_info *) 1065 (lvid->tables + num_partmappings * 2); 1066 udf_set_regid(&lvinfo->impl_id, context.impl_name); 1067 udf_add_impl_regid(&lvinfo->impl_id); 1068 1069 lvinfo->num_files = udf_rw32(context.num_files); 1070 lvinfo->num_directories = udf_rw32(context.num_directories); 1071 1072 lvid->lvint_next_unique_id = udf_rw64(context.unique_id); 1073 1074 /* XXX sane enough ? */ 1075 lvinfo->min_udf_readver = udf_rw16(context.min_udf); 1076 lvinfo->min_udf_writever = udf_rw16(context.min_udf); 1077 lvinfo->max_udf_writever = udf_rw16(context.max_udf); 1078 1079 lvid->num_part = udf_rw32(num_partmappings); 1080 1081 /* no impl. use needed */ 1082 l_iu = sizeof(struct udf_logvol_info); 1083 lvid->l_iu = udf_rw32(l_iu); 1084 1085 pos = &lvid->tables[0]; 1086 for (cnt = 0; cnt < num_partmappings; cnt++) { 1087 *pos++ = udf_rw32(context.part_free[cnt]); 1088 } 1089 for (cnt = 0; cnt < num_partmappings; cnt++) { 1090 *pos++ = udf_rw32(context.part_size[cnt]); 1091 } 1092 1093 crclen = sizeof(struct logvol_int_desc) -4 -UDF_DESC_TAG_LENGTH + l_iu; 1094 crclen += num_partmappings * 2 * 4; 1095/* XXX ensure crclen doesn't exceed UINT16_MAX ? */ 1096 lvid->tag.desc_crc_len = udf_rw16(crclen); 1097 1098 context.logvol_info = lvinfo; 1099} 1100 1101 1102int 1103udf_create_lvintd(int type) 1104{ 1105 struct logvol_int_desc *lvid; 1106 1107 lvid = calloc(1, context.sector_size); 1108 if (lvid == NULL) 1109 return ENOMEM; 1110 1111 udf_inittag(&lvid->tag, TAGID_LOGVOL_INTEGRITY, /* loc */ 0); 1112 1113 context.logvol_integrity = lvid; 1114 1115 udf_update_lvintd(type); 1116 1117 return 0; 1118} 1119 1120 1121int 1122udf_create_fsd(void) 1123{ 1124 struct fileset_desc *fsd; 1125 uint16_t crclen; 1126 1127 fsd = calloc(1, context.sector_size); 1128 if (fsd == NULL) 1129 return ENOMEM; 1130 1131 udf_inittag(&fsd->tag, TAGID_FSD, /* loc */ 0); 1132 1133 udf_set_timestamp_now(&fsd->time); 1134 fsd->ichg_lvl = udf_rw16(3); /* UDF 2.3.2.1 */ 1135 fsd->max_ichg_lvl = udf_rw16(3); /* UDF 2.3.2.2 */ 1136 1137 fsd->charset_list = udf_rw32(1); /* only CS0 */ 1138 fsd->max_charset_list = udf_rw32(1); /* only CS0 */ 1139 1140 fsd->fileset_num = udf_rw32(0); /* only one fsd */ 1141 fsd->fileset_desc_num = udf_rw32(0); /* origional */ 1142 1143 udf_osta_charset(&fsd->logvol_id_charset); 1144 udf_encode_osta_id(fsd->logvol_id, 128, context.logvol_name); 1145 1146 udf_osta_charset(&fsd->fileset_charset); 1147 udf_encode_osta_id(fsd->fileset_id, 32, context.fileset_name); 1148 1149 /* copyright file and abstract file names obmitted */ 1150 1151 fsd->rootdir_icb.len = udf_rw32(context.sector_size); 1152 fsd->rootdir_icb.loc.lb_num = udf_rw32(layout.rootdir); 1153 fsd->rootdir_icb.loc.part_num = udf_rw16(context.metadata_part); 1154 1155 udf_set_regid(&fsd->domain_id, "*OSTA UDF Compliant"); 1156 udf_add_domain_regid(&fsd->domain_id); 1157 1158 /* next_ex stays zero */ 1159 /* no system streamdirs yet */ 1160 1161 crclen = sizeof(struct fileset_desc) - UDF_DESC_TAG_LENGTH; 1162 fsd->tag.desc_crc_len = udf_rw16(crclen); 1163 1164 context.fileset_desc = fsd; 1165 1166 return 0; 1167} 1168 1169 1170int 1171udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba, 1172 struct space_bitmap_desc **sbdp) 1173{ 1174 struct space_bitmap_desc *sbd; 1175 uint32_t cnt; 1176 uint16_t crclen; 1177 1178 *sbdp = NULL; 1179 sbd = calloc(context.sector_size, dscr_size); 1180 if (sbd == NULL) 1181 return ENOMEM; 1182 1183 udf_inittag(&sbd->tag, TAGID_SPACE_BITMAP, /* loc */ 0); 1184 1185 sbd->num_bits = udf_rw32(part_size_lba); 1186 sbd->num_bytes = udf_rw32((part_size_lba + 7)/8); 1187 1188 /* fill space with 0xff to indicate free */ 1189 for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++) 1190 sbd->data[cnt] = 0xff; 1191 1192 /* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */ 1193 crclen = sizeof(struct space_bitmap_desc) -1 - UDF_DESC_TAG_LENGTH; 1194 sbd->tag.desc_crc_len = udf_rw16(crclen); 1195 1196 *sbdp = sbd; 1197 return 0; 1198} 1199 1200 1201/* --------------------------------------------------------------------- */ 1202 1203int 1204udf_register_bad_block(uint32_t location) 1205{ 1206 struct udf_sparing_table *spt; 1207 struct spare_map_entry *sme, *free_sme; 1208 uint32_t cnt; 1209 1210 spt = context.sparing_table; 1211 if (spt == NULL) { 1212 printf("internal error: adding bad block to non sparable\n"); 1213 return EINVAL; 1214 } 1215 1216 /* find us a free spare map entry */ 1217 free_sme = NULL; 1218 for (cnt = 0; cnt < layout.sparable_blocks; cnt++) { 1219 sme = &spt->entries[cnt]; 1220 /* if we are allready in it, bail out */ 1221 if (udf_rw32(sme->org) == location) 1222 return 0; 1223 if (udf_rw32(sme->org) == 0xffffffff) { 1224 free_sme = sme; 1225 break; 1226 } 1227 } 1228 if (free_sme == NULL) { 1229 printf("Disc relocation blocks full; disc too damanged\n"); 1230 return EINVAL; 1231 } 1232 free_sme->org = udf_rw32(location); 1233 1234 return 0; 1235} 1236 1237 1238void 1239udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks) 1240{ 1241 union dscrptr *dscr; 1242 uint8_t *bpos; 1243 uint32_t cnt, bit; 1244 1245 /* make not on space used on underlying partition */ 1246 context.part_free[partnr] -= blocks; 1247#ifdef DEBUG 1248 printf("mark allocated : partnr %d, start_lb %d for %d blocks\n", 1249 partnr, start_lb, blocks); 1250#endif 1251 1252 switch (context.vtop_tp[partnr]) { 1253 case UDF_VTOP_TYPE_VIRT: 1254 /* nothing */ 1255 break; 1256 case UDF_VTOP_TYPE_PHYS: 1257 case UDF_VTOP_TYPE_SPARABLE: 1258 case UDF_VTOP_TYPE_META: 1259#ifdef DEBUG 1260 printf("Marking %d+%d as used\n", start_lb, blocks); 1261#endif 1262 dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]); 1263 for (cnt = start_lb; cnt < start_lb + blocks; cnt++) { 1264 bpos = &dscr->sbd.data[cnt / 8]; 1265 bit = cnt % 8; 1266 *bpos &= ~(1<< bit); 1267 } 1268 break; 1269 default: 1270 printf("internal error: reality check in mapping type %d\n", 1271 context.vtop_tp[partnr]); 1272 exit(EXIT_FAILURE); 1273 } 1274} 1275 1276 1277/* --------------------------------------------------------------------- */ 1278 1279static void 1280udf_advance_uniqueid(void) 1281{ 1282 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */ 1283 context.unique_id++; 1284 if (context.unique_id < 0x10) 1285 context.unique_id = 0x10; 1286} 1287 1288 1289static int 1290udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent, 1291 uint64_t unique_id) 1292{ 1293 /* the size of an empty FID is 38 but needs to be a multiple of 4 */ 1294 int fidsize = 40; 1295 1296 udf_inittag(&fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num)); 1297 fid->file_version_num = udf_rw16(1); /* UDF 2.3.4.1 */ 1298 fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR; 1299 fid->icb = *parent; 1300 fid->icb.longad_uniqueid = udf_rw32((uint32_t) unique_id); 1301 fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH); 1302 1303 /* we have to do the fid here explicitly for simplicity */ 1304 udf_validate_tag_and_crc_sums((union dscrptr *) fid); 1305 1306 return fidsize; 1307} 1308 1309 1310/* 1311 * Order of extended attributes : 1312 * ECMA 167 EAs 1313 * Non block aligned Implementation Use EAs 1314 * Block aligned Implementation Use EAs (not in newfs_udf) 1315 * Application Use EAs (not in newfs_udf) 1316 * 1317 * no checks for doubles, must be called in-order 1318 */ 1319static void 1320udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr) 1321{ 1322 struct file_entry *fe; 1323 struct extfile_entry *efe; 1324 struct extattrhdr_desc *extattrhdr; 1325 struct impl_extattr_entry *implext; 1326 uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len; 1327 uint32_t *l_eap, l_ad; 1328 uint16_t *spos; 1329 uint8_t *bpos, *data; 1330 1331 if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { 1332 fe = &dscr->fe; 1333 data = fe->data; 1334 l_eap = &fe->l_ea; 1335 l_ad = udf_rw32(fe->l_ad); 1336 } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { 1337 efe = &dscr->efe; 1338 data = efe->data; 1339 l_eap = &efe->l_ea; 1340 l_ad = udf_rw32(efe->l_ad); 1341 } else { 1342 errx(1, "Bad tag passed to udf_extattr_append_internal"); 1343 } 1344 1345 /* should have a header! */ 1346 extattrhdr = (struct extattrhdr_desc *) data; 1347 l_ea = udf_rw32(*l_eap); 1348 if (l_ea == 0) { 1349 assert(l_ad == 0); 1350 /* create empty extended attribute header */ 1351 exthdr_len = sizeof(struct extattrhdr_desc); 1352 1353 udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0); 1354 extattrhdr->impl_attr_loc = udf_rw32(exthdr_len); 1355 extattrhdr->appl_attr_loc = udf_rw32(exthdr_len); 1356 extattrhdr->tag.desc_crc_len = udf_rw16(8); 1357 1358 /* record extended attribute header length */ 1359 l_ea = exthdr_len; 1360 *l_eap = udf_rw32(l_ea); 1361 } 1362 1363 /* extract locations */ 1364 impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc); 1365 appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc); 1366 if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 1367 impl_attr_loc = l_ea; 1368 if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT) 1369 appl_attr_loc = l_ea; 1370 1371 /* Ecma 167 EAs */ 1372 if (udf_rw32(extattr->type) < 2048) { 1373 assert(impl_attr_loc == l_ea); 1374 assert(appl_attr_loc == l_ea); 1375 } 1376 1377 /* implementation use extended attributes */ 1378 if (udf_rw32(extattr->type) == 2048) { 1379 assert(appl_attr_loc == l_ea); 1380 1381 /* calculate and write extended attribute header checksum */ 1382 implext = (struct impl_extattr_entry *) extattr; 1383 assert(udf_rw32(implext->iu_l) == 4); /* [UDF 3.3.4.5] */ 1384 spos = (uint16_t *) implext->data; 1385 *spos = udf_rw16(udf_ea_cksum((uint8_t *) implext)); 1386 } 1387 1388 /* application use extended attributes */ 1389 assert(udf_rw32(extattr->type) != 65536); 1390 assert(appl_attr_loc == l_ea); 1391 1392 /* append the attribute at the end of the current space */ 1393 bpos = data + udf_rw32(*l_eap); 1394 a_l = udf_rw32(extattr->a_l); 1395 1396 /* update impl. attribute locations */ 1397 if (udf_rw32(extattr->type) < 2048) { 1398 impl_attr_loc = l_ea + a_l; 1399 appl_attr_loc = l_ea + a_l; 1400 } 1401 if (udf_rw32(extattr->type) == 2048) { 1402 appl_attr_loc = l_ea + a_l; 1403 } 1404 1405 /* copy and advance */ 1406 memcpy(bpos, extattr, a_l); 1407 l_ea += a_l; 1408 *l_eap = udf_rw32(l_ea); 1409 1410 /* do the `dance` again backwards */ 1411 if (context.dscrver != 2) { 1412 if (impl_attr_loc == l_ea) 1413 impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT; 1414 if (appl_attr_loc == l_ea) 1415 appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT; 1416 } 1417 1418 /* store offsets */ 1419 extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc); 1420 extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc); 1421 1422 /* make sure the header sums stays correct */ 1423 udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr); 1424} 1425 1426 1427int 1428udf_create_new_fe(struct file_entry **fep, int file_type, 1429 struct long_ad *parent_icb) 1430{ 1431 struct file_entry *fe; 1432 struct icb_tag *icb; 1433 struct timestamp birthtime; 1434 struct filetimes_extattr_entry *ft_extattr; 1435 uint32_t fidsize; 1436 uint8_t *bpos; 1437 uint32_t crclen; /* XXX: should be 16; need to detect overflow */ 1438 1439 *fep = NULL; 1440 fe = calloc(1, context.sector_size); 1441 if (fe == NULL) 1442 return ENOMEM; 1443 1444 udf_inittag(&fe->tag, TAGID_FENTRY, /* loc */ 0); 1445 icb = &fe->icbtag; 1446 1447 /* 1448 * Always use strategy type 4 unless on WORM wich we don't support 1449 * (yet). Fill in defaults and set for internal allocation of data. 1450 */ 1451 icb->strat_type = udf_rw16(4); 1452 icb->max_num_entries = udf_rw16(1); 1453 icb->file_type = file_type; /* 8 bit */ 1454 icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 1455 1456 fe->perm = udf_rw32(0x7fff); /* all is allowed */ 1457 fe->link_cnt = udf_rw16(0); /* explicit setting */ 1458 1459 fe->ckpoint = udf_rw32(1); /* user supplied file version */ 1460 udf_set_timestamp_now(&birthtime); 1461 udf_set_timestamp_now(&fe->atime); 1462 udf_set_timestamp_now(&fe->attrtime); 1463 udf_set_timestamp_now(&fe->mtime); 1464 1465 udf_set_regid(&fe->imp_id, context.impl_name); 1466 udf_add_impl_regid(&fe->imp_id); 1467 fe->unique_id = udf_rw64(context.unique_id); 1468 fe->l_ea = udf_rw32(0); 1469 1470 /* create extended attribute to record our creation time */ 1471 ft_extattr = calloc(1, UDF_FILETIMES_ATTR_SIZE(1)); 1472 ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO); 1473 ft_extattr->hdr.subtype = 1; /* [4/48.10.5] */ 1474 ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1)); 1475 ft_extattr->d_l = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */ 1476 ft_extattr->existence = UDF_FILETIMES_FILE_CREATION; 1477 ft_extattr->times[0] = birthtime; 1478 1479 udf_extattr_append_internal((union dscrptr *) fe, 1480 (struct extattr_entry *) ft_extattr); 1481 free(ft_extattr); 1482 1483 /* if its a directory, create '..' */ 1484 bpos = (uint8_t *) fe->data + udf_rw32(fe->l_ea); 1485 fidsize = 0; 1486 if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 1487 fidsize = udf_create_parentfid((struct fileid_desc *) bpos, 1488 parent_icb, context.unique_id); 1489 } 1490 udf_advance_uniqueid(); 1491 1492 /* record fidlength information */ 1493 fe->inf_len = udf_rw64(fidsize); 1494 fe->l_ad = udf_rw32(fidsize); 1495 fe->logblks_rec = udf_rw64(0); /* intern */ 1496 1497 crclen = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH; 1498 crclen += udf_rw32(fe->l_ea) + fidsize; 1499/* XXX ensure crclen doesn't exceed UINT16_MAX ? */ 1500 fe->tag.desc_crc_len = udf_rw16(crclen); 1501 1502 *fep = fe; 1503 return 0; 1504} 1505 1506 1507int 1508udf_create_new_efe(struct extfile_entry **efep, int file_type, 1509 struct long_ad *parent_icb) 1510{ 1511 struct extfile_entry *efe; 1512 struct icb_tag *icb; 1513 uint32_t fidsize; 1514 uint32_t crclen; /* XXX: should be 16; need to detect overflow */ 1515 1516 *efep = NULL; 1517 efe = calloc(1, context.sector_size); 1518 if (efe == NULL) 1519 return ENOMEM; 1520 1521 udf_inittag(&efe->tag, TAGID_EXTFENTRY, /* loc */ 0); 1522 icb = &efe->icbtag; 1523 1524 /* 1525 * Always use strategy type 4 unless on WORM wich we don't support 1526 * (yet). Fill in defaults and set for internal allocation of data. 1527 */ 1528 icb->strat_type = udf_rw16(4); 1529 icb->max_num_entries = udf_rw16(1); 1530 icb->file_type = file_type; /* 8 bit */ 1531 icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC); 1532 1533 efe->perm = udf_rw32(0x7fff); /* all is allowed */ 1534 efe->link_cnt = udf_rw16(0); /* explicit setting */ 1535 1536 efe->ckpoint = udf_rw32(1); /* user supplied file version */ 1537 udf_set_timestamp_now(&efe->ctime); 1538 udf_set_timestamp_now(&efe->atime); 1539 udf_set_timestamp_now(&efe->attrtime); 1540 udf_set_timestamp_now(&efe->mtime); 1541 1542 udf_set_regid(&efe->imp_id, context.impl_name); 1543 udf_add_impl_regid(&efe->imp_id); 1544 1545 fidsize = 0; 1546 efe->unique_id = udf_rw64(context.unique_id); 1547 if (file_type == UDF_ICB_FILETYPE_DIRECTORY) { 1548 fidsize = udf_create_parentfid((struct fileid_desc *) efe->data, 1549 parent_icb, context.unique_id); 1550 } 1551 udf_advance_uniqueid(); 1552 1553 /* record fidlength information */ 1554 efe->inf_len = udf_rw64(fidsize); 1555 efe->obj_size = udf_rw64(fidsize); 1556 efe->l_ad = udf_rw32(fidsize); 1557 efe->logblks_rec = udf_rw64(0); 1558 1559 crclen = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH; 1560 crclen += fidsize; 1561/* XXX ensure crclen doesn't exceed UINT16_MAX ? */ 1562 efe->tag.desc_crc_len = udf_rw16(crclen); 1563 1564 *efep = efe; 1565 return 0; 1566} 1567 1568/* --------------------------------------------------------------------- */ 1569 1570static void 1571udf_append_mapping_part_to_efe(struct extfile_entry *efe, struct short_ad *mapping) 1572{ 1573 struct icb_tag *icb; 1574 uint64_t inf_len, obj_size, logblks_rec; 1575 uint32_t l_ad, l_ea; 1576 uint16_t crclen; 1577 uint8_t *bpos; 1578 1579 inf_len = udf_rw64(efe->inf_len); 1580 obj_size = udf_rw64(efe->obj_size); 1581 logblks_rec = udf_rw64(efe->logblks_rec); 1582 l_ad = udf_rw32(efe->l_ad); 1583 l_ea = udf_rw32(efe->l_ea); 1584 crclen = udf_rw16(efe->tag.desc_crc_len); 1585 icb = &efe->icbtag; 1586 1587 /* set our allocation to shorts if not already done */ 1588 icb->flags = udf_rw16(UDF_ICB_SHORT_ALLOC); 1589 1590 /* append short_ad */ 1591 bpos = (uint8_t *) efe->data + l_ea + l_ad; 1592 memcpy(bpos, mapping, sizeof(struct short_ad)); 1593 1594 l_ad += sizeof(struct short_ad); 1595 crclen += sizeof(struct short_ad); 1596 inf_len += UDF_EXT_LEN(udf_rw32(mapping->len)); 1597 obj_size += UDF_EXT_LEN(udf_rw32(mapping->len)); 1598 logblks_rec = UDF_ROUNDUP(inf_len, context.sector_size) / 1599 context.sector_size; 1600 1601 efe->l_ad = udf_rw32(l_ad); 1602 efe->inf_len = udf_rw64(inf_len); 1603 efe->obj_size = udf_rw64(obj_size); 1604 efe->logblks_rec = udf_rw64(logblks_rec); 1605 efe->tag.desc_crc_len = udf_rw16(crclen); 1606} 1607 1608 1609static void 1610udf_append_meta_mapping_to_efe(struct extfile_entry *efe, uint16_t partnr, uint32_t lb_num, 1611 uint64_t len) 1612{ 1613 struct short_ad mapping; 1614 uint64_t max_len, part_len; 1615 1616 /* calculate max length meta allocation sizes */ 1617 max_len = UDF_EXT_MAXLEN / context.sector_size; /* in sectors */ 1618 max_len = (max_len / layout.meta_blockingnr) * layout.meta_blockingnr; 1619 max_len = max_len * context.sector_size; 1620 1621 memset(&mapping, 0, sizeof(struct short_ad)); 1622 while (len) { 1623 part_len = MIN(len, max_len); 1624 mapping.lb_num = udf_rw32(lb_num); 1625 mapping.len = udf_rw32(part_len); 1626 1627 udf_append_mapping_part_to_efe(efe, &mapping); 1628 1629 lb_num += part_len / context.sector_size; 1630 len -= part_len; 1631 } 1632} 1633 1634 1635int 1636udf_create_meta_files(void) 1637{ 1638 struct extfile_entry *efe; 1639 struct long_ad meta_icb; 1640 uint64_t bytes; 1641 uint32_t sector_size; 1642 int filetype, error; 1643 1644 sector_size = context.sector_size; 1645 1646 bzero(&meta_icb, sizeof(struct long_ad)); 1647 meta_icb.len = udf_rw32(sector_size); 1648 meta_icb.loc.part_num = udf_rw16(context.data_part); 1649 1650 /* create metadata file */ 1651 meta_icb.loc.lb_num = udf_rw32(layout.meta_file); 1652 filetype = UDF_ICB_FILETYPE_META_MAIN; 1653 error = udf_create_new_efe(&efe, filetype, &meta_icb); 1654 if (error) 1655 return error; 1656 context.meta_file = efe; 1657 1658 /* create metadata mirror file */ 1659 meta_icb.loc.lb_num = udf_rw32(layout.meta_mirror); 1660 filetype = UDF_ICB_FILETYPE_META_MIRROR; 1661 error = udf_create_new_efe(&efe, filetype, &meta_icb); 1662 if (error) 1663 return error; 1664 context.meta_mirror = efe; 1665 1666 /* create metadata bitmap file */ 1667 meta_icb.loc.lb_num = udf_rw32(layout.meta_bitmap); 1668 filetype = UDF_ICB_FILETYPE_META_BITMAP; 1669 error = udf_create_new_efe(&efe, filetype, &meta_icb); 1670 if (error) 1671 return error; 1672 context.meta_bitmap = efe; 1673 1674 /* patch up files */ 1675 context.meta_file->unique_id = udf_rw64(0); 1676 context.meta_mirror->unique_id = udf_rw64(0); 1677 context.meta_bitmap->unique_id = udf_rw64(0); 1678 1679 /* restart unique id */ 1680 context.unique_id = 0x10; 1681 1682 /* XXX no support for metadata mirroring yet */ 1683 /* insert extents */ 1684 efe = context.meta_file; 1685 udf_append_meta_mapping_to_efe(efe, context.data_part, 1686 layout.meta_part_start_lba, 1687 (uint64_t) layout.meta_part_size_lba * sector_size); 1688 1689 efe = context.meta_mirror; 1690 udf_append_meta_mapping_to_efe(efe, context.data_part, 1691 layout.meta_part_start_lba, 1692 (uint64_t) layout.meta_part_size_lba * sector_size); 1693 1694 efe = context.meta_bitmap; 1695 bytes = udf_space_bitmap_len(layout.meta_part_size_lba); 1696 udf_append_meta_mapping_to_efe(efe, context.data_part, 1697 layout.meta_bitmap_space, bytes); 1698 1699 return 0; 1700} 1701 1702 1703/* --------------------------------------------------------------------- */ 1704 1705int 1706udf_create_new_rootdir(union dscrptr **dscr) 1707{ 1708 struct file_entry *fe; 1709 struct extfile_entry *efe; 1710 struct long_ad root_icb; 1711 int filetype, error; 1712 1713 bzero(&root_icb, sizeof(struct long_ad)); 1714 root_icb.len = udf_rw32(context.sector_size); 1715 root_icb.loc.lb_num = udf_rw32(layout.rootdir); 1716 root_icb.loc.part_num = udf_rw16(context.metadata_part); 1717 1718 filetype = UDF_ICB_FILETYPE_DIRECTORY; 1719 if (context.dscrver == 2) { 1720 error = udf_create_new_fe(&fe, filetype, &root_icb); 1721 *dscr = (union dscrptr *) fe; 1722 } else { 1723 error = udf_create_new_efe(&efe, filetype, &root_icb); 1724 *dscr = (union dscrptr *) efe; 1725 } 1726 if (error) 1727 return error; 1728 1729 /* Rootdir has explicit only one link on creation; '..' is no link */ 1730 if (context.dscrver == 2) { 1731 fe->link_cnt = udf_rw16(1); 1732 } else { 1733 efe->link_cnt = udf_rw16(1); 1734 } 1735 1736 context.num_directories++; 1737 assert(context.num_directories == 1); 1738 1739 return 0; 1740} 1741 1742 1743int 1744udf_create_new_VAT(union dscrptr **vat_dscr) 1745{ 1746 struct file_entry *fe; 1747 struct extfile_entry *efe; 1748 struct impl_extattr_entry *implext; 1749 struct vatlvext_extattr_entry *vatlvext; 1750 struct udf_oldvat_tail *oldvat_tail; 1751 struct udf_vat *vathdr; 1752 uint32_t *vat_pos; 1753 uint8_t *bpos, *extattr; 1754 uint32_t ea_len, inf_len, vat_len; 1755 int filetype; 1756 int error; 1757 1758 assert((layout.rootdir < 2) && (layout.fsd < 2)); 1759 if (context.dscrver == 2) { 1760 /* old style VAT */ 1761 filetype = UDF_ICB_FILETYPE_UNKNOWN; 1762 error = udf_create_new_fe(&fe, filetype, NULL); 1763 if (error) 1764 return error; 1765 1766 /* append VAT LVExtension attribute */ 1767 ea_len = sizeof(struct impl_extattr_entry) - 1 + 1768 sizeof(struct vatlvext_extattr_entry) + 4; 1769 1770 extattr = calloc(1, ea_len); 1771 1772 implext = (struct impl_extattr_entry *) extattr; 1773 implext->hdr.type = udf_rw32(2048); /* [4/48.10.8] */ 1774 implext->hdr.subtype = 1; /* [4/48.10.8.2] */ 1775 implext->hdr.a_l = udf_rw32(ea_len); /* VAT LVext EA size */ 1776 /* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */ 1777 implext->iu_l = udf_rw32(4); 1778 udf_set_regid(&implext->imp_id, "*UDF VAT LVExtension"); 1779 udf_add_udf_regid(&implext->imp_id); 1780 1781 /* VAT LVExtension data follows UDF IU space */ 1782 bpos = ((uint8_t *) implext->data) + 4; 1783 vatlvext = (struct vatlvext_extattr_entry *) bpos; 1784 1785 vatlvext->unique_id_chk = udf_rw64(fe->unique_id); 1786 vatlvext->num_files = udf_rw32(context.num_files); 1787 vatlvext->num_directories = udf_rw32(context.num_directories); 1788 memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id, 128); 1789 1790 udf_extattr_append_internal((union dscrptr *) fe, 1791 (struct extattr_entry *) extattr); 1792 1793 free(extattr); 1794 1795 /* writeout VAT locations (partition offsets) */ 1796 vat_pos = (uint32_t *) (fe->data + udf_rw32(fe->l_ea)); 1797 vat_pos[layout.rootdir] = udf_rw32(layout.rootdir); 1798 vat_pos[layout.fsd ] = udf_rw32(layout.fsd); 1799 1800 /* Append "*UDF Virtual Alloc Tbl" id and prev. VAT location */ 1801 oldvat_tail = (struct udf_oldvat_tail *) (vat_pos + 2); 1802 udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl"); 1803 udf_add_udf_regid(&oldvat_tail->id); 1804 oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT); 1805 1806 /* set length */ 1807 inf_len = 2 * 4 + sizeof(struct udf_oldvat_tail); 1808 fe->inf_len = udf_rw64(inf_len); 1809 fe->l_ad = udf_rw32(inf_len); 1810 1811 /* update vat descriptor's CRC length */ 1812 vat_len = inf_len + udf_rw32(fe->l_ea) + 1813 sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH; 1814 fe->tag.desc_crc_len = udf_rw16(vat_len); 1815 1816 *vat_dscr = (union dscrptr *) fe; 1817 } else { 1818 /* new style VAT */ 1819 filetype = UDF_ICB_FILETYPE_VAT; 1820 error = udf_create_new_efe(&efe, filetype, NULL); 1821 if (error) 1822 return error; 1823 1824 /* set up VATv2 descriptor */ 1825 vathdr = (struct udf_vat *) efe->data; 1826 vathdr->header_len = udf_rw16(sizeof(struct udf_vat) - 1); 1827 vathdr->impl_use_len = udf_rw16(0); 1828 memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128); 1829 vathdr->prev_vat = udf_rw32(UDF_NO_PREV_VAT); 1830 vathdr->num_files = udf_rw32(context.num_files); 1831 vathdr->num_directories = udf_rw32(context.num_directories); 1832 1833 vathdr->min_udf_readver = udf_rw16(context.min_udf); 1834 vathdr->min_udf_writever = udf_rw16(context.min_udf); 1835 vathdr->max_udf_writever = udf_rw16(context.max_udf); 1836 1837 /* writeout VAT locations */ 1838 vat_pos = (uint32_t *) vathdr->data; 1839 vat_pos[layout.rootdir] = udf_rw32(layout.rootdir); 1840 vat_pos[layout.fsd ] = udf_rw32(layout.fsd); 1841 1842 /* set length */ 1843 inf_len = 2 * 4 + sizeof(struct udf_vat) - 1; 1844 efe->inf_len = udf_rw64(inf_len); 1845 efe->obj_size = udf_rw64(inf_len); 1846 efe->l_ad = udf_rw32(inf_len); 1847 efe->logblks_rec = udf_rw32(0); 1848 1849 vat_len = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH; 1850 vat_len += inf_len; 1851 efe->tag.desc_crc_len = udf_rw16(vat_len); 1852 1853 *vat_dscr = (union dscrptr *) efe; 1854 } 1855 1856 return 0; 1857} 1858 1859