Home | History | Annotate | Line # | Download | only in newfs_udf
udf_core.c revision 1.1
      1 /* $NetBSD: udf_core.c,v 1.1 2022/04/06 13:29:15 reinoud Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2006, 2008, 2021, 2022 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_core.c,v 1.1 2022/04/06 13:29:15 reinoud Exp $");
     34 
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <stddef.h>
     38 #include <string.h>
     39 #include <strings.h>
     40 #include <unistd.h>
     41 #include <errno.h>
     42 #include <time.h>
     43 #include <assert.h>
     44 #include <err.h>
     45 #include <fcntl.h>
     46 #include <util.h>
     47 #include <sys/types.h>
     48 #include <sys/param.h>
     49 #include <sys/ioctl.h>
     50 #include <sys/queue.h>
     51 #include "newfs_udf.h"
     52 #include "unicode.h"
     53 #include "udf_core.h"
     54 
     55 
     56 /* disk partition support */
     57 #if !HAVE_NBTOOL_CONFIG_H
     58 #include "../fsck/partutil.h"
     59 #include "../fsck/partutil.c"
     60 #endif
     61 
     62 
     63 /* queue for temporary storage of sectors to be written out */
     64 struct wrpacket {
     65 	uint64_t  start_sectornr;
     66 	uint8_t	 *packet_data;
     67 	uint64_t  present;
     68 	TAILQ_ENTRY(wrpacket) next;
     69 };
     70 
     71 
     72 /* global variables describing disc and format requests */
     73 struct udf_create_context context;
     74 struct udf_disclayout     layout;
     75 
     76 
     77 int		 dev_fd_rdonly;		/* device: open readonly!	*/
     78 int		 dev_fd;		/* device: file descriptor	*/
     79 struct stat	 dev_fd_stat;	  	/* device: last stat info	*/
     80 char		*dev_name;		/* device: name			*/
     81 int	 	 emul_mmc_profile;	/* for files			*/
     82 int	 	 emul_packetsize;	/* for discs and files		*/
     83 int		 emul_sectorsize;	/* for files			*/
     84 off_t		 emul_size;		/* for files			*/
     85 
     86 struct mmc_discinfo mmc_discinfo;	/* device: disc info		*/
     87 union dscrptr *terminator_dscr;		/* generic terminator descriptor*/
     88 
     89 
     90 /* write queue and track blocking skew */
     91 TAILQ_HEAD(wrpacket_list, wrpacket) write_queue;
     92 int	  write_queuelen;
     93 int	  write_queue_suspend;
     94 uint32_t  wrtrack_skew;			/* offset for writing sector0	*/
     95 
     96 static void udf_init_writequeue(int write_strategy);
     97 static int  udf_writeout_writequeue(bool complete);
     98 
     99 /*
    100  * NOTE that there is some overlap between this code and the udf kernel fs.
    101  * This is intentionally though it might better be factored out one day.
    102  */
    103 
    104 void
    105 udf_init_create_context(void)
    106 {
    107 	/* clear */
    108 	memset(&context, 0, sizeof(struct udf_create_context));
    109 
    110 	/* fill with defaults currently known */
    111 	context.dscrver   = 3;
    112 	context.min_udf   = 0x0102;
    113 	context.max_udf   = 0x0250;
    114 	context.serialnum = 1;		/* default */
    115 
    116 	context.gmtoff        = 0;
    117 	context.meta_perc     = UDF_META_PERC;
    118 	context.check_surface = 0;
    119 	context.create_new_session  = 0;
    120 
    121 	context.sector_size      = 512;	/* minimum for UDF */
    122 	context.media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
    123 	context.format_flags     = FORMAT_INVALID;
    124 	context.write_strategy   = UDF_WRITE_PACKET;
    125 
    126 	context.logvol_name  = NULL;
    127 	context.primary_name = NULL;
    128 	context.volset_name  = NULL;
    129 	context.fileset_name = NULL;
    130 
    131 	/* most basic identification */
    132 	context.app_name	 = "*NetBSD";
    133 	context.app_version_main = 0;
    134 	context.app_version_sub  = 0;
    135 	context.impl_name        = "*NetBSD";
    136 
    137 	context.vds_seq = 0;	/* first one starts with zero */
    138 
    139 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
    140 	context.unique_id       = 0x10;
    141 
    142 	context.num_files       = 0;
    143 	context.num_directories = 0;
    144 
    145 	context.data_part          = 0;
    146 	context.metadata_part      = 0;
    147 }
    148 
    149 
    150 /* version can be specified as 0xabc or a.bc */
    151 static int
    152 parse_udfversion(const char *pos, uint32_t *version) {
    153 	int hex = 0;
    154 	char c1, c2, c3, c4;
    155 
    156 	*version = 0;
    157 	if (*pos == '0') {
    158 		pos++;
    159 		/* expect hex format */
    160 		hex = 1;
    161 		if (*pos++ != 'x')
    162 			return 1;
    163 	}
    164 
    165 	c1 = *pos++;
    166 	if (c1 < '0' || c1 > '9')
    167 		return 1;
    168 	c1 -= '0';
    169 
    170 	c2 = *pos++;
    171 	if (!hex) {
    172 		if (c2 != '.')
    173 			return 1;
    174 		c2 = *pos++;
    175 	}
    176 	if (c2 < '0' || c2 > '9')
    177 		return 1;
    178 	c2 -= '0';
    179 
    180 	c3 = *pos++;
    181 	if (c3 < '0' || c3 > '9')
    182 		return 1;
    183 	c3 -= '0';
    184 
    185 	c4 = *pos++;
    186 	if (c4 != 0)
    187 		return 1;
    188 
    189 	*version = c1 * 0x100 + c2 * 0x10 + c3;
    190 	return 0;
    191 }
    192 
    193 
    194 /*
    195  * Parse a given string for an udf version.
    196  * May exit.
    197  */
    198 int
    199 a_udf_version(const char *s, const char *id_type)
    200 {
    201 	uint32_t version;
    202 
    203 	if (parse_udfversion(s, &version))
    204 		errx(1, "unknown %s version %s; specify as hex or float", id_type, s);
    205 	switch (version) {
    206 		case 0x102:
    207 		case 0x150:
    208 		case 0x200:
    209 		case 0x201:
    210 		case 0x250:
    211 			break;
    212 		case 0x260:
    213 			/* we don't support this one */
    214 			errx(1, "UDF version 0x260 is not supported");
    215 			break;
    216 		default:
    217 			errx(1, "unknown %s version %s, choose from "
    218 				"0x102, 0x150, 0x200, 0x201, 0x250",
    219 				id_type, s);
    220 	}
    221 	return version;
    222 }
    223 
    224 
    225 static uint32_t
    226 udf_space_bitmap_len(uint32_t part_size)
    227 {
    228 	return  sizeof(struct space_bitmap_desc)-1 +
    229 		part_size/8;
    230 }
    231 
    232 
    233 uint32_t
    234 udf_bytes_to_sectors(uint64_t bytes)
    235 {
    236 	uint32_t sector_size = context.sector_size;
    237 	return (bytes + sector_size -1) / sector_size;
    238 }
    239 
    240 
    241 void
    242 udf_dump_layout(void) {
    243 #ifdef DEBUG
    244 	int format_flags = context.format_flags;
    245 	int sector_size  = context.sector_size;
    246 
    247 	printf("Summary so far\n");
    248 	printf("\tiso9660_vrs\t\t%d\n", layout.iso9660_vrs);
    249 	printf("\tanchor0\t\t\t%d\n", layout.anchors[0]);
    250 	printf("\tanchor1\t\t\t%d\n", layout.anchors[1]);
    251 	printf("\tanchor2\t\t\t%d\n", layout.anchors[2]);
    252 	printf("\tvds1_size\t\t%d\n", layout.vds1_size);
    253 	printf("\tvds2_size\t\t%d\n", layout.vds2_size);
    254 	printf("\tvds1\t\t\t%d\n", layout.vds1);
    255 	printf("\tvds2\t\t\t%d\n", layout.vds2);
    256 	printf("\tlvis_size\t\t%d\n", layout.lvis_size);
    257 	printf("\tlvis\t\t\t%d\n", layout.lvis);
    258 	if (format_flags & FORMAT_SPAREABLE) {
    259 		printf("\tspareable size\t\t%d\n", layout.spareable_area_size);
    260 		printf("\tspareable\t\t%d\n", layout.spareable_area);
    261 	}
    262 	printf("\tpartition start lba\t%d\n", layout.part_start_lba);
    263 	printf("\tpartition size\t\t%ld KiB, %ld MiB\n",
    264 		((uint64_t) layout.part_size_lba * sector_size) / 1024,
    265 		((uint64_t) layout.part_size_lba * sector_size) / (1024*1024));
    266 	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
    267 		printf("\tpart bitmap start\t%d\n",   layout.unalloc_space);
    268 		printf("\t\tfor %d lba\n", layout.alloc_bitmap_dscr_size);
    269 	}
    270 	if (format_flags & FORMAT_META) {
    271 		printf("\tmeta blockingnr\t\t%d\n", layout.meta_blockingnr);
    272 		printf("\tmeta alignment\t\t%d\n",  layout.meta_alignment);
    273 		printf("\tmeta size\t\t%ld KiB, %ld MiB\n",
    274 			((uint64_t) layout.meta_part_size_lba * sector_size) / 1024,
    275 			((uint64_t) layout.meta_part_size_lba * sector_size) / (1024*1024));
    276 		printf("\tmeta file\t\t%d\n", layout.meta_file);
    277 		printf("\tmeta mirror\t\t%d\n", layout.meta_mirror);
    278 		printf("\tmeta bitmap\t\t%d\n", layout.meta_bitmap);
    279 		printf("\tmeta bitmap start\t%d\n", layout.meta_bitmap_space);
    280 		printf("\t\tfor %d lba\n", layout.meta_bitmap_dscr_size);
    281 		printf("\tmeta space start\t%d\n",  layout.meta_part_start_lba);
    282 		printf("\t\tfor %d lba\n", layout.meta_part_size_lba);
    283 	}
    284 	printf("\n");
    285 #endif
    286 }
    287 
    288 
    289 int
    290 udf_calculate_disc_layout(int min_udf,
    291 	uint32_t first_lba, uint32_t last_lba,
    292 	uint32_t sector_size, uint32_t blockingnr)
    293 {
    294 	uint64_t kbsize, bytes;
    295 	uint32_t spareable_blockingnr;
    296 	uint32_t align_blockingnr;
    297 	uint32_t pos, mpos;
    298 	int	 format_flags = context.format_flags;
    299 
    300 	/* clear */
    301 	memset(&layout, 0, sizeof(layout));
    302 
    303 	/* fill with parameters */
    304 	layout.wrtrack_skew    = wrtrack_skew;
    305 	layout.first_lba       = first_lba;
    306 	layout.last_lba        = last_lba;
    307 	layout.blockingnr      = blockingnr;
    308 	layout.spareable_blocks = udf_spareable_blocks();
    309 
    310 	/* start disc layouting */
    311 
    312 	/*
    313 	 * location of iso9660 vrs is defined as first sector AFTER 32kb,
    314 	 * minimum `sector size' 2048
    315 	 */
    316 	layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
    317 		+ first_lba;
    318 
    319 	/* anchor starts at specified offset in sectors */
    320 	layout.anchors[0] = first_lba + 256;
    321 	if (format_flags & FORMAT_TRACK512)
    322 		layout.anchors[0] = first_lba + 512;
    323 	layout.anchors[1] = last_lba - 256;
    324 	layout.anchors[2] = last_lba;
    325 
    326 	/* update workable space */
    327 	first_lba = layout.anchors[0] + blockingnr;
    328 	last_lba  = layout.anchors[1] - 1;
    329 
    330 	/* XXX rest of anchor packet can be added to unallocated space descr */
    331 
    332 	/* reserve space for VRS and VRS copy and associated tables */
    333 	layout.vds1_size = MAX(16, blockingnr);     /* UDF 2.2.3.1+2 */
    334 	layout.vds1 = first_lba;
    335 	first_lba += layout.vds1_size;              /* next packet */
    336 
    337 	layout.vds2_size = layout.vds1_size;
    338 	if (format_flags & FORMAT_SEQUENTIAL) {
    339 		/* for sequential, append them ASAP */
    340 		layout.vds2 = first_lba;
    341 		first_lba += layout.vds2_size;
    342 	} else {
    343 		layout.vds2 = layout.anchors[1] +1 - layout.vds2_size;
    344 		last_lba = layout.vds2 - 1;
    345 	}
    346 
    347 	/*
    348 	 * Reserve space for logvol integrity sequence, at least 8192 bytes
    349 	 * for overwritable and rewritable media UDF 2.2.4.6, ECMA 3/10.6.12.
    350 	 */
    351 	layout.lvis_size = MAX(8192.0/sector_size, 2 * blockingnr);
    352 	if (layout.lvis_size * sector_size < 8192)
    353 		layout.lvis_size++;
    354 	if (format_flags & FORMAT_VAT)
    355 		layout.lvis_size = 2;
    356 	if (format_flags & FORMAT_WORM)
    357 		layout.lvis_size = 64 * blockingnr;
    358 
    359 	/* TODO skip bad blocks in LVID sequence */
    360 	layout.lvis = first_lba;
    361 	first_lba += layout.lvis_size;
    362 
    363 	/* initial guess of UDF partition size */
    364 	layout.part_start_lba = first_lba;
    365 	layout.part_size_lba = last_lba - layout.part_start_lba;
    366 
    367 	/* all non sequential media needs an unallocated space bitmap */
    368 	layout.alloc_bitmap_dscr_size = 0;
    369 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
    370 		bytes = udf_space_bitmap_len(layout.part_size_lba);
    371 		layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
    372 
    373 		/* XXX freed space map when applicable */
    374 	}
    375 
    376 	spareable_blockingnr = udf_spareable_blockingnr();
    377 	align_blockingnr = blockingnr;
    378 
    379 	if (format_flags & (FORMAT_SPAREABLE | FORMAT_META))
    380 		align_blockingnr = spareable_blockingnr;
    381 
    382 	layout.align_blockingnr    = align_blockingnr;
    383 	layout.spareable_blockingnr = spareable_blockingnr;
    384 
    385 	/*
    386 	 * Align partition LBA space to blocking granularity. Not strictly
    387 	 * necessary for non spareables but safer for the VRS data since it is
    388 	 * updated sporadically
    389 	 */
    390 
    391 #ifdef DEBUG
    392 	printf("Lost %lu slack sectors at start\n", UDF_ROUNDUP(
    393 		first_lba, align_blockingnr) -
    394 		first_lba);
    395 	printf("Lost %lu slack sectors at end\n",
    396 		last_lba - UDF_ROUNDDOWN(
    397 		last_lba, align_blockingnr));
    398 #endif
    399 
    400 	first_lba = UDF_ROUNDUP(first_lba, align_blockingnr);
    401 	last_lba  = UDF_ROUNDDOWN(last_lba, align_blockingnr);
    402 
    403 	if ((format_flags & FORMAT_SPAREABLE) == 0)
    404 		layout.spareable_blocks = 0;
    405 
    406 	if (format_flags & FORMAT_SPAREABLE) {
    407 		layout.spareable_area_size =
    408 			layout.spareable_blocks * spareable_blockingnr;
    409 
    410 		/* a sparing table descriptor is a whole blockingnr sectors */
    411 		layout.sparing_table_dscr_lbas = spareable_blockingnr;
    412 
    413 		/* place the descriptors at the start and end of the area */
    414 		layout.spt_1 = first_lba;
    415 		first_lba += layout.sparing_table_dscr_lbas;
    416 
    417 		layout.spt_2 = last_lba - layout.sparing_table_dscr_lbas;
    418 		last_lba -= layout.sparing_table_dscr_lbas;
    419 
    420 		/* allocate spareable section */
    421 		layout.spareable_area = first_lba;
    422 		first_lba += layout.spareable_area_size;
    423 	}
    424 
    425 	/* update guess of UDF partition size */
    426 	layout.part_start_lba = first_lba;
    427 	layout.part_size_lba = last_lba - layout.part_start_lba;
    428 
    429 	/* determine partition selection for data and metadata */
    430 	context.data_part     = 0;
    431 	context.metadata_part = context.data_part;
    432 	if ((format_flags & FORMAT_VAT) || (format_flags & FORMAT_META))
    433 		context.metadata_part = context.data_part + 1;
    434 	context.fids_part = context.metadata_part;
    435 	if (format_flags & FORMAT_VAT)
    436 		context.fids_part = context.data_part;
    437 
    438 	/*
    439 	 * Pick fixed logical space sector numbers for main FSD, rootdir and
    440 	 * unallocated space. The reason for this pre-allocation is that they
    441 	 * are referenced in the volume descriptor sequence and hence can't be
    442 	 * allocated later.
    443 	 */
    444 	pos = 0;
    445 	layout.unalloc_space = pos;
    446 	pos += layout.alloc_bitmap_dscr_size;
    447 
    448 	/* claim metadata descriptors and partition space [UDF 2.2.10] */
    449 	if (format_flags & FORMAT_META) {
    450 		/* note: all in backing partition space */
    451 		layout.meta_file   = pos++;
    452 		layout.meta_bitmap = 0xffffffff;
    453 		if (!(context.format_flags & FORMAT_READONLY))
    454 			layout.meta_bitmap = pos++;
    455 		layout.meta_mirror = layout.part_size_lba-1;
    456 		layout.meta_alignment  = MAX(blockingnr, spareable_blockingnr);
    457 		layout.meta_blockingnr = MAX(layout.meta_alignment, 32);
    458 
    459 		/* calculate our partition length and store in sectors */
    460 		layout.meta_part_size_lba = layout.part_size_lba *
    461 			((float) context.meta_perc / 100.0);
    462 		layout.meta_part_size_lba = MAX(layout.meta_part_size_lba, 32);
    463 		layout.meta_part_size_lba =
    464 			UDF_ROUNDDOWN(layout.meta_part_size_lba, layout.meta_blockingnr);
    465 
    466 		if (!(context.format_flags & FORMAT_READONLY)) {
    467 			/* metadata partition free space bitmap */
    468 			bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
    469 			layout.meta_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
    470 
    471 			layout.meta_bitmap_space = pos;
    472 			pos += layout.meta_bitmap_dscr_size;
    473 		}
    474 
    475 		layout.meta_part_start_lba  = UDF_ROUNDUP(pos, layout.meta_alignment);
    476 		pos = layout.meta_part_start_lba + layout.meta_part_size_lba;
    477 	}
    478 
    479 	if (context.metadata_part == context.data_part) {
    480 		mpos = pos;
    481 		layout.fsd           = mpos;	mpos += 1;
    482 		layout.rootdir       = mpos;
    483 		pos = mpos;
    484 	} else {
    485 		mpos = 0;
    486 		layout.fsd           = mpos;	mpos += 1;
    487 		layout.rootdir       = mpos;
    488 	}
    489 
    490 	/* pos and mpos now refer to the rootdir block */
    491 	context.alloc_pos[context.data_part] = pos;
    492 	context.alloc_pos[context.metadata_part] = mpos;
    493 
    494 	udf_dump_layout();
    495 
    496 	kbsize = (uint64_t) last_lba * sector_size;
    497 	printf("Total space on this medium approx. "
    498 			"%"PRIu64" KiB, %"PRIu64" MiB\n",
    499 			kbsize/1024, kbsize/(1024*1024));
    500 	kbsize = (uint64_t)(layout.part_size_lba - layout.alloc_bitmap_dscr_size
    501 		- layout.meta_bitmap_dscr_size) * sector_size;
    502 	printf("Recordable free space on this volume approx.  "
    503 			"%"PRIu64" KiB, %"PRIu64" MiB\n\n",
    504 			kbsize/1024, kbsize/(1024*1024));
    505 
    506 	return 0;
    507 }
    508 
    509 
    510 /*
    511  * Check if the blob starts with a good UDF tag. Tags are protected by a
    512  * checksum over the header, except one byte at position 4 that is the
    513  * checksum itself.
    514  */
    515 int
    516 udf_check_tag(void *blob)
    517 {
    518 	struct desc_tag *tag = blob;
    519 	uint8_t *pos, sum, cnt;
    520 
    521 	/* check TAG header checksum */
    522 	pos = (uint8_t *) tag;
    523 	sum = 0;
    524 
    525 	for(cnt = 0; cnt < 16; cnt++) {
    526 		if (cnt != 4)
    527 			sum += *pos;
    528 		pos++;
    529 	}
    530 	if (sum != tag->cksum) {
    531 		/* bad tag header checksum; this is not a valid tag */
    532 		return EINVAL;
    533 	}
    534 
    535 	return 0;
    536 }
    537 
    538 
    539 /*
    540  * check tag payload will check descriptor CRC as specified.
    541  * If the descriptor is too long, it will return EIO otherwise EINVAL.
    542  */
    543 int
    544 udf_check_tag_payload(void *blob, uint32_t max_length)
    545 {
    546 	struct desc_tag *tag = blob;
    547 	uint16_t crc, crc_len;
    548 
    549 	crc_len = udf_rw16(tag->desc_crc_len);
    550 
    551 	/* check payload CRC if applicable */
    552 	if (crc_len == 0)
    553 		return 0;
    554 
    555 	if (crc_len > max_length)
    556 		return EIO;
    557 
    558 	crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH, crc_len);
    559 	if (crc != udf_rw16(tag->desc_crc)) {
    560 		/* bad payload CRC; this is a broken tag */
    561 		return EINVAL;
    562 	}
    563 
    564 	return 0;
    565 }
    566 
    567 
    568 int
    569 udf_check_tag_and_location(void *blob, uint32_t location)
    570 {
    571 	struct desc_tag *tag = blob;
    572 
    573 	if (udf_check_tag(blob))
    574 		return 1;
    575 	if (udf_rw32(tag->tag_loc) != location)
    576 		return 1;
    577 	return 0;
    578 }
    579 
    580 
    581 int
    582 udf_validate_tag_sum(union dscrptr *dscr)
    583 {
    584 	struct desc_tag *tag = &dscr->tag;
    585 	uint8_t *pos, sum, cnt;
    586 
    587 	/* calculate TAG header checksum */
    588 	pos = (uint8_t *) tag;
    589 	sum = 0;
    590 
    591 	for (cnt = 0; cnt < 16; cnt++) {
    592 		if (cnt != 4) sum += *pos;
    593 		pos++;
    594 	};
    595 	tag->cksum = sum;	/* 8 bit */
    596 
    597 	return 0;
    598 }
    599 
    600 
    601 /* assumes sector number of descriptor to be already present */
    602 int
    603 udf_validate_tag_and_crc_sums(union dscrptr *dscr)
    604 {
    605 	struct desc_tag *tag = &dscr->tag;
    606 	uint16_t crc;
    607 
    608 	/* check payload CRC if applicable */
    609 	if (udf_rw16(tag->desc_crc_len) > 0) {
    610 		crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH,
    611 			udf_rw16(tag->desc_crc_len));
    612 		tag->desc_crc = udf_rw16(crc);
    613 	};
    614 
    615 	/* calculate TAG header checksum */
    616 	return udf_validate_tag_sum(dscr);
    617 }
    618 
    619 
    620 void
    621 udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc)
    622 {
    623 	tag->id 		= udf_rw16(tagid);
    624 	tag->descriptor_ver	= udf_rw16(context.dscrver);
    625 	tag->cksum		= 0;
    626 	tag->reserved		= 0;
    627 	tag->serial_num		= udf_rw16(context.serialnum);
    628 	tag->tag_loc            = udf_rw32(loc);
    629 }
    630 
    631 
    632 int
    633 udf_create_anchor(int num)
    634 {
    635 	struct anchor_vdp *avdp;
    636 	uint32_t vds1_extent_len = layout.vds1_size * context.sector_size;
    637 	uint32_t vds2_extent_len = layout.vds2_size * context.sector_size;
    638 
    639 	avdp = context.anchors[num];
    640 	if (!avdp)
    641 		if ((avdp = calloc(1, context.sector_size)) == NULL)
    642 			return ENOMEM;
    643 
    644 	udf_inittag(&avdp->tag, TAGID_ANCHOR, layout.anchors[num]);
    645 
    646 	avdp->main_vds_ex.loc = udf_rw32(layout.vds1);
    647 	avdp->main_vds_ex.len = udf_rw32(vds1_extent_len);
    648 
    649 	avdp->reserve_vds_ex.loc = udf_rw32(layout.vds2);
    650 	avdp->reserve_vds_ex.len = udf_rw32(vds2_extent_len);
    651 
    652 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
    653 	avdp->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
    654 
    655 	context.anchors[num] = avdp;
    656 	return 0;
    657 }
    658 
    659 
    660 void
    661 udf_create_terminator(union dscrptr *dscr, uint32_t loc)
    662 {
    663 	memset(dscr, 0, context.sector_size);
    664 	udf_inittag(&dscr->tag, TAGID_TERM, loc);
    665 
    666 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
    667 	dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
    668 }
    669 
    670 
    671 void
    672 udf_osta_charset(struct charspec *charspec)
    673 {
    674 	memset(charspec, 0, sizeof(*charspec));
    675 	charspec->type = 0;
    676 	strcpy((char *) charspec->inf, "OSTA Compressed Unicode");
    677 }
    678 
    679 
    680 /* ---- shared from kernel's udf_subr.c, slightly modified ---- */
    681 void
    682 udf_to_unix_name(char *result, int result_len, char *id, int len,
    683 	struct charspec *chsp)
    684 {
    685 	uint16_t   *raw_name, *unix_name;
    686 	uint16_t   *inchp, ch;
    687 	char	   *outchp;
    688 	const char *osta_id = "OSTA Compressed Unicode";
    689 	int         ucode_chars, nice_uchars, is_osta_typ0, nout;
    690 
    691 	raw_name = malloc(2048 * sizeof(uint16_t));
    692 	assert(raw_name);
    693 
    694 	unix_name = raw_name + 1024;			/* split space in half */
    695 	assert(sizeof(char) == sizeof(uint8_t));
    696 	outchp = result;
    697 
    698 	is_osta_typ0  = (chsp->type == 0);
    699 	is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
    700 	if (is_osta_typ0) {
    701 		/* TODO clean up */
    702 		*raw_name = *unix_name = 0;
    703 		ucode_chars = udf_UncompressUnicode(len, (uint8_t *) id, raw_name);
    704 		ucode_chars = MIN(ucode_chars, UnicodeLength((unicode_t *) raw_name));
    705 		nice_uchars = UDFTransName(unix_name, raw_name, ucode_chars);
    706 		/* output UTF8 */
    707 		for (inchp = unix_name; nice_uchars>0; inchp++, nice_uchars--) {
    708 			ch = *inchp;
    709 			nout = wput_utf8(outchp, result_len, ch);
    710 			outchp += nout; result_len -= nout;
    711 			if (!ch) break;
    712 		}
    713 		*outchp++ = 0;
    714 	} else {
    715 		/* assume 8bit char length byte latin-1 */
    716 		assert(*id == 8);
    717 		assert(strlen((char *) (id+1)) <= NAME_MAX);
    718 		memcpy((char *) result, (char *) (id+1), strlen((char *) (id+1)));
    719 	}
    720 	free(raw_name);
    721 }
    722 
    723 
    724 void
    725 unix_to_udf_name(char *result, uint8_t *result_len, char const *name, int name_len,
    726 	struct charspec *chsp)
    727 {
    728 	uint16_t   *raw_name;
    729 	uint16_t   *outchp;
    730 	const char *inchp;
    731 	const char *osta_id = "OSTA Compressed Unicode";
    732 	int         udf_chars, is_osta_typ0, bits;
    733 	size_t      cnt;
    734 
    735 	/* allocate temporary unicode-16 buffer */
    736 	raw_name = malloc(1024);
    737 	assert(raw_name);
    738 
    739 	/* convert utf8 to unicode-16 */
    740 	*raw_name = 0;
    741 	inchp  = name;
    742 	outchp = raw_name;
    743 	bits = 8;
    744 	for (cnt = name_len, udf_chars = 0; cnt;) {
    745 		*outchp = wget_utf8(&inchp, &cnt);
    746 		if (*outchp > 0xff)
    747 			bits=16;
    748 		outchp++;
    749 		udf_chars++;
    750 	}
    751 	/* null terminate just in case */
    752 	*outchp++ = 0;
    753 
    754 	is_osta_typ0  = (chsp->type == 0);
    755 	is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
    756 	if (is_osta_typ0) {
    757 		udf_chars = udf_CompressUnicode(udf_chars, bits,
    758 				(unicode_t *) raw_name,
    759 				(byte *) result);
    760 	} else {
    761 		printf("unix to udf name: no CHSP0 ?\n");
    762 		/* XXX assume 8bit char length byte latin-1 */
    763 		*result++ = 8; udf_chars = 1;
    764 		strncpy(result, name + 1, name_len);
    765 		udf_chars += name_len;
    766 	}
    767 	*result_len = udf_chars;
    768 	free(raw_name);
    769 }
    770 
    771 
    772 /* first call udf_set_regid and then the suffix */
    773 void
    774 udf_set_regid(struct regid *regid, char const *name)
    775 {
    776 	memset(regid, 0, sizeof(*regid));
    777 	regid->flags    = 0;		/* not dirty and not protected */
    778 	strcpy((char *) regid->id, name);
    779 }
    780 
    781 
    782 void
    783 udf_add_domain_regid(struct regid *regid)
    784 {
    785 	uint16_t *ver;
    786 
    787 	ver  = (uint16_t *) regid->id_suffix;
    788 	*ver = udf_rw16(context.min_udf);
    789 }
    790 
    791 
    792 void
    793 udf_add_udf_regid(struct regid *regid)
    794 {
    795 	uint16_t *ver;
    796 
    797 	ver  = (uint16_t *) regid->id_suffix;
    798 	*ver = udf_rw16(context.min_udf);
    799 
    800 	regid->id_suffix[2] = 4;	/* unix */
    801 	regid->id_suffix[3] = 8;	/* NetBSD */
    802 }
    803 
    804 
    805 void
    806 udf_add_impl_regid(struct regid *regid)
    807 {
    808 	regid->id_suffix[0] = 4;	/* unix */
    809 	regid->id_suffix[1] = 8;	/* NetBSD */
    810 }
    811 
    812 
    813 void
    814 udf_add_app_regid(struct regid *regid)
    815 {
    816 	regid->id_suffix[0] = context.app_version_main;
    817 	regid->id_suffix[1] = context.app_version_sub;
    818 }
    819 
    820 
    821 /*
    822  * Timestamp to timespec conversion code is taken with small modifications
    823  * from FreeBSD /sys/fs/udf by Scott Long <scottl (at) freebsd.org>
    824  */
    825 
    826 static int mon_lens[2][12] = {
    827 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    828 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    829 };
    830 
    831 
    832 static int
    833 udf_isaleapyear(int year)
    834 {
    835 	int i;
    836 
    837 	i = (year % 4) ? 0 : 1;
    838 	i &= (year % 100) ? 1 : 0;
    839 	i |= (year % 400) ? 0 : 1;
    840 
    841 	return i;
    842 }
    843 
    844 
    845 void
    846 udf_timestamp_to_timespec(struct timestamp *timestamp, struct timespec *timespec)
    847 {
    848 	uint32_t usecs, secs, nsecs;
    849 	uint16_t tz;
    850 	int i, lpyear, daysinyear, year;
    851 
    852 	timespec->tv_sec  = secs  = 0;
    853 	timespec->tv_nsec = nsecs = 0;
    854 
    855        /*
    856 	* DirectCD seems to like using bogus year values.
    857 	* Distrust time->month especially, since it will be used for an array
    858 	* index.
    859 	*/
    860 	year = udf_rw16(timestamp->year);
    861 	if ((year < 1970) || (timestamp->month > 12)) {
    862 		return;
    863 	}
    864 
    865 	/* Calculate the time and day */
    866 	usecs = timestamp->usec + 100*timestamp->hund_usec + 10000*timestamp->centisec;
    867 	nsecs = usecs * 1000;
    868 	secs  = timestamp->second;
    869 	secs += timestamp->minute * 60;
    870 	secs += timestamp->hour * 3600;
    871 	secs += (timestamp->day-1) * 3600 * 24;			/* day : 1-31 */
    872 
    873 	/* Calclulate the month */
    874 	lpyear = udf_isaleapyear(year);
    875 	for (i = 1; i < timestamp->month; i++)
    876 		secs += mon_lens[lpyear][i-1] * 3600 * 24;	/* month: 1-12 */
    877 
    878 	for (i = 1970; i < year; i++) {
    879 		daysinyear = udf_isaleapyear(i) + 365 ;
    880 		secs += daysinyear * 3600 * 24;
    881 	}
    882 
    883 	/*
    884 	 * Calculate the time zone.  The timezone is 12 bit signed 2's
    885 	 * compliment, so we gotta do some extra magic to handle it right.
    886 	 */
    887 	tz  = udf_rw16(timestamp->type_tz);
    888 	tz &= 0x0fff;				/* only lower 12 bits are significant */
    889 	if (tz & 0x0800)			/* sign extention */
    890 		tz |= 0xf000;
    891 
    892 	/* TODO check timezone conversion */
    893 #if 1
    894 	/* check if we are specified a timezone to convert */
    895 	if (udf_rw16(timestamp->type_tz) & 0x1000)
    896 		if ((int16_t) tz != -2047)
    897 			secs -= (int16_t) tz * 60;
    898 #endif
    899 	timespec->tv_sec  = secs;
    900 	timespec->tv_nsec = nsecs;
    901 }
    902 
    903 
    904 /*
    905  * Fill in timestamp structure based on clock_gettime(). Time is reported back
    906  * as a time_t accompanied with a nano second field.
    907  *
    908  * The husec, usec and csec could be relaxed in type.
    909  */
    910 void
    911 udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp)
    912 {
    913 	struct tm tm;
    914 	uint64_t husec, usec, csec;
    915 
    916 	memset(timestamp, 0, sizeof(*timestamp));
    917 	gmtime_r(&timespec->tv_sec, &tm);
    918 
    919 	/*
    920 	 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
    921 	 *
    922 	 * Lower 12 bits are two complement signed timezone offset if bit 12
    923 	 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
    924 	 * offset to -2047 i.e. unsigned `zero'
    925 	 */
    926 
    927 	/* set method 1 for CUT/GMT */
    928 	timestamp->type_tz	= udf_rw16((1<<12) + 0);
    929 	timestamp->year		= udf_rw16(tm.tm_year + 1900);
    930 	timestamp->month	= tm.tm_mon + 1;	/* `tm' uses 0..11 for months */
    931 	timestamp->day		= tm.tm_mday;
    932 	timestamp->hour		= tm.tm_hour;
    933 	timestamp->minute	= tm.tm_min;
    934 	timestamp->second	= tm.tm_sec;
    935 
    936 	usec   = (timespec->tv_nsec + 500) / 1000;	/* round */
    937 	husec  =   usec / 100;
    938 	usec  -=  husec * 100;				/* only 0-99 in usec  */
    939 	csec   =  husec / 100;				/* only 0-99 in csec  */
    940 	husec -=   csec * 100;				/* only 0-99 in husec */
    941 
    942 	/* in rare cases there is overflow in csec */
    943 	csec  = MIN(99, csec);
    944 	husec = MIN(99, husec);
    945 	usec  = MIN(99, usec);
    946 
    947 	timestamp->centisec	= csec;
    948 	timestamp->hund_usec	= husec;
    949 	timestamp->usec		= usec;
    950 }
    951 
    952 
    953 static void
    954 udf_set_timestamp(struct timestamp *timestamp, time_t value)
    955 {
    956 	struct timespec t;
    957 
    958 	memset(&t, 0, sizeof(struct timespec));
    959 	t.tv_sec  = value;
    960 	t.tv_nsec = 0;
    961 	udf_timespec_to_timestamp(&t, timestamp);
    962 }
    963 
    964 
    965 static uint32_t
    966 unix_mode_to_udf_perm(mode_t mode)
    967 {
    968 	uint32_t perm;
    969 
    970 	perm  = ((mode & S_IRWXO)     );
    971 	perm |= ((mode & S_IRWXG) << 2);
    972 	perm |= ((mode & S_IRWXU) << 4);
    973 	perm |= ((mode & S_IWOTH) << 3);
    974 	perm |= ((mode & S_IWGRP) << 5);
    975 	perm |= ((mode & S_IWUSR) << 7);
    976 
    977 	return perm;
    978 }
    979 
    980 /* end of copied code */
    981 
    982 
    983 void
    984 udf_encode_osta_id(char *osta_id, uint16_t len, char *text)
    985 {
    986 	struct charspec osta_charspec;
    987 	uint8_t result_len;
    988 
    989 	memset(osta_id, 0, len);
    990 	if (!text || (strlen(text) == 0)) return;
    991 
    992 	udf_osta_charset(&osta_charspec);
    993 	unix_to_udf_name(osta_id, &result_len, text, strlen(text),
    994 		&osta_charspec);
    995 
    996 	/* Ecma 167/7.2.13 states that length is recorded in the last byte */
    997 	osta_id[len-1] = strlen(text)+1;
    998 }
    999 
   1000 
   1001 void
   1002 udf_set_timestamp_now(struct timestamp *timestamp)
   1003 {
   1004 	struct timespec now;
   1005 
   1006 #ifdef CLOCK_REALTIME
   1007 	(void)clock_gettime(CLOCK_REALTIME, &now);
   1008 #else
   1009 	struct timeval time_of_day;
   1010 
   1011 	(void)gettimeofday(&time_of_day, NULL);
   1012 	now.tv_sec = time_of_day.tv_sec;
   1013 	now.tv_nsec = time_of_day.tv_usec * 1000;
   1014 #endif
   1015 	udf_timespec_to_timestamp(&now, timestamp);
   1016 }
   1017 
   1018 
   1019 int
   1020 udf_create_primaryd(void)
   1021 {
   1022 	struct pri_vol_desc *pri;
   1023 	uint16_t crclen;
   1024 
   1025 	pri = calloc(1, context.sector_size);
   1026 	if (pri == NULL)
   1027 		return ENOMEM;
   1028 
   1029 	memset(pri, 0, context.sector_size);
   1030 	udf_inittag(&pri->tag, TAGID_PRI_VOL, /* loc */ 0);
   1031 	pri->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
   1032 
   1033 	pri->pvd_num = udf_rw32(0);		/* default serial */
   1034 	udf_encode_osta_id(pri->vol_id, 32, context.primary_name);
   1035 
   1036 	/* set defaults for single disc volumes as UDF prescribes */
   1037 	pri->vds_num      = udf_rw16(1);
   1038 	pri->max_vol_seq  = udf_rw16(1);
   1039 	pri->ichg_lvl     = udf_rw16(2);
   1040 	pri->max_ichg_lvl = udf_rw16(3);
   1041 	pri->flags        = udf_rw16(0);
   1042 
   1043 	pri->charset_list     = udf_rw32(1);	/* only CS0 */
   1044 	pri->max_charset_list = udf_rw32(1);	/* only CS0 */
   1045 
   1046 	udf_encode_osta_id(pri->volset_id, 128, context.volset_name);
   1047 	udf_osta_charset(&pri->desc_charset);
   1048 	udf_osta_charset(&pri->explanatory_charset);
   1049 
   1050 	udf_set_regid(&pri->app_id, context.app_name);
   1051 	udf_add_app_regid(&pri->app_id);
   1052 
   1053 	udf_set_regid(&pri->imp_id, context.impl_name);
   1054 	udf_add_impl_regid(&pri->imp_id);
   1055 
   1056 	udf_set_timestamp_now(&pri->time);
   1057 
   1058 	crclen = sizeof(struct pri_vol_desc) - UDF_DESC_TAG_LENGTH;
   1059 	pri->tag.desc_crc_len = udf_rw16(crclen);
   1060 
   1061 	context.primary_vol = pri;
   1062 
   1063 	return 0;
   1064 }
   1065 
   1066 
   1067 /*
   1068  * BUGALERT: some rogue implementations use random physical partition
   1069  * numbers to break other implementations so lookup the number.
   1070  */
   1071 
   1072 uint16_t
   1073 udf_find_raw_phys(uint16_t raw_phys_part)
   1074 {
   1075 	struct part_desc *part;
   1076 	uint16_t phys_part;
   1077 
   1078 	for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
   1079 		part = context.partitions[phys_part];
   1080 		if (part == NULL)
   1081 			break;
   1082 		if (udf_rw16(part->part_num) == raw_phys_part)
   1083 			break;
   1084 	}
   1085 	return phys_part;
   1086 }
   1087 
   1088 
   1089 /* XXX no support for unallocated or freed space tables yet (!) */
   1090 int
   1091 udf_create_partitiond(int part_num)
   1092 {
   1093 	struct part_desc     *pd;
   1094 	struct part_hdr_desc *phd;
   1095 	uint32_t sector_size, bitmap_bytes;
   1096 	uint16_t crclen;
   1097 	int part_accesstype = context.media_accesstype;
   1098 
   1099 	sector_size = context.sector_size;
   1100 	bitmap_bytes = layout.alloc_bitmap_dscr_size * sector_size;
   1101 
   1102 	if (context.partitions[part_num])
   1103 		errx(1, "internal error, partition %d already defined in %s",
   1104 			part_num, __func__);
   1105 
   1106 	pd = calloc(1, context.sector_size);
   1107 	if (pd == NULL)
   1108 		return ENOMEM;
   1109 	phd = &pd->_impl_use.part_hdr;
   1110 
   1111 	udf_inittag(&pd->tag, TAGID_PARTITION, /* loc */ 0);
   1112 	pd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1113 
   1114 	pd->flags    = udf_rw16(1);		/* allocated */
   1115 	pd->part_num = udf_rw16(part_num);	/* only one physical partition */
   1116 
   1117 	if (context.dscrver == 2) {
   1118 		udf_set_regid(&pd->contents, "+NSR02");
   1119 	} else {
   1120 		udf_set_regid(&pd->contents, "+NSR03");
   1121 	}
   1122 	udf_add_app_regid(&pd->contents);
   1123 
   1124 	phd->unalloc_space_bitmap.len    = udf_rw32(bitmap_bytes);
   1125 	phd->unalloc_space_bitmap.lb_num = udf_rw32(layout.unalloc_space);
   1126 
   1127 	if (layout.freed_space) {
   1128 		phd->freed_space_bitmap.len    = udf_rw32(bitmap_bytes);
   1129 		phd->freed_space_bitmap.lb_num = udf_rw32(layout.freed_space);
   1130 	}
   1131 
   1132 	pd->access_type = udf_rw32(part_accesstype);
   1133 	pd->start_loc   = udf_rw32(layout.part_start_lba);
   1134 	pd->part_len    = udf_rw32(layout.part_size_lba);
   1135 
   1136 	udf_set_regid(&pd->imp_id, context.impl_name);
   1137 	udf_add_impl_regid(&pd->imp_id);
   1138 
   1139 	crclen = sizeof(struct part_desc) - UDF_DESC_TAG_LENGTH;
   1140 	pd->tag.desc_crc_len = udf_rw16(crclen);
   1141 
   1142 	context.partitions[part_num] = pd;
   1143 
   1144 	return 0;
   1145 }
   1146 
   1147 
   1148 int
   1149 udf_create_unalloc_spaced(void)
   1150 {
   1151 	struct unalloc_sp_desc *usd;
   1152 	uint16_t crclen;
   1153 
   1154 	usd = calloc(1, context.sector_size);
   1155 	if (usd == NULL)
   1156 		return ENOMEM;
   1157 
   1158 	udf_inittag(&usd->tag, TAGID_UNALLOC_SPACE, /* loc */ 0);
   1159 	usd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1160 
   1161 	/* no default entries */
   1162 	usd->alloc_desc_num = udf_rw32(0);		/* no entries */
   1163 
   1164 	crclen  = sizeof(struct unalloc_sp_desc) - sizeof(struct extent_ad);
   1165 	crclen -= UDF_DESC_TAG_LENGTH;
   1166 	usd->tag.desc_crc_len = udf_rw16(crclen);
   1167 
   1168 	context.unallocated = usd;
   1169 
   1170 	return 0;
   1171 }
   1172 
   1173 
   1174 static int
   1175 udf_create_base_logical_dscr(void)
   1176 {
   1177 	struct logvol_desc *lvd;
   1178 	uint32_t sector_size;
   1179 	uint16_t crclen;
   1180 
   1181 	sector_size = context.sector_size;
   1182 
   1183 	lvd = calloc(1, sector_size);
   1184 	if (lvd == NULL)
   1185 		return ENOMEM;
   1186 
   1187 	udf_inittag(&lvd->tag, TAGID_LOGVOL, /* loc */ 0);
   1188 	lvd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1189 
   1190 	udf_osta_charset(&lvd->desc_charset);
   1191 	udf_encode_osta_id(lvd->logvol_id, 128, context.logvol_name);
   1192 	lvd->lb_size = udf_rw32(sector_size);
   1193 
   1194 	udf_set_regid(&lvd->domain_id, "*OSTA UDF Compliant");
   1195 	udf_add_domain_regid(&lvd->domain_id);
   1196 
   1197 	/* no partition mappings/entries yet */
   1198 	lvd->mt_l = udf_rw32(0);
   1199 	lvd->n_pm = udf_rw32(0);
   1200 
   1201 	udf_set_regid(&lvd->imp_id, context.impl_name);
   1202 	udf_add_impl_regid(&lvd->imp_id);
   1203 
   1204 	lvd->integrity_seq_loc.loc = udf_rw32(layout.lvis);
   1205 	lvd->integrity_seq_loc.len = udf_rw32(layout.lvis_size * sector_size);
   1206 
   1207 	/* just one fsd for now */
   1208 	lvd->lv_fsd_loc.len = udf_rw32(sector_size);
   1209 	lvd->lv_fsd_loc.loc.part_num = udf_rw32(context.metadata_part);
   1210 	lvd->lv_fsd_loc.loc.lb_num   = udf_rw32(layout.fsd);
   1211 
   1212 	crclen  = sizeof(struct logvol_desc) - 1 - UDF_DESC_TAG_LENGTH;
   1213 	lvd->tag.desc_crc_len = udf_rw16(crclen);
   1214 
   1215 	context.logical_vol = lvd;
   1216 	context.vtop_tp[UDF_VTOP_RAWPART]     = UDF_VTOP_TYPE_RAW;
   1217 
   1218 	return 0;
   1219 }
   1220 
   1221 
   1222 static void
   1223 udf_add_logvol_part_physical(uint16_t phys_part)
   1224 {
   1225 	struct logvol_desc *logvol = context.logical_vol;
   1226 	union  udf_pmap *pmap;
   1227 	uint8_t         *pmap_pos;
   1228 	uint16_t crclen;
   1229 	uint32_t pmap1_size, log_part;
   1230 
   1231 	log_part = udf_rw32(logvol->n_pm);
   1232 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1233 	pmap1_size = sizeof(struct part_map_1);
   1234 
   1235 	pmap = (union udf_pmap *) pmap_pos;
   1236 	pmap->pm1.type        = 1;
   1237 	pmap->pm1.len         = sizeof(struct part_map_1);
   1238 	pmap->pm1.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1239 	pmap->pm1.part_num    = udf_rw16(phys_part);
   1240 
   1241 	context.vtop       [log_part] = phys_part;
   1242 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_PHYS;
   1243 	context.part_size[log_part] = layout.part_size_lba;
   1244 	context.part_free[log_part] = layout.part_size_lba;
   1245 
   1246 	/* increment number of partitions and length */
   1247 	logvol->n_pm = udf_rw32(log_part + 1);
   1248 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmap1_size);
   1249 
   1250 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmap1_size;
   1251 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1252 }
   1253 
   1254 
   1255 static void
   1256 udf_add_logvol_part_virtual(uint16_t phys_part)
   1257 {
   1258 	union  udf_pmap *pmap;
   1259 	struct logvol_desc *logvol = context.logical_vol;
   1260 	uint8_t *pmap_pos;
   1261 	uint16_t crclen;
   1262 	uint32_t pmapv_size, log_part;
   1263 
   1264 	log_part = udf_rw32(logvol->n_pm);
   1265 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1266 	pmapv_size = sizeof(struct part_map_2);
   1267 
   1268 	pmap = (union udf_pmap *) pmap_pos;
   1269 	pmap->pmv.type        = 2;
   1270 	pmap->pmv.len         = pmapv_size;
   1271 
   1272 	udf_set_regid(&pmap->pmv.id, "*UDF Virtual Partition");
   1273 	udf_add_udf_regid(&pmap->pmv.id);
   1274 
   1275 	pmap->pmv.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1276 	pmap->pmv.part_num    = udf_rw16(phys_part);
   1277 
   1278 	context.vtop       [log_part] = phys_part;
   1279 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_VIRT;
   1280 	context.part_size[log_part] = 0xffffffff;
   1281 	context.part_free[log_part] = 0xffffffff;
   1282 
   1283 	/* increment number of partitions and length */
   1284 	logvol->n_pm = udf_rw32(log_part + 1);
   1285 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
   1286 
   1287 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
   1288 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1289 }
   1290 
   1291 
   1292 /* sparing table size is in bytes */
   1293 static void
   1294 udf_add_logvol_part_spareable(uint16_t phys_part)
   1295 {
   1296 	union  udf_pmap *pmap;
   1297 	struct logvol_desc *logvol = context.logical_vol;
   1298 	uint32_t *st_pos, spareable_bytes, pmaps_size;
   1299 	uint8_t  *pmap_pos, num;
   1300 	uint16_t crclen;
   1301 	uint32_t log_part;
   1302 
   1303 	log_part = udf_rw32(logvol->n_pm);
   1304 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1305 	pmaps_size = sizeof(struct part_map_2);
   1306 	spareable_bytes = layout.spareable_area_size * context.sector_size;
   1307 
   1308 	pmap = (union udf_pmap *) pmap_pos;
   1309 	pmap->pms.type        = 2;
   1310 	pmap->pms.len         = pmaps_size;
   1311 
   1312 	udf_set_regid(&pmap->pmv.id, "*UDF Sparable Partition");
   1313 	udf_add_udf_regid(&pmap->pmv.id);
   1314 
   1315 	pmap->pms.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1316 	pmap->pms.part_num    = udf_rw16(phys_part);
   1317 
   1318 	pmap->pms.packet_len  = udf_rw16(layout.spareable_blockingnr);
   1319 	pmap->pms.st_size     = udf_rw32(spareable_bytes);
   1320 
   1321 	/* enter spare tables  */
   1322 	st_pos = &pmap->pms.st_loc[0];
   1323 	*st_pos++ = udf_rw32(layout.spt_1);
   1324 	*st_pos++ = udf_rw32(layout.spt_2);
   1325 
   1326 	num = 2;
   1327 	if (layout.spt_2 == 0) num--;
   1328 	if (layout.spt_1 == 0) num--;
   1329 	pmap->pms.n_st = num;		/* 8 bit */
   1330 
   1331 	context.vtop       [log_part] = phys_part;
   1332 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_SPAREABLE;
   1333 	context.part_size[log_part] = layout.part_size_lba;
   1334 	context.part_free[log_part] = layout.part_size_lba;
   1335 
   1336 	/* increment number of partitions and length */
   1337 	logvol->n_pm = udf_rw32(log_part + 1);
   1338 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmaps_size);
   1339 
   1340 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmaps_size;
   1341 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1342 }
   1343 
   1344 
   1345 int
   1346 udf_create_sparing_tabled(void)
   1347 {
   1348 	struct udf_sparing_table *spt;
   1349 	struct spare_map_entry   *sme;
   1350 	uint32_t loc, cnt;
   1351 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   1352 
   1353 	spt = calloc(context.sector_size, layout.sparing_table_dscr_lbas);
   1354 	if (spt == NULL)
   1355 		return ENOMEM;
   1356 
   1357 	/* a sparing table descriptor is a whole spareable_blockingnr sectors */
   1358 	udf_inittag(&spt->tag, TAGID_SPARING_TABLE, /* loc */ 0);
   1359 
   1360 	udf_set_regid(&spt->id, "*UDF Sparing Table");
   1361 	udf_add_udf_regid(&spt->id);
   1362 
   1363 	spt->rt_l    = udf_rw16(layout.spareable_blocks);
   1364 	spt->seq_num = udf_rw32(0);			/* first generation */
   1365 
   1366 	for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
   1367 		sme = &spt->entries[cnt];
   1368 		loc = layout.spareable_area + cnt * layout.spareable_blockingnr;
   1369 		sme->org = udf_rw32(0xffffffff);	/* open for reloc */
   1370 		sme->map = udf_rw32(loc);
   1371 	}
   1372 
   1373 	/* calculate crc len for actual size */
   1374 	crclen  = sizeof(struct udf_sparing_table) - UDF_DESC_TAG_LENGTH;
   1375 	crclen += (layout.spareable_blocks-1) * sizeof(struct spare_map_entry);
   1376 
   1377 	assert(crclen <= UINT16_MAX);
   1378 	spt->tag.desc_crc_len = udf_rw16((uint16_t)crclen);
   1379 
   1380 	context.sparing_table = spt;
   1381 
   1382 	return 0;
   1383 }
   1384 
   1385 
   1386 static void
   1387 udf_add_logvol_part_meta(uint16_t phys_part)
   1388 {
   1389 	union  udf_pmap *pmap;
   1390 	struct logvol_desc *logvol = context.logical_vol;
   1391 	uint8_t *pmap_pos;
   1392 	uint32_t pmapv_size, log_part;
   1393 	uint16_t crclen;
   1394 
   1395 	log_part = udf_rw32(logvol->n_pm);
   1396 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
   1397 	pmapv_size = sizeof(struct part_map_2);
   1398 
   1399 	pmap = (union udf_pmap *) pmap_pos;
   1400 	pmap->pmm.type        = 2;
   1401 	pmap->pmm.len         = pmapv_size;
   1402 
   1403 	udf_set_regid(&pmap->pmm.id, "*UDF Metadata Partition");
   1404 	udf_add_udf_regid(&pmap->pmm.id);
   1405 
   1406 	pmap->pmm.vol_seq_num = udf_rw16(1);		/* no multi-volume */
   1407 	pmap->pmm.part_num    = udf_rw16(phys_part);
   1408 
   1409 	/* fill in meta data file(s) and alloc/alignment unit sizes */
   1410 	pmap->pmm.meta_file_lbn        = udf_rw32(layout.meta_file);
   1411 	pmap->pmm.meta_mirror_file_lbn = udf_rw32(layout.meta_mirror);
   1412 	pmap->pmm.meta_bitmap_file_lbn = udf_rw32(layout.meta_bitmap);
   1413 	pmap->pmm.alloc_unit_size      = udf_rw32(layout.meta_blockingnr);
   1414 	pmap->pmm.alignment_unit_size  = udf_rw16(layout.meta_alignment);
   1415 	pmap->pmm.flags                = 0; /* METADATA_DUPLICATED */
   1416 
   1417 	context.vtop       [log_part] = phys_part;
   1418 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_META;
   1419 	context.part_size[log_part] = layout.meta_part_size_lba;
   1420 	context.part_free[log_part] = layout.meta_part_size_lba;
   1421 
   1422 	/* increment number of partitions and length */
   1423 	logvol->n_pm = udf_rw32(log_part + 1);
   1424 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
   1425 
   1426 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
   1427 	logvol->tag.desc_crc_len = udf_rw16(crclen);
   1428 }
   1429 
   1430 
   1431 int
   1432 udf_create_logical_dscr(void)
   1433 {
   1434 	int error;
   1435 
   1436 	if ((error = udf_create_base_logical_dscr()))
   1437 		return error;
   1438 
   1439 	/* we pass data_part for there might be a read-only part one day */
   1440 	if (context.format_flags & FORMAT_SPAREABLE) {
   1441 		/* spareable partition mapping has no physical mapping */
   1442 		udf_add_logvol_part_spareable(context.data_part);
   1443 	} else {
   1444 		udf_add_logvol_part_physical(context.data_part);
   1445 	}
   1446 
   1447 	if (context.format_flags & FORMAT_VAT) {
   1448 		/* add VAT virtual mapping; reflects on datapart */
   1449 		udf_add_logvol_part_virtual(context.data_part);
   1450 	}
   1451 	if (context.format_flags & FORMAT_META) {
   1452 		/* add META data mapping; reflects on datapart */
   1453 		udf_add_logvol_part_meta(context.data_part);
   1454 	}
   1455 
   1456 	return 0;
   1457 }
   1458 
   1459 
   1460 int
   1461 udf_create_impvold(char *field1, char *field2, char *field3)
   1462 {
   1463 	struct impvol_desc *ivd;
   1464 	struct udf_lv_info *lvi;
   1465 	uint16_t crclen;
   1466 
   1467 	ivd = calloc(1, context.sector_size);
   1468 	if (ivd == NULL)
   1469 		return ENOMEM;
   1470 	lvi = &ivd->_impl_use.lv_info;
   1471 
   1472 	udf_inittag(&ivd->tag, TAGID_IMP_VOL, /* loc */ 0);
   1473 	ivd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
   1474 
   1475 	udf_set_regid(&ivd->impl_id, "*UDF LV Info");
   1476 	udf_add_udf_regid(&ivd->impl_id);
   1477 
   1478 	/* fill in UDF specific part */
   1479 	udf_osta_charset(&lvi->lvi_charset);
   1480 	udf_encode_osta_id(lvi->logvol_id, 128, context.logvol_name);
   1481 
   1482 	udf_encode_osta_id(lvi->lvinfo1, 36, field1);
   1483 	udf_encode_osta_id(lvi->lvinfo2, 36, field2);
   1484 	udf_encode_osta_id(lvi->lvinfo3, 36, field3);
   1485 
   1486 	udf_set_regid(&lvi->impl_id, context.impl_name);
   1487 	udf_add_impl_regid(&lvi->impl_id);
   1488 
   1489 	crclen  = sizeof(struct impvol_desc) - UDF_DESC_TAG_LENGTH;
   1490 	ivd->tag.desc_crc_len = udf_rw16(crclen);
   1491 
   1492 	context.implementation = ivd;
   1493 
   1494 	return 0;
   1495 }
   1496 
   1497 
   1498 /* XXX might need to be sanitised a bit */
   1499 void
   1500 udf_update_lvintd(int type)
   1501 {
   1502 	struct logvol_int_desc *lvid;
   1503 	struct udf_logvol_info *lvinfo;
   1504 	struct logvol_desc     *logvol;
   1505 	uint32_t *pos;
   1506 	uint32_t cnt, num_partmappings;
   1507 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   1508 
   1509 	lvid   = context.logvol_integrity;
   1510 	logvol = context.logical_vol;
   1511 	assert(lvid);
   1512 	assert(logvol);
   1513 
   1514 	lvid->integrity_type = udf_rw32(type);
   1515 	udf_set_timestamp_now(&lvid->time);
   1516 
   1517 	/* initialise lvinfo just in case its not set yet */
   1518 	num_partmappings = udf_rw32(logvol->n_pm);
   1519 	assert(num_partmappings > 0);
   1520 
   1521 	lvinfo = (struct udf_logvol_info *)
   1522 		(lvid->tables + num_partmappings * 2);
   1523 	context.logvol_info = lvinfo;
   1524 
   1525 	udf_set_regid(&lvinfo->impl_id, context.impl_name);
   1526 	udf_add_impl_regid(&lvinfo->impl_id);
   1527 
   1528 	if (type == UDF_INTEGRITY_CLOSED) {
   1529 		lvinfo->num_files          = udf_rw32(context.num_files);
   1530 		lvinfo->num_directories    = udf_rw32(context.num_directories);
   1531 
   1532 		lvid->lvint_next_unique_id = udf_rw64(context.unique_id);
   1533 	}
   1534 
   1535 	/* sane enough? */
   1536 	if (udf_rw16(lvinfo->min_udf_readver) < context.min_udf)
   1537 		lvinfo->min_udf_readver  = udf_rw16(context.min_udf);
   1538 	if (udf_rw16(lvinfo->min_udf_writever) < context.min_udf)
   1539 		lvinfo->min_udf_writever = udf_rw16(context.min_udf);
   1540 	if (udf_rw16(lvinfo->max_udf_writever) < context.max_udf)
   1541 		lvinfo->max_udf_writever = udf_rw16(context.max_udf);
   1542 
   1543 	lvid->num_part = udf_rw32(num_partmappings);
   1544 
   1545 	pos = &lvid->tables[0];
   1546 	for (cnt = 0; cnt < num_partmappings; cnt++) {
   1547 		*pos++ = udf_rw32(context.part_free[cnt]);
   1548 	}
   1549 	for (cnt = 0; cnt < num_partmappings; cnt++) {
   1550 		*pos++ = udf_rw32(context.part_size[cnt]);
   1551 	}
   1552 
   1553 	crclen  = sizeof(struct logvol_int_desc) -4 -UDF_DESC_TAG_LENGTH +
   1554 		udf_rw32(lvid->l_iu);
   1555 	crclen += num_partmappings * 2 * 4;
   1556 
   1557 	assert(crclen <= UINT16_MAX);
   1558 	if (lvid->tag.desc_crc_len == 0)
   1559 		lvid->tag.desc_crc_len = udf_rw16(crclen);
   1560 
   1561 	context.logvol_info = lvinfo;
   1562 }
   1563 
   1564 
   1565 int
   1566 udf_create_lvintd(int type)
   1567 {
   1568 	struct logvol_int_desc *lvid;
   1569 	int l_iu;
   1570 
   1571 	lvid = calloc(1, context.sector_size);
   1572 	if (lvid == NULL)
   1573 		return ENOMEM;
   1574 
   1575 	udf_inittag(&lvid->tag, TAGID_LOGVOL_INTEGRITY, /* loc */ 0);
   1576 	context.logvol_integrity = lvid;
   1577 
   1578 	/* only set for standard UDF info, no extra impl. use needed */
   1579 	l_iu = sizeof(struct udf_logvol_info);
   1580 	lvid->l_iu = udf_rw32(l_iu);
   1581 
   1582 	udf_update_lvintd(type);
   1583 
   1584 	return 0;
   1585 }
   1586 
   1587 
   1588 int
   1589 udf_create_fsd(void)
   1590 {
   1591 	struct fileset_desc *fsd;
   1592 	uint16_t crclen;
   1593 
   1594 	fsd = calloc(1, context.sector_size);
   1595 	if (fsd == NULL)
   1596 		return ENOMEM;
   1597 
   1598 	udf_inittag(&fsd->tag, TAGID_FSD, /* loc */ 0);
   1599 
   1600 	udf_set_timestamp_now(&fsd->time);
   1601 	fsd->ichg_lvl     = udf_rw16(3);		/* UDF 2.3.2.1 */
   1602 	fsd->max_ichg_lvl = udf_rw16(3);		/* UDF 2.3.2.2 */
   1603 
   1604 	fsd->charset_list     = udf_rw32(1);		/* only CS0 */
   1605 	fsd->max_charset_list = udf_rw32(1);		/* only CS0 */
   1606 
   1607 	fsd->fileset_num      = udf_rw32(0);		/* only one fsd */
   1608 	fsd->fileset_desc_num = udf_rw32(0);		/* original    */
   1609 
   1610 	udf_osta_charset(&fsd->logvol_id_charset);
   1611 	udf_encode_osta_id(fsd->logvol_id, 128, context.logvol_name);
   1612 
   1613 	udf_osta_charset(&fsd->fileset_charset);
   1614 	udf_encode_osta_id(fsd->fileset_id, 32, context.fileset_name);
   1615 
   1616 	/* copyright file and abstract file names obmitted */
   1617 
   1618 	fsd->rootdir_icb.len	      = udf_rw32(context.sector_size);
   1619 	fsd->rootdir_icb.loc.lb_num   = udf_rw32(layout.rootdir);
   1620 	fsd->rootdir_icb.loc.part_num = udf_rw16(context.metadata_part);
   1621 
   1622 	udf_set_regid(&fsd->domain_id, "*OSTA UDF Compliant");
   1623 	udf_add_domain_regid(&fsd->domain_id);
   1624 
   1625 	/* next_ex stays zero */
   1626 	/* no system streamdirs yet */
   1627 
   1628 	crclen = sizeof(struct fileset_desc) - UDF_DESC_TAG_LENGTH;
   1629 	fsd->tag.desc_crc_len = udf_rw16(crclen);
   1630 
   1631 	context.fileset_desc = fsd;
   1632 
   1633 	return 0;
   1634 }
   1635 
   1636 
   1637 int
   1638 udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba,
   1639 	struct space_bitmap_desc **sbdp)
   1640 {
   1641 	struct space_bitmap_desc *sbd;
   1642 	uint32_t cnt;
   1643 	uint16_t crclen;
   1644 
   1645 	*sbdp = NULL;
   1646 	sbd = calloc(context.sector_size, dscr_size);
   1647 	if (sbd == NULL)
   1648 		return ENOMEM;
   1649 
   1650 	udf_inittag(&sbd->tag, TAGID_SPACE_BITMAP, /* loc */ 0);
   1651 
   1652 	sbd->num_bits  = udf_rw32(part_size_lba);
   1653 	sbd->num_bytes = udf_rw32((part_size_lba + 7)/8);
   1654 
   1655 	/* fill space with 0xff to indicate free */
   1656 	for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
   1657 		sbd->data[cnt] = 0xff;
   1658 
   1659 	/* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
   1660 	crclen = sizeof(struct space_bitmap_desc) -1 - UDF_DESC_TAG_LENGTH;
   1661 	sbd->tag.desc_crc_len = udf_rw16(crclen);
   1662 
   1663 	*sbdp = sbd;
   1664 	return 0;
   1665 }
   1666 
   1667 /* --------------------------------------------------------------------- */
   1668 
   1669 int
   1670 udf_register_bad_block(uint32_t location)
   1671 {
   1672 	struct udf_sparing_table *spt;
   1673 	struct spare_map_entry   *sme, *free_sme;
   1674 	uint32_t cnt;
   1675 
   1676 	spt = context.sparing_table;
   1677 	if (spt == NULL)
   1678 		errx(1, "internal error, adding bad block to "
   1679 			"non spareable in %s", __func__);
   1680 
   1681 	/* find us a free spare map entry */
   1682 	free_sme = NULL;
   1683 	for (cnt = 0; cnt < layout.spareable_blocks; cnt++) {
   1684 		sme = &spt->entries[cnt];
   1685 		/* if we are allready in it, bail out */
   1686 		if (udf_rw32(sme->org) == location)
   1687 			return 0;
   1688 		if (udf_rw32(sme->org) == 0xffffffff) {
   1689 			free_sme = sme;
   1690 			break;
   1691 		}
   1692 	}
   1693 	if (free_sme == NULL) {
   1694 		warnx("disc relocation blocks full; disc too damaged");
   1695 		return EINVAL;
   1696 	}
   1697 	free_sme->org = udf_rw32(location);
   1698 
   1699 	return 0;
   1700 }
   1701 
   1702 
   1703 void
   1704 udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks)
   1705 {
   1706 	union dscrptr *dscr;
   1707 	uint8_t *bpos;
   1708 	uint32_t cnt, bit;
   1709 
   1710 	/* account for space used on underlying partition */
   1711 #ifdef DEBUG
   1712 	printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
   1713 		partnr, start_lb, blocks);
   1714 #endif
   1715 
   1716 	switch (context.vtop_tp[partnr]) {
   1717 	case UDF_VTOP_TYPE_VIRT:
   1718 		/* nothing */
   1719 		break;
   1720 	case UDF_VTOP_TYPE_PHYS:
   1721 	case UDF_VTOP_TYPE_SPAREABLE:
   1722 	case UDF_VTOP_TYPE_META:
   1723 		if (context.part_unalloc_bits[context.vtop[partnr]] == NULL) {
   1724 			context.part_free[partnr] = 0;
   1725 			break;
   1726 		}
   1727 #ifdef DEBUG
   1728 		printf("marking %d+%d as used\n", start_lb, blocks);
   1729 #endif
   1730 		dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
   1731 		for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
   1732 			 bpos  = &dscr->sbd.data[cnt / 8];
   1733 			 bit   = cnt % 8;
   1734 			 /* only account for bits marked free */
   1735 			 if ((*bpos & (1 << bit)))
   1736 				context.part_free[partnr] -= 1;
   1737 			*bpos &= ~(1<< bit);
   1738 		}
   1739 		break;
   1740 	default:
   1741 		errx(1, "internal error: bad mapping type %d in %s",
   1742 			context.vtop_tp[partnr], __func__);
   1743 	}
   1744 }
   1745 
   1746 
   1747 void
   1748 udf_advance_uniqueid(void)
   1749 {
   1750 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
   1751 	context.unique_id++;
   1752 	if (context.unique_id < 0x10)
   1753 		context.unique_id = 0x10;
   1754 }
   1755 
   1756 /* --------------------------------------------------------------------- */
   1757 
   1758 /* XXX implement the using of the results */
   1759 int
   1760 udf_surface_check(void)
   1761 {
   1762 	uint32_t loc, block_bytes;
   1763 	uint32_t sector_size, blockingnr, bpos;
   1764 	uint8_t *buffer;
   1765 	int error, num_errors;
   1766 
   1767 	if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
   1768 		return 0;
   1769 
   1770 	sector_size = context.sector_size;
   1771 	blockingnr  = layout.blockingnr;
   1772 
   1773 	block_bytes = layout.blockingnr * sector_size;
   1774 	if ((buffer = malloc(block_bytes)) == NULL)
   1775 		return ENOMEM;
   1776 
   1777 	/* set all one to not kill Flash memory? */
   1778 	for (bpos = 0; bpos < block_bytes; bpos++)
   1779 		buffer[bpos] = 0x00;
   1780 
   1781 	printf("\nChecking disc surface : phase 1 - writing\n");
   1782 	num_errors = 0;
   1783 	loc = layout.first_lba;
   1784 	while (loc <= layout.last_lba) {
   1785 		/* write blockingnr sectors */
   1786 		error = pwrite(dev_fd, buffer, block_bytes,
   1787 				(uint64_t) loc*sector_size);
   1788 		printf("   %08d + %d (%02d %%)\r", loc, blockingnr,
   1789 			(int)((100.0 * loc)/layout.last_lba));
   1790 		fflush(stdout);
   1791 		if (error == -1) {
   1792 			/* block is bad */
   1793 			printf("BAD block at %08d + %d         \n",
   1794 				loc, layout.blockingnr);
   1795 			if ((error = udf_register_bad_block(loc))) {
   1796 				free(buffer);
   1797 				return error;
   1798 			}
   1799 			num_errors ++;
   1800 		}
   1801 		loc += layout.blockingnr;
   1802 	}
   1803 
   1804 	printf("\nChecking disc surface : phase 2 - reading\n");
   1805 	num_errors = 0;
   1806 	loc = layout.first_lba;
   1807 	while (loc <= layout.last_lba) {
   1808 		/* read blockingnr sectors */
   1809 		error = pread(dev_fd, buffer, block_bytes, loc*sector_size);
   1810 		printf("   %08d + %d (%02d %%)\r", loc, blockingnr,
   1811 			(int)((100.0 * loc)/layout.last_lba));
   1812 		fflush(stdout);
   1813 		if (error == -1) {
   1814 			/* block is bad */
   1815 			printf("BAD block at %08d + %d         \n",
   1816 				loc, layout.blockingnr);
   1817 			if ((error = udf_register_bad_block(loc))) {
   1818 				free(buffer);
   1819 				return error;
   1820 			}
   1821 			num_errors ++;
   1822 		}
   1823 		loc += layout.blockingnr;
   1824 	}
   1825 	printf("Scan complete : %d bad blocks found\n", num_errors);
   1826 	free(buffer);
   1827 
   1828 	return 0;
   1829 }
   1830 
   1831 /* --------------------------------------------------------------------- */
   1832 
   1833 #define UDF_SYMLINKBUFLEN    (64*1024)               /* picked */
   1834 int
   1835 udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target)
   1836 {
   1837 	struct charspec osta_charspec;
   1838 	struct pathcomp pathcomp;
   1839 	char *pathbuf, *pathpos, *compnamepos;
   1840 //	char *mntonname;
   1841 //	int   mntonnamelen;
   1842 	int pathlen, len, compnamelen;
   1843 	int error;
   1844 
   1845 	/* process `target' to an UDF structure */
   1846 	pathbuf = malloc(UDF_SYMLINKBUFLEN);
   1847 	assert(pathbuf);
   1848 
   1849 	*pathbufp = NULL;
   1850 	*pathlenp = 0;
   1851 
   1852 	pathpos = pathbuf;
   1853 	pathlen = 0;
   1854 	udf_osta_charset(&osta_charspec);
   1855 
   1856 	if (*target == '/') {
   1857 		/* symlink starts from the root */
   1858 		len = UDF_PATH_COMP_SIZE;
   1859 		memset(&pathcomp, 0, len);
   1860 		pathcomp.type = UDF_PATH_COMP_ROOT;
   1861 
   1862 #if 0
   1863 		/* XXX how to check for in makefs? */
   1864 		/* check if its mount-point relative! */
   1865 		mntonname    = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
   1866 		mntonnamelen = strlen(mntonname);
   1867 		if (strlen(target) >= mntonnamelen) {
   1868 			if (strncmp(target, mntonname, mntonnamelen) == 0) {
   1869 				pathcomp.type = UDF_PATH_COMP_MOUNTROOT;
   1870 				target += mntonnamelen;
   1871 			}
   1872 		} else {
   1873 			target++;
   1874 		}
   1875 #else
   1876 		target++;
   1877 #endif
   1878 
   1879 		memcpy(pathpos, &pathcomp, len);
   1880 		pathpos += len;
   1881 		pathlen += len;
   1882 	}
   1883 
   1884 	error = 0;
   1885 	while (*target) {
   1886 		/* ignore multiple '/' */
   1887 		while (*target == '/') {
   1888 			target++;
   1889 		}
   1890 		if (!*target)
   1891 			break;
   1892 
   1893 		/* extract component name */
   1894 		compnamelen = 0;
   1895 		compnamepos = target;
   1896 		while ((*target) && (*target != '/')) {
   1897 			target++;
   1898 			compnamelen++;
   1899 		}
   1900 
   1901 		/* just trunc if too long ?? (security issue) */
   1902 		if (compnamelen >= 127) {
   1903 			error = ENAMETOOLONG;
   1904 			break;
   1905 		}
   1906 
   1907 		/* convert unix name to UDF name */
   1908 		len = sizeof(struct pathcomp);
   1909 		memset(&pathcomp, 0, len);
   1910 		pathcomp.type = UDF_PATH_COMP_NAME;
   1911 		len = UDF_PATH_COMP_SIZE;
   1912 
   1913 		if ((compnamelen == 2) && (strncmp(compnamepos, "..", 2) == 0))
   1914 			pathcomp.type = UDF_PATH_COMP_PARENTDIR;
   1915 		if ((compnamelen == 1) && (*compnamepos == '.'))
   1916 			pathcomp.type = UDF_PATH_COMP_CURDIR;
   1917 
   1918 		if (pathcomp.type == UDF_PATH_COMP_NAME) {
   1919 			unix_to_udf_name(
   1920 				(char *) &pathcomp.ident, &pathcomp.l_ci,
   1921 				compnamepos, compnamelen,
   1922 				&osta_charspec);
   1923 			len = UDF_PATH_COMP_SIZE + pathcomp.l_ci;
   1924 		}
   1925 
   1926 		if (pathlen + len >= UDF_SYMLINKBUFLEN) {
   1927 			error = ENAMETOOLONG;
   1928 			break;
   1929 		}
   1930 
   1931 		memcpy(pathpos, &pathcomp, len);
   1932 		pathpos += len;
   1933 		pathlen += len;
   1934 	}
   1935 
   1936 	if (error) {
   1937 		/* aparently too big */
   1938 		free(pathbuf);
   1939 		return error;
   1940 	}
   1941 
   1942 	/* return status of symlink contents writeout */
   1943 	*pathbufp = (uint8_t *) pathbuf;
   1944 	*pathlenp = pathlen;
   1945 
   1946 	return 0;
   1947 
   1948 }
   1949 #undef UDF_SYMLINKBUFLEN
   1950 
   1951 
   1952 /*
   1953  * XXX note the different semantics from udfclient: for FIDs it still rounds
   1954  * up to sectors. Use udf_fidsize() for a correct length.
   1955  */
   1956 uint32_t
   1957 udf_tagsize(union dscrptr *dscr, uint32_t lb_size)
   1958 {
   1959 	uint32_t size, tag_id, num_lb, elmsz;
   1960 
   1961 	tag_id = udf_rw16(dscr->tag.id);
   1962 
   1963 	switch (tag_id) {
   1964 	case TAGID_LOGVOL :
   1965 		size  = sizeof(struct logvol_desc) - 1;
   1966 		size += udf_rw32(dscr->lvd.mt_l);
   1967 		break;
   1968 	case TAGID_UNALLOC_SPACE :
   1969 		elmsz = sizeof(struct extent_ad);
   1970 		size  = sizeof(struct unalloc_sp_desc) - elmsz;
   1971 		size += udf_rw32(dscr->usd.alloc_desc_num) * elmsz;
   1972 		break;
   1973 	case TAGID_FID :
   1974 		size = UDF_FID_SIZE + dscr->fid.l_fi + udf_rw16(dscr->fid.l_iu);
   1975 		size = (size + 3) & ~3;
   1976 		break;
   1977 	case TAGID_LOGVOL_INTEGRITY :
   1978 		size  = sizeof(struct logvol_int_desc) - sizeof(uint32_t);
   1979 		size += udf_rw32(dscr->lvid.l_iu);
   1980 		size += (2 * udf_rw32(dscr->lvid.num_part) * sizeof(uint32_t));
   1981 		break;
   1982 	case TAGID_SPACE_BITMAP :
   1983 		size  = sizeof(struct space_bitmap_desc) - 1;
   1984 		size += udf_rw32(dscr->sbd.num_bytes);
   1985 		break;
   1986 	case TAGID_SPARING_TABLE :
   1987 		elmsz = sizeof(struct spare_map_entry);
   1988 		size  = sizeof(struct udf_sparing_table) - elmsz;
   1989 		size += udf_rw16(dscr->spt.rt_l) * elmsz;
   1990 		break;
   1991 	case TAGID_FENTRY :
   1992 		size  = sizeof(struct file_entry);
   1993 		size += udf_rw32(dscr->fe.l_ea) + udf_rw32(dscr->fe.l_ad)-1;
   1994 		break;
   1995 	case TAGID_EXTFENTRY :
   1996 		size  = sizeof(struct extfile_entry);
   1997 		size += udf_rw32(dscr->efe.l_ea) + udf_rw32(dscr->efe.l_ad)-1;
   1998 		break;
   1999 	case TAGID_FSD :
   2000 		size  = sizeof(struct fileset_desc);
   2001 		break;
   2002 	default :
   2003 		size = sizeof(union dscrptr);
   2004 		break;
   2005 	}
   2006 
   2007 	if ((size == 0) || (lb_size == 0))
   2008 		return 0;
   2009 
   2010 	if (lb_size == 1)
   2011 		return size;
   2012 
   2013 	/* round up in sectors */
   2014 	num_lb = (size + lb_size -1) / lb_size;
   2015 	return num_lb * lb_size;
   2016 }
   2017 
   2018 
   2019 int
   2020 udf_fidsize(struct fileid_desc *fid)
   2021 {
   2022 	uint32_t size;
   2023 
   2024 	if (udf_rw16(fid->tag.id) != TAGID_FID)
   2025 		errx(1, "internal error, bad tag in %s", __func__);
   2026 
   2027 	size = UDF_FID_SIZE + udf_rw16(fid->l_fi) + udf_rw16(fid->l_iu);
   2028 	size = (size + 3) & ~3;
   2029 
   2030 	return size;
   2031 }
   2032 
   2033 
   2034 int
   2035 udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent)
   2036 {
   2037 	/* the size of an empty FID is 38 but needs to be a multiple of 4 */
   2038 	int fidsize = 40;
   2039 
   2040 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num));
   2041 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
   2042 	fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
   2043 	fid->icb = *parent;
   2044 	fid->icb.longad_uniqueid = parent->longad_uniqueid;
   2045 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
   2046 
   2047 	/* we have to do the fid here explicitly for simplicity */
   2048 	udf_validate_tag_and_crc_sums((union dscrptr *) fid);
   2049 
   2050 	return fidsize;
   2051 }
   2052 
   2053 
   2054 void
   2055 udf_create_fid(uint32_t diroff, struct fileid_desc *fid, char *name,
   2056 	int file_char, struct long_ad *ref)
   2057 {
   2058 	struct charspec osta_charspec;
   2059 	uint32_t endfid;
   2060 	uint32_t fidsize, lb_rest;
   2061 
   2062 	memset(fid, 0, sizeof(*fid));
   2063 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(ref->loc.lb_num));
   2064 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
   2065 	fid->file_char = file_char;
   2066 	fid->l_iu = udf_rw16(0);
   2067 	fid->icb = *ref;
   2068 	fid->icb.longad_uniqueid = ref->longad_uniqueid;
   2069 
   2070 	udf_osta_charset(&osta_charspec);
   2071 	unix_to_udf_name((char *) fid->data, &fid->l_fi, name, strlen(name),
   2072 			&osta_charspec);
   2073 
   2074 	/*
   2075 	 * OK, tricky part: we need to pad so the next descriptor header won't
   2076 	 * cross the sector boundary
   2077 	 */
   2078 	endfid = diroff + udf_fidsize(fid);
   2079 	lb_rest = context.sector_size - (endfid % context.sector_size);
   2080 	if (lb_rest < sizeof(struct desc_tag)) {
   2081 		/* add at least 32 */
   2082 		fid->l_iu = udf_rw16(32);
   2083 		udf_set_regid((struct regid *) fid->data, context.impl_name);
   2084 		udf_add_impl_regid((struct regid *) fid->data);
   2085 
   2086 		unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
   2087 			&fid->l_fi, name, strlen(name), &osta_charspec);
   2088 	}
   2089 
   2090 	fidsize = udf_fidsize(fid);
   2091 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
   2092 
   2093 	/* make sure the header sums stays correct */
   2094 	udf_validate_tag_and_crc_sums((union dscrptr *)fid);
   2095 }
   2096 
   2097 
   2098 static void
   2099 udf_append_parentfid(union dscrptr *dscr, struct long_ad *parent_icb)
   2100 {
   2101 	struct file_entry      *fe;
   2102 	struct extfile_entry   *efe;
   2103 	struct fileid_desc     *fid;
   2104 	uint32_t l_ea;
   2105 	uint32_t fidsize, crclen;
   2106 	uint8_t *bpos, *data;
   2107 
   2108 	fe = NULL;
   2109 	efe = NULL;
   2110 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   2111 		fe    = &dscr->fe;
   2112 		data  = fe->data;
   2113 		l_ea  = udf_rw32(fe->l_ea);
   2114 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   2115 		efe   = &dscr->efe;
   2116 		data  = efe->data;
   2117 		l_ea  = udf_rw32(efe->l_ea);
   2118 	} else {
   2119 		errx(1, "internal error, bad tag in %s", __func__);
   2120 	}
   2121 
   2122 	/* create '..' */
   2123 	bpos = data + l_ea;
   2124 	fid  = (struct fileid_desc *) bpos;
   2125 	fidsize = udf_create_parentfid(fid, parent_icb);
   2126 
   2127 	/* record fidlength information */
   2128 	if (fe) {
   2129 		fe->inf_len     = udf_rw64(fidsize);
   2130 		fe->l_ad        = udf_rw32(fidsize);
   2131 		fe->logblks_rec = udf_rw64(0);		/* intern */
   2132 		crclen  = sizeof(struct file_entry);
   2133 	} else {
   2134 		efe->inf_len     = udf_rw64(fidsize);
   2135 		efe->obj_size    = udf_rw64(fidsize);
   2136 		efe->l_ad        = udf_rw32(fidsize);
   2137 		efe->logblks_rec = udf_rw64(0);		/* intern */
   2138 		crclen  = sizeof(struct extfile_entry);
   2139 	}
   2140 	crclen -= 1 + UDF_DESC_TAG_LENGTH;
   2141 	crclen += l_ea + fidsize;
   2142 	dscr->tag.desc_crc_len = udf_rw16(crclen);
   2143 
   2144 	/* make sure the header sums stays correct */
   2145 	udf_validate_tag_and_crc_sums(dscr);
   2146 }
   2147 
   2148 /* --------------------------------------------------------------------- */
   2149 
   2150 /*
   2151  * Extended attribute support. UDF knows of 3 places for extended attributes:
   2152  *
   2153  * (a) inside the file's (e)fe in the length of the extended attribute area
   2154  * before the allocation descriptors/filedata
   2155  *
   2156  * (b) in a file referenced by (e)fe->ext_attr_icb and
   2157  *
   2158  * (c) in the e(fe)'s associated stream directory that can hold various
   2159  * sub-files. In the stream directory a few fixed named subfiles are reserved
   2160  * for NT/Unix ACL's and OS/2 attributes.
   2161  *
   2162  * NOTE: Extended attributes are read randomly but always written
   2163  * *atomically*. For ACL's this interface is probably different but not known
   2164  * to me yet.
   2165  *
   2166  * Order of extended attributes in a space:
   2167  *   ECMA 167 EAs
   2168  *   Non block aligned Implementation Use EAs
   2169  *   Block aligned Implementation Use EAs
   2170  *   Application Use EAs
   2171  */
   2172 
   2173 int
   2174 udf_impl_extattr_check(struct impl_extattr_entry *implext)
   2175 {
   2176 	uint16_t   *spos;
   2177 
   2178 	if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
   2179 		/* checksum valid? */
   2180 		spos = (uint16_t *) implext->data;
   2181 		if (udf_rw16(*spos) != udf_ea_cksum((uint8_t *) implext))
   2182 			return EINVAL;
   2183 	}
   2184 	return 0;
   2185 }
   2186 
   2187 void
   2188 udf_calc_impl_extattr_checksum(struct impl_extattr_entry *implext)
   2189 {
   2190 	uint16_t   *spos;
   2191 
   2192 	if (strncmp((char *) implext->imp_id.id, "*UDF", 4) == 0) {
   2193 		/* set checksum */
   2194 		spos = (uint16_t *) implext->data;
   2195 		*spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
   2196 	}
   2197 }
   2198 
   2199 
   2200 int
   2201 udf_extattr_search_intern(union dscrptr *dscr,
   2202 	uint32_t sattr, char const *sattrname,
   2203 	uint32_t *offsetp, uint32_t *lengthp)
   2204 {
   2205 	struct extattrhdr_desc    *eahdr;
   2206 	struct extattr_entry      *attrhdr;
   2207 	struct impl_extattr_entry *implext;
   2208 	uint32_t    offset, a_l, sector_size;
   2209 	uint32_t    l_ea;
   2210 	uint8_t    *pos;
   2211 	int         tag_id, error;
   2212 
   2213 	sector_size = context.sector_size;
   2214 
   2215 	/* get information from fe/efe */
   2216 	tag_id = udf_rw16(dscr->tag.id);
   2217 	if (tag_id == TAGID_FENTRY) {
   2218 		l_ea  = udf_rw32(dscr->fe.l_ea);
   2219 		eahdr = (struct extattrhdr_desc *) dscr->fe.data;
   2220 	} else {
   2221 		assert(tag_id == TAGID_EXTFENTRY);
   2222 		l_ea  = udf_rw32(dscr->efe.l_ea);
   2223 		eahdr = (struct extattrhdr_desc *) dscr->efe.data;
   2224 	}
   2225 
   2226 	/* something recorded here? */
   2227 	if (l_ea == 0)
   2228 		return ENOENT;
   2229 
   2230 	/* check extended attribute tag; what to do if it fails? */
   2231 	error = udf_check_tag(eahdr);
   2232 	if (error)
   2233 		return EINVAL;
   2234 	if (udf_rw16(eahdr->tag.id) != TAGID_EXTATTR_HDR)
   2235 		return EINVAL;
   2236 	error = udf_check_tag_payload(eahdr, sizeof(struct extattrhdr_desc));
   2237 	if (error)
   2238 		return EINVAL;
   2239 
   2240 	/* looking for Ecma-167 attributes? */
   2241 	offset = sizeof(struct extattrhdr_desc);
   2242 
   2243 	/* looking for either implementation use or application use */
   2244 	if (sattr == 2048) {				/* [4/48.10.8] */
   2245 		offset = udf_rw32(eahdr->impl_attr_loc);
   2246 		if (offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2247 			return ENOENT;
   2248 	}
   2249 	if (sattr == 65536) {				/* [4/48.10.9] */
   2250 		offset = udf_rw32(eahdr->appl_attr_loc);
   2251 		if (offset == UDF_APPL_ATTR_LOC_NOT_PRESENT)
   2252 			return ENOENT;
   2253 	}
   2254 
   2255 	/* paranoia check offset and l_ea */
   2256 	if (l_ea + offset >= sector_size - sizeof(struct extattr_entry))
   2257 		return EINVAL;
   2258 
   2259 	/* find our extended attribute  */
   2260 	l_ea -= offset;
   2261 	pos = (uint8_t *) eahdr + offset;
   2262 
   2263 	while (l_ea >= sizeof(struct extattr_entry)) {
   2264 		attrhdr = (struct extattr_entry *) pos;
   2265 		implext = (struct impl_extattr_entry *) pos;
   2266 
   2267 		/* get complete attribute length and check for roque values */
   2268 		a_l = udf_rw32(attrhdr->a_l);
   2269 		if ((a_l == 0) || (a_l > l_ea))
   2270 			return EINVAL;
   2271 
   2272 		if (attrhdr->type != sattr)
   2273 			goto next_attribute;
   2274 
   2275 		/* we might have found it! */
   2276 		if (attrhdr->type < 2048) {	/* Ecma-167 attribute */
   2277 			*offsetp = offset;
   2278 			*lengthp = a_l;
   2279 			return 0;		/* success */
   2280 		}
   2281 
   2282 		/*
   2283 		 * Implementation use and application use extended attributes
   2284 		 * have a name to identify. They share the same structure only
   2285 		 * UDF implementation use extended attributes have a checksum
   2286 		 * we need to check
   2287 		 */
   2288 
   2289 		if (strcmp((char *) implext->imp_id.id, sattrname) == 0) {
   2290 			/* we have found our appl/implementation attribute */
   2291 			*offsetp = offset;
   2292 			*lengthp = a_l;
   2293 			return 0;		/* success */
   2294 		}
   2295 
   2296 next_attribute:
   2297 		/* next attribute */
   2298 		pos    += a_l;
   2299 		l_ea   -= a_l;
   2300 		offset += a_l;
   2301 	}
   2302 	/* not found */
   2303 	return ENOENT;
   2304 }
   2305 
   2306 
   2307 static void
   2308 udf_extattr_insert_internal(union dscrptr *dscr, struct extattr_entry *extattr)
   2309 {
   2310 	struct file_entry      *fe;
   2311 	struct extfile_entry   *efe;
   2312 	struct extattrhdr_desc *extattrhdr;
   2313 	struct impl_extattr_entry *implext;
   2314 	uint32_t impl_attr_loc, appl_attr_loc, l_ea, l_ad, a_l;
   2315 	uint16_t *spos;
   2316 	uint8_t *bpos, *data;
   2317 	void *l_eap;
   2318 
   2319 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   2320 		fe    = &dscr->fe;
   2321 		data  = fe->data;
   2322 		l_eap = &fe->l_ea;
   2323 		l_ad  = udf_rw32(fe->l_ad);
   2324 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   2325 		efe   = &dscr->efe;
   2326 		data  = efe->data;
   2327 		l_eap = &efe->l_ea;
   2328 		l_ad  = udf_rw32(efe->l_ad);
   2329 	} else {
   2330 		errx(1, "internal error, bad tag in %s", __func__);
   2331 	}
   2332 
   2333 	/* should have a header! */
   2334 	extattrhdr = (struct extattrhdr_desc *) data;
   2335 	memcpy(&l_ea, l_eap, sizeof(l_ea));
   2336 	l_ea = udf_rw32(l_ea);
   2337 	if (l_ea == 0) {
   2338 		uint32_t exthdr_len;
   2339 		assert(l_ad == 0);
   2340 		/* create empty extended attribute header */
   2341 		l_ea = sizeof(struct extattrhdr_desc);
   2342 		exthdr_len = udf_rw32(l_ea);
   2343 
   2344 		udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0);
   2345 		extattrhdr->impl_attr_loc = exthdr_len;
   2346 		extattrhdr->appl_attr_loc = exthdr_len;
   2347 		extattrhdr->tag.desc_crc_len = udf_rw16(8);
   2348 
   2349 		/* record extended attribute header length */
   2350 		memcpy(l_eap, &exthdr_len, sizeof(exthdr_len));
   2351 	}
   2352 
   2353 	/* extract locations */
   2354 	impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc);
   2355 	appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc);
   2356 	if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2357 		impl_attr_loc = l_ea;
   2358 	if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
   2359 		appl_attr_loc = l_ea;
   2360 
   2361 	/* Ecma 167 EAs */
   2362 	if (udf_rw32(extattr->type) < 2048) {
   2363 		assert(impl_attr_loc == l_ea);
   2364 		assert(appl_attr_loc == l_ea);
   2365 	}
   2366 
   2367 	/* implementation use extended attributes */
   2368 	if (udf_rw32(extattr->type) == 2048) {
   2369 		assert(appl_attr_loc == l_ea);
   2370 
   2371 		/* calculate and write extended attribute header checksum */
   2372 		implext = (struct impl_extattr_entry *) extattr;
   2373 		assert(udf_rw32(implext->iu_l) == 4);	/* [UDF 3.3.4.5] */
   2374 		spos = (uint16_t *) implext->data;
   2375 		*spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
   2376 	}
   2377 
   2378 	/* application use extended attributes */
   2379 	assert(udf_rw32(extattr->type) != 65536);
   2380 	assert(appl_attr_loc == l_ea);
   2381 
   2382 	/* append the attribute at the end of the current space */
   2383 	bpos = data + l_ea;
   2384 	a_l  = udf_rw32(extattr->a_l);
   2385 
   2386 	/* update impl. attribute locations */
   2387 	if (udf_rw32(extattr->type) < 2048) {
   2388 		impl_attr_loc = l_ea + a_l;
   2389 		appl_attr_loc = l_ea + a_l;
   2390 	}
   2391 	if (udf_rw32(extattr->type) == 2048) {
   2392 		appl_attr_loc = l_ea + a_l;
   2393 	}
   2394 
   2395 	/* copy and advance */
   2396 	memcpy(bpos, extattr, a_l);
   2397 	l_ea += a_l;
   2398 	l_ea = udf_rw32(l_ea);
   2399 	memcpy(l_eap, &l_ea, sizeof(l_ea));
   2400 
   2401 	/* do the `dance` again backwards */
   2402 	if (context.dscrver != 2) {
   2403 		if (impl_attr_loc == l_ea)
   2404 			impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT;
   2405 		if (appl_attr_loc == l_ea)
   2406 			appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT;
   2407 	}
   2408 
   2409 	/* store offsets */
   2410 	extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc);
   2411 	extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc);
   2412 
   2413 	/* make sure the header sums stays correct */
   2414 	udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
   2415 }
   2416 
   2417 /* --------------------------------------------------------------------- */
   2418 
   2419 int
   2420 udf_create_new_fe(struct file_entry **fep, int file_type, struct stat *st)
   2421 {
   2422 	struct file_entry      *fe;
   2423 	struct icb_tag         *icb;
   2424 	struct timestamp        birthtime;
   2425 	struct filetimes_extattr_entry *ft_extattr;
   2426 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   2427 	uint16_t icbflags;
   2428 
   2429 	*fep = NULL;
   2430 	fe = calloc(1, context.sector_size);
   2431 	if (fe == NULL)
   2432 		return ENOMEM;
   2433 
   2434 	udf_inittag(&fe->tag, TAGID_FENTRY, /* loc */ 0);
   2435 	icb = &fe->icbtag;
   2436 
   2437 	/*
   2438 	 * Always use strategy type 4 unless on WORM wich we don't support
   2439 	 * (yet). Fill in defaults and set for internal allocation of data.
   2440 	 */
   2441 	icb->strat_type      = udf_rw16(4);
   2442 	icb->max_num_entries = udf_rw16(1);
   2443 	icb->file_type       = file_type;	/* 8 bit */
   2444 	icb->flags           = udf_rw16(UDF_ICB_INTERN_ALLOC);
   2445 
   2446 	fe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
   2447 	fe->link_cnt = udf_rw16(0);		/* explicit setting */
   2448 
   2449 	fe->ckpoint  = udf_rw32(1);		/* user supplied file version */
   2450 
   2451 	udf_set_timestamp_now(&birthtime);
   2452 	udf_set_timestamp_now(&fe->atime);
   2453 	udf_set_timestamp_now(&fe->attrtime);
   2454 	udf_set_timestamp_now(&fe->mtime);
   2455 
   2456 	/* set attributes */
   2457 	if (st) {
   2458 #if !HAVE_NBTOOL_CONFIG_H
   2459 		udf_set_timestamp(&birthtime,    st->st_birthtime);
   2460 #else
   2461 		udf_set_timestamp(&birthtime,    0);
   2462 #endif
   2463 		udf_set_timestamp(&fe->atime,    st->st_atime);
   2464 		udf_set_timestamp(&fe->attrtime, st->st_ctime);
   2465 		udf_set_timestamp(&fe->mtime,    st->st_mtime);
   2466 		fe->uid  = udf_rw32(st->st_uid);
   2467 		fe->gid  = udf_rw32(st->st_gid);
   2468 
   2469 		fe->perm = unix_mode_to_udf_perm(st->st_mode);
   2470 
   2471 		icbflags = udf_rw16(fe->icbtag.flags);
   2472 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
   2473 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
   2474 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
   2475 		if (st->st_mode & S_ISUID)
   2476 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
   2477 		if (st->st_mode & S_ISGID)
   2478 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
   2479 		if (st->st_mode & S_ISVTX)
   2480 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
   2481 		fe->icbtag.flags  = udf_rw16(icbflags);
   2482 	}
   2483 
   2484 	udf_set_regid(&fe->imp_id, context.impl_name);
   2485 	udf_add_impl_regid(&fe->imp_id);
   2486 	fe->unique_id = udf_rw64(context.unique_id);
   2487 	udf_advance_uniqueid();
   2488 
   2489 	fe->l_ea = udf_rw32(0);
   2490 
   2491 	/* create extended attribute to record our creation time */
   2492 	ft_extattr = calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
   2493 	ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO);
   2494 	ft_extattr->hdr.subtype = 1;	/* [4/48.10.5] */
   2495 	ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
   2496 	ft_extattr->d_l     = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */
   2497 	ft_extattr->existence = UDF_FILETIMES_FILE_CREATION;
   2498 	ft_extattr->times[0]  = birthtime;
   2499 
   2500 	udf_extattr_insert_internal((union dscrptr *) fe,
   2501 		(struct extattr_entry *) ft_extattr);
   2502 	free(ft_extattr);
   2503 
   2504 	/* record fidlength information */
   2505 	fe->inf_len = udf_rw64(0);
   2506 	fe->l_ad    = udf_rw32(0);
   2507 	fe->logblks_rec = udf_rw64(0);		/* intern */
   2508 
   2509 	crclen  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2510 	crclen += udf_rw32(fe->l_ea);
   2511 
   2512 	/* make sure the header sums stays correct */
   2513 	fe->tag.desc_crc_len = udf_rw16(crclen);
   2514 	udf_validate_tag_and_crc_sums((union dscrptr *) fe);
   2515 
   2516 	*fep = fe;
   2517 	return 0;
   2518 }
   2519 
   2520 
   2521 int
   2522 udf_create_new_efe(struct extfile_entry **efep, int file_type, struct stat *st)
   2523 {
   2524 	struct extfile_entry *efe;
   2525 	struct icb_tag       *icb;
   2526 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
   2527 	uint16_t icbflags;
   2528 
   2529 	*efep = NULL;
   2530 	efe = calloc(1, context.sector_size);
   2531 	if (efe == NULL)
   2532 		return ENOMEM;
   2533 
   2534 	udf_inittag(&efe->tag, TAGID_EXTFENTRY, /* loc */ 0);
   2535 	icb = &efe->icbtag;
   2536 
   2537 	/*
   2538 	 * Always use strategy type 4 unless on WORM wich we don't support
   2539 	 * (yet). Fill in defaults and set for internal allocation of data.
   2540 	 */
   2541 	icb->strat_type      = udf_rw16(4);
   2542 	icb->max_num_entries = udf_rw16(1);
   2543 	icb->file_type       = file_type;	/* 8 bit */
   2544 	icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC);
   2545 
   2546 	efe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
   2547 	efe->link_cnt = udf_rw16(0);		/* explicit setting */
   2548 
   2549 	efe->ckpoint  = udf_rw32(1);		/* user supplied file version */
   2550 
   2551 	udf_set_timestamp_now(&efe->ctime);
   2552 	udf_set_timestamp_now(&efe->atime);
   2553 	udf_set_timestamp_now(&efe->attrtime);
   2554 	udf_set_timestamp_now(&efe->mtime);
   2555 
   2556 	/* set attributes */
   2557 	if (st) {
   2558 #if !HAVE_NBTOOL_CONFIG_H
   2559 		udf_set_timestamp(&efe->ctime,    st->st_birthtime);
   2560 #else
   2561 		udf_set_timestamp(&efe->ctime,    0);
   2562 #endif
   2563 		udf_set_timestamp(&efe->atime,    st->st_atime);
   2564 		udf_set_timestamp(&efe->attrtime, st->st_ctime);
   2565 		udf_set_timestamp(&efe->mtime,    st->st_mtime);
   2566 		efe->uid = udf_rw32(st->st_uid);
   2567 		efe->gid = udf_rw32(st->st_gid);
   2568 
   2569 		efe->perm = unix_mode_to_udf_perm(st->st_mode);
   2570 
   2571 		icbflags = udf_rw16(efe->icbtag.flags);
   2572 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
   2573 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
   2574 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
   2575 		if (st->st_mode & S_ISUID)
   2576 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
   2577 		if (st->st_mode & S_ISGID)
   2578 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
   2579 		if (st->st_mode & S_ISVTX)
   2580 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
   2581 		efe->icbtag.flags = udf_rw16(icbflags);
   2582 	}
   2583 
   2584 	udf_set_regid(&efe->imp_id, context.impl_name);
   2585 	udf_add_impl_regid(&efe->imp_id);
   2586 
   2587 	efe->unique_id = udf_rw64(context.unique_id);
   2588 	udf_advance_uniqueid();
   2589 
   2590 	/* record fidlength information */
   2591 	efe->inf_len  = udf_rw64(0);
   2592 	efe->obj_size = udf_rw64(0);
   2593 	efe->l_ad     = udf_rw32(0);
   2594 	efe->logblks_rec = udf_rw64(0);
   2595 
   2596 	crclen  = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2597 
   2598 	/* make sure the header sums stays correct */
   2599 	efe->tag.desc_crc_len = udf_rw16(crclen);
   2600 	udf_validate_tag_and_crc_sums((union dscrptr *) efe);
   2601 
   2602 	*efep = efe;
   2603 	return 0;
   2604 }
   2605 
   2606 /* --------------------------------------------------------------------- */
   2607 
   2608 /* for METADATA file appending only */
   2609 static void
   2610 udf_append_meta_mapping_part_to_efe(struct extfile_entry *efe,
   2611 		struct short_ad *mapping)
   2612 {
   2613 	struct icb_tag *icb;
   2614 	uint64_t inf_len, obj_size, logblks_rec;
   2615 	uint32_t l_ad, l_ea;
   2616 	uint16_t crclen;
   2617 	uintptr_t bpos;
   2618 
   2619 	inf_len     = udf_rw64(efe->inf_len);
   2620 	obj_size    = udf_rw64(efe->obj_size);
   2621 	logblks_rec = udf_rw64(efe->logblks_rec);
   2622 	l_ad   = udf_rw32(efe->l_ad);
   2623 	l_ea   = udf_rw32(efe->l_ea);
   2624 	crclen = udf_rw16(efe->tag.desc_crc_len);
   2625 	icb    = &efe->icbtag;
   2626 
   2627 	/* set our allocation to shorts if not already done */
   2628 	icb->flags = udf_rw16(UDF_ICB_SHORT_ALLOC);
   2629 
   2630 	/* append short_ad */
   2631 	bpos = (uintptr_t)efe->data + l_ea + l_ad;
   2632 	memcpy((void *)bpos, mapping, sizeof(struct short_ad));
   2633 
   2634 	l_ad   += sizeof(struct short_ad);
   2635 	crclen += sizeof(struct short_ad);
   2636 	inf_len  += UDF_EXT_LEN(udf_rw32(mapping->len));
   2637 	obj_size += UDF_EXT_LEN(udf_rw32(mapping->len));
   2638 	logblks_rec = UDF_ROUNDUP(inf_len, context.sector_size) /
   2639 				context.sector_size;
   2640 
   2641 	efe->l_ad = udf_rw32(l_ad);
   2642 	efe->inf_len     = udf_rw64(inf_len);
   2643 	efe->obj_size    = udf_rw64(obj_size);
   2644 	efe->logblks_rec = udf_rw64(logblks_rec);
   2645 	efe->tag.desc_crc_len = udf_rw16(crclen);
   2646 }
   2647 
   2648 
   2649 /* for METADATA file appending only */
   2650 static void
   2651 udf_append_meta_mapping_to_efe(struct extfile_entry *efe,
   2652 	uint16_t partnr, uint32_t lb_num,
   2653 	uint64_t len)
   2654 {
   2655 	struct short_ad mapping;
   2656 	uint64_t max_len, part_len;
   2657 
   2658 	/* calculate max length meta allocation sizes */
   2659 	max_len = UDF_EXT_MAXLEN / context.sector_size; /* in sectors */
   2660 	max_len = (max_len / layout.meta_blockingnr) * layout.meta_blockingnr;
   2661 	max_len = max_len * context.sector_size;
   2662 
   2663 	memset(&mapping, 0, sizeof(mapping));
   2664 	while (len) {
   2665 		part_len = MIN(len, max_len);
   2666 		mapping.lb_num   = udf_rw32(lb_num);
   2667 		mapping.len      = udf_rw32(part_len);
   2668 
   2669 		udf_append_meta_mapping_part_to_efe(efe, &mapping);
   2670 
   2671 		lb_num += part_len / context.sector_size;
   2672 		len    -= part_len;
   2673 	}
   2674 }
   2675 
   2676 
   2677 int
   2678 udf_create_meta_files(void)
   2679 {
   2680 	struct extfile_entry *efe;
   2681 	struct long_ad meta_icb;
   2682 	uint64_t bytes;
   2683 	uint32_t sector_size;
   2684 	int filetype, error;
   2685 
   2686 	sector_size = context.sector_size;
   2687 
   2688 	memset(&meta_icb, 0, sizeof(meta_icb));
   2689 	meta_icb.len          = udf_rw32(sector_size);
   2690 	meta_icb.loc.part_num = udf_rw16(context.data_part);
   2691 
   2692 	/* create metadata file */
   2693 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_file);
   2694 	filetype = UDF_ICB_FILETYPE_META_MAIN;
   2695 	error = udf_create_new_efe(&efe, filetype, NULL);
   2696 	if (error)
   2697 		return error;
   2698 	context.meta_file = efe;
   2699 	context.meta_file->unique_id   = udf_rw64(0);
   2700 
   2701 	/* create metadata mirror file */
   2702 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_mirror);
   2703 	filetype = UDF_ICB_FILETYPE_META_MIRROR;
   2704 	error = udf_create_new_efe(&efe, filetype, NULL);
   2705 	if (error)
   2706 		return error;
   2707 	context.meta_mirror = efe;
   2708 	context.meta_mirror->unique_id = udf_rw64(0);
   2709 
   2710 	if (!(context.format_flags & FORMAT_READONLY)) {
   2711 		/* create metadata bitmap file */
   2712 		meta_icb.loc.lb_num   = udf_rw32(layout.meta_bitmap);
   2713 		filetype = UDF_ICB_FILETYPE_META_BITMAP;
   2714 		error = udf_create_new_efe(&efe, filetype, NULL);
   2715 		if (error)
   2716 			return error;
   2717 		context.meta_bitmap = efe;
   2718 		context.meta_bitmap->unique_id = udf_rw64(0);
   2719 	}
   2720 
   2721 	/* restart unique id */
   2722 	context.unique_id = 0x10;
   2723 
   2724 	/* XXX no support for metadata mirroring yet */
   2725 	/* insert extents */
   2726 	efe = context.meta_file;
   2727 	udf_append_meta_mapping_to_efe(efe, context.data_part,
   2728 		layout.meta_part_start_lba,
   2729 		(uint64_t) layout.meta_part_size_lba * sector_size);
   2730 
   2731 	efe = context.meta_mirror;
   2732 	udf_append_meta_mapping_to_efe(efe, context.data_part,
   2733 		layout.meta_part_start_lba,
   2734 		(uint64_t) layout.meta_part_size_lba * sector_size);
   2735 
   2736 	if (context.meta_bitmap) {
   2737 		efe = context.meta_bitmap;
   2738 		bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
   2739 		udf_append_meta_mapping_to_efe(efe, context.data_part,
   2740 			layout.meta_bitmap_space, bytes);
   2741 	}
   2742 
   2743 	return 0;
   2744 }
   2745 
   2746 
   2747 /* --------------------------------------------------------------------- */
   2748 
   2749 int
   2750 udf_create_new_rootdir(union dscrptr **dscr)
   2751 {
   2752 	struct file_entry *fe;
   2753 	struct extfile_entry *efe;
   2754 	struct long_ad root_icb;
   2755 	int filetype, error;
   2756 
   2757 	memset(&root_icb, 0, sizeof(root_icb));
   2758 	root_icb.len          = udf_rw32(context.sector_size);
   2759 	root_icb.loc.lb_num   = udf_rw32(layout.rootdir);
   2760 	root_icb.loc.part_num = udf_rw16(context.metadata_part);
   2761 
   2762 	filetype = UDF_ICB_FILETYPE_DIRECTORY;
   2763 	if (context.dscrver == 2) {
   2764 		error = udf_create_new_fe(&fe, filetype, NULL);
   2765 		*dscr = (union dscrptr *) fe;
   2766 	} else {
   2767 		error = udf_create_new_efe(&efe, filetype, NULL);
   2768 		*dscr = (union dscrptr *) efe;
   2769 	}
   2770 	if (error)
   2771 		return error;
   2772 
   2773 	/* append '..' */
   2774 	udf_append_parentfid(*dscr, &root_icb);
   2775 
   2776 	/* rootdir has explicit only one link on creation; '..' is no link */
   2777 	if (context.dscrver == 2) {
   2778 		fe->link_cnt  = udf_rw16(1);
   2779 	} else {
   2780 		efe->link_cnt = udf_rw16(1);
   2781 	}
   2782 
   2783 	context.num_directories++;
   2784 	assert(context.num_directories == 1);
   2785 
   2786 	return 0;
   2787 }
   2788 
   2789 
   2790 void
   2791 udf_prepend_VAT_file(void)
   2792 {
   2793 	/* old style VAT has no prepend */
   2794 	if (context.dscrver == 2) {
   2795 		context.vat_start = 0;
   2796 		context.vat_size  = 0;
   2797 		return;
   2798 	}
   2799 
   2800 	context.vat_start = offsetof(struct udf_vat, data);
   2801 	context.vat_size  = offsetof(struct udf_vat, data);
   2802 }
   2803 
   2804 
   2805 void
   2806 udf_vat_update(uint32_t virt, uint32_t phys)
   2807 {
   2808 	uint32_t *vatpos;
   2809 	uint32_t new_size;
   2810 
   2811 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
   2812 		return;
   2813 
   2814 	new_size = MAX(context.vat_size,
   2815 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
   2816 
   2817 	if (new_size > context.vat_allocated) {
   2818 		context.vat_allocated =
   2819 			UDF_ROUNDUP(new_size, context.sector_size);
   2820 		context.vat_contents = realloc(context.vat_contents,
   2821 			context.vat_allocated);
   2822 		assert(context.vat_contents);
   2823 		/* XXX could also report error */
   2824 	}
   2825 	vatpos  = (uint32_t *) (context.vat_contents + context.vat_start);
   2826 	vatpos[virt] = udf_rw32(phys);
   2827 
   2828 	context.vat_size = MAX(context.vat_size,
   2829 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
   2830 }
   2831 
   2832 
   2833 int
   2834 udf_append_VAT_file(void)
   2835 {
   2836 	struct udf_oldvat_tail *oldvat_tail;
   2837 	struct udf_vat *vathdr;
   2838 	int32_t len_diff;
   2839 
   2840 	/* new style VAT has VAT LVInt analog in front */
   2841 	if (context.dscrver == 3) {
   2842 		/* set up VATv2 descriptor */
   2843 		vathdr = (struct udf_vat *) context.vat_contents;
   2844 		vathdr->header_len      = udf_rw16(sizeof(struct udf_vat) - 1);
   2845 		vathdr->impl_use_len    = udf_rw16(0);
   2846 		memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
   2847 		vathdr->prev_vat        = udf_rw32(UDF_NO_PREV_VAT);
   2848 		vathdr->num_files       = udf_rw32(context.num_files);
   2849 		vathdr->num_directories = udf_rw32(context.num_directories);
   2850 
   2851 		vathdr->min_udf_readver  = udf_rw16(context.min_udf);
   2852 		vathdr->min_udf_writever = udf_rw16(context.min_udf);
   2853 		vathdr->max_udf_writever = udf_rw16(context.max_udf);
   2854 
   2855 		return 0;
   2856 	}
   2857 
   2858 	/* old style VAT has identifier appended */
   2859 
   2860 	/* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
   2861 	len_diff = context.vat_allocated - context.vat_size;
   2862 	assert(len_diff >= 0);
   2863 	if (len_diff < (int32_t) sizeof(struct udf_oldvat_tail)) {
   2864 		context.vat_allocated += context.sector_size;
   2865 		context.vat_contents = realloc(context.vat_contents,
   2866 			context.vat_allocated);
   2867 		assert(context.vat_contents);
   2868 		/* XXX could also report error */
   2869 	}
   2870 
   2871 	oldvat_tail = (struct udf_oldvat_tail *) (context.vat_contents +
   2872 			context.vat_size);
   2873 
   2874 	udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
   2875 	udf_add_udf_regid(&oldvat_tail->id);
   2876 	oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
   2877 
   2878 	context.vat_size += sizeof(struct udf_oldvat_tail);
   2879 
   2880 	return 0;
   2881 }
   2882 
   2883 
   2884 int
   2885 udf_create_VAT(union dscrptr **vat_dscr, struct long_ad *vatdata_loc)
   2886 {
   2887 	struct impl_extattr_entry *implext;
   2888 	struct vatlvext_extattr_entry *vatlvext;
   2889 	struct long_ad *allocpos;
   2890 	uint8_t *bpos, *extattr;
   2891 	uint32_t ea_len, inf_len, vat_len, blks;
   2892 	int filetype;
   2893 	int error;
   2894 
   2895 	assert((layout.rootdir < 2) && (layout.fsd < 2));
   2896 
   2897 	if (context.dscrver == 2) {
   2898 		struct file_entry *fe;
   2899 
   2900 		/* old style VAT */
   2901 		filetype = UDF_ICB_FILETYPE_UNKNOWN;
   2902 		error = udf_create_new_fe(&fe, filetype, NULL);
   2903 		if (error)
   2904 			return error;
   2905 
   2906 		/* append VAT LVExtension attribute */
   2907 		ea_len = sizeof(struct impl_extattr_entry) - 2 + 4 +
   2908 			 sizeof(struct vatlvext_extattr_entry);
   2909 
   2910 		extattr = calloc(1, ea_len);
   2911 
   2912 		implext  = (struct impl_extattr_entry *) extattr;
   2913 		implext->hdr.type = udf_rw32(2048);	/* [4/48.10.8] */
   2914 		implext->hdr.subtype = 1;		/* [4/48.10.8.2] */
   2915 		implext->hdr.a_l = udf_rw32(ea_len);	/* VAT LVext EA size */
   2916 		/* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
   2917 		implext->iu_l = udf_rw32(4);
   2918 		udf_set_regid(&implext->imp_id, "*UDF VAT LVExtension");
   2919 		udf_add_udf_regid(&implext->imp_id);
   2920 
   2921 		/* VAT LVExtension data follows UDF IU space */
   2922 		bpos = ((uint8_t *) implext->data) + 4;
   2923 		vatlvext = (struct vatlvext_extattr_entry *) bpos;
   2924 
   2925 		vatlvext->unique_id_chk = udf_rw64(fe->unique_id);
   2926 		vatlvext->num_files = udf_rw32(context.num_files);
   2927 		vatlvext->num_directories = udf_rw32(context.num_directories);
   2928 		memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id,128);
   2929 
   2930 		udf_extattr_insert_internal((union dscrptr *) fe,
   2931 			(struct extattr_entry *) extattr);
   2932 
   2933 		free(extattr);
   2934 
   2935 		fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2936 
   2937 		allocpos = (struct long_ad *) (fe->data + udf_rw32(fe->l_ea));
   2938 		*allocpos = *vatdata_loc;
   2939 
   2940 		/* set length */
   2941 		inf_len       = context.vat_size;
   2942 		fe->inf_len   = udf_rw64(inf_len);
   2943 		allocpos->len = udf_rw32(inf_len);
   2944 		fe->l_ad      = udf_rw32(sizeof(struct long_ad));
   2945 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   2946 			context.sector_size;
   2947 		fe->logblks_rec = udf_rw32(blks);
   2948 
   2949 		/* update vat descriptor's CRC length */
   2950 		vat_len  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
   2951 		vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
   2952 		fe->tag.desc_crc_len = udf_rw16(vat_len);
   2953 
   2954 		*vat_dscr = (union dscrptr *) fe;
   2955 	} else {
   2956 		/* the choice is between an EFE or an FE as VAT */
   2957 #if 1
   2958 		struct extfile_entry *efe;
   2959 
   2960 		/* new style VAT on FE */
   2961 		filetype = UDF_ICB_FILETYPE_VAT;
   2962 		error = udf_create_new_efe(&efe, filetype, NULL);
   2963 		if (error)
   2964 			return error;
   2965 
   2966 		efe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2967 
   2968 		allocpos = (struct long_ad *) efe->data;
   2969 		*allocpos = *vatdata_loc;
   2970 
   2971 		/* set length */
   2972 		inf_len = context.vat_size;
   2973 		efe->inf_len     = udf_rw64(inf_len);
   2974 		allocpos->len    = udf_rw32(inf_len);
   2975 		efe->obj_size    = udf_rw64(inf_len);
   2976 		efe->l_ad        = udf_rw32(sizeof(struct long_ad));
   2977 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   2978 			context.sector_size;
   2979 		efe->logblks_rec = udf_rw32(blks);
   2980 
   2981 		vat_len  = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH;
   2982 		vat_len += udf_rw32(efe->l_ad);
   2983 		efe->tag.desc_crc_len = udf_rw16(vat_len);
   2984 
   2985 		*vat_dscr = (union dscrptr *) efe;
   2986 #else
   2987 		struct file_entry *fe;
   2988 		uint32_t l_ea;
   2989 
   2990 		/* new style VAT on EFE */
   2991 		filetype = UDF_ICB_FILETYPE_VAT;
   2992 		error = udf_create_new_fe(&fe, filetype, NULL);
   2993 		if (error)
   2994 			return error;
   2995 
   2996 		fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
   2997 
   2998 		l_ea = udf_rw32(fe->l_ea);
   2999 		allocpos  = (struct long_ad *) (fe->data + l_ea);
   3000 		*allocpos = *vatdata_loc;
   3001 
   3002 		/* set length */
   3003 		inf_len         = context.vat_size;
   3004 		fe->inf_len     = udf_rw64(inf_len);
   3005 		allocpos->len   = udf_rw32(inf_len);
   3006 		fe->l_ad        = udf_rw32(sizeof(struct long_ad));
   3007 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
   3008 			context.sector_size;
   3009 		fe->logblks_rec = udf_rw32(blks);
   3010 
   3011 		vat_len  = sizeof(struct file_entry)-1 - UDF_DESC_TAG_LENGTH;
   3012 		vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
   3013 		fe->tag.desc_crc_len = udf_rw16(vat_len);
   3014 
   3015 		*vat_dscr = (union dscrptr *) fe;
   3016 #endif
   3017 	}
   3018 
   3019 	return 0;
   3020 }
   3021 
   3022 
   3023 int
   3024 udf_writeout_VAT(void)
   3025 {
   3026 	union dscrptr *vat_dscr;
   3027 	struct long_ad vatdata;
   3028 	uint32_t loc, phys, ext, sects;
   3029 	int rel_block, rest_block, error;
   3030 
   3031 	vat_dscr = NULL;
   3032 	/* update lvint to reflect the newest values (no writeout) */
   3033 	udf_update_lvintd(UDF_INTEGRITY_CLOSED);
   3034 
   3035 	error = udf_append_VAT_file();
   3036 	if (error)
   3037 		return error;
   3038 
   3039 	/* write out VAT data */
   3040 	sects = UDF_ROUNDUP(context.vat_size, context.sector_size) /
   3041 		context.sector_size;
   3042 	layout.vat = context.alloc_pos[context.data_part];
   3043 	udf_data_alloc(sects, &vatdata);
   3044 //printf("layout.vat %d\n", layout.vat + udf_rw32(context.partitions[context.data_part]->start_loc));
   3045 
   3046 	loc = udf_rw32(vatdata.loc.lb_num);
   3047 	udf_translate_vtop(loc, context.data_part, &phys, &ext);
   3048 
   3049 	error = udf_write_phys(context.vat_contents, phys, sects);
   3050 	if (error)
   3051 		return error;
   3052 	loc += sects;
   3053 
   3054 	/* create new VAT descriptor */
   3055 	error = udf_create_VAT(&vat_dscr, &vatdata);
   3056 	if (error)
   3057 		return error;
   3058 
   3059 //printf("VAT data at %d\n", vatdata.loc.lb_num);
   3060 //printf("VAT itself at %d\n", loc + udf_rw32(context.partitions[context.data_part]->start_loc));
   3061 
   3062 	/* at least one */
   3063 	error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
   3064 	loc++;
   3065 
   3066 	error = udf_translate_vtop(loc, context.data_part, &phys, &ext);
   3067 	assert(!error);
   3068 
   3069 	rel_block  = phys - (UDF_ROUNDDOWN(phys, layout.blockingnr) + wrtrack_skew);
   3070 	rest_block = layout.blockingnr - rel_block;
   3071 
   3072 	for (int i = 0; i < rest_block; i++) {
   3073 		error = udf_write_dscr_virt(vat_dscr, loc, context.data_part, 1);
   3074 		loc++;
   3075 	}
   3076 	free(vat_dscr);
   3077 
   3078 	return error;
   3079 }
   3080 
   3081 
   3082 /* --------------------------------------------------------------------- */
   3083 /*
   3084  * mmc_discinfo and mmc_trackinfo readers modified from origional in udf main
   3085  * code in sys/fs/udf/
   3086  */
   3087 
   3088 void
   3089 udf_dump_discinfo(struct mmc_discinfo *di)
   3090 {
   3091 #ifdef DEBUG
   3092 	char bits[128];
   3093 
   3094 	printf("Device/media info  :\n");
   3095 	printf("\tMMC profile        0x%02x\n", di->mmc_profile);
   3096 	printf("\tderived class      %d\n", di->mmc_class);
   3097 	printf("\tsector size        %d\n", di->sector_size);
   3098 	printf("\tdisc state         %d\n", di->disc_state);
   3099 	printf("\tlast ses state     %d\n", di->last_session_state);
   3100 	printf("\tbg format state    %d\n", di->bg_format_state);
   3101 	printf("\tfrst track         %d\n", di->first_track);
   3102 	printf("\tfst on last ses    %d\n", di->first_track_last_session);
   3103 	printf("\tlst on last ses    %d\n", di->last_track_last_session);
   3104 	printf("\tlink block penalty %d\n", di->link_block_penalty);
   3105 	snprintb(bits, sizeof(bits), MMC_DFLAGS_FLAGBITS, (uint64_t) di->disc_flags);
   3106 	printf("\tdisc flags         %s\n", bits);
   3107 	printf("\tdisc id            %x\n", di->disc_id);
   3108 	printf("\tdisc barcode       %"PRIx64"\n", di->disc_barcode);
   3109 
   3110 	printf("\tnum sessions       %d\n", di->num_sessions);
   3111 	printf("\tnum tracks         %d\n", di->num_tracks);
   3112 
   3113 	snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cur);
   3114 	printf("\tcapabilities cur   %s\n", bits);
   3115 	snprintb(bits, sizeof(bits), MMC_CAP_FLAGBITS, di->mmc_cap);
   3116 	printf("\tcapabilities cap   %s\n", bits);
   3117 	printf("\n");
   3118 	printf("\tlast_possible_lba  %d\n", di->last_possible_lba);
   3119 	printf("\n");
   3120 #endif
   3121 }
   3122 
   3123 
   3124 void
   3125 udf_synchronise_caches(void)
   3126 {
   3127 #if !HAVE_NBTOOL_CONFIG_H
   3128 	struct mmc_op mmc_op;
   3129 
   3130 	bzero(&mmc_op, sizeof(struct mmc_op));
   3131 	mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
   3132 
   3133 	/* this device might not know this ioct, so just be ignorant */
   3134 	(void) ioctl(dev_fd, MMCOP, &mmc_op);
   3135 #endif
   3136 }
   3137 
   3138 
   3139 /*
   3140  * General Idea:
   3141  *
   3142  * stat the dev_fd
   3143  *
   3144  * If a S_ISREG(), we emulate using the emul_* settings.
   3145  *
   3146  * If its a device :
   3147  * 	try the MMCGETDISCINFO ioctl() and be done.
   3148  *
   3149  * If that fails, its a regular disc and set the type to disc media.
   3150  *
   3151  */
   3152 
   3153 
   3154 int
   3155 udf_update_discinfo(void)
   3156 {
   3157 	off_t size, last_sector, secsize;
   3158 	int error;
   3159 
   3160 	memset(&mmc_discinfo, 0, sizeof(struct mmc_discinfo));
   3161 
   3162 #if !HAVE_NBTOOL_CONFIG_H
   3163 	/* check if we're on a MMC capable device, i.e. CD/DVD */
   3164 	error = ioctl(dev_fd, MMCGETDISCINFO, &mmc_discinfo);
   3165 	if (error == 0) {
   3166 		if ((emul_mmc_profile != -1) &&
   3167 		   (emul_mmc_profile != mmc_discinfo.mmc_profile)) {
   3168 			errno = EINVAL;
   3169 			perror("media and specified disc type mismatch");
   3170 			return errno;
   3171 		}
   3172 		emul_size = 0;
   3173 		return 0;
   3174 	}
   3175 #endif
   3176 
   3177 	if (S_ISREG(dev_fd_stat.st_mode)) {
   3178 		/* file support; we pick the minimum sector size allowed */
   3179 		if (emul_mmc_profile < 0)
   3180 			emul_mmc_profile = 0x01;
   3181 		if (emul_size == 0)
   3182 			emul_size = dev_fd_stat.st_size;
   3183 		size = emul_size;
   3184 		secsize = emul_sectorsize;
   3185 		last_sector = (size / secsize) - 1;
   3186 		if (ftruncate(dev_fd, size)) {
   3187 			perror("can't resize file");
   3188 			return EXIT_FAILURE;
   3189 		}
   3190 	} else {
   3191 #if !HAVE_NBTOOL_CONFIG_H
   3192 		struct disk_geom	geo;
   3193 		struct dkwedge_info	dkw;
   3194 
   3195 		/* sanity */
   3196 		if (emul_mmc_profile <= 0)
   3197 			emul_mmc_profile = 0x01;
   3198 		if (emul_mmc_profile != 0x01) {
   3199 			warnx("format incompatible with disc partition");
   3200 			return EXIT_FAILURE;
   3201 		}
   3202 
   3203 		/* get our disc info */
   3204 		error = getdiskinfo(dev_name, dev_fd, NULL, &geo, &dkw);
   3205 		if (error) {
   3206 			warn("retrieving disc info failed");
   3207 			return EXIT_FAILURE;
   3208 		}
   3209 		secsize = emul_sectorsize;
   3210 		last_sector = (dkw.dkw_size - 1) * geo.dg_secsize / secsize;
   3211 #else
   3212 		warnx("disk partitions only usable outside tools");
   3213 		return EIO;
   3214 #endif
   3215 	}
   3216 
   3217 	/* commons */
   3218 	mmc_discinfo.mmc_profile	= emul_mmc_profile;
   3219 	mmc_discinfo.disc_state		= MMC_STATE_CLOSED;
   3220 	mmc_discinfo.last_session_state	= MMC_STATE_CLOSED;
   3221 	mmc_discinfo.bg_format_state	= MMC_BGFSTATE_COMPLETED;
   3222 	mmc_discinfo.link_block_penalty	= 0;
   3223 
   3224 	mmc_discinfo.disc_flags = MMC_DFLAGS_UNRESTRICTED;
   3225 
   3226 	mmc_discinfo.last_possible_lba = last_sector;
   3227 	mmc_discinfo.sector_size       = secsize;
   3228 
   3229 	mmc_discinfo.num_sessions = 1;
   3230 	mmc_discinfo.num_tracks   = 1;
   3231 
   3232 	mmc_discinfo.first_track  = 1;
   3233 	mmc_discinfo.first_track_last_session = mmc_discinfo.last_track_last_session = 1;
   3234 
   3235 	mmc_discinfo.mmc_cur = MMC_CAP_RECORDABLE | MMC_CAP_ZEROLINKBLK;
   3236 	switch (emul_mmc_profile) {
   3237 	case 0x00:	/* unknown, treat as CDROM */
   3238 	case 0x08:	/* CDROM */
   3239 	case 0x10:	/* DVDROM */
   3240 	case 0x40:	/* BDROM */
   3241 		/* FALLTHROUGH */
   3242 	case 0x01:	/* disc */
   3243 		/* set up a disc info profile for partitions/files */
   3244 		mmc_discinfo.mmc_class	= MMC_CLASS_DISC;
   3245 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
   3246 		break;
   3247 	case 0x09:	/* CD-R */
   3248 		mmc_discinfo.mmc_class	= MMC_CLASS_CD;
   3249 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL;
   3250 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3251 		break;
   3252 	case 0x0a:	/* CD-RW + CD-MRW (regretably) */
   3253 		mmc_discinfo.mmc_class	= MMC_CLASS_CD;
   3254 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE;
   3255 		break;
   3256 	case 0x13:	/* DVD-RW */
   3257 	case 0x1a:	/* DVD+RW */
   3258 		mmc_discinfo.mmc_class	= MMC_CLASS_DVD;
   3259 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE;
   3260 		break;
   3261 	case 0x11:	/* DVD-R */
   3262 	case 0x14:	/* DVD-RW sequential */
   3263 	case 0x1b:	/* DVD+R */
   3264 	case 0x2b:	/* DVD+R DL */
   3265 	case 0x51:	/* HD DVD-R */
   3266 		mmc_discinfo.mmc_class	= MMC_CLASS_DVD;
   3267 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL;
   3268 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3269 		break;
   3270 	case 0x41:	/* BD-R */
   3271 		mmc_discinfo.mmc_class   = MMC_CLASS_BD;
   3272 		mmc_discinfo.mmc_cur    |= MMC_CAP_SEQUENTIAL | MMC_CAP_HW_DEFECTFREE;
   3273 		mmc_discinfo.disc_state  = MMC_STATE_EMPTY;
   3274 		break;
   3275 	case 0x43:	/* BD-RE */
   3276 		mmc_discinfo.mmc_class   = MMC_CLASS_BD;
   3277 		mmc_discinfo.mmc_cur    |= MMC_CAP_REWRITABLE | MMC_CAP_HW_DEFECTFREE;
   3278 		break;
   3279 	default:
   3280 		errno = EINVAL;
   3281 		perror("unknown or unimplemented device type");
   3282 		return errno;
   3283 	}
   3284 	mmc_discinfo.mmc_cap    = mmc_discinfo.mmc_cur;
   3285 
   3286 	return 0;
   3287 }
   3288 
   3289 
   3290 int
   3291 udf_update_trackinfo(struct mmc_trackinfo *ti)
   3292 {
   3293 	int error, class;
   3294 
   3295 #if !HAVE_NBTOOL_CONFIG_H
   3296 	class = mmc_discinfo.mmc_class;
   3297 	if (class != MMC_CLASS_DISC) {
   3298 		/* tracknr specified in struct ti */
   3299 		error = ioctl(dev_fd, MMCGETTRACKINFO, ti);
   3300 		if (!error)
   3301 			return 0;
   3302 	}
   3303 #endif
   3304 
   3305 	/* discs partition support */
   3306 	if (ti->tracknr != 1)
   3307 		return EIO;
   3308 
   3309 	/* create fake ti (TODO check for resized vnds) */
   3310 	ti->sessionnr  = 1;
   3311 
   3312 	ti->track_mode = 0;	/* XXX */
   3313 	ti->data_mode  = 0;	/* XXX */
   3314 	ti->flags = MMC_TRACKINFO_LRA_VALID | MMC_TRACKINFO_NWA_VALID;
   3315 
   3316 	ti->track_start    = 0;
   3317 	ti->packet_size    = emul_packetsize;
   3318 
   3319 	/* TODO support for resizable vnd */
   3320 	ti->track_size    = mmc_discinfo.last_possible_lba;
   3321 	ti->next_writable = mmc_discinfo.last_possible_lba + 1; //0;
   3322 	ti->last_recorded = ti->next_writable;
   3323 	ti->free_blocks   = 0;
   3324 
   3325 	return 0;
   3326 }
   3327 
   3328 
   3329 int
   3330 udf_opendisc(const char *device, int open_flags)
   3331 {
   3332 	/* set global variable to the passed name */
   3333 	dev_name = strdup(device);
   3334 
   3335 	/* open device */
   3336 	if (open_flags & O_RDONLY) {
   3337 		dev_fd_rdonly = 1;
   3338 		if ((dev_fd = open(dev_name, O_RDONLY, 0)) == -1) {
   3339 			warn("device/image not found");
   3340 			return EXIT_FAILURE;
   3341 		}
   3342 	} else {
   3343 		dev_fd_rdonly = 0;
   3344 		if ((dev_fd = open(dev_name, O_RDWR, 0)) == -1) {
   3345 			/* check if we need to create a file */
   3346 			dev_fd = open(dev_name, O_RDONLY, 0);
   3347 			if (dev_fd > 0) {
   3348 				warn("device is there but can't be opened for "
   3349 					"read/write");
   3350 				return EXIT_FAILURE;
   3351 			}
   3352 			if ((open_flags & O_CREAT) == 0) {
   3353 				warnx("device/image not found");
   3354 				return EXIT_FAILURE;
   3355 			}
   3356 			/* need to create a file */
   3357 			dev_fd = open(dev_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
   3358 			if (dev_fd == -1) {
   3359 				warn("can't create image file");
   3360 				return EXIT_FAILURE;
   3361 			}
   3362 		}
   3363 	}
   3364 
   3365 	/* stat the device/image */
   3366 	if (fstat(dev_fd, &dev_fd_stat) != 0) {
   3367 		warn("can't stat the disc image");
   3368 		return EXIT_FAILURE;
   3369 	}
   3370 
   3371 	/* sanity check and resizing of file */
   3372 	if (S_ISREG(dev_fd_stat.st_mode)) {
   3373 		if (emul_size == 0)
   3374 			emul_size = dev_fd_stat.st_size;
   3375 		/* sanitise arguments */
   3376 		emul_sectorsize &= ~511;
   3377 		if (emul_size & (emul_sectorsize-1)) {
   3378 			warnx("size of file is not a multiple of sector size, "
   3379 				"shrinking");
   3380 			emul_size -= emul_size & (emul_sectorsize-1);
   3381 		}
   3382 
   3383 		/* grow the image */
   3384 		if (ftruncate(dev_fd, emul_size)) {
   3385 			warn("can't resize file");
   3386 			return EXIT_FAILURE;
   3387 		}
   3388 		/* restat the device/image */
   3389 		if (fstat(dev_fd, &dev_fd_stat) != 0) {
   3390 			warn("can't re-stat the disc image");
   3391 			return EXIT_FAILURE;
   3392 		}
   3393 	} else {
   3394 		if (!S_ISCHR(dev_fd_stat.st_mode)) {
   3395 			warnx("%s is not a raw device", dev_name);
   3396 			return EXIT_FAILURE;
   3397 		}
   3398 	}
   3399 
   3400 	/* just in case something went wrong, synchronise the drive's cache */
   3401 	udf_synchronise_caches();
   3402 	if (udf_update_discinfo()) {
   3403 		warnx("update discinfo failed");
   3404 		return EXIT_FAILURE;
   3405 	}
   3406 
   3407 	/* honour minimum sector size of the device */
   3408 	if (mmc_discinfo.sector_size > context.sector_size)
   3409 		context.sector_size = mmc_discinfo.sector_size;
   3410 
   3411 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
   3412 		udf_init_writequeue(UDF_WRITE_SEQUENTIAL);
   3413 	else {
   3414 		udf_init_writequeue(UDF_WRITE_PACKET);
   3415 	}
   3416 	return 0;
   3417 }
   3418 
   3419 
   3420 void
   3421 udf_closedisc(void)
   3422 {
   3423 	if (!write_queue_suspend) {
   3424 		udf_writeout_writequeue(true);
   3425 		assert(write_queuelen == 0);
   3426 	}
   3427 
   3428 	udf_synchronise_caches();
   3429 	if (dev_fd)
   3430 		close(dev_fd);
   3431 }
   3432 
   3433 /* --------------------------------------------------------------------- */
   3434 
   3435 static int
   3436 udf_setup_writeparams(void)
   3437 {
   3438 #if !HAVE_NBTOOL_CONFIG_H
   3439 	struct mmc_writeparams mmc_writeparams;
   3440 	int error;
   3441 
   3442 	if (mmc_discinfo.mmc_class == MMC_CLASS_DISC)
   3443 		return 0;
   3444 
   3445 	if (S_ISREG(dev_fd_stat.st_mode))
   3446 		return 0;
   3447 
   3448 	/*
   3449 	 * only CD burning normally needs setting up, but other disc types
   3450 	 * might need other settings to be made. The MMC framework will set up
   3451 	 * the necessary recording parameters according to the disc
   3452 	 * characteristics read in. Modifications can be made in the discinfo
   3453 	 * structure passed to change the nature of the disc.
   3454 	 */
   3455 	memset(&mmc_writeparams, 0, sizeof(struct mmc_writeparams));
   3456 	mmc_writeparams.mmc_class  = mmc_discinfo.mmc_class;
   3457 	mmc_writeparams.mmc_cur    = mmc_discinfo.mmc_cur;
   3458 
   3459 	/*
   3460 	 * UDF dictates first track to determine track mode for the whole
   3461 	 * disc. [UDF 1.50/6.10.1.1, UDF 1.50/6.10.2.1]
   3462 	 * To prevent problems with a `reserved' track in front we start with
   3463 	 * the 2nd track and if that is not valid, go for the 1st.
   3464 	 */
   3465 	mmc_writeparams.tracknr = 2;
   3466 	mmc_writeparams.data_mode  = MMC_DATAMODE_DEFAULT;	/* XA disc */
   3467 	mmc_writeparams.track_mode = MMC_TRACKMODE_DEFAULT;	/* data */
   3468 
   3469 	error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
   3470 	if (error) {
   3471 		mmc_writeparams.tracknr = 1;
   3472 		error = ioctl(dev_fd, MMCSETUPWRITEPARAMS, &mmc_writeparams);
   3473 	}
   3474 	return error;
   3475 #else
   3476 	return 0;
   3477 #endif
   3478 }
   3479 
   3480 
   3481 /*
   3482  * On sequential recordable media, we might need to close the last session to
   3483  * be able to write new anchors/new fs.
   3484  */
   3485 static int
   3486 udf_open_new_session(void)
   3487 {
   3488 #if !HAVE_NBTOOL_CONFIG_H
   3489 	struct mmc_trackinfo ti;
   3490 	struct mmc_op        op;
   3491 	int tracknr, error;
   3492 
   3493 	/* if the drive is not sequential, we're done */
   3494 	if ((mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) == 0)
   3495 		return 0;
   3496 
   3497 	/* close the last session if its still open */
   3498 	if (mmc_discinfo.last_session_state == MMC_STATE_INCOMPLETE) {
   3499 		/*
   3500 		 * Leave the disc alone if force format is not set, it will
   3501 		 * error out later
   3502 		 */
   3503 		if (!context.create_new_session)
   3504 			return 0;
   3505 
   3506 //		printf("Closing last open session if present\n");
   3507 		/* close all associated tracks */
   3508 		tracknr = mmc_discinfo.first_track_last_session;
   3509 		while (tracknr <= mmc_discinfo.last_track_last_session) {
   3510 			ti.tracknr = tracknr;
   3511 			error = udf_update_trackinfo(&ti);
   3512 			if (error)
   3513 				return error;
   3514 //			printf("\tClosing open track %d\n", tracknr);
   3515 			memset(&op, 0, sizeof(op));
   3516 			op.operation   = MMC_OP_CLOSETRACK;
   3517 			op.mmc_profile = mmc_discinfo.mmc_profile;
   3518 			op.tracknr     = tracknr;
   3519 			error = ioctl(dev_fd, MMCOP, &op);
   3520 			if (error)
   3521 				return error;
   3522 			tracknr ++;
   3523 		}
   3524 //		printf("Closing session\n");
   3525 		memset(&op, 0, sizeof(op));
   3526 		op.operation   = MMC_OP_CLOSESESSION;
   3527 		op.mmc_profile = mmc_discinfo.mmc_profile;
   3528 		op.sessionnr   = mmc_discinfo.num_sessions;
   3529 		error = ioctl(dev_fd, MMCOP, &op);
   3530 		if (error)
   3531 			return error;
   3532 
   3533 		/* update discinfo since it changed by the operations */
   3534 		error = udf_update_discinfo();
   3535 		if (error)
   3536 			return error;
   3537 	}
   3538 #endif
   3539 	return 0;
   3540 }
   3541 
   3542 
   3543 /* bit paranoid but tracks may need repair before they can be written to */
   3544 static void
   3545 udf_repair_tracks(void)
   3546 {
   3547 #if !HAVE_NBTOOL_CONFIG_H
   3548 	struct mmc_trackinfo ti;
   3549 	struct mmc_op        op;
   3550 	int tracknr, error;
   3551 
   3552 	tracknr = mmc_discinfo.first_track_last_session;
   3553 	while (tracknr <= mmc_discinfo.last_track_last_session) {
   3554 		ti.tracknr = tracknr;
   3555 		error = udf_update_trackinfo(&ti);
   3556 		if (error) {
   3557 			warnx("error updating track information for track %d",
   3558 				tracknr);
   3559 			/* resume */
   3560 			tracknr++;
   3561 			continue;
   3562 		}
   3563 
   3564 		if (ti.flags & MMC_TRACKINFO_DAMAGED) {
   3565 			/*
   3566 			 * Need to repair last track before anything can be done.
   3567 			 * this is an optional command, so ignore its error but report
   3568 			 * warning.
   3569 			 */
   3570 			memset(&op, 0, sizeof(op));
   3571 			op.operation   = MMC_OP_REPAIRTRACK;
   3572 			op.mmc_profile = mmc_discinfo.mmc_profile;
   3573 			op.tracknr     = ti.tracknr;
   3574 			error = ioctl(dev_fd, MMCOP, &op);
   3575 
   3576 			if (error)
   3577 				warnx("drive notifies it can't explicitly repair "
   3578 					"damaged track, but it might autorepair\n");
   3579 		}
   3580 		tracknr++;
   3581 	}
   3582 	/* tracks (if any) might not be damaged now, operations are ok now */
   3583 #endif
   3584 }
   3585 
   3586 
   3587 int
   3588 udf_prepare_disc(void)
   3589 {
   3590 #if !HAVE_NBTOOL_CONFIG_H
   3591 	int error;
   3592 
   3593 	/* setup write parameters from discinfo */
   3594 	error = udf_setup_writeparams();
   3595 	if (error)
   3596 		return error;
   3597 
   3598 	udf_repair_tracks();
   3599 
   3600 	/* open new session if needed */
   3601 	return udf_open_new_session();
   3602 #endif
   3603 	return 0;
   3604 }
   3605 
   3606 
   3607 /* --------------------------------------------------------------------- */
   3608 
   3609 /*
   3610  * write queue implementation
   3611  */
   3612 
   3613 void
   3614 udf_suspend_writing(void)
   3615 {
   3616 	write_queue_suspend = 1;
   3617 }
   3618 
   3619 
   3620 void
   3621 udf_allow_writing(void)
   3622 {
   3623 	write_queue_suspend = 0;
   3624 }
   3625 
   3626 
   3627 static void
   3628 udf_init_writequeue(int write_strategy)
   3629 {
   3630 	context.write_strategy = write_strategy;
   3631 	write_queue_suspend = 0;
   3632 
   3633 	/* setup sector writeout queue's */
   3634 	TAILQ_INIT(&write_queue);
   3635 	write_queuelen = 0;
   3636 }
   3637 
   3638 
   3639 int
   3640 udf_write_sector(void *sector, uint64_t location)
   3641 {
   3642 	struct wrpacket *packet, *found_packet;
   3643 	uint64_t rel_loc;
   3644 	uint64_t blockingnr = layout.blockingnr;
   3645 	int error;
   3646 
   3647 	assert(!dev_fd_rdonly);
   3648 	assert(blockingnr >= 1);
   3649 	assert(blockingnr <= 64);
   3650 
   3651 	/*
   3652 	 * We have a write strategy but in practice packet writing is
   3653 	 * preferable for all media types.
   3654 	 */
   3655 
   3656 again:
   3657 	/* search location */
   3658 	found_packet = NULL;
   3659 	TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
   3660 		if (packet->start_sectornr <= location) {
   3661 			found_packet = packet;
   3662 			break;
   3663 		}
   3664 	}
   3665 
   3666 	/* are we in a current packet? */
   3667 	if (found_packet) {
   3668 		uint64_t base = found_packet->start_sectornr;
   3669 		if ((location >= base) && (location -base < blockingnr)) {
   3670 			/* fill in existing packet */
   3671 			rel_loc = location - base;
   3672 			memcpy(found_packet->packet_data +
   3673 				rel_loc * context.sector_size,
   3674 				sector, context.sector_size);
   3675 			found_packet->present |= ((uint64_t) 1 << rel_loc);
   3676 			return 0;
   3677 		}
   3678 	}
   3679 
   3680 	if ((write_queuelen > UDF_MAX_QUEUELEN) && !write_queue_suspend) {
   3681 		/* we purge the queue and reset found_packet! */
   3682 		error = udf_writeout_writequeue(false);
   3683 		if (error)
   3684 			return error;
   3685 		goto again;
   3686 	}
   3687 
   3688 	/* create new packet */
   3689 	packet = calloc(1, sizeof(struct wrpacket));
   3690 	if (packet == NULL)
   3691 		return errno;
   3692 	packet->packet_data = calloc(1, context.sector_size * blockingnr);
   3693 	if (packet->packet_data == NULL) {
   3694 		free(packet);
   3695 		return errno;
   3696 	}
   3697 	packet->start_sectornr =
   3698 		UDF_ROUNDDOWN(location, blockingnr) + wrtrack_skew;
   3699 	rel_loc = location - packet->start_sectornr;
   3700 
   3701 	memcpy(packet->packet_data +
   3702 		rel_loc * context.sector_size,
   3703 		sector, context.sector_size);
   3704 	packet->present = ((uint64_t) 1 << rel_loc);
   3705 
   3706 	if (found_packet) {
   3707 		TAILQ_INSERT_AFTER(&write_queue, found_packet, packet, next);
   3708 	} else {
   3709 		TAILQ_INSERT_HEAD(&write_queue, packet, next);
   3710 	}
   3711 	write_queuelen++;
   3712 
   3713 	return 0;
   3714 }
   3715 
   3716 
   3717 int
   3718 udf_read_sector(void *sector, uint64_t location)
   3719 {
   3720 	struct wrpacket *packet, *found_packet;
   3721 	ssize_t ret;
   3722 	uint64_t rpos, rel_loc;
   3723 	uint64_t blockingnr = layout.blockingnr;
   3724 
   3725 	rpos = (uint64_t) location * context.sector_size;
   3726 
   3727 	/* search location */
   3728 	found_packet = NULL;
   3729 	TAILQ_FOREACH_REVERSE(packet, &write_queue, wrpacket_list, next) {
   3730 		if (packet->start_sectornr <= location) {
   3731 			found_packet = packet;
   3732 			break;
   3733 		}
   3734 	}
   3735 
   3736 	/* are we in a current packet? */
   3737 	if (found_packet) {
   3738 		uint64_t base = found_packet->start_sectornr;
   3739 		if ((location >= base) && (location -base < blockingnr)) {
   3740 			/* fill in existing packet */
   3741 			rel_loc = location - base;
   3742 			if (found_packet->present & ((uint64_t) 1 << rel_loc)) {
   3743 				memcpy(sector, found_packet->packet_data +
   3744 					rel_loc * context.sector_size,
   3745 					context.sector_size);
   3746 			} else {
   3747 				ret = pread(dev_fd, sector, context.sector_size, rpos);
   3748 				if (ret == -1)
   3749 					return errno;
   3750 				if (ret < (int) context.sector_size)
   3751 					return EIO;
   3752 				memcpy(found_packet->packet_data +
   3753 					rel_loc * context.sector_size,
   3754 					sector, context.sector_size);
   3755 				found_packet->present |= ((uint64_t) 1 << rel_loc);
   3756 				return 0;
   3757 			}
   3758 		}
   3759 	}
   3760 	/* don't create a packet just for we read something */
   3761 	ret = pread(dev_fd, sector, context.sector_size, rpos);
   3762 	if (ret == -1)
   3763 		return errno;
   3764 	if (ret < (int) context.sector_size)
   3765 		return EIO;
   3766 	return 0;
   3767 }
   3768 
   3769 
   3770 /*
   3771  * Now all write requests are queued in the TAILQ, write them out to the
   3772  * disc/file image. Special care needs to be taken for devices that are only
   3773  * strict overwritable i.e. only in packet size chunks
   3774  *
   3775  * XXX support for growing vnd?
   3776  */
   3777 
   3778 static int
   3779 udf_writeout_writequeue(bool complete)
   3780 {
   3781 	struct wrpacket *packet, *next_packet;
   3782 	int		 blockingnr = layout.blockingnr;
   3783 	int		 linesize, offset, ret;
   3784 	uint8_t		*linebuf;
   3785 	uint64_t	 present, all_present = -1;
   3786 	uint64_t	 rpos, wpos;
   3787 	static int	 t = 0;
   3788 
   3789 	if (write_queuelen == 0)
   3790 		return 0;
   3791 
   3792 	if (blockingnr < 64)
   3793 		all_present = ((uint64_t) 1 << blockingnr) -1;
   3794 	linesize = blockingnr * context.sector_size;
   3795 	linebuf = calloc(1, linesize);
   3796 	assert(linebuf);
   3797 
   3798 	/* fill in blanks if needed */
   3799 	if (complete && (context.write_strategy != UDF_WRITE_SEQUENTIAL)) {
   3800 		TAILQ_FOREACH(packet, &write_queue, next) {
   3801 			present = packet->present;
   3802 			if (present != all_present) {
   3803 				printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
   3804 //printf("%16lu : readin %08lx\n", packet->start_sectornr, packet->present ^ all_present);
   3805 				rpos = (uint64_t)  packet->start_sectornr * context.sector_size;
   3806 				ret = pread(dev_fd, linebuf, linesize, rpos);
   3807 				if (ret == -1) {
   3808 					printf("\b");
   3809 					warn("error reading in blanks, "
   3810 						"could indicate bad disc");
   3811 					printf(" ");
   3812 				}
   3813 				for (int i = 0; i < blockingnr; i++) {
   3814 //printf("present %08lx, testing bit %08lx, value %08lx\n", present, ((uint64_t) 1 << i), (present & ((uint64_t) 1 << i)));
   3815 					if ((present & ((uint64_t) 1 << i)) > 0)
   3816 						continue;
   3817 //printf("NOT PRESENT\n");
   3818 					offset = i * context.sector_size;
   3819 					memcpy(packet->packet_data + offset,
   3820 						linebuf + offset,
   3821 						context.sector_size);
   3822 					packet->present |= ((uint64_t) 1<<i);
   3823 				}
   3824 				printf("\b");
   3825 			}
   3826 			assert(packet->present == all_present);
   3827 		}
   3828 	}
   3829 
   3830 	/* writeout */
   3831 	TAILQ_FOREACH(packet, &write_queue, next) {
   3832 		if (complete || (packet->present == all_present)) {
   3833 			printf("%c", "\\|/-"[t++ % 4]); fflush(stdout);fflush(stderr);
   3834 //printf("write %lu + %d\n", packet->start_sectornr, linesize / context.sector_size);
   3835 			wpos = (uint64_t) packet->start_sectornr * context.sector_size;
   3836 			ret = pwrite(dev_fd, packet->packet_data, linesize, wpos);
   3837 			printf("\b");
   3838 			if (ret == -1)
   3839 				warn("error writing packet, "
   3840 					"could indicate bad disc");
   3841 		}
   3842 	}
   3843 
   3844 	/* removing completed packets */
   3845 	TAILQ_FOREACH_SAFE(packet, &write_queue, next, next_packet) {
   3846 		if (complete || (packet->present == all_present)) {
   3847 			TAILQ_REMOVE(&write_queue, packet, next);
   3848 			free(packet->packet_data);
   3849 			free(packet);
   3850 			write_queuelen--;
   3851 		}
   3852 	}
   3853 	if (complete) {
   3854 		assert(TAILQ_EMPTY(&write_queue));
   3855 		write_queuelen = 0;
   3856 	}
   3857 
   3858 	free(linebuf);
   3859 	return 0;
   3860 }
   3861 
   3862 
   3863 /* --------------------------------------------------------------------- */
   3864 
   3865 /* simplified version of kernel routine */
   3866 int
   3867 udf_translate_vtop(uint32_t lb_num, uint16_t vpart,
   3868 		   uint32_t *lb_numres, uint32_t *extres)
   3869 {
   3870 	struct part_desc       *pdesc;
   3871 	struct spare_map_entry *sme;
   3872 	struct short_ad        *short_ad;
   3873 	struct extfile_entry   *efe;
   3874 	uint32_t ext, len, lb_rel, lb_packet, vat_off;
   3875 	uint32_t start_lb, lb_offset, end_lb_offset;
   3876 	uint32_t udf_rw32_lbmap;
   3877 	uint32_t flags;
   3878 	uint8_t *vat_pos, *data_pos;
   3879 	int dscr_size, l_ea, l_ad, icbflags, addr_type;
   3880 	int rel, part;
   3881 
   3882 	if (vpart > UDF_VTOP_RAWPART)
   3883 		return EINVAL;
   3884 
   3885 	ext = INT_MAX;
   3886 translate_again:
   3887 	part = context.vtop[vpart];
   3888 	pdesc = context.partitions[part];
   3889 
   3890 	switch (context.vtop_tp[vpart]) {
   3891 	case UDF_VTOP_TYPE_RAW :
   3892 		/* 1:1 to the end of the device */
   3893 		*lb_numres = lb_num;
   3894 		*extres = MIN(ext, INT_MAX);
   3895 		return 0;
   3896 	case UDF_VTOP_TYPE_PHYS :
   3897 		/* transform into its disc logical block */
   3898 		if (lb_num > udf_rw32(pdesc->part_len))
   3899 			return EINVAL;
   3900 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3901 
   3902 		/* extent from here to the end of the partition */
   3903 		*extres = MIN(ext, udf_rw32(pdesc->part_len) - lb_num);
   3904 		if (*extres == 0)
   3905 			return EINVAL;
   3906 		return 0;
   3907 	case UDF_VTOP_TYPE_VIRT :
   3908 		/* only maps one logical block, lookup in VAT */
   3909 		if (lb_num * 4 >= context.vat_size)
   3910 			return EINVAL;
   3911 		vat_off = context.vat_start + lb_num * 4;
   3912 		vat_pos = context.vat_contents + vat_off;
   3913 		udf_rw32_lbmap = *((uint32_t *) vat_pos);
   3914 
   3915 		if (vat_off >= context.vat_size)		/* XXX > or >= ? */
   3916 			return EINVAL;
   3917 		lb_num = udf_rw32(udf_rw32_lbmap);
   3918 
   3919 		/* transform into its disc logical block */
   3920 		if (lb_num > udf_rw32(pdesc->part_len))
   3921 			return EINVAL;
   3922 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3923 
   3924 		/* just one logical block */
   3925 		*extres = 1;
   3926 		return 0;
   3927 	case UDF_VTOP_TYPE_SPAREABLE :
   3928 		/* check if the packet containing the lb_num is remapped */
   3929 		lb_packet = lb_num / layout.spareable_blockingnr;
   3930 		lb_rel    = lb_num % layout.spareable_blockingnr;
   3931 
   3932 		for (rel = 0; rel < udf_rw16(context.sparing_table->rt_l); rel++) {
   3933 			sme = &context.sparing_table->entries[rel];
   3934 			if (lb_packet == udf_rw32(sme->org)) {
   3935 				/* NOTE maps to absolute disc logical block! */
   3936 				*lb_numres = udf_rw32(sme->map) + lb_rel;
   3937 				*extres    = layout.spareable_blockingnr - lb_rel;
   3938 				return 0;
   3939 			}
   3940 		}
   3941 
   3942 		/* transform into its disc logical block */
   3943 		if (lb_num > udf_rw32(pdesc->part_len))
   3944 			return EINVAL;
   3945 		*lb_numres = lb_num + udf_rw32(pdesc->start_loc);
   3946 
   3947 		/* rest of block */
   3948 		*extres = MIN(ext, layout.spareable_blockingnr - lb_rel);
   3949 		return 0;
   3950 	case UDF_VTOP_TYPE_META :
   3951 		/* we have to look into the file's allocation descriptors */
   3952 
   3953 		/* get first overlapping extent */
   3954 		efe = context.meta_file;
   3955 		dscr_size = sizeof(struct extfile_entry) - 1;
   3956 		l_ea = udf_rw32(efe->l_ea);
   3957 		l_ad = udf_rw32(efe->l_ad);
   3958 
   3959 		icbflags = udf_rw16(efe->icbtag.flags);
   3960 		addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
   3961 		if (addr_type != UDF_ICB_SHORT_ALLOC) {
   3962 			warnx("specification violation: metafile not using"
   3963 				"short allocs");
   3964 			return EINVAL;
   3965 		}
   3966 
   3967 		data_pos = (uint8_t *) context.meta_file + dscr_size + l_ea;
   3968 		short_ad = (struct short_ad *) data_pos;
   3969 		lb_offset = 0;
   3970 		while (l_ad > 0) {
   3971 			len      = udf_rw32(short_ad->len);
   3972 			start_lb = udf_rw32(short_ad->lb_num);
   3973 			flags    = UDF_EXT_FLAGS(len);
   3974 			len      = UDF_EXT_LEN(len);
   3975 			if (flags == UDF_EXT_REDIRECT) {
   3976 				warnx("implementation limit: no support for "
   3977 				      "extent redirection in metadata file");
   3978 				return EINVAL;
   3979 			}
   3980 			end_lb_offset = lb_offset + len / context.sector_size;
   3981 			/* overlap? */
   3982 			if (end_lb_offset > lb_num)
   3983 				break;
   3984 			short_ad++;
   3985 			lb_offset = end_lb_offset;
   3986 			l_ad -= sizeof(struct short_ad);
   3987 		}
   3988 		if (l_ad <= 0) {
   3989 			warnx("looking up outside metadata partition!");
   3990 			return EINVAL;
   3991 		}
   3992 		lb_num = start_lb + (lb_num - lb_offset);
   3993 		vpart  = part;
   3994 		ext = end_lb_offset - lb_num;
   3995 		/*
   3996 		 * vpart and lb_num are updated, translate again since we
   3997 		 * might be mapped on spareable media
   3998 		 */
   3999 		goto translate_again;
   4000 	default:
   4001 		printf("UDF vtop translation scheme %d unimplemented yet\n",
   4002 			context.vtop_tp[vpart]);
   4003 	}
   4004 
   4005 	return EINVAL;
   4006 }
   4007 
   4008 /* --------------------------------------------------------------------- */
   4009 
   4010 int
   4011 udf_read_phys(void *blob, uint32_t location, uint32_t sects)
   4012 {
   4013 	uint32_t phys, cnt;
   4014 	uint8_t *bpos;
   4015 	int error;
   4016 
   4017 	for (cnt = 0; cnt < sects; cnt++) {
   4018 		bpos  = (uint8_t *) blob;
   4019 		bpos += context.sector_size * cnt;
   4020 
   4021 		phys = location + cnt;
   4022 		error = udf_read_sector(bpos, phys);
   4023 		if (error)
   4024 			return error;
   4025 	}
   4026 	return 0;
   4027 }
   4028 
   4029 
   4030 int
   4031 udf_write_phys(void *blob, uint32_t location, uint32_t sects)
   4032 {
   4033 	uint32_t phys, cnt;
   4034 	uint8_t *bpos;
   4035 	int error;
   4036 
   4037 	for (cnt = 0; cnt < sects; cnt++) {
   4038 		bpos  = (uint8_t *) blob;
   4039 		bpos += context.sector_size * cnt;
   4040 
   4041 		phys = location + cnt;
   4042 		error = udf_write_sector(bpos, phys);
   4043 		if (error)
   4044 			return error;
   4045 	}
   4046 	return 0;
   4047 }
   4048 
   4049 
   4050 int
   4051 udf_read_virt(void *blob, uint32_t location, uint16_t vpart,
   4052 	uint32_t sectors)
   4053 {
   4054 	uint32_t phys, ext;
   4055 	uint8_t *data;
   4056 	int error;
   4057 
   4058 	/* determine physical location */
   4059 	data = (uint8_t *) blob;
   4060 	while (sectors) {
   4061 		if (udf_translate_vtop(location, vpart, &phys, &ext)) {
   4062 			// warnx("internal error: bad translation");
   4063 			return EINVAL;
   4064 		}
   4065 		ext = MIN(sectors, ext);
   4066 		error = udf_read_phys(data, phys, ext);
   4067 		if (error)
   4068 			return error;
   4069 		location += ext;
   4070 		data     += ext * context.sector_size;
   4071 		sectors  -= ext;
   4072 	}
   4073 	return 0;
   4074 }
   4075 
   4076 
   4077 int
   4078 udf_write_virt(void *blob, uint32_t location, uint16_t vpart,
   4079 	uint32_t sectors)
   4080 {
   4081 	uint32_t phys, ext, alloc_pos;
   4082 	uint8_t *data;
   4083 	int error;
   4084 
   4085 	/* determine physical location */
   4086 	if (context.vtop_tp[vpart] == UDF_VTOP_TYPE_VIRT) {
   4087 		assert(sectors == 1);
   4088 		alloc_pos = context.alloc_pos[context.data_part];
   4089 		udf_vat_update(location, alloc_pos);
   4090 		udf_translate_vtop(alloc_pos, context.vtop[vpart], &phys, &ext);
   4091 		context.alloc_pos[context.data_part]++;
   4092 		return udf_write_phys(blob, phys, sectors);
   4093 	}
   4094 
   4095 	data = (uint8_t *) blob;
   4096 	while (sectors) {
   4097 		if (udf_translate_vtop(location, vpart, &phys, &ext)) {
   4098 			warnx("internal error: bad translation");
   4099 			return EINVAL;
   4100 		}
   4101 		ext = MIN(sectors, ext);
   4102 		error = udf_write_phys(data, phys, ext);
   4103 		if (error)
   4104 			return error;
   4105 		location += ext;
   4106 		data     += ext * context.sector_size;
   4107 		sectors  -= ext;
   4108 	}
   4109 	return 0;
   4110 }
   4111 
   4112 
   4113 int
   4114 udf_read_dscr_phys(uint32_t sector, union dscrptr **dstp)
   4115 {
   4116 	union dscrptr *dst, *new_dst;
   4117 	uint8_t *pos;
   4118 	uint32_t sectors, dscrlen, sector_size;
   4119 	int error;
   4120 
   4121 	sector_size = context.sector_size;
   4122 
   4123 	*dstp = dst = NULL;
   4124 	dscrlen = sector_size;
   4125 
   4126 	/* read initial piece */
   4127 	dst = malloc(sector_size);
   4128 	assert(dst);
   4129 	error = udf_read_sector(dst, sector);
   4130 //	if (error)
   4131 //		warn("read error");
   4132 
   4133 	if (!error) {
   4134 		/* check if its an empty block */
   4135 		if (is_zero(dst, sector_size)) {
   4136 			/* return no error but with no dscrptr */
   4137 			/* dispose first block */
   4138 			free(dst);
   4139 			return 0;
   4140 		}
   4141 		/* check if its a valid tag */
   4142 		error = udf_check_tag(dst);
   4143 		if (error) {
   4144 			free(dst);
   4145 			return 0;
   4146 		}
   4147 		/* calculate descriptor size */
   4148 		dscrlen = udf_tagsize(dst, sector_size);
   4149 	}
   4150 
   4151 	if (!error && (dscrlen > sector_size)) {
   4152 		/* read the rest of descriptor */
   4153 
   4154 		new_dst = realloc(dst, dscrlen);
   4155 		if (new_dst == NULL) {
   4156 			free(dst);
   4157 			return ENOMEM;
   4158 		}
   4159 		dst = new_dst;
   4160 
   4161 		sectors = dscrlen / sector_size;
   4162 		pos = (uint8_t *) dst + sector_size;
   4163 		error = udf_read_phys(pos, sector + 1, sectors-1);
   4164 		if (error)
   4165 			warnx("read error");
   4166 	}
   4167 	if (!error)
   4168 		error = udf_check_tag_payload(dst, dscrlen);
   4169 	if (error && dst) {
   4170 		free(dst);
   4171 		dst = NULL;
   4172 	}
   4173 	*dstp = dst;
   4174 
   4175 	return error;
   4176 }
   4177 
   4178 
   4179 int
   4180 udf_write_dscr_phys(union dscrptr *dscr, uint32_t location,
   4181 	uint32_t sectors)
   4182 {
   4183 	dscr->tag.tag_loc = udf_rw32(location);
   4184 	(void) udf_validate_tag_and_crc_sums(dscr);
   4185 
   4186 	assert(sectors == udf_tagsize(dscr, context.sector_size) / context.sector_size);
   4187 	return udf_write_phys(dscr, location, sectors);
   4188 }
   4189 
   4190 
   4191 int
   4192 udf_read_dscr_virt(uint32_t sector, uint16_t vpart, union dscrptr **dstp)
   4193 {
   4194 	union dscrptr *dst, *new_dst;
   4195 	uint8_t *pos;
   4196 	uint32_t sectors, dscrlen, sector_size;
   4197 	int error;
   4198 
   4199 	sector_size = context.sector_size;
   4200 
   4201 	*dstp = dst = NULL;
   4202 	dscrlen = sector_size;
   4203 
   4204 	/* read initial piece */
   4205 	dst = calloc(1, sector_size);
   4206 	assert(dst);
   4207 	error = udf_read_virt(dst, sector, vpart, 1);
   4208 	if (error)
   4209 		return error;
   4210 
   4211 	if (!error) {
   4212 		/* check if its a valid tag */
   4213 		error = udf_check_tag(dst);
   4214 		if (error) {
   4215 			/* check if its an empty block */
   4216 			if (is_zero(dst, sector_size)) {
   4217 				/* return no error but with no dscrptr */
   4218 				/* dispose first block */
   4219 				free(dst);
   4220 				return 0;
   4221 			}
   4222 		}
   4223 		/* calculate descriptor size */
   4224 		dscrlen = udf_tagsize(dst, sector_size);
   4225 	}
   4226 
   4227 	if (!error && (dscrlen > sector_size)) {
   4228 		/* read the rest of descriptor */
   4229 
   4230 		new_dst = realloc(dst, dscrlen);
   4231 		if (new_dst == NULL) {
   4232 			free(dst);
   4233 			return ENOMEM;
   4234 		}
   4235 		dst = new_dst;
   4236 
   4237 		sectors = dscrlen / sector_size;
   4238 		pos = (uint8_t *) dst + sector_size;
   4239 		error = udf_read_virt(pos, sector + 1, vpart, sectors-1);
   4240 		if (error)
   4241 			warn("read error");
   4242 	}
   4243 	if (!error)
   4244 		error = udf_check_tag_payload(dst, dscrlen);
   4245 	if (error && dst) {
   4246 		free(dst);
   4247 		dst = NULL;
   4248 	}
   4249 	*dstp = dst;
   4250 
   4251 	return error;
   4252 }
   4253 
   4254 
   4255 int
   4256 udf_write_dscr_virt(union dscrptr *dscr, uint32_t location, uint16_t vpart,
   4257 	uint32_t sectors)
   4258 {
   4259 	struct file_entry *fe;
   4260 	struct extfile_entry *efe;
   4261 	struct extattrhdr_desc *extattrhdr;
   4262 
   4263 	extattrhdr = NULL;
   4264 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
   4265 		fe = (struct file_entry *) dscr;
   4266 		if (udf_rw32(fe->l_ea) > 0)
   4267 			extattrhdr = (struct extattrhdr_desc *) fe->data;
   4268 	}
   4269 	if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
   4270 		efe = (struct extfile_entry *) dscr;
   4271 		if (udf_rw32(efe->l_ea) > 0)
   4272 			extattrhdr = (struct extattrhdr_desc *) efe->data;
   4273 	}
   4274 	if (extattrhdr) {
   4275 		extattrhdr->tag.tag_loc = udf_rw32(location);
   4276 		udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
   4277 	}
   4278 
   4279 	dscr->tag.tag_loc = udf_rw32(location);
   4280 	udf_validate_tag_and_crc_sums(dscr);
   4281 
   4282 	assert(sectors >= (udf_tagsize(dscr, context.sector_size) / context.sector_size));
   4283 	return udf_write_virt(dscr, location, vpart, sectors);
   4284 }
   4285 
   4286 
   4287 int
   4288 is_zero(void *blob, int size) {
   4289 	uint8_t *p = blob;
   4290 	for (int i = 0; i < size; i++, p++)
   4291 		if (*p)
   4292 			return 0;
   4293 	return 1;
   4294 }
   4295 
   4296 /* --------------------------------------------------------------------- */
   4297 
   4298 static void
   4299 udf_partition_alloc(int nblk, int vpart, struct long_ad *pos)
   4300 {
   4301 	memset(pos, 0, sizeof(*pos));
   4302 	pos->len	  = udf_rw32(nblk * context.sector_size);
   4303 	pos->loc.lb_num   = udf_rw32(context.alloc_pos[vpart]);
   4304 	pos->loc.part_num = udf_rw16(vpart);
   4305 
   4306 	udf_mark_allocated(context.alloc_pos[vpart], vpart, nblk);
   4307 	context.alloc_pos[vpart] += nblk;
   4308 }
   4309 
   4310 
   4311 void
   4312 udf_metadata_alloc(int nblk, struct long_ad *pos)
   4313 {
   4314 	udf_partition_alloc(nblk, context.metadata_part, pos);
   4315 }
   4316 
   4317 
   4318 void
   4319 udf_data_alloc(int nblk, struct long_ad *pos)
   4320 {
   4321 	udf_partition_alloc(nblk, context.data_part, pos);
   4322 }
   4323 
   4324 
   4325 void
   4326 udf_fids_alloc(int nblk, struct long_ad *pos)
   4327 {
   4328 	udf_partition_alloc(nblk, context.fids_part, pos);
   4329 }
   4330 
   4331 
   4332 /* --------------------------------------------------------------------- */
   4333 
   4334 /*
   4335  * udf_derive_format derives the format_flags from the disc's mmc_discinfo.
   4336  * The resulting flags uniquely define a disc format. Note there are at least
   4337  * 7 distinct format types defined in UDF.
   4338  */
   4339 
   4340 #define UDF_VERSION(a) \
   4341 	(((a) == 0x102) || ((a) == 0x150) || ((a) == 0x200) || \
   4342 	 ((a) == 0x201) || ((a) == 0x250) || ((a) == 0x260))
   4343 
   4344 int
   4345 udf_derive_format(int req_enable, int req_disable)
   4346 {
   4347 	int format_flags;
   4348 	int media_accesstype;
   4349 
   4350 	/* disc writability, formatted, appendable */
   4351 	if ((mmc_discinfo.mmc_cur & MMC_CAP_RECORDABLE) == 0) {
   4352 		warnx("can't newfs readonly device");
   4353 		return EROFS;
   4354 	}
   4355 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
   4356 		/* sequentials need sessions appended */
   4357 		if (mmc_discinfo.disc_state == MMC_STATE_CLOSED) {
   4358 			warnx("can't append session to a closed disc");
   4359 			return EROFS;
   4360 		}
   4361 		if ((mmc_discinfo.disc_state != MMC_STATE_EMPTY) &&
   4362 				!context.create_new_session) {
   4363 			warnx("disc not empty! Use -F to force "
   4364 			    "initialisation");
   4365 			return EROFS;
   4366 		}
   4367 	} else {
   4368 		/* check if disc (being) formatted or has been started on */
   4369 		if (mmc_discinfo.disc_state == MMC_STATE_EMPTY) {
   4370 			warnx("disc is not formatted");
   4371 			return EROFS;
   4372 		}
   4373 	}
   4374 
   4375 	/* determine UDF format */
   4376 	format_flags = 0;
   4377 	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
   4378 		/* all rewritable media */
   4379 		format_flags |= FORMAT_REWRITABLE;
   4380 		if (context.min_udf >= 0x0250) {
   4381 			/* standard dictates meta as default */
   4382 			format_flags |= FORMAT_META;
   4383 		}
   4384 
   4385 		if ((mmc_discinfo.mmc_cur & MMC_CAP_HW_DEFECTFREE) == 0) {
   4386 			/* spareables for defect management */
   4387 			if (context.min_udf >= 0x150)
   4388 				format_flags |= FORMAT_SPAREABLE;
   4389 		}
   4390 	} else {
   4391 		/* all once recordable media */
   4392 		format_flags |= FORMAT_WRITEONCE;
   4393 		if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL) {
   4394 			format_flags |= FORMAT_SEQUENTIAL;
   4395 
   4396 			if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE) {
   4397 				/* logical overwritable */
   4398 				format_flags |= FORMAT_LOW;
   4399 			} else {
   4400 				/* have to use VAT for overwriting */
   4401 				format_flags |= FORMAT_VAT;
   4402 			}
   4403 		} else {
   4404 			/* rare WORM devices, but BluRay has one, strat4096 */
   4405 			format_flags |= FORMAT_WORM;
   4406 		}
   4407 	}
   4408 
   4409 	/* enable/disable requests */
   4410 	if (req_disable & FORMAT_META) {
   4411 		format_flags &= ~(FORMAT_META | FORMAT_LOW);
   4412 		req_disable  &= ~FORMAT_META;
   4413 	}
   4414 	if ((format_flags & FORMAT_VAT) & UDF_512_TRACK)
   4415 		format_flags |= FORMAT_TRACK512;
   4416 
   4417 	if (req_enable & FORMAT_READONLY) {
   4418 		format_flags |= FORMAT_READONLY;
   4419 	}
   4420 
   4421 	/* determine partition/media access type */
   4422 	media_accesstype = UDF_ACCESSTYPE_NOT_SPECIFIED;
   4423 	if (mmc_discinfo.mmc_cur & MMC_CAP_REWRITABLE) {
   4424 		media_accesstype = UDF_ACCESSTYPE_OVERWRITABLE;
   4425 		if (mmc_discinfo.mmc_cur & MMC_CAP_ERASABLE)
   4426 			media_accesstype = UDF_ACCESSTYPE_REWRITEABLE;
   4427 	} else {
   4428 		/* all once recordable media */
   4429 		media_accesstype = UDF_ACCESSTYPE_WRITE_ONCE;
   4430 	}
   4431 	if (mmc_discinfo.mmc_cur & MMC_CAP_PSEUDOOVERWRITE)
   4432 		media_accesstype = UDF_ACCESSTYPE_PSEUDO_OVERWITE;
   4433 
   4434 	/* patch up media accesstype */
   4435 	if (req_enable & FORMAT_READONLY) {
   4436 		/* better now */
   4437 		media_accesstype = UDF_ACCESSTYPE_READ_ONLY;
   4438 	}
   4439 
   4440 	/* adjust minimum version limits */
   4441 	if (format_flags & FORMAT_VAT)
   4442 		context.min_udf = MAX(context.min_udf, 0x0150);
   4443 	if (format_flags & FORMAT_SPAREABLE)
   4444 		context.min_udf = MAX(context.min_udf, 0x0150);
   4445 	if (format_flags & FORMAT_META)
   4446 		context.min_udf = MAX(context.min_udf, 0x0250);
   4447 	if (format_flags & FORMAT_LOW)
   4448 		context.min_udf = MAX(context.min_udf, 0x0260);
   4449 
   4450 	/* adjust maximum version limits not to tease or break things */
   4451 	if (!(format_flags & (FORMAT_META | FORMAT_LOW | FORMAT_VAT)) &&
   4452 	    (context.max_udf > 0x200))
   4453 		context.max_udf = 0x201;
   4454 
   4455 	if ((format_flags & (FORMAT_VAT | FORMAT_SPAREABLE)) == 0)
   4456 		if (context.max_udf <= 0x150)
   4457 			context.min_udf = 0x102;
   4458 
   4459 	/* limit Ecma 167 descriptor if possible/needed */
   4460 	context.dscrver = 3;
   4461 	if ((context.min_udf < 0x200) || (context.max_udf < 0x200)) {
   4462 		context.dscrver = 2;
   4463 		context.max_udf = 0x150;	/* last version < 0x200 */
   4464 	}
   4465 
   4466 	/* is it possible ? */
   4467 	if (context.min_udf > context.max_udf) {
   4468 		warnx("initialisation prohibited by specified maximum "
   4469 		    "UDF version 0x%04x. Minimum version required 0x%04x",
   4470 		    context.max_udf, context.min_udf);
   4471 		return EPERM;
   4472 	}
   4473 
   4474 	if (!UDF_VERSION(context.min_udf) || !UDF_VERSION(context.max_udf)) {
   4475 		warnx("internal error, invalid min/max udf versionsi in %s",
   4476 			__func__);
   4477 		return EPERM;
   4478 	}
   4479 	context.format_flags = format_flags;
   4480 	context.media_accesstype = media_accesstype;
   4481 
   4482 	return 0;
   4483 }
   4484 
   4485 #undef UDF_VERSION
   4486 
   4487 
   4488 /* --------------------------------------------------------------------- */
   4489 
   4490 int
   4491 udf_proces_names(void)
   4492 {
   4493 	struct timeval time_of_day;
   4494 	uint32_t primary_nr;
   4495 	uint64_t volset_nr;
   4496 
   4497 	if (context.logvol_name == NULL)
   4498 		context.logvol_name = strdup("anonymous");
   4499 	if (context.primary_name == NULL) {
   4500 		if (mmc_discinfo.disc_flags & MMC_DFLAGS_DISCIDVALID) {
   4501 			primary_nr = mmc_discinfo.disc_id;
   4502 		} else {
   4503 			primary_nr = (uint32_t) random();
   4504 		}
   4505 		context.primary_name = calloc(32, 1);
   4506 		sprintf(context.primary_name, "%08"PRIx32, primary_nr);
   4507 	}
   4508 	if (context.volset_name == NULL) {
   4509 		if (mmc_discinfo.disc_flags & MMC_DFLAGS_BARCODEVALID) {
   4510 			volset_nr = mmc_discinfo.disc_barcode;
   4511 		} else {
   4512 			(void)gettimeofday(&time_of_day, NULL);
   4513 			volset_nr  =  (uint64_t) random();
   4514 			volset_nr |= ((uint64_t) time_of_day.tv_sec) << 32;
   4515 		}
   4516 		context.volset_name = calloc(128,1);
   4517 		sprintf(context.volset_name, "%016"PRIx64, volset_nr);
   4518 	}
   4519 	if (context.fileset_name == NULL)
   4520 		context.fileset_name = strdup("anonymous");
   4521 
   4522 	/* check passed/created identifiers */
   4523 	if (strlen(context.logvol_name)  > 128) {
   4524 		warnx("logical volume name too long");
   4525 		return EINVAL;
   4526 	}
   4527 	if (strlen(context.primary_name) >  32) {
   4528 		warnx("primary volume name too long");
   4529 		return EINVAL;
   4530 	}
   4531 	if (strlen(context.volset_name)  > 128) {
   4532 		warnx("volume set name too long");
   4533 		return EINVAL;
   4534 	}
   4535 	if (strlen(context.fileset_name) > 32) {
   4536 		warnx("fileset name too long");
   4537 		return EINVAL;
   4538 	}
   4539 
   4540 	/* signal all OK */
   4541 	return 0;
   4542 }
   4543 
   4544 /* --------------------------------------------------------------------- */
   4545 
   4546 int
   4547 udf_write_iso9660_vrs(void)
   4548 {
   4549 	struct vrs_desc *iso9660_vrs_desc;
   4550 	uint32_t pos;
   4551 	int error, cnt, dpos;
   4552 
   4553 	/* create ISO/Ecma-167 identification descriptors */
   4554 	if ((iso9660_vrs_desc = calloc(1, context.sector_size)) == NULL)
   4555 		return ENOMEM;
   4556 
   4557 	/*
   4558 	 * All UDF formats should have their ISO/Ecma-167 descriptors written
   4559 	 * except when not possible due to track reservation in the case of
   4560 	 * VAT
   4561 	 */
   4562 	if ((context.format_flags & FORMAT_TRACK512) == 0) {
   4563 		dpos = (2048 + context.sector_size - 1) / context.sector_size;
   4564 
   4565 		/* wipe at least 6 times 2048 byte `sectors' */
   4566 		for (cnt = 0; cnt < 6 *dpos; cnt++) {
   4567 			pos = layout.iso9660_vrs + cnt;
   4568 			if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4569 				free(iso9660_vrs_desc);
   4570 				return error;
   4571 			}
   4572 		}
   4573 
   4574 		/* common VRS fields in all written out ISO descriptors */
   4575 		iso9660_vrs_desc->struct_type = 0;
   4576 		iso9660_vrs_desc->version     = 1;
   4577 		pos = layout.iso9660_vrs;
   4578 
   4579 		/* BEA01, NSR[23], TEA01 */
   4580 		memcpy(iso9660_vrs_desc->identifier, "BEA01", 5);
   4581 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4582 			free(iso9660_vrs_desc);
   4583 			return error;
   4584 		}
   4585 		pos += dpos;
   4586 
   4587 		if (context.dscrver == 2)
   4588 			memcpy(iso9660_vrs_desc->identifier, "NSR02", 5);
   4589 		else
   4590 			memcpy(iso9660_vrs_desc->identifier, "NSR03", 5);
   4591 		;
   4592 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4593 			free(iso9660_vrs_desc);
   4594 			return error;
   4595 		}
   4596 		pos += dpos;
   4597 
   4598 		memcpy(iso9660_vrs_desc->identifier, "TEA01", 5);
   4599 		if ((error = udf_write_sector(iso9660_vrs_desc, pos))) {
   4600 			free(iso9660_vrs_desc);
   4601 			return error;
   4602 		}
   4603 	}
   4604 
   4605 	free(iso9660_vrs_desc);
   4606 	/* return success */
   4607 	return 0;
   4608 }
   4609 
   4610 
   4611 /* --------------------------------------------------------------------- */
   4612 
   4613 int
   4614 udf_get_blockingnr(struct mmc_trackinfo *ti)
   4615 {
   4616 	int blockingnr;
   4617 
   4618 	/* determine blockingnr */
   4619 	blockingnr = ti->packet_size;
   4620 	if (blockingnr <= 1) {
   4621 		/* paranoia on blockingnr */
   4622 		switch (mmc_discinfo.mmc_profile) {
   4623 		case 0x01 : /* DISC */
   4624 			blockingnr = 64;
   4625 			break;
   4626 		case 0x08 : /* CDROM */
   4627 		case 0x09 : /* CD-R    */
   4628 		case 0x0a : /* CD-RW   */
   4629 			blockingnr = 32;	/* UDF requirement */
   4630 			break;
   4631 		case 0x10 : /* DVDROM */
   4632 		case 0x11 : /* DVD-R (DL) */
   4633 		case 0x12 : /* DVD-RAM */
   4634 		case 0x1b : /* DVD+R      */
   4635 		case 0x2b : /* DVD+R Dual layer */
   4636 		case 0x13 : /* DVD-RW restricted overwrite */
   4637 		case 0x14 : /* DVD-RW sequential */
   4638 		case 0x1a : /* DVD+RW */
   4639 			blockingnr = 16;	/* SCSI definition */
   4640 			break;
   4641 		case 0x40 : /* BDROM */
   4642 		case 0x41 : /* BD-R Sequential recording (SRM) */
   4643 		case 0x42 : /* BD-R Random recording (RRM) */
   4644 		case 0x43 : /* BD-RE */
   4645 		case 0x51 : /* HD DVD-R   */
   4646 		case 0x52 : /* HD DVD-RW  */
   4647 			blockingnr = 32;	/* SCSI definition */
   4648 			break;
   4649 		default:
   4650 			break;
   4651 		}
   4652 	}
   4653 	return blockingnr;
   4654 }
   4655 
   4656 
   4657 int
   4658 udf_spareable_blocks(void)
   4659 {
   4660 	if (mmc_discinfo.mmc_class == MMC_CLASS_CD) {
   4661 		/* not too much for CD-RW, still 20MiB */
   4662 		return 32;
   4663 	} else {
   4664 		/* take a value for DVD*RW mainly, BD is `defect free' */
   4665 		return 512;
   4666 	}
   4667 }
   4668 
   4669 
   4670 int
   4671 udf_spareable_blockingnr(void)
   4672 {
   4673 	struct mmc_trackinfo ti;
   4674 	int spareable_blockingnr;
   4675 	int error;
   4676 
   4677 	/* determine span/size */
   4678 	ti.tracknr = mmc_discinfo.first_track_last_session;
   4679 	error = udf_update_trackinfo(&ti);
   4680 	spareable_blockingnr = udf_get_blockingnr(&ti);
   4681 	if (error)
   4682 		spareable_blockingnr = 32;
   4683 
   4684 	/*
   4685 	 * Note that for (bug) compatibility with version UDF 2.00
   4686 	 * (fixed in 2.01 and higher) the blocking size needs to be 32
   4687 	 * sectors otherwise the drive's blockingnr.
   4688 	 */
   4689 	if (context.min_udf <= 0x200)
   4690 		spareable_blockingnr = 32;
   4691 	return spareable_blockingnr;
   4692 }
   4693 
   4694 
   4695 /*
   4696  * Main function that creates and writes out disc contents based on the
   4697  * format_flags's that uniquely define the type of disc to create.
   4698  */
   4699 
   4700 int
   4701 udf_do_newfs_prefix(void)
   4702 {
   4703 	union dscrptr *zero_dscr;
   4704 	union dscrptr *dscr;
   4705 	struct mmc_trackinfo ti;
   4706 	uint32_t blockingnr;
   4707 	uint32_t cnt, loc, len;
   4708 	int sectcopy;
   4709 	int error, integrity_type;
   4710 	int data_part, metadata_part;
   4711 	int format_flags;
   4712 
   4713 	/* init */
   4714 	format_flags = context.format_flags;
   4715 
   4716 	/* determine span/size */
   4717 	ti.tracknr = mmc_discinfo.first_track_last_session;
   4718 	error = udf_update_trackinfo(&ti);
   4719 	if (error)
   4720 		return error;
   4721 
   4722 	if (mmc_discinfo.sector_size > context.sector_size) {
   4723 		warnx("impossible to format: "
   4724 			"sector size %d too small for media sector size %d",
   4725 			context.sector_size, mmc_discinfo.sector_size);
   4726 		return EIO;
   4727 	}
   4728 
   4729 	/* determine blockingnr */
   4730 	blockingnr = udf_get_blockingnr(&ti);
   4731 	if (blockingnr <= 0) {
   4732 		warnx("can't fixup blockingnumber for device "
   4733 			"type %d", mmc_discinfo.mmc_profile);
   4734 		warnx("device is not returning valid blocking"
   4735 			" number and media type is unknown");
   4736 		return EINVAL;
   4737 	}
   4738 
   4739 	wrtrack_skew = 0;
   4740 	if (mmc_discinfo.mmc_cur & MMC_CAP_SEQUENTIAL)
   4741 		wrtrack_skew = ti.next_writable % blockingnr;
   4742 
   4743 	/* get layout */
   4744 	error = udf_calculate_disc_layout(context.min_udf,
   4745 		ti.track_start, mmc_discinfo.last_possible_lba,
   4746 		context.sector_size, blockingnr);
   4747 
   4748 	/* cache partition for we need it often */
   4749 	data_part     = context.data_part;
   4750 	metadata_part = context.metadata_part;
   4751 
   4752 	/* Create sparing table descriptor if applicable */
   4753 	if (format_flags & FORMAT_SPAREABLE) {
   4754 		if ((error = udf_create_sparing_tabled()))
   4755 			return error;
   4756 
   4757 		if (context.check_surface) {
   4758 			if ((error = udf_surface_check()))
   4759 				return error;
   4760 		}
   4761 	}
   4762 
   4763 	/* Create a generic terminator descriptor (later reused) */
   4764 	terminator_dscr = calloc(1, context.sector_size);
   4765 	if (terminator_dscr == NULL)
   4766 		return ENOMEM;
   4767 	udf_create_terminator(terminator_dscr, 0);
   4768 
   4769 	/*
   4770 	 * Create the two Volume Descriptor Sets (VDS) each containing the
   4771 	 * following descriptors : primary volume, partition space,
   4772 	 * unallocated space, logical volume, implementation use and the
   4773 	 * terminator
   4774 	 */
   4775 
   4776 	/* start of volume recognition sequence building */
   4777 	context.vds_seq = 0;
   4778 
   4779 	/* Create primary volume descriptor */
   4780 	if ((error = udf_create_primaryd()))
   4781 		return error;
   4782 
   4783 	/* Create partition descriptor */
   4784 	if ((error = udf_create_partitiond(context.data_part)))
   4785 		return error;
   4786 
   4787 	/* Create unallocated space descriptor */
   4788 	if ((error = udf_create_unalloc_spaced()))
   4789 		return error;
   4790 
   4791 	/* Create logical volume descriptor */
   4792 	if ((error = udf_create_logical_dscr()))
   4793 		return error;
   4794 
   4795 	/* Create implementation use descriptor */
   4796 	/* TODO input of fields 1,2,3 and passing them */
   4797 	if ((error = udf_create_impvold(NULL, NULL, NULL)))
   4798 		return error;
   4799 
   4800 	/* Create anchors */
   4801 	for (cnt = 0; cnt < 3; cnt++) {
   4802 		if ((error = udf_create_anchor(cnt))) {
   4803 			return error;
   4804 		}
   4805 	}
   4806 
   4807 	/*
   4808 	 * Write out what we've created so far.
   4809 	 *
   4810 	 * Start with wipeout of VRS1 upto start of partition. This allows
   4811 	 * formatting for sequentials with the track reservation and it
   4812 	 * cleans old rubbish on rewritables. For sequentials without the
   4813 	 * track reservation all is wiped from track start.
   4814 	 */
   4815 	if ((zero_dscr = calloc(1, context.sector_size)) == NULL)
   4816 		return ENOMEM;
   4817 
   4818 	loc = (format_flags & FORMAT_TRACK512) ? layout.vds1 : ti.track_start;
   4819 	for (; loc < layout.part_start_lba; loc++) {
   4820 		if ((error = udf_write_sector(zero_dscr, loc))) {
   4821 			free(zero_dscr);
   4822 			return error;
   4823 		}
   4824 	}
   4825 	free(zero_dscr);
   4826 
   4827 	/* writeout iso9660 vrs */
   4828 	if ((error = udf_write_iso9660_vrs()))
   4829 		return error;
   4830 
   4831 	/* Writeout anchors */
   4832 	for (cnt = 0; cnt < 3; cnt++) {
   4833 		dscr = (union dscrptr *) context.anchors[cnt];
   4834 		loc  = layout.anchors[cnt];
   4835 		if ((error = udf_write_dscr_phys(dscr, loc, 1))) {
   4836 			err(1, "ERR!");
   4837 			return error;
   4838 		}
   4839 
   4840 		/* sequential media has only one anchor */
   4841 		if (format_flags & FORMAT_SEQUENTIAL)
   4842 			break;
   4843 	}
   4844 
   4845 	/* write out main and secondary VRS */
   4846 	for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
   4847 		loc = (sectcopy == 1) ? layout.vds1 : layout.vds2;
   4848 
   4849 		/* primary volume descriptor */
   4850 		dscr = (union dscrptr *) context.primary_vol;
   4851 		error = udf_write_dscr_phys(dscr, loc, 1);
   4852 		if (error)
   4853 			return error;
   4854 		loc++;
   4855 
   4856 		/* partition descriptor(s) */
   4857 		for (cnt = 0; cnt < UDF_PARTITIONS; cnt++) {
   4858 			dscr = (union dscrptr *) context.partitions[cnt];
   4859 			if (dscr) {
   4860 				error = udf_write_dscr_phys(dscr, loc, 1);
   4861 				if (error)
   4862 					return error;
   4863 				loc++;
   4864 			}
   4865 		}
   4866 
   4867 		/* unallocated space descriptor */
   4868 		dscr = (union dscrptr *) context.unallocated;
   4869 		error = udf_write_dscr_phys(dscr, loc, 1);
   4870 		if (error)
   4871 			return error;
   4872 		loc++;
   4873 
   4874 		/* logical volume descriptor */
   4875 		dscr = (union dscrptr *) context.logical_vol;
   4876 		error = udf_write_dscr_phys(dscr, loc, 1);
   4877 		if (error)
   4878 			return error;
   4879 		loc++;
   4880 
   4881 		/* implementation use descriptor */
   4882 		dscr = (union dscrptr *) context.implementation;
   4883 		error = udf_write_dscr_phys(dscr, loc, 1);
   4884 		if (error)
   4885 			return error;
   4886 		loc++;
   4887 
   4888 		/* terminator descriptor */
   4889 		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   4890 		if (error)
   4891 			return error;
   4892 		loc++;
   4893 	}
   4894 
   4895 	/* writeout the two spareable table descriptors (if needed) */
   4896 	if (format_flags & FORMAT_SPAREABLE) {
   4897 		for (sectcopy = 1; sectcopy <= 2; sectcopy++) {
   4898 			loc  = (sectcopy == 1) ? layout.spt_1 : layout.spt_2;
   4899 			dscr = (union dscrptr *) context.sparing_table;
   4900 			len  = udf_tagsize(dscr, context.sector_size) /
   4901 					context.sector_size;
   4902 
   4903 			/* writeout */
   4904 			error = udf_write_dscr_phys(dscr, loc, len);
   4905 			if (error)
   4906 				return error;
   4907 		}
   4908 	}
   4909 
   4910 	/*
   4911 	 * Create unallocated space bitmap descriptor. Sequential recorded
   4912 	 * media report their own free/used space; no free/used space tables
   4913 	 * should be recorded for these.
   4914 	 */
   4915 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
   4916 		error = udf_create_space_bitmap(
   4917 				layout.alloc_bitmap_dscr_size,
   4918 				layout.part_size_lba,
   4919 				&context.part_unalloc_bits[data_part]);
   4920 		if (error)
   4921 			return error;
   4922 		/* TODO: freed space bitmap if applicable */
   4923 
   4924 		/* mark space allocated for the unallocated space bitmap */
   4925 		udf_mark_allocated(layout.unalloc_space, data_part,
   4926 			layout.alloc_bitmap_dscr_size);
   4927 	}
   4928 
   4929 	/*
   4930 	 * Create metadata partition file entries and allocate and init their
   4931 	 * space and free space maps.
   4932 	 */
   4933 	if (format_flags & FORMAT_META) {
   4934 		error = udf_create_meta_files();
   4935 		if (error)
   4936 			return error;
   4937 
   4938 		/* mark space allocated for meta partition and its bitmap */
   4939 		udf_mark_allocated(layout.meta_file,   data_part, 1);
   4940 		udf_mark_allocated(layout.meta_mirror, data_part, 1);
   4941 		udf_mark_allocated(layout.meta_part_start_lba, data_part,
   4942 			layout.meta_part_size_lba);
   4943 
   4944 		if (context.meta_bitmap) {
   4945 			/* metadata bitmap creation and accounting */
   4946 			error = udf_create_space_bitmap(
   4947 					layout.meta_bitmap_dscr_size,
   4948 					layout.meta_part_size_lba,
   4949 					&context.part_unalloc_bits[metadata_part]);
   4950 			if (error)
   4951 				return error;
   4952 
   4953 			udf_mark_allocated(layout.meta_bitmap, data_part, 1);
   4954 			/* mark space allocated for the unallocated space bitmap */
   4955 			udf_mark_allocated(layout.meta_bitmap_space,
   4956 					data_part,
   4957 				layout.meta_bitmap_dscr_size);
   4958 		}
   4959 	}
   4960 
   4961 	/* create logical volume integrity descriptor */
   4962 	context.num_files = 0;
   4963 	context.num_directories = 0;
   4964 	integrity_type = UDF_INTEGRITY_OPEN;
   4965 	if ((error = udf_create_lvintd(integrity_type)))
   4966 		return error;
   4967 
   4968 	/* writeout initial open integrity sequence + terminator */
   4969 	loc = layout.lvis;
   4970 	dscr = (union dscrptr *) context.logvol_integrity;
   4971 	error = udf_write_dscr_phys(dscr, loc, 1);
   4972 	if (error)
   4973 		return error;
   4974 	loc++;
   4975 	error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   4976 	if (error)
   4977 		return error;
   4978 
   4979 	/* create VAT if needed */
   4980 	if (format_flags & FORMAT_VAT) {
   4981 		context.vat_allocated = context.sector_size;
   4982 		context.vat_contents  = malloc(context.vat_allocated);
   4983 		assert(context.vat_contents);
   4984 
   4985 		udf_prepend_VAT_file();
   4986 	}
   4987 
   4988 	/* create FSD and writeout */
   4989 	if ((error = udf_create_fsd()))
   4990 		return error;
   4991 	udf_mark_allocated(layout.fsd, metadata_part, 1);
   4992 
   4993 	dscr = (union dscrptr *) context.fileset_desc;
   4994 	error = udf_write_dscr_virt(dscr, layout.fsd, metadata_part, 1);
   4995 
   4996 	return error;
   4997 }
   4998 
   4999 
   5000 /* specific routine for newfs to create empty rootdirectory */
   5001 int
   5002 udf_do_rootdir(void)
   5003 {
   5004 	union dscrptr *root_dscr;
   5005 	int error;
   5006 
   5007 	/* create root directory and write out */
   5008 	assert(context.unique_id == 0x10);
   5009 	context.unique_id = 0;
   5010 	if ((error = udf_create_new_rootdir(&root_dscr)))
   5011 		return error;
   5012 	udf_mark_allocated(layout.rootdir, context.metadata_part, 1);
   5013 
   5014 	error = udf_write_dscr_virt(root_dscr,
   5015 		layout.rootdir, context.metadata_part, 1);
   5016 
   5017 	free(root_dscr);
   5018 
   5019 	return error;
   5020 }
   5021 
   5022 
   5023 int
   5024 udf_do_newfs_postfix(void)
   5025 {
   5026 	union dscrptr *dscr;
   5027 	uint32_t loc, len;
   5028 	int data_part, metadata_part;
   5029 	int format_flags = context.format_flags;
   5030 	int error;
   5031 
   5032 	/* cache partition for we need it often */
   5033 	data_part     = context.data_part;
   5034 	metadata_part = context.metadata_part;
   5035 
   5036 	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
   5037 		/* update lvint and mark it closed */
   5038 		udf_update_lvintd(UDF_INTEGRITY_CLOSED);
   5039 
   5040 		/* overwrite initial terminator */
   5041 		loc = layout.lvis+1;
   5042 		dscr = (union dscrptr *) context.logvol_integrity;
   5043 		error = udf_write_dscr_phys(dscr, loc, 1);
   5044 		if (error)
   5045 			return error;
   5046 		loc++;
   5047 
   5048 		/* mark end of integrity descriptor sequence again */
   5049 		error = udf_write_dscr_phys(terminator_dscr, loc, 1);
   5050 		if (error)
   5051 			return error;
   5052 	}
   5053 
   5054 	/* write out unallocated space bitmap on non sequential media */
   5055 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
   5056 		/* writeout unallocated space bitmap */
   5057 		loc  = layout.unalloc_space;
   5058 		dscr = (union dscrptr *) (context.part_unalloc_bits[data_part]);
   5059 		len  = layout.alloc_bitmap_dscr_size;
   5060 		error = udf_write_dscr_virt(dscr, loc, data_part, len);
   5061 		if (error)
   5062 			return error;
   5063 	}
   5064 
   5065 	if (format_flags & FORMAT_META) {
   5066 		loc = layout.meta_file;
   5067 		dscr = (union dscrptr *) context.meta_file;
   5068 		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5069 		if (error)
   5070 			return error;
   5071 
   5072 		loc = layout.meta_mirror;
   5073 		dscr = (union dscrptr *) context.meta_mirror;
   5074 		error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5075 		if (error)
   5076 			return error;
   5077 
   5078 		if (context.meta_bitmap) {
   5079 			loc = layout.meta_bitmap;
   5080 			dscr = (union dscrptr *) context.meta_bitmap;
   5081 			error = udf_write_dscr_virt(dscr, loc, data_part, 1);
   5082 			if (error)
   5083 				return error;
   5084 
   5085 			/* writeout unallocated space bitmap */
   5086 			loc  = layout.meta_bitmap_space;
   5087 			dscr = (union dscrptr *)
   5088 				(context.part_unalloc_bits[metadata_part]);
   5089 			len  = layout.meta_bitmap_dscr_size;
   5090 			error = udf_write_dscr_virt(dscr, loc, data_part, len);
   5091 			if (error)
   5092 				return error;
   5093 		}
   5094 	}
   5095 
   5096 	/* create and writeout a VAT */
   5097 	if (format_flags & FORMAT_VAT)
   5098 		udf_writeout_VAT();
   5099 
   5100 	/* done */
   5101 	return 0;
   5102 }
   5103