xref: /minix3/sbin/newfs_udf/udf_create.c (revision e1cdaee10649323af446eb1a74571984b2ab3181)
10a6a1f1dSLionel Sambuc /* $NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $ */
29f988b79SJean-Baptiste Boric 
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric  * Copyright (c) 2006, 2008 Reinoud Zandijk
59f988b79SJean-Baptiste Boric  * All rights reserved.
69f988b79SJean-Baptiste Boric  *
79f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
89f988b79SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
99f988b79SJean-Baptiste Boric  * are met:
109f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
119f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
129f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
139f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in the
149f988b79SJean-Baptiste Boric  *    documentation and/or other materials provided with the distribution.
159f988b79SJean-Baptiste Boric  *
169f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
179f988b79SJean-Baptiste Boric  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
189f988b79SJean-Baptiste Boric  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
199f988b79SJean-Baptiste Boric  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
209f988b79SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
219f988b79SJean-Baptiste Boric  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
229f988b79SJean-Baptiste Boric  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
239f988b79SJean-Baptiste Boric  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249f988b79SJean-Baptiste Boric  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
259f988b79SJean-Baptiste Boric  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269f988b79SJean-Baptiste Boric  *
279f988b79SJean-Baptiste Boric  */
289f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
299f988b79SJean-Baptiste Boric #include "nbtool_config.h"
309f988b79SJean-Baptiste Boric #endif
319f988b79SJean-Baptiste Boric 
329f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
330a6a1f1dSLionel Sambuc __RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $");
349f988b79SJean-Baptiste Boric 
359f988b79SJean-Baptiste Boric #include <stdio.h>
369f988b79SJean-Baptiste Boric #include <stdlib.h>
379f988b79SJean-Baptiste Boric #include <stddef.h>
389f988b79SJean-Baptiste Boric #include <string.h>
399f988b79SJean-Baptiste Boric #include <errno.h>
409f988b79SJean-Baptiste Boric #include <time.h>
419f988b79SJean-Baptiste Boric #include <assert.h>
429f988b79SJean-Baptiste Boric #include <err.h>
439f988b79SJean-Baptiste Boric #include <sys/types.h>
449f988b79SJean-Baptiste Boric #include <sys/param.h>
459f988b79SJean-Baptiste Boric #include "unicode.h"
469f988b79SJean-Baptiste Boric #include "udf_create.h"
479f988b79SJean-Baptiste Boric 
489f988b79SJean-Baptiste Boric 
499f988b79SJean-Baptiste Boric #if 0
509f988b79SJean-Baptiste Boric # ifndef DEBUG
519f988b79SJean-Baptiste Boric #   define DEBUG
529f988b79SJean-Baptiste Boric #  endif
539f988b79SJean-Baptiste Boric #endif
549f988b79SJean-Baptiste Boric 
559f988b79SJean-Baptiste Boric /*
569f988b79SJean-Baptiste Boric  * NOTE that there is some overlap between this code and the udf kernel fs.
579f988b79SJean-Baptiste Boric  * This is intentially though it might better be factored out one day.
589f988b79SJean-Baptiste Boric  */
599f988b79SJean-Baptiste Boric 
609f988b79SJean-Baptiste Boric void
udf_init_create_context(void)619f988b79SJean-Baptiste Boric udf_init_create_context(void)
629f988b79SJean-Baptiste Boric {
639f988b79SJean-Baptiste Boric 	/* clear */
649f988b79SJean-Baptiste Boric 	memset(&context, 0, sizeof(struct udf_create_context));
659f988b79SJean-Baptiste Boric 
669f988b79SJean-Baptiste Boric 	/* fill with defaults currently known */
679f988b79SJean-Baptiste Boric 	context.dscrver = 3;
689f988b79SJean-Baptiste Boric 	context.min_udf = 0x0102;
699f988b79SJean-Baptiste Boric 	context.max_udf = 0x0260;
709f988b79SJean-Baptiste Boric 	context.serialnum = 1;		/* default */
719f988b79SJean-Baptiste Boric 
729f988b79SJean-Baptiste Boric 	context.gmtoff  = 0;
739f988b79SJean-Baptiste Boric 	context.sector_size = 512;	/* minimum for UDF */
749f988b79SJean-Baptiste Boric 
759f988b79SJean-Baptiste Boric 	context.logvol_name  = NULL;
769f988b79SJean-Baptiste Boric 	context.primary_name = NULL;
779f988b79SJean-Baptiste Boric 	context.volset_name  = NULL;
789f988b79SJean-Baptiste Boric 	context.fileset_name = NULL;
799f988b79SJean-Baptiste Boric 
809f988b79SJean-Baptiste Boric 	/* most basic identification */
819f988b79SJean-Baptiste Boric 	context.app_name	 = "*NetBSD";
829f988b79SJean-Baptiste Boric 	context.app_version_main = 0;
839f988b79SJean-Baptiste Boric 	context.app_version_sub  = 0;
849f988b79SJean-Baptiste Boric 	context.impl_name        = "*NetBSD";
859f988b79SJean-Baptiste Boric 
869f988b79SJean-Baptiste Boric 	context.vds_seq = 0;		/* first one starts with zero */
879f988b79SJean-Baptiste Boric 
889f988b79SJean-Baptiste Boric 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
899f988b79SJean-Baptiste Boric 	context.unique_id       = 0x10;
909f988b79SJean-Baptiste Boric 
919f988b79SJean-Baptiste Boric 	context.num_files       = 0;
929f988b79SJean-Baptiste Boric 	context.num_directories = 0;
939f988b79SJean-Baptiste Boric 
949f988b79SJean-Baptiste Boric 	context.data_part          = 0;
959f988b79SJean-Baptiste Boric 	context.metadata_part      = 0;
969f988b79SJean-Baptiste Boric 	context.metadata_alloc_pos = 0;
979f988b79SJean-Baptiste Boric 	context.data_alloc_pos     = 0;
989f988b79SJean-Baptiste Boric }
999f988b79SJean-Baptiste Boric 
1009f988b79SJean-Baptiste Boric 
1019f988b79SJean-Baptiste Boric /* version can be specified as 0xabc or a.bc */
1029f988b79SJean-Baptiste Boric static int
parse_udfversion(const char * pos,uint32_t * version)1039f988b79SJean-Baptiste Boric parse_udfversion(const char *pos, uint32_t *version) {
1049f988b79SJean-Baptiste Boric 	int hex = 0;
1059f988b79SJean-Baptiste Boric 	char c1, c2, c3, c4;
1069f988b79SJean-Baptiste Boric 
1079f988b79SJean-Baptiste Boric 	*version = 0;
1089f988b79SJean-Baptiste Boric 	if (*pos == '0') {
1099f988b79SJean-Baptiste Boric 		pos++;
1109f988b79SJean-Baptiste Boric 		/* expect hex format */
1119f988b79SJean-Baptiste Boric 		hex = 1;
1129f988b79SJean-Baptiste Boric 		if (*pos++ != 'x')
1139f988b79SJean-Baptiste Boric 			return 1;
1149f988b79SJean-Baptiste Boric 	}
1159f988b79SJean-Baptiste Boric 
1169f988b79SJean-Baptiste Boric 	c1 = *pos++;
1179f988b79SJean-Baptiste Boric 	if (c1 < '0' || c1 > '9')
1189f988b79SJean-Baptiste Boric 		return 1;
1199f988b79SJean-Baptiste Boric 	c1 -= '0';
1209f988b79SJean-Baptiste Boric 
1219f988b79SJean-Baptiste Boric 	c2 = *pos++;
1229f988b79SJean-Baptiste Boric 	if (!hex) {
1239f988b79SJean-Baptiste Boric 		if (c2 != '.')
1249f988b79SJean-Baptiste Boric 			return 1;
1259f988b79SJean-Baptiste Boric 		c2 = *pos++;
1269f988b79SJean-Baptiste Boric 	}
1279f988b79SJean-Baptiste Boric 	if (c2 < '0' || c2 > '9')
1289f988b79SJean-Baptiste Boric 		return 1;
1299f988b79SJean-Baptiste Boric 	c2 -= '0';
1309f988b79SJean-Baptiste Boric 
1319f988b79SJean-Baptiste Boric 	c3 = *pos++;
1329f988b79SJean-Baptiste Boric 	if (c3 < '0' || c3 > '9')
1339f988b79SJean-Baptiste Boric 		return 1;
1349f988b79SJean-Baptiste Boric 	c3 -= '0';
1359f988b79SJean-Baptiste Boric 
1369f988b79SJean-Baptiste Boric 	c4 = *pos++;
1379f988b79SJean-Baptiste Boric 	if (c4 != 0)
1389f988b79SJean-Baptiste Boric 		return 1;
1399f988b79SJean-Baptiste Boric 
1409f988b79SJean-Baptiste Boric 	*version = c1 * 0x100 + c2 * 0x10 + c3;
1419f988b79SJean-Baptiste Boric 	return 0;
1429f988b79SJean-Baptiste Boric }
1439f988b79SJean-Baptiste Boric 
1449f988b79SJean-Baptiste Boric 
1459f988b79SJean-Baptiste Boric /* parse a given string for an udf version */
1469f988b79SJean-Baptiste Boric int
a_udf_version(const char * s,const char * id_type)1479f988b79SJean-Baptiste Boric a_udf_version(const char *s, const char *id_type)
1489f988b79SJean-Baptiste Boric {
1499f988b79SJean-Baptiste Boric 	uint32_t version;
1509f988b79SJean-Baptiste Boric 
1519f988b79SJean-Baptiste Boric 	if (parse_udfversion(s, &version))
1529f988b79SJean-Baptiste Boric 		errx(1, "unknown %s id %s; specify as hex or float", id_type, s);
1539f988b79SJean-Baptiste Boric 	return version;
1549f988b79SJean-Baptiste Boric }
1559f988b79SJean-Baptiste Boric 
1569f988b79SJean-Baptiste Boric 
1579f988b79SJean-Baptiste Boric static uint32_t
udf_space_bitmap_len(uint32_t part_size)1589f988b79SJean-Baptiste Boric udf_space_bitmap_len(uint32_t part_size)
1599f988b79SJean-Baptiste Boric {
1609f988b79SJean-Baptiste Boric 	return  sizeof(struct space_bitmap_desc)-1 +
1619f988b79SJean-Baptiste Boric 		part_size/8;
1629f988b79SJean-Baptiste Boric }
1639f988b79SJean-Baptiste Boric 
1649f988b79SJean-Baptiste Boric 
1659f988b79SJean-Baptiste Boric static uint32_t
udf_bytes_to_sectors(uint64_t bytes)1669f988b79SJean-Baptiste Boric udf_bytes_to_sectors(uint64_t bytes)
1679f988b79SJean-Baptiste Boric {
1689f988b79SJean-Baptiste Boric 	uint32_t sector_size = layout.sector_size;
1699f988b79SJean-Baptiste Boric 	return (bytes + sector_size -1) / sector_size;
1709f988b79SJean-Baptiste Boric }
1719f988b79SJean-Baptiste Boric 
1729f988b79SJean-Baptiste Boric 
1739f988b79SJean-Baptiste Boric int
udf_calculate_disc_layout(int format_flags,int min_udf,uint32_t wrtrack_skew,uint32_t first_lba,uint32_t last_lba,uint32_t sector_size,uint32_t blockingnr,uint32_t sparable_blocks,float meta_fract)1749f988b79SJean-Baptiste Boric udf_calculate_disc_layout(int format_flags, int min_udf,
1759f988b79SJean-Baptiste Boric 	uint32_t wrtrack_skew,
1769f988b79SJean-Baptiste Boric 	uint32_t first_lba, uint32_t last_lba,
1779f988b79SJean-Baptiste Boric 	uint32_t sector_size, uint32_t blockingnr,
1789f988b79SJean-Baptiste Boric 	uint32_t sparable_blocks, float meta_fract)
1799f988b79SJean-Baptiste Boric {
1809f988b79SJean-Baptiste Boric 	uint64_t kbsize, bytes;
1819f988b79SJean-Baptiste Boric 	uint32_t sparable_blockingnr;
1829f988b79SJean-Baptiste Boric 	uint32_t align_blockingnr;
1839f988b79SJean-Baptiste Boric 	uint32_t pos, mpos;
1849f988b79SJean-Baptiste Boric 
1859f988b79SJean-Baptiste Boric 	/* clear */
1869f988b79SJean-Baptiste Boric 	memset(&layout, 0, sizeof(layout));
1879f988b79SJean-Baptiste Boric 
1889f988b79SJean-Baptiste Boric 	/* fill with parameters */
1899f988b79SJean-Baptiste Boric 	layout.wrtrack_skew    = wrtrack_skew;
1909f988b79SJean-Baptiste Boric 	layout.first_lba       = first_lba;
1919f988b79SJean-Baptiste Boric 	layout.last_lba        = last_lba;
1929f988b79SJean-Baptiste Boric 	layout.sector_size     = sector_size;
1939f988b79SJean-Baptiste Boric 	layout.blockingnr      = blockingnr;
1949f988b79SJean-Baptiste Boric 	layout.sparable_blocks = sparable_blocks;
1959f988b79SJean-Baptiste Boric 
1969f988b79SJean-Baptiste Boric 	/* start disc layouting */
1979f988b79SJean-Baptiste Boric 
1989f988b79SJean-Baptiste Boric 	/*
1999f988b79SJean-Baptiste Boric 	 * location of iso9660 vrs is defined as first sector AFTER 32kb,
2009f988b79SJean-Baptiste Boric 	 * minimum `sector size' 2048
2019f988b79SJean-Baptiste Boric 	 */
2029f988b79SJean-Baptiste Boric 	layout.iso9660_vrs = ((32*1024 + sector_size - 1) / sector_size)
2039f988b79SJean-Baptiste Boric 		+ first_lba;
2049f988b79SJean-Baptiste Boric 
2059f988b79SJean-Baptiste Boric 	/* anchor starts at specified offset in sectors */
2069f988b79SJean-Baptiste Boric 	layout.anchors[0] = first_lba + 256;
2079f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_TRACK512)
2089f988b79SJean-Baptiste Boric 		layout.anchors[0] = first_lba + 512;
2099f988b79SJean-Baptiste Boric 	layout.anchors[1] = last_lba - 256;
2109f988b79SJean-Baptiste Boric 	layout.anchors[2] = last_lba;
2119f988b79SJean-Baptiste Boric 
2129f988b79SJean-Baptiste Boric 	/* update workable space */
2139f988b79SJean-Baptiste Boric 	first_lba = layout.anchors[0] + blockingnr;
2149f988b79SJean-Baptiste Boric 	last_lba  = layout.anchors[1] - 1;
2159f988b79SJean-Baptiste Boric 
2169f988b79SJean-Baptiste Boric 	/* XXX rest of anchor packet can be added to unallocated space descr */
2179f988b79SJean-Baptiste Boric 
2189f988b79SJean-Baptiste Boric 	/* reserve space for VRS and VRS copy and associated tables */
2199f988b79SJean-Baptiste Boric 	layout.vds_size = MAX(16, blockingnr);     /* UDF 2.2.3.1+2 */
2209f988b79SJean-Baptiste Boric 	layout.vds1 = first_lba;
2219f988b79SJean-Baptiste Boric 	first_lba += layout.vds_size;              /* next packet */
2229f988b79SJean-Baptiste Boric 
2239f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_SEQUENTIAL) {
2249f988b79SJean-Baptiste Boric 		/* for sequential, append them ASAP */
2259f988b79SJean-Baptiste Boric 		layout.vds2 = first_lba;
2269f988b79SJean-Baptiste Boric 		first_lba += layout.vds_size;
2279f988b79SJean-Baptiste Boric 	} else {
2289f988b79SJean-Baptiste Boric 		layout.vds2 = layout.anchors[1] - layout.vds_size;
2299f988b79SJean-Baptiste Boric 		last_lba = layout.vds2 - 1;	/* XXX -1 ?? */
2309f988b79SJean-Baptiste Boric 	}
2319f988b79SJean-Baptiste Boric 
2329f988b79SJean-Baptiste Boric 	/* reserve space for logvol integrity sequence */
2339f988b79SJean-Baptiste Boric 	layout.lvis_size = MAX(8192/sector_size, 2 * blockingnr);
2349f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_VAT)
2359f988b79SJean-Baptiste Boric 		layout.lvis_size = 2;
2369f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_WORM)
2379f988b79SJean-Baptiste Boric 		layout.lvis_size = 64 * blockingnr;
2389f988b79SJean-Baptiste Boric 
2399f988b79SJean-Baptiste Boric 	/* TODO skip bad blocks in LVID sequence; for now use f.e. */
2409f988b79SJean-Baptiste Boric //first_lba+=128;
2419f988b79SJean-Baptiste Boric 	layout.lvis = first_lba;
2429f988b79SJean-Baptiste Boric 	first_lba += layout.lvis_size;
2439f988b79SJean-Baptiste Boric 
2449f988b79SJean-Baptiste Boric 	/* initial guess of UDF partition size */
2459f988b79SJean-Baptiste Boric 	layout.part_start_lba = first_lba;
2469f988b79SJean-Baptiste Boric 	layout.part_size_lba = last_lba - layout.part_start_lba;
2479f988b79SJean-Baptiste Boric 
2489f988b79SJean-Baptiste Boric 	/* all non sequential media needs an unallocated space bitmap */
2499f988b79SJean-Baptiste Boric 	layout.alloc_bitmap_dscr_size = 0;
2509f988b79SJean-Baptiste Boric 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
2519f988b79SJean-Baptiste Boric 		bytes = udf_space_bitmap_len(layout.part_size_lba);
2529f988b79SJean-Baptiste Boric 		layout.alloc_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
2539f988b79SJean-Baptiste Boric 
2549f988b79SJean-Baptiste Boric 		/* XXX freed space map when applicable */
2559f988b79SJean-Baptiste Boric 	}
2569f988b79SJean-Baptiste Boric 
2579f988b79SJean-Baptiste Boric 	/*
2589f988b79SJean-Baptiste Boric 	 * Note that for (bug) compatibility with version UDF 2.00 (fixed in
2599f988b79SJean-Baptiste Boric 	 * 2.01 and higher) the blocking size needs to be 32 sectors otherwise
2609f988b79SJean-Baptiste Boric 	 * the drive's blockingnr.
2619f988b79SJean-Baptiste Boric 	 */
2629f988b79SJean-Baptiste Boric 
2639f988b79SJean-Baptiste Boric 	sparable_blockingnr = blockingnr;
2649f988b79SJean-Baptiste Boric 	if (min_udf <= 0x200)
2659f988b79SJean-Baptiste Boric 		sparable_blockingnr = 32;
2669f988b79SJean-Baptiste Boric 
2679f988b79SJean-Baptiste Boric 	align_blockingnr = blockingnr;
2689f988b79SJean-Baptiste Boric 	if (format_flags & (FORMAT_SPARABLE | FORMAT_META))
2699f988b79SJean-Baptiste Boric 		align_blockingnr = sparable_blockingnr;
2709f988b79SJean-Baptiste Boric 
2719f988b79SJean-Baptiste Boric 	layout.align_blockingnr    = align_blockingnr;
2729f988b79SJean-Baptiste Boric 	layout.sparable_blockingnr = sparable_blockingnr;
2739f988b79SJean-Baptiste Boric 
2749f988b79SJean-Baptiste Boric 	/*
2759f988b79SJean-Baptiste Boric 	 * Align partition LBA space to blocking granularity. Not strickly
2769f988b79SJean-Baptiste Boric 	 * nessisary for non sparables but safer for the VRS data since it is
2779f988b79SJean-Baptiste Boric 	 * not updated sporadically
2789f988b79SJean-Baptiste Boric 	 */
2799f988b79SJean-Baptiste Boric 
2809f988b79SJean-Baptiste Boric 	if ((format_flags & (FORMAT_SEQUENTIAL | FORMAT_READONLY)) == 0) {
2819f988b79SJean-Baptiste Boric #ifdef DEBUG
2829f988b79SJean-Baptiste Boric 		printf("Lost %d slack sectors at start\n", UDF_ROUNDUP(
2839f988b79SJean-Baptiste Boric 			first_lba - wrtrack_skew, align_blockingnr) -
2849f988b79SJean-Baptiste Boric 				(first_lba - wrtrack_skew));
2859f988b79SJean-Baptiste Boric 		printf("Lost %d slack sectors at end\n",
2869f988b79SJean-Baptiste Boric 			(first_lba - wrtrack_skew) - UDF_ROUNDDOWN(
2879f988b79SJean-Baptiste Boric 				first_lba - wrtrack_skew, align_blockingnr));
2889f988b79SJean-Baptiste Boric #endif
2899f988b79SJean-Baptiste Boric 
2909f988b79SJean-Baptiste Boric 		first_lba = UDF_ROUNDUP( first_lba - wrtrack_skew,
2919f988b79SJean-Baptiste Boric 				align_blockingnr);
2929f988b79SJean-Baptiste Boric 		last_lba  = UDF_ROUNDDOWN(last_lba - wrtrack_skew,
2939f988b79SJean-Baptiste Boric 				align_blockingnr);
2949f988b79SJean-Baptiste Boric 	}
2959f988b79SJean-Baptiste Boric 
2969f988b79SJean-Baptiste Boric 	if ((format_flags & FORMAT_SPARABLE) == 0)
2979f988b79SJean-Baptiste Boric 		layout.sparable_blocks = 0;
2989f988b79SJean-Baptiste Boric 
2999f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_SPARABLE) {
3009f988b79SJean-Baptiste Boric 		layout.sparable_area_size =
3019f988b79SJean-Baptiste Boric 			layout.sparable_blocks * sparable_blockingnr;
3029f988b79SJean-Baptiste Boric 
3039f988b79SJean-Baptiste Boric 		/* a sparing table descriptor is a whole blockingnr sectors */
3049f988b79SJean-Baptiste Boric 		layout.sparing_table_dscr_lbas = sparable_blockingnr;
3059f988b79SJean-Baptiste Boric 
3069f988b79SJean-Baptiste Boric 		/* place the descriptors at the start and end of the area */
3079f988b79SJean-Baptiste Boric 		layout.spt_1 = first_lba;
3089f988b79SJean-Baptiste Boric 		first_lba += layout.sparing_table_dscr_lbas;
3099f988b79SJean-Baptiste Boric 
3109f988b79SJean-Baptiste Boric 		layout.spt_2 = last_lba - layout.sparing_table_dscr_lbas;
3119f988b79SJean-Baptiste Boric 		last_lba -= layout.sparing_table_dscr_lbas;
3129f988b79SJean-Baptiste Boric 
3139f988b79SJean-Baptiste Boric 		/* allocate sparable section */
3149f988b79SJean-Baptiste Boric 		layout.sparable_area = first_lba;
3159f988b79SJean-Baptiste Boric 		first_lba += layout.sparable_area_size;
3169f988b79SJean-Baptiste Boric 	}
3179f988b79SJean-Baptiste Boric 
3189f988b79SJean-Baptiste Boric 	/* update guess of UDF partition size */
3199f988b79SJean-Baptiste Boric 	layout.part_start_lba = first_lba;
3209f988b79SJean-Baptiste Boric 	layout.part_size_lba = last_lba - layout.part_start_lba;
3219f988b79SJean-Baptiste Boric 
3229f988b79SJean-Baptiste Boric 	/* determine partition selection for data and metadata */
3239f988b79SJean-Baptiste Boric 	context.data_part     = 0;
3249f988b79SJean-Baptiste Boric 	context.metadata_part = context.data_part;
3259f988b79SJean-Baptiste Boric 	if ((format_flags & FORMAT_VAT) || (format_flags & FORMAT_META))
3269f988b79SJean-Baptiste Boric 		context.metadata_part = context.data_part + 1;
3279f988b79SJean-Baptiste Boric 
3289f988b79SJean-Baptiste Boric 	/*
3299f988b79SJean-Baptiste Boric 	 * Pick fixed logical space sector numbers for main FSD, rootdir and
3309f988b79SJean-Baptiste Boric 	 * unallocated space. The reason for this pre-allocation is that they
3319f988b79SJean-Baptiste Boric 	 * are referenced in the volume descriptor sequence and hence can't be
3329f988b79SJean-Baptiste Boric 	 * allocated later.
3339f988b79SJean-Baptiste Boric 	 */
3349f988b79SJean-Baptiste Boric 	pos = 0;
3359f988b79SJean-Baptiste Boric 	layout.unalloc_space = pos;
3369f988b79SJean-Baptiste Boric 	pos += layout.alloc_bitmap_dscr_size;
3379f988b79SJean-Baptiste Boric 
3389f988b79SJean-Baptiste Boric 	/* claim metadata descriptors and partition space [UDF 2.2.10] */
3399f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_META) {
3409f988b79SJean-Baptiste Boric 		/* note: all in backing partition space */
3419f988b79SJean-Baptiste Boric 		layout.meta_file   = pos++;
3429f988b79SJean-Baptiste Boric 		layout.meta_bitmap = pos++;;
3439f988b79SJean-Baptiste Boric 		layout.meta_mirror = layout.part_size_lba-1;
3449f988b79SJean-Baptiste Boric 		layout.meta_alignment  = MAX(blockingnr, sparable_blockingnr);
3459f988b79SJean-Baptiste Boric 		layout.meta_blockingnr = MAX(layout.meta_alignment, 32);
3469f988b79SJean-Baptiste Boric 
3479f988b79SJean-Baptiste Boric 		/* calculate our partition length and store in sectors */
3489f988b79SJean-Baptiste Boric 		layout.meta_part_size_lba = layout.part_size_lba * meta_fract;
3499f988b79SJean-Baptiste Boric 		layout.meta_part_size_lba = MAX(layout.meta_part_size_lba, 32);
3509f988b79SJean-Baptiste Boric 		layout.meta_part_size_lba =
3519f988b79SJean-Baptiste Boric 			UDF_ROUNDDOWN(layout.meta_part_size_lba, layout.meta_blockingnr);
3529f988b79SJean-Baptiste Boric 
3539f988b79SJean-Baptiste Boric 		/* calculate positions */
3549f988b79SJean-Baptiste Boric 		bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
3559f988b79SJean-Baptiste Boric 		layout.meta_bitmap_dscr_size = udf_bytes_to_sectors(bytes);
3569f988b79SJean-Baptiste Boric 
3579f988b79SJean-Baptiste Boric 		layout.meta_bitmap_space = pos;
3589f988b79SJean-Baptiste Boric 		pos += layout.meta_bitmap_dscr_size;
3599f988b79SJean-Baptiste Boric 
3609f988b79SJean-Baptiste Boric 		layout.meta_part_start_lba  = UDF_ROUNDUP(pos, layout.meta_alignment);
3619f988b79SJean-Baptiste Boric 	}
3629f988b79SJean-Baptiste Boric 
3639f988b79SJean-Baptiste Boric 	mpos = (context.metadata_part == context.data_part) ? pos : 0;
3649f988b79SJean-Baptiste Boric 	layout.fsd           = mpos;	mpos += 1;
3659f988b79SJean-Baptiste Boric 	layout.rootdir       = mpos;	mpos += 1;
3669f988b79SJean-Baptiste Boric 	layout.vat           = mpos;	mpos += 1;	/* if present */
3679f988b79SJean-Baptiste Boric 
3689f988b79SJean-Baptiste Boric #if 0
3699f988b79SJean-Baptiste Boric 	printf("Summary so far\n");
3709f988b79SJean-Baptiste Boric 	printf("\tiso9660_vrs\t\t%d\n", layout.iso9660_vrs);
3719f988b79SJean-Baptiste Boric 	printf("\tanchor0\t\t\t%d\n", layout.anchors[0]);
3729f988b79SJean-Baptiste Boric 	printf("\tanchor1\t\t\t%d\n", layout.anchors[1]);
3739f988b79SJean-Baptiste Boric 	printf("\tanchor2\t\t\t%d\n", layout.anchors[2]);
3749f988b79SJean-Baptiste Boric 	printf("\tvds_size\t\t%d\n", layout.vds_size);
3759f988b79SJean-Baptiste Boric 	printf("\tvds1\t\t\t%d\n", layout.vds1);
3769f988b79SJean-Baptiste Boric 	printf("\tvds2\t\t\t%d\n", layout.vds2);
3779f988b79SJean-Baptiste Boric 	printf("\tlvis_size\t\t%d\n", layout.lvis_size);
3789f988b79SJean-Baptiste Boric 	printf("\tlvis\t\t\t%d\n", layout.lvis);
3799f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_SPARABLE) {
3809f988b79SJean-Baptiste Boric 		printf("\tsparable size\t\t%d\n", layout.sparable_area_size);
3819f988b79SJean-Baptiste Boric 		printf("\tsparable\t\t%d\n", layout.sparable_area);
3829f988b79SJean-Baptiste Boric 	}
3839f988b79SJean-Baptiste Boric 	printf("\tpartition start lba\t%d\n", layout.part_start_lba);
3849f988b79SJean-Baptiste Boric 	printf("\tpartition size\t\t%d KiB, %d MiB\n",
3859f988b79SJean-Baptiste Boric 		(layout.part_size_lba * sector_size) / 1024,
3869f988b79SJean-Baptiste Boric 		(layout.part_size_lba * sector_size) / (1024*1024));
3879f988b79SJean-Baptiste Boric 	if ((format_flags & FORMAT_SEQUENTIAL) == 0) {
3889f988b79SJean-Baptiste Boric 		printf("\tpart bitmap start\t%d\n",   layout.unalloc_space);
3899f988b79SJean-Baptiste Boric 		printf("\t\tfor %d lba\n", layout.alloc_bitmap_dscr_size);
3909f988b79SJean-Baptiste Boric 	}
3919f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_META) {
3929f988b79SJean-Baptiste Boric 		printf("\tmeta blockingnr\t\t%d\n", layout.meta_blockingnr);
3939f988b79SJean-Baptiste Boric 		printf("\tmeta alignment\t\t%d\n",  layout.meta_alignment);
3949f988b79SJean-Baptiste Boric 		printf("\tmeta size\t\t%d KiB, %d MiB\n",
3959f988b79SJean-Baptiste Boric 			(layout.meta_part_size_lba * sector_size) / 1024,
3969f988b79SJean-Baptiste Boric 			(layout.meta_part_size_lba * sector_size) / (1024*1024));
3979f988b79SJean-Baptiste Boric 		printf("\tmeta file\t\t%d\n", layout.meta_file);
3989f988b79SJean-Baptiste Boric 		printf("\tmeta mirror\t\t%d\n", layout.meta_mirror);
3999f988b79SJean-Baptiste Boric 		printf("\tmeta bitmap\t\t%d\n", layout.meta_bitmap);
4009f988b79SJean-Baptiste Boric 		printf("\tmeta bitmap start\t%d\n", layout.meta_bitmap_space);
4019f988b79SJean-Baptiste Boric 		printf("\t\tfor %d lba\n", layout.meta_bitmap_dscr_size);
4029f988b79SJean-Baptiste Boric 		printf("\tmeta space start\t%d\n",  layout.meta_part_start_lba);
4039f988b79SJean-Baptiste Boric 		printf("\t\tfor %d lba\n", layout.meta_part_size_lba);
4049f988b79SJean-Baptiste Boric 	}
4059f988b79SJean-Baptiste Boric 	printf("\n");
4069f988b79SJean-Baptiste Boric #endif
4079f988b79SJean-Baptiste Boric 
4089f988b79SJean-Baptiste Boric 	kbsize = (uint64_t) last_lba * sector_size;
4099f988b79SJean-Baptiste Boric 	printf("Total space on this medium approx. "
4109f988b79SJean-Baptiste Boric 			"%"PRIu64" KiB, %"PRIu64" MiB\n",
4119f988b79SJean-Baptiste Boric 			kbsize/1024, kbsize/(1024*1024));
4129f988b79SJean-Baptiste Boric 	kbsize = (uint64_t)(layout.part_size_lba - layout.alloc_bitmap_dscr_size
4139f988b79SJean-Baptiste Boric 		- layout.meta_bitmap_dscr_size) * sector_size;
4149f988b79SJean-Baptiste Boric 	printf("Free space on this volume approx.  "
4159f988b79SJean-Baptiste Boric 			"%"PRIu64" KiB, %"PRIu64" MiB\n\n",
4169f988b79SJean-Baptiste Boric 			kbsize/1024, kbsize/(1024*1024));
4179f988b79SJean-Baptiste Boric 
4189f988b79SJean-Baptiste Boric 	return 0;
4199f988b79SJean-Baptiste Boric }
4209f988b79SJean-Baptiste Boric 
4219f988b79SJean-Baptiste Boric 
4229f988b79SJean-Baptiste Boric int
udf_validate_tag_sum(union dscrptr * dscr)4239f988b79SJean-Baptiste Boric udf_validate_tag_sum(union dscrptr *dscr)
4249f988b79SJean-Baptiste Boric {
4259f988b79SJean-Baptiste Boric 	struct desc_tag *tag = &dscr->tag;
4269f988b79SJean-Baptiste Boric 	uint8_t *pos, sum, cnt;
4279f988b79SJean-Baptiste Boric 
4289f988b79SJean-Baptiste Boric 	/* calculate TAG header checksum */
4299f988b79SJean-Baptiste Boric 	pos = (uint8_t *) tag;
4309f988b79SJean-Baptiste Boric 	sum = 0;
4319f988b79SJean-Baptiste Boric 
4329f988b79SJean-Baptiste Boric 	for(cnt = 0; cnt < 16; cnt++) {
4339f988b79SJean-Baptiste Boric 		if (cnt != 4) sum += *pos;
4349f988b79SJean-Baptiste Boric 		pos++;
4359f988b79SJean-Baptiste Boric 	};
4369f988b79SJean-Baptiste Boric 	tag->cksum = sum;	/* 8 bit */
4379f988b79SJean-Baptiste Boric 
4389f988b79SJean-Baptiste Boric 	return 0;
4399f988b79SJean-Baptiste Boric }
4409f988b79SJean-Baptiste Boric 
4419f988b79SJean-Baptiste Boric 
4429f988b79SJean-Baptiste Boric /* assumes sector number of descriptor to be allready present */
4439f988b79SJean-Baptiste Boric int
udf_validate_tag_and_crc_sums(union dscrptr * dscr)4449f988b79SJean-Baptiste Boric udf_validate_tag_and_crc_sums(union dscrptr *dscr)
4459f988b79SJean-Baptiste Boric {
4469f988b79SJean-Baptiste Boric 	struct desc_tag *tag = &dscr->tag;
4479f988b79SJean-Baptiste Boric 	uint16_t crc;
4489f988b79SJean-Baptiste Boric 
4499f988b79SJean-Baptiste Boric 	/* check payload CRC if applicable */
4509f988b79SJean-Baptiste Boric 	if (udf_rw16(tag->desc_crc_len) > 0) {
4519f988b79SJean-Baptiste Boric 		crc = udf_cksum(((uint8_t *) tag) + UDF_DESC_TAG_LENGTH,
4529f988b79SJean-Baptiste Boric 			udf_rw16(tag->desc_crc_len));
4539f988b79SJean-Baptiste Boric 		tag->desc_crc = udf_rw16(crc);
4549f988b79SJean-Baptiste Boric 	};
4559f988b79SJean-Baptiste Boric 
4569f988b79SJean-Baptiste Boric 	/* calculate TAG header checksum */
4579f988b79SJean-Baptiste Boric 	return udf_validate_tag_sum(dscr);
4589f988b79SJean-Baptiste Boric }
4599f988b79SJean-Baptiste Boric 
4609f988b79SJean-Baptiste Boric 
4619f988b79SJean-Baptiste Boric void
udf_inittag(struct desc_tag * tag,int tagid,uint32_t loc)4629f988b79SJean-Baptiste Boric udf_inittag(struct desc_tag *tag, int tagid, uint32_t loc)
4639f988b79SJean-Baptiste Boric {
4649f988b79SJean-Baptiste Boric 	tag->id 		= udf_rw16(tagid);
4659f988b79SJean-Baptiste Boric 	tag->descriptor_ver	= udf_rw16(context.dscrver);
4669f988b79SJean-Baptiste Boric 	tag->cksum		= 0;
4679f988b79SJean-Baptiste Boric 	tag->reserved		= 0;
4689f988b79SJean-Baptiste Boric 	tag->serial_num		= udf_rw16(context.serialnum);
4699f988b79SJean-Baptiste Boric 	tag->tag_loc            = udf_rw32(loc);
4709f988b79SJean-Baptiste Boric }
4719f988b79SJean-Baptiste Boric 
4729f988b79SJean-Baptiste Boric 
4739f988b79SJean-Baptiste Boric int
udf_create_anchor(int num)4749f988b79SJean-Baptiste Boric udf_create_anchor(int num)
4759f988b79SJean-Baptiste Boric {
4769f988b79SJean-Baptiste Boric 	struct anchor_vdp *avdp;
4779f988b79SJean-Baptiste Boric 	uint32_t vds_extent_len = layout.vds_size * context.sector_size;
4789f988b79SJean-Baptiste Boric 
4799f988b79SJean-Baptiste Boric 	if ((avdp = calloc(1, context.sector_size)) == NULL)
4809f988b79SJean-Baptiste Boric 		return ENOMEM;
4819f988b79SJean-Baptiste Boric 
4829f988b79SJean-Baptiste Boric 	udf_inittag(&avdp->tag, TAGID_ANCHOR, layout.anchors[num]);
4839f988b79SJean-Baptiste Boric 
4849f988b79SJean-Baptiste Boric 	avdp->main_vds_ex.loc = udf_rw32(layout.vds1);
4859f988b79SJean-Baptiste Boric 	avdp->main_vds_ex.len = udf_rw32(vds_extent_len);
4869f988b79SJean-Baptiste Boric 
4879f988b79SJean-Baptiste Boric 	avdp->reserve_vds_ex.loc = udf_rw32(layout.vds2);
4889f988b79SJean-Baptiste Boric 	avdp->reserve_vds_ex.len = udf_rw32(vds_extent_len);
4899f988b79SJean-Baptiste Boric 
4909f988b79SJean-Baptiste Boric 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
4919f988b79SJean-Baptiste Boric 	avdp->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
4929f988b79SJean-Baptiste Boric 
4939f988b79SJean-Baptiste Boric 	context.anchors[num] = avdp;
4949f988b79SJean-Baptiste Boric 	return 0;
4959f988b79SJean-Baptiste Boric }
4969f988b79SJean-Baptiste Boric 
4979f988b79SJean-Baptiste Boric 
4989f988b79SJean-Baptiste Boric void
udf_create_terminator(union dscrptr * dscr,uint32_t loc)4999f988b79SJean-Baptiste Boric udf_create_terminator(union dscrptr *dscr, uint32_t loc)
5009f988b79SJean-Baptiste Boric {
5019f988b79SJean-Baptiste Boric 	memset(dscr, 0, context.sector_size);
5029f988b79SJean-Baptiste Boric 	udf_inittag(&dscr->tag, TAGID_TERM, loc);
5039f988b79SJean-Baptiste Boric 
5049f988b79SJean-Baptiste Boric 	/* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
5059f988b79SJean-Baptiste Boric 	dscr->tag.desc_crc_len = udf_rw16(512-UDF_DESC_TAG_LENGTH);
5069f988b79SJean-Baptiste Boric }
5079f988b79SJean-Baptiste Boric 
5089f988b79SJean-Baptiste Boric 
5099f988b79SJean-Baptiste Boric void
udf_osta_charset(struct charspec * charspec)5109f988b79SJean-Baptiste Boric udf_osta_charset(struct charspec *charspec)
5119f988b79SJean-Baptiste Boric {
5129f988b79SJean-Baptiste Boric 	memset(charspec, 0, sizeof(*charspec));
5139f988b79SJean-Baptiste Boric 	charspec->type = 0;
5149f988b79SJean-Baptiste Boric 	strcpy((char *) charspec->inf, "OSTA Compressed Unicode");
5159f988b79SJean-Baptiste Boric }
5169f988b79SJean-Baptiste Boric 
5179f988b79SJean-Baptiste Boric 
5189f988b79SJean-Baptiste Boric void
udf_encode_osta_id(char * osta_id,uint16_t len,char * text)5199f988b79SJean-Baptiste Boric udf_encode_osta_id(char *osta_id, uint16_t len, char *text)
5209f988b79SJean-Baptiste Boric {
5219f988b79SJean-Baptiste Boric 	uint16_t  u16_name[1024];
5229f988b79SJean-Baptiste Boric 	uint8_t  *pos;
5239f988b79SJean-Baptiste Boric 	uint16_t *pos16;
5249f988b79SJean-Baptiste Boric 
5259f988b79SJean-Baptiste Boric 	memset(osta_id, 0, len);
5269f988b79SJean-Baptiste Boric 	if (!text || (strlen(text) == 0)) return;
5279f988b79SJean-Baptiste Boric 
5289f988b79SJean-Baptiste Boric 	memset(u16_name, 0, sizeof(uint16_t) * 1023);
5299f988b79SJean-Baptiste Boric 
5309f988b79SJean-Baptiste Boric 	/* convert ascii to 16 bits unicode */
5319f988b79SJean-Baptiste Boric 	pos   = (uint8_t *) text;
5329f988b79SJean-Baptiste Boric 	pos16 = u16_name;
5339f988b79SJean-Baptiste Boric 	while (*pos) {
5349f988b79SJean-Baptiste Boric 		*pos16 = *pos;
5359f988b79SJean-Baptiste Boric 		pos++; pos16++;
5369f988b79SJean-Baptiste Boric 	};
5379f988b79SJean-Baptiste Boric 	*pos16 = 0;
5389f988b79SJean-Baptiste Boric 
5399f988b79SJean-Baptiste Boric 	udf_CompressUnicode(len, 8, (unicode_t *) u16_name, (byte *) osta_id);
5409f988b79SJean-Baptiste Boric 
5419f988b79SJean-Baptiste Boric 	/* Ecma 167/7.2.13 states that length is recorded in the last byte */
5429f988b79SJean-Baptiste Boric 	osta_id[len-1] = strlen(text)+1;
5439f988b79SJean-Baptiste Boric }
5449f988b79SJean-Baptiste Boric 
5459f988b79SJean-Baptiste Boric 
5469f988b79SJean-Baptiste Boric /* first call udf_set_regid and then the suffix */
5479f988b79SJean-Baptiste Boric void
udf_set_regid(struct regid * regid,char const * name)5489f988b79SJean-Baptiste Boric udf_set_regid(struct regid *regid, char const *name)
5499f988b79SJean-Baptiste Boric {
5509f988b79SJean-Baptiste Boric 	memset(regid, 0, sizeof(*regid));
5519f988b79SJean-Baptiste Boric 	regid->flags    = 0;		/* not dirty and not protected */
5529f988b79SJean-Baptiste Boric 	strcpy((char *) regid->id, name);
5539f988b79SJean-Baptiste Boric }
5549f988b79SJean-Baptiste Boric 
5559f988b79SJean-Baptiste Boric 
5569f988b79SJean-Baptiste Boric void
udf_add_domain_regid(struct regid * regid)5579f988b79SJean-Baptiste Boric udf_add_domain_regid(struct regid *regid)
5589f988b79SJean-Baptiste Boric {
5599f988b79SJean-Baptiste Boric 	uint16_t *ver;
5609f988b79SJean-Baptiste Boric 
5619f988b79SJean-Baptiste Boric 	ver  = (uint16_t *) regid->id_suffix;
5629f988b79SJean-Baptiste Boric 	*ver = udf_rw16(context.min_udf);
5639f988b79SJean-Baptiste Boric }
5649f988b79SJean-Baptiste Boric 
5659f988b79SJean-Baptiste Boric 
5669f988b79SJean-Baptiste Boric void
udf_add_udf_regid(struct regid * regid)5679f988b79SJean-Baptiste Boric udf_add_udf_regid(struct regid *regid)
5689f988b79SJean-Baptiste Boric {
5699f988b79SJean-Baptiste Boric 	uint16_t *ver;
5709f988b79SJean-Baptiste Boric 
5719f988b79SJean-Baptiste Boric 	ver  = (uint16_t *) regid->id_suffix;
5729f988b79SJean-Baptiste Boric 	*ver = udf_rw16(context.min_udf);
5739f988b79SJean-Baptiste Boric 
5749f988b79SJean-Baptiste Boric 	regid->id_suffix[2] = 4;	/* unix */
5759f988b79SJean-Baptiste Boric 	regid->id_suffix[3] = 8;	/* NetBSD */
5769f988b79SJean-Baptiste Boric }
5779f988b79SJean-Baptiste Boric 
5789f988b79SJean-Baptiste Boric 
5799f988b79SJean-Baptiste Boric void
udf_add_impl_regid(struct regid * regid)5809f988b79SJean-Baptiste Boric udf_add_impl_regid(struct regid *regid)
5819f988b79SJean-Baptiste Boric {
5829f988b79SJean-Baptiste Boric 	regid->id_suffix[0] = 4;	/* unix */
5839f988b79SJean-Baptiste Boric 	regid->id_suffix[1] = 8;	/* NetBSD */
5849f988b79SJean-Baptiste Boric }
5859f988b79SJean-Baptiste Boric 
5869f988b79SJean-Baptiste Boric 
5879f988b79SJean-Baptiste Boric void
udf_add_app_regid(struct regid * regid)5889f988b79SJean-Baptiste Boric udf_add_app_regid(struct regid *regid)
5899f988b79SJean-Baptiste Boric {
5909f988b79SJean-Baptiste Boric 	regid->id_suffix[0] = context.app_version_main;
5919f988b79SJean-Baptiste Boric 	regid->id_suffix[1] = context.app_version_sub;
5929f988b79SJean-Baptiste Boric }
5939f988b79SJean-Baptiste Boric 
5949f988b79SJean-Baptiste Boric 
5959f988b79SJean-Baptiste Boric /*
5969f988b79SJean-Baptiste Boric  * Fill in timestamp structure based on clock_gettime(). Time is reported back
5979f988b79SJean-Baptiste Boric  * as a time_t accompanied with a nano second field.
5989f988b79SJean-Baptiste Boric  *
5999f988b79SJean-Baptiste Boric  * The husec, usec and csec could be relaxed in type.
6009f988b79SJean-Baptiste Boric  */
6019f988b79SJean-Baptiste Boric static void
udf_timespec_to_timestamp(struct timespec * timespec,struct timestamp * timestamp)6029f988b79SJean-Baptiste Boric udf_timespec_to_timestamp(struct timespec *timespec, struct timestamp *timestamp)
6039f988b79SJean-Baptiste Boric {
6049f988b79SJean-Baptiste Boric 	struct tm tm;
6059f988b79SJean-Baptiste Boric 	uint64_t husec, usec, csec;
6069f988b79SJean-Baptiste Boric 
6079f988b79SJean-Baptiste Boric 	memset(timestamp, 0, sizeof(*timestamp));
6089f988b79SJean-Baptiste Boric 	gmtime_r(&timespec->tv_sec, &tm);
6099f988b79SJean-Baptiste Boric 
6109f988b79SJean-Baptiste Boric 	/*
6119f988b79SJean-Baptiste Boric 	 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
6129f988b79SJean-Baptiste Boric 	 *
6139f988b79SJean-Baptiste Boric 	 * Lower 12 bits are two complement signed timezone offset if bit 12
6149f988b79SJean-Baptiste Boric 	 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
6159f988b79SJean-Baptiste Boric 	 * offset to -2047 i.e. unsigned `zero'
6169f988b79SJean-Baptiste Boric 	 */
6179f988b79SJean-Baptiste Boric 
6189f988b79SJean-Baptiste Boric 	/* set method 1 for CUT/GMT */
6199f988b79SJean-Baptiste Boric 	timestamp->type_tz	= udf_rw16((1<<12) + 0);
6209f988b79SJean-Baptiste Boric 	timestamp->year		= udf_rw16(tm.tm_year + 1900);
6219f988b79SJean-Baptiste Boric 	timestamp->month	= tm.tm_mon + 1;	/* `tm' uses 0..11 for months */
6229f988b79SJean-Baptiste Boric 	timestamp->day		= tm.tm_mday;
6239f988b79SJean-Baptiste Boric 	timestamp->hour		= tm.tm_hour;
6249f988b79SJean-Baptiste Boric 	timestamp->minute	= tm.tm_min;
6259f988b79SJean-Baptiste Boric 	timestamp->second	= tm.tm_sec;
6269f988b79SJean-Baptiste Boric 
6279f988b79SJean-Baptiste Boric 	usec   = (timespec->tv_nsec + 500) / 1000;	/* round */
6289f988b79SJean-Baptiste Boric 	husec  =   usec / 100;
6299f988b79SJean-Baptiste Boric 	usec  -=  husec * 100;				/* only 0-99 in usec  */
6309f988b79SJean-Baptiste Boric 	csec   =  husec / 100;				/* only 0-99 in csec  */
6319f988b79SJean-Baptiste Boric 	husec -=   csec * 100;				/* only 0-99 in husec */
6329f988b79SJean-Baptiste Boric 
6339f988b79SJean-Baptiste Boric 	/* in rare cases there is overflow in csec */
6349f988b79SJean-Baptiste Boric 	csec  = MIN(99, csec);
6359f988b79SJean-Baptiste Boric 	husec = MIN(99, husec);
6369f988b79SJean-Baptiste Boric 	usec  = MIN(99, usec);
6379f988b79SJean-Baptiste Boric 
6389f988b79SJean-Baptiste Boric 	timestamp->centisec	= csec;
6399f988b79SJean-Baptiste Boric 	timestamp->hund_usec	= husec;
6409f988b79SJean-Baptiste Boric 	timestamp->usec		= usec;
6419f988b79SJean-Baptiste Boric }
6429f988b79SJean-Baptiste Boric 
6439f988b79SJean-Baptiste Boric 
6449f988b79SJean-Baptiste Boric void
udf_set_timestamp_now(struct timestamp * timestamp)6459f988b79SJean-Baptiste Boric udf_set_timestamp_now(struct timestamp *timestamp)
6469f988b79SJean-Baptiste Boric {
6479f988b79SJean-Baptiste Boric 	struct timespec now;
6489f988b79SJean-Baptiste Boric 
6499f988b79SJean-Baptiste Boric #ifdef CLOCK_REALTIME
6509f988b79SJean-Baptiste Boric 	(void)clock_gettime(CLOCK_REALTIME, &now);
6519f988b79SJean-Baptiste Boric #else
6529f988b79SJean-Baptiste Boric 	struct timeval time_of_day;
6539f988b79SJean-Baptiste Boric 
6549f988b79SJean-Baptiste Boric 	(void)gettimeofday(&time_of_day, NULL);
6559f988b79SJean-Baptiste Boric 	now.tv_sec = time_of_day.tv_sec;
6569f988b79SJean-Baptiste Boric 	now.tv_nsec = time_of_day.tv_usec * 1000;
6579f988b79SJean-Baptiste Boric #endif
6589f988b79SJean-Baptiste Boric 	udf_timespec_to_timestamp(&now, timestamp);
6599f988b79SJean-Baptiste Boric }
6609f988b79SJean-Baptiste Boric 
6619f988b79SJean-Baptiste Boric 
6629f988b79SJean-Baptiste Boric /* some code copied from sys/fs/udf */
6639f988b79SJean-Baptiste Boric 
6649f988b79SJean-Baptiste Boric static void
udf_set_timestamp(struct timestamp * timestamp,time_t value)6659f988b79SJean-Baptiste Boric udf_set_timestamp(struct timestamp *timestamp, time_t value)
6669f988b79SJean-Baptiste Boric {
6679f988b79SJean-Baptiste Boric 	struct timespec t;
6689f988b79SJean-Baptiste Boric 
6699f988b79SJean-Baptiste Boric 	memset(&t, 0, sizeof(struct timespec));
6709f988b79SJean-Baptiste Boric 	t.tv_sec  = value;
6719f988b79SJean-Baptiste Boric 	t.tv_nsec = 0;
6729f988b79SJean-Baptiste Boric 	udf_timespec_to_timestamp(&t, timestamp);
6739f988b79SJean-Baptiste Boric }
6749f988b79SJean-Baptiste Boric 
6759f988b79SJean-Baptiste Boric 
6769f988b79SJean-Baptiste Boric static uint32_t
unix_mode_to_udf_perm(mode_t mode)6779f988b79SJean-Baptiste Boric unix_mode_to_udf_perm(mode_t mode)
6789f988b79SJean-Baptiste Boric {
6799f988b79SJean-Baptiste Boric 	uint32_t perm;
6809f988b79SJean-Baptiste Boric 
6819f988b79SJean-Baptiste Boric 	perm  = ((mode & S_IRWXO)     );
6829f988b79SJean-Baptiste Boric 	perm |= ((mode & S_IRWXG) << 2);
6839f988b79SJean-Baptiste Boric 	perm |= ((mode & S_IRWXU) << 4);
6849f988b79SJean-Baptiste Boric 	perm |= ((mode & S_IWOTH) << 3);
6859f988b79SJean-Baptiste Boric 	perm |= ((mode & S_IWGRP) << 5);
6869f988b79SJean-Baptiste Boric 	perm |= ((mode & S_IWUSR) << 7);
6879f988b79SJean-Baptiste Boric 
6889f988b79SJean-Baptiste Boric 	return perm;
6899f988b79SJean-Baptiste Boric }
6909f988b79SJean-Baptiste Boric 
6919f988b79SJean-Baptiste Boric /* end of copied code */
6929f988b79SJean-Baptiste Boric 
6939f988b79SJean-Baptiste Boric 
6949f988b79SJean-Baptiste Boric int
udf_create_primaryd(void)6959f988b79SJean-Baptiste Boric udf_create_primaryd(void)
6969f988b79SJean-Baptiste Boric {
6979f988b79SJean-Baptiste Boric 	struct pri_vol_desc *pri;
6989f988b79SJean-Baptiste Boric 	uint16_t crclen;
6999f988b79SJean-Baptiste Boric 
7009f988b79SJean-Baptiste Boric 	pri = calloc(1, context.sector_size);
7019f988b79SJean-Baptiste Boric 	if (pri == NULL)
7029f988b79SJean-Baptiste Boric 		return ENOMEM;
7039f988b79SJean-Baptiste Boric 
7049f988b79SJean-Baptiste Boric 	memset(pri, 0, context.sector_size);
7059f988b79SJean-Baptiste Boric 	udf_inittag(&pri->tag, TAGID_PRI_VOL, /* loc */ 0);
7069f988b79SJean-Baptiste Boric 	pri->seq_num = udf_rw32(context.vds_seq); context.vds_seq++;
7079f988b79SJean-Baptiste Boric 
7089f988b79SJean-Baptiste Boric 	pri->pvd_num = udf_rw32(0);		/* default serial */
7099f988b79SJean-Baptiste Boric 	udf_encode_osta_id(pri->vol_id, 32, context.primary_name);
7109f988b79SJean-Baptiste Boric 
7119f988b79SJean-Baptiste Boric 	/* set defaults for single disc volumes as UDF prescribes */
7129f988b79SJean-Baptiste Boric 	pri->vds_num      = udf_rw16(1);
7139f988b79SJean-Baptiste Boric 	pri->max_vol_seq  = udf_rw16(1);
7149f988b79SJean-Baptiste Boric 	pri->ichg_lvl     = udf_rw16(2);
7159f988b79SJean-Baptiste Boric 	pri->max_ichg_lvl = udf_rw16(3);
7169f988b79SJean-Baptiste Boric 	pri->flags        = udf_rw16(0);
7179f988b79SJean-Baptiste Boric 
7189f988b79SJean-Baptiste Boric 	pri->charset_list     = udf_rw32(1);	/* only CS0 */
7199f988b79SJean-Baptiste Boric 	pri->max_charset_list = udf_rw32(1);	/* only CS0 */
7209f988b79SJean-Baptiste Boric 
7219f988b79SJean-Baptiste Boric 	udf_encode_osta_id(pri->volset_id, 128, context.volset_name);
7229f988b79SJean-Baptiste Boric 	udf_osta_charset(&pri->desc_charset);
7239f988b79SJean-Baptiste Boric 	udf_osta_charset(&pri->explanatory_charset);
7249f988b79SJean-Baptiste Boric 
7259f988b79SJean-Baptiste Boric 	udf_set_regid(&pri->app_id, context.app_name);
7269f988b79SJean-Baptiste Boric 	udf_add_app_regid(&pri->app_id);
7279f988b79SJean-Baptiste Boric 
7289f988b79SJean-Baptiste Boric 	udf_set_regid(&pri->imp_id, context.impl_name);
7299f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&pri->imp_id);
7309f988b79SJean-Baptiste Boric 
7319f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&pri->time);
7329f988b79SJean-Baptiste Boric 
7339f988b79SJean-Baptiste Boric 	crclen = sizeof(struct pri_vol_desc) - UDF_DESC_TAG_LENGTH;
7349f988b79SJean-Baptiste Boric 	pri->tag.desc_crc_len = udf_rw16(crclen);
7359f988b79SJean-Baptiste Boric 
7369f988b79SJean-Baptiste Boric 	context.primary_vol = pri;
7379f988b79SJean-Baptiste Boric 
7389f988b79SJean-Baptiste Boric 	return 0;
7399f988b79SJean-Baptiste Boric }
7409f988b79SJean-Baptiste Boric 
7419f988b79SJean-Baptiste Boric 
7429f988b79SJean-Baptiste Boric /* XXX no support for unallocated or freed space tables yet (!) */
7439f988b79SJean-Baptiste Boric int
udf_create_partitiond(int part_num,int part_accesstype)7449f988b79SJean-Baptiste Boric udf_create_partitiond(int part_num, int part_accesstype)
7459f988b79SJean-Baptiste Boric {
7469f988b79SJean-Baptiste Boric 	struct part_desc     *pd;
7479f988b79SJean-Baptiste Boric 	struct part_hdr_desc *phd;
7489f988b79SJean-Baptiste Boric 	uint32_t sector_size, bitmap_bytes;
7499f988b79SJean-Baptiste Boric 	uint16_t crclen;
7509f988b79SJean-Baptiste Boric 
7519f988b79SJean-Baptiste Boric 	sector_size = context.sector_size;
7529f988b79SJean-Baptiste Boric 	bitmap_bytes = layout.alloc_bitmap_dscr_size * sector_size;
7539f988b79SJean-Baptiste Boric 
7549f988b79SJean-Baptiste Boric 	if (context.partitions[part_num]) {
7559f988b79SJean-Baptiste Boric 		printf("Internal error: partition %d allready defined\n",
7569f988b79SJean-Baptiste Boric 			part_num);
7579f988b79SJean-Baptiste Boric 		return EINVAL;
7589f988b79SJean-Baptiste Boric 	}
7599f988b79SJean-Baptiste Boric 
7609f988b79SJean-Baptiste Boric 	pd = calloc(1, context.sector_size);
7619f988b79SJean-Baptiste Boric 	if (pd == NULL)
7629f988b79SJean-Baptiste Boric 		return ENOMEM;
7639f988b79SJean-Baptiste Boric 	phd = &pd->_impl_use.part_hdr;
7649f988b79SJean-Baptiste Boric 
7659f988b79SJean-Baptiste Boric 	udf_inittag(&pd->tag, TAGID_PARTITION, /* loc */ 0);
7669f988b79SJean-Baptiste Boric 	pd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
7679f988b79SJean-Baptiste Boric 
7689f988b79SJean-Baptiste Boric 	pd->flags    = udf_rw16(1);		/* allocated */
7699f988b79SJean-Baptiste Boric 	pd->part_num = udf_rw16(part_num);	/* only one physical partition */
7709f988b79SJean-Baptiste Boric 
7719f988b79SJean-Baptiste Boric 	if (context.dscrver == 2) {
7729f988b79SJean-Baptiste Boric 		udf_set_regid(&pd->contents, "+NSR02");
7739f988b79SJean-Baptiste Boric 	} else {
7749f988b79SJean-Baptiste Boric 		udf_set_regid(&pd->contents, "+NSR03");
7759f988b79SJean-Baptiste Boric 	}
7769f988b79SJean-Baptiste Boric 	udf_add_app_regid(&pd->contents);
7779f988b79SJean-Baptiste Boric 
7789f988b79SJean-Baptiste Boric 	phd->unalloc_space_bitmap.len    = udf_rw32(bitmap_bytes);
7799f988b79SJean-Baptiste Boric 	phd->unalloc_space_bitmap.lb_num = udf_rw32(layout.unalloc_space);
7809f988b79SJean-Baptiste Boric 
7819f988b79SJean-Baptiste Boric 	if (layout.freed_space) {
7829f988b79SJean-Baptiste Boric 		phd->freed_space_bitmap.len    = udf_rw32(bitmap_bytes);
7839f988b79SJean-Baptiste Boric 		phd->freed_space_bitmap.lb_num = udf_rw32(layout.freed_space);
7849f988b79SJean-Baptiste Boric 	}
7859f988b79SJean-Baptiste Boric 
7869f988b79SJean-Baptiste Boric 	pd->access_type = udf_rw32(part_accesstype);
7879f988b79SJean-Baptiste Boric 	pd->start_loc   = udf_rw32(layout.part_start_lba);
7889f988b79SJean-Baptiste Boric 	pd->part_len    = udf_rw32(layout.part_size_lba);
7899f988b79SJean-Baptiste Boric 
7909f988b79SJean-Baptiste Boric 	udf_set_regid(&pd->imp_id, context.impl_name);
7919f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&pd->imp_id);
7929f988b79SJean-Baptiste Boric 
7939f988b79SJean-Baptiste Boric 	crclen = sizeof(struct part_desc) - UDF_DESC_TAG_LENGTH;
7949f988b79SJean-Baptiste Boric 	pd->tag.desc_crc_len = udf_rw16(crclen);
7959f988b79SJean-Baptiste Boric 
7969f988b79SJean-Baptiste Boric 	context.partitions[part_num] = pd;
7979f988b79SJean-Baptiste Boric 
7989f988b79SJean-Baptiste Boric 	return 0;
7999f988b79SJean-Baptiste Boric }
8009f988b79SJean-Baptiste Boric 
8019f988b79SJean-Baptiste Boric 
8029f988b79SJean-Baptiste Boric int
udf_create_unalloc_spaced(void)8039f988b79SJean-Baptiste Boric udf_create_unalloc_spaced(void)
8049f988b79SJean-Baptiste Boric {
8059f988b79SJean-Baptiste Boric 	struct unalloc_sp_desc *usd;
8069f988b79SJean-Baptiste Boric 	uint16_t crclen;
8079f988b79SJean-Baptiste Boric 
8089f988b79SJean-Baptiste Boric 	usd = calloc(1, context.sector_size);
8099f988b79SJean-Baptiste Boric 	if (usd == NULL)
8109f988b79SJean-Baptiste Boric 		return ENOMEM;
8119f988b79SJean-Baptiste Boric 
8129f988b79SJean-Baptiste Boric 	udf_inittag(&usd->tag, TAGID_UNALLOC_SPACE, /* loc */ 0);
8139f988b79SJean-Baptiste Boric 	usd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
8149f988b79SJean-Baptiste Boric 
8159f988b79SJean-Baptiste Boric 	/* no default entries */
8169f988b79SJean-Baptiste Boric 	usd->alloc_desc_num = udf_rw32(0);		/* no entries */
8179f988b79SJean-Baptiste Boric 
8189f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct unalloc_sp_desc) - sizeof(struct extent_ad);
8199f988b79SJean-Baptiste Boric 	crclen -= UDF_DESC_TAG_LENGTH;
8209f988b79SJean-Baptiste Boric 	usd->tag.desc_crc_len = udf_rw16(crclen);
8219f988b79SJean-Baptiste Boric 
8229f988b79SJean-Baptiste Boric 	context.unallocated = usd;
8239f988b79SJean-Baptiste Boric 
8249f988b79SJean-Baptiste Boric 	return 0;
8259f988b79SJean-Baptiste Boric }
8269f988b79SJean-Baptiste Boric 
8279f988b79SJean-Baptiste Boric 
8289f988b79SJean-Baptiste Boric static int
udf_create_base_logical_dscr(void)8299f988b79SJean-Baptiste Boric udf_create_base_logical_dscr(void)
8309f988b79SJean-Baptiste Boric {
8319f988b79SJean-Baptiste Boric 	struct logvol_desc *lvd;
8329f988b79SJean-Baptiste Boric 	uint32_t sector_size;
8339f988b79SJean-Baptiste Boric 	uint16_t crclen;
8349f988b79SJean-Baptiste Boric 
8359f988b79SJean-Baptiste Boric 	sector_size = context.sector_size;
8369f988b79SJean-Baptiste Boric 
8379f988b79SJean-Baptiste Boric 	lvd = calloc(1, sector_size);
8389f988b79SJean-Baptiste Boric 	if (lvd == NULL)
8399f988b79SJean-Baptiste Boric 		return ENOMEM;
8409f988b79SJean-Baptiste Boric 
8419f988b79SJean-Baptiste Boric 	udf_inittag(&lvd->tag, TAGID_LOGVOL, /* loc */ 0);
8429f988b79SJean-Baptiste Boric 	lvd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
8439f988b79SJean-Baptiste Boric 
8449f988b79SJean-Baptiste Boric 	udf_osta_charset(&lvd->desc_charset);
8459f988b79SJean-Baptiste Boric 	udf_encode_osta_id(lvd->logvol_id, 128, context.logvol_name);
8469f988b79SJean-Baptiste Boric 	lvd->lb_size = udf_rw32(context.sector_size);
8479f988b79SJean-Baptiste Boric 
8489f988b79SJean-Baptiste Boric 	udf_set_regid(&lvd->domain_id, "*OSTA UDF Compliant");
8499f988b79SJean-Baptiste Boric 	udf_add_domain_regid(&lvd->domain_id);
8509f988b79SJean-Baptiste Boric 
8519f988b79SJean-Baptiste Boric 	/* no partition mappings/entries yet */
8529f988b79SJean-Baptiste Boric 	lvd->mt_l = udf_rw32(0);
8539f988b79SJean-Baptiste Boric 	lvd->n_pm = udf_rw32(0);
8549f988b79SJean-Baptiste Boric 
8559f988b79SJean-Baptiste Boric 	udf_set_regid(&lvd->imp_id, context.impl_name);
8569f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&lvd->imp_id);
8579f988b79SJean-Baptiste Boric 
8589f988b79SJean-Baptiste Boric 	lvd->integrity_seq_loc.loc = udf_rw32(layout.lvis);
8599f988b79SJean-Baptiste Boric 	lvd->integrity_seq_loc.len = udf_rw32(layout.lvis_size * sector_size);
8609f988b79SJean-Baptiste Boric 
8619f988b79SJean-Baptiste Boric 	/* just one fsd for now */
8629f988b79SJean-Baptiste Boric 	lvd->lv_fsd_loc.len = udf_rw32(sector_size);
8639f988b79SJean-Baptiste Boric 	lvd->lv_fsd_loc.loc.part_num = udf_rw32(context.metadata_part);
8649f988b79SJean-Baptiste Boric 	lvd->lv_fsd_loc.loc.lb_num   = udf_rw32(layout.fsd);
8659f988b79SJean-Baptiste Boric 
8669f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct logvol_desc) - 1 - UDF_DESC_TAG_LENGTH;
8679f988b79SJean-Baptiste Boric 	lvd->tag.desc_crc_len = udf_rw16(crclen);
8689f988b79SJean-Baptiste Boric 
8699f988b79SJean-Baptiste Boric 	context.logical_vol = lvd;
8709f988b79SJean-Baptiste Boric 	context.vtop_tp[UDF_VTOP_RAWPART]      = UDF_VTOP_TYPE_RAW;
8719f988b79SJean-Baptiste Boric 	context.vtop_offset[UDF_VTOP_RAWPART] = 0;
8729f988b79SJean-Baptiste Boric 
8739f988b79SJean-Baptiste Boric 	return 0;
8749f988b79SJean-Baptiste Boric }
8759f988b79SJean-Baptiste Boric 
8769f988b79SJean-Baptiste Boric 
8779f988b79SJean-Baptiste Boric static void
udf_add_logvol_part_physical(uint16_t phys_part)8789f988b79SJean-Baptiste Boric udf_add_logvol_part_physical(uint16_t phys_part)
8799f988b79SJean-Baptiste Boric {
8809f988b79SJean-Baptiste Boric 	struct logvol_desc *logvol = context.logical_vol;
8819f988b79SJean-Baptiste Boric 	union  udf_pmap *pmap;
8829f988b79SJean-Baptiste Boric 	uint8_t         *pmap_pos;
8839f988b79SJean-Baptiste Boric 	uint16_t crclen;
8849f988b79SJean-Baptiste Boric 	uint32_t pmap1_size, log_part;
8859f988b79SJean-Baptiste Boric 
8869f988b79SJean-Baptiste Boric 	log_part = udf_rw32(logvol->n_pm);
8879f988b79SJean-Baptiste Boric 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
8889f988b79SJean-Baptiste Boric 	pmap1_size = sizeof(struct part_map_1);
8899f988b79SJean-Baptiste Boric 
8909f988b79SJean-Baptiste Boric 	pmap = (union udf_pmap *) pmap_pos;
8919f988b79SJean-Baptiste Boric 	pmap->pm1.type        = 1;
8929f988b79SJean-Baptiste Boric 	pmap->pm1.len         = sizeof(struct part_map_1);
8939f988b79SJean-Baptiste Boric 	pmap->pm1.vol_seq_num = udf_rw16(1);		/* no multi-volume */
8949f988b79SJean-Baptiste Boric 	pmap->pm1.part_num    = udf_rw16(phys_part);
8959f988b79SJean-Baptiste Boric 
8969f988b79SJean-Baptiste Boric 	context.vtop       [log_part] = phys_part;
8979f988b79SJean-Baptiste Boric 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_PHYS;
8989f988b79SJean-Baptiste Boric 	context.vtop_offset[log_part] = layout.part_start_lba;
8999f988b79SJean-Baptiste Boric 	context.part_size[log_part] = layout.part_size_lba;
9009f988b79SJean-Baptiste Boric 	context.part_free[log_part] = layout.part_size_lba;
9019f988b79SJean-Baptiste Boric 
9029f988b79SJean-Baptiste Boric 	/* increment number of partitions and length */
9039f988b79SJean-Baptiste Boric 	logvol->n_pm = udf_rw32(log_part + 1);
9049f988b79SJean-Baptiste Boric 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmap1_size);
9059f988b79SJean-Baptiste Boric 
9069f988b79SJean-Baptiste Boric 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmap1_size;
9079f988b79SJean-Baptiste Boric 	logvol->tag.desc_crc_len = udf_rw16(crclen);
9089f988b79SJean-Baptiste Boric }
9099f988b79SJean-Baptiste Boric 
9109f988b79SJean-Baptiste Boric 
9119f988b79SJean-Baptiste Boric static void
udf_add_logvol_part_virtual(uint16_t phys_part)9129f988b79SJean-Baptiste Boric udf_add_logvol_part_virtual(uint16_t phys_part)
9139f988b79SJean-Baptiste Boric {
9149f988b79SJean-Baptiste Boric 	union  udf_pmap *pmap;
9159f988b79SJean-Baptiste Boric 	struct logvol_desc *logvol = context.logical_vol;
9169f988b79SJean-Baptiste Boric 	uint8_t *pmap_pos;
9179f988b79SJean-Baptiste Boric 	uint16_t crclen;
9189f988b79SJean-Baptiste Boric 	uint32_t pmapv_size, log_part;
9199f988b79SJean-Baptiste Boric 
9209f988b79SJean-Baptiste Boric 	log_part = udf_rw32(logvol->n_pm);
9219f988b79SJean-Baptiste Boric 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
9229f988b79SJean-Baptiste Boric 	pmapv_size = sizeof(struct part_map_2);
9239f988b79SJean-Baptiste Boric 
9249f988b79SJean-Baptiste Boric 	pmap = (union udf_pmap *) pmap_pos;
9259f988b79SJean-Baptiste Boric 	pmap->pmv.type        = 2;
9269f988b79SJean-Baptiste Boric 	pmap->pmv.len         = pmapv_size;
9279f988b79SJean-Baptiste Boric 
9289f988b79SJean-Baptiste Boric 	udf_set_regid(&pmap->pmv.id, "*UDF Virtual Partition");
9299f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&pmap->pmv.id);
9309f988b79SJean-Baptiste Boric 
9319f988b79SJean-Baptiste Boric 	pmap->pmv.vol_seq_num = udf_rw16(1);		/* no multi-volume */
9329f988b79SJean-Baptiste Boric 	pmap->pmv.part_num    = udf_rw16(phys_part);
9339f988b79SJean-Baptiste Boric 
9349f988b79SJean-Baptiste Boric 	context.vtop       [log_part] = phys_part;
9359f988b79SJean-Baptiste Boric 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_VIRT;
9369f988b79SJean-Baptiste Boric 	context.vtop_offset[log_part] = context.vtop_offset[phys_part];
9379f988b79SJean-Baptiste Boric 	context.part_size[log_part] = 0xffffffff;
9389f988b79SJean-Baptiste Boric 	context.part_free[log_part] = 0xffffffff;
9399f988b79SJean-Baptiste Boric 
9409f988b79SJean-Baptiste Boric 	/* increment number of partitions and length */
9419f988b79SJean-Baptiste Boric 	logvol->n_pm = udf_rw32(log_part + 1);
9429f988b79SJean-Baptiste Boric 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
9439f988b79SJean-Baptiste Boric 
9449f988b79SJean-Baptiste Boric 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
9459f988b79SJean-Baptiste Boric 	logvol->tag.desc_crc_len = udf_rw16(crclen);
9469f988b79SJean-Baptiste Boric }
9479f988b79SJean-Baptiste Boric 
9489f988b79SJean-Baptiste Boric 
9499f988b79SJean-Baptiste Boric /* sparing table size is in bytes */
9509f988b79SJean-Baptiste Boric static void
udf_add_logvol_part_sparable(uint16_t phys_part)9519f988b79SJean-Baptiste Boric udf_add_logvol_part_sparable(uint16_t phys_part)
9529f988b79SJean-Baptiste Boric {
9539f988b79SJean-Baptiste Boric 	union  udf_pmap *pmap;
9549f988b79SJean-Baptiste Boric 	struct logvol_desc *logvol = context.logical_vol;
9559f988b79SJean-Baptiste Boric 	uint32_t *st_pos, sparable_bytes, pmaps_size;
9569f988b79SJean-Baptiste Boric 	uint8_t  *pmap_pos, num;
9579f988b79SJean-Baptiste Boric 	uint16_t crclen;
9589f988b79SJean-Baptiste Boric 	uint32_t log_part;
9599f988b79SJean-Baptiste Boric 
9609f988b79SJean-Baptiste Boric 	log_part = udf_rw32(logvol->n_pm);
9619f988b79SJean-Baptiste Boric 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
9629f988b79SJean-Baptiste Boric 	pmaps_size = sizeof(struct part_map_2);
9639f988b79SJean-Baptiste Boric 	sparable_bytes = layout.sparable_area_size * context.sector_size;
9649f988b79SJean-Baptiste Boric 
9659f988b79SJean-Baptiste Boric 	pmap = (union udf_pmap *) pmap_pos;
9669f988b79SJean-Baptiste Boric 	pmap->pms.type        = 2;
9679f988b79SJean-Baptiste Boric 	pmap->pms.len         = pmaps_size;
9689f988b79SJean-Baptiste Boric 
9699f988b79SJean-Baptiste Boric 	udf_set_regid(&pmap->pmv.id, "*UDF Sparable Partition");
9709f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&pmap->pmv.id);
9719f988b79SJean-Baptiste Boric 
9729f988b79SJean-Baptiste Boric 	pmap->pms.vol_seq_num = udf_rw16(1);		/* no multi-volume */
9739f988b79SJean-Baptiste Boric 	pmap->pms.part_num    = udf_rw16(phys_part);
9749f988b79SJean-Baptiste Boric 
9759f988b79SJean-Baptiste Boric 	pmap->pms.packet_len  = udf_rw16(layout.sparable_blockingnr);
9769f988b79SJean-Baptiste Boric 	pmap->pms.st_size     = udf_rw32(sparable_bytes);
9779f988b79SJean-Baptiste Boric 
9789f988b79SJean-Baptiste Boric 	/* enter spare tables  */
9799f988b79SJean-Baptiste Boric 	st_pos = &pmap->pms.st_loc[0];
9809f988b79SJean-Baptiste Boric 	*st_pos++ = udf_rw32(layout.spt_1);
9819f988b79SJean-Baptiste Boric 	*st_pos++ = udf_rw32(layout.spt_2);
9829f988b79SJean-Baptiste Boric 
9839f988b79SJean-Baptiste Boric 	num = 2;
9849f988b79SJean-Baptiste Boric 	if (layout.spt_2 == 0) num--;
9859f988b79SJean-Baptiste Boric 	if (layout.spt_1 == 0) num--;
9869f988b79SJean-Baptiste Boric 	pmap->pms.n_st = num;		/* 8 bit */
9879f988b79SJean-Baptiste Boric 
9889f988b79SJean-Baptiste Boric 	/* the vtop_offset needs to explicitly set since there is no phys. */
9899f988b79SJean-Baptiste Boric 	context.vtop       [log_part] = phys_part;
9909f988b79SJean-Baptiste Boric 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_SPARABLE;
9919f988b79SJean-Baptiste Boric 	context.vtop_offset[log_part] = layout.part_start_lba;
9929f988b79SJean-Baptiste Boric 	context.part_size[log_part] = layout.part_size_lba;
9939f988b79SJean-Baptiste Boric 	context.part_free[log_part] = layout.part_size_lba;
9949f988b79SJean-Baptiste Boric 
9959f988b79SJean-Baptiste Boric 	/* increment number of partitions and length */
9969f988b79SJean-Baptiste Boric 	logvol->n_pm = udf_rw32(log_part + 1);
9979f988b79SJean-Baptiste Boric 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmaps_size);
9989f988b79SJean-Baptiste Boric 
9999f988b79SJean-Baptiste Boric 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmaps_size;
10009f988b79SJean-Baptiste Boric 	logvol->tag.desc_crc_len = udf_rw16(crclen);
10019f988b79SJean-Baptiste Boric }
10029f988b79SJean-Baptiste Boric 
10039f988b79SJean-Baptiste Boric 
10049f988b79SJean-Baptiste Boric int
udf_create_sparing_tabled(void)10059f988b79SJean-Baptiste Boric udf_create_sparing_tabled(void)
10069f988b79SJean-Baptiste Boric {
10079f988b79SJean-Baptiste Boric 	struct udf_sparing_table *spt;
10089f988b79SJean-Baptiste Boric 	struct spare_map_entry   *sme;
10099f988b79SJean-Baptiste Boric 	uint32_t loc, cnt;
10109f988b79SJean-Baptiste Boric 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
10119f988b79SJean-Baptiste Boric 
10129f988b79SJean-Baptiste Boric 	spt = calloc(context.sector_size, layout.sparing_table_dscr_lbas);
10139f988b79SJean-Baptiste Boric 	if (spt == NULL)
10149f988b79SJean-Baptiste Boric 		return ENOMEM;
10159f988b79SJean-Baptiste Boric 
10169f988b79SJean-Baptiste Boric 	/* a sparing table descriptor is a whole sparable_blockingnr sectors */
10179f988b79SJean-Baptiste Boric 	udf_inittag(&spt->tag, TAGID_SPARING_TABLE, /* loc */ 0);
10189f988b79SJean-Baptiste Boric 
10199f988b79SJean-Baptiste Boric 	udf_set_regid(&spt->id, "*UDF Sparing Table");
10209f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&spt->id);
10219f988b79SJean-Baptiste Boric 
10229f988b79SJean-Baptiste Boric 	spt->rt_l    = udf_rw16(layout.sparable_blocks);
10239f988b79SJean-Baptiste Boric 	spt->seq_num = udf_rw32(0);			/* first generation */
10249f988b79SJean-Baptiste Boric 
10259f988b79SJean-Baptiste Boric 	for (cnt = 0; cnt < layout.sparable_blocks; cnt++) {
10269f988b79SJean-Baptiste Boric 		sme = &spt->entries[cnt];
10279f988b79SJean-Baptiste Boric 		loc = layout.sparable_area + cnt * layout.sparable_blockingnr;
10289f988b79SJean-Baptiste Boric 		sme->org = udf_rw32(0xffffffff);	/* open for reloc */
10299f988b79SJean-Baptiste Boric 		sme->map = udf_rw32(loc);
10309f988b79SJean-Baptiste Boric 	}
10319f988b79SJean-Baptiste Boric 
10329f988b79SJean-Baptiste Boric 	/* calculate crc len for actual size */
10339f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct udf_sparing_table) - UDF_DESC_TAG_LENGTH;
10349f988b79SJean-Baptiste Boric 	crclen += (layout.sparable_blocks-1) * sizeof(struct spare_map_entry);
10359f988b79SJean-Baptiste Boric /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
10369f988b79SJean-Baptiste Boric 	spt->tag.desc_crc_len = udf_rw16((uint16_t)crclen);
10379f988b79SJean-Baptiste Boric 
10389f988b79SJean-Baptiste Boric 	context.sparing_table = spt;
10399f988b79SJean-Baptiste Boric 
10409f988b79SJean-Baptiste Boric 	return 0;
10419f988b79SJean-Baptiste Boric }
10429f988b79SJean-Baptiste Boric 
10439f988b79SJean-Baptiste Boric 
10449f988b79SJean-Baptiste Boric static void
udf_add_logvol_part_meta(uint16_t phys_part)10459f988b79SJean-Baptiste Boric udf_add_logvol_part_meta(uint16_t phys_part)
10469f988b79SJean-Baptiste Boric {
10479f988b79SJean-Baptiste Boric 	union  udf_pmap *pmap;
10489f988b79SJean-Baptiste Boric 	struct logvol_desc *logvol = context.logical_vol;
10499f988b79SJean-Baptiste Boric 	uint8_t *pmap_pos;
10509f988b79SJean-Baptiste Boric 	uint32_t pmapv_size, log_part;
10519f988b79SJean-Baptiste Boric 	uint16_t crclen;
10529f988b79SJean-Baptiste Boric 
10539f988b79SJean-Baptiste Boric 	log_part = udf_rw32(logvol->n_pm);
10549f988b79SJean-Baptiste Boric 	pmap_pos = logvol->maps + udf_rw32(logvol->mt_l);
10559f988b79SJean-Baptiste Boric 	pmapv_size = sizeof(struct part_map_2);
10569f988b79SJean-Baptiste Boric 
10579f988b79SJean-Baptiste Boric 	pmap = (union udf_pmap *) pmap_pos;
10589f988b79SJean-Baptiste Boric 	pmap->pmm.type        = 2;
10599f988b79SJean-Baptiste Boric 	pmap->pmm.len         = pmapv_size;
10609f988b79SJean-Baptiste Boric 
10619f988b79SJean-Baptiste Boric 	udf_set_regid(&pmap->pmm.id, "*UDF Metadata Partition");
10629f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&pmap->pmm.id);
10639f988b79SJean-Baptiste Boric 
10649f988b79SJean-Baptiste Boric 	pmap->pmm.vol_seq_num = udf_rw16(1);		/* no multi-volume */
10659f988b79SJean-Baptiste Boric 	pmap->pmm.part_num    = udf_rw16(phys_part);
10669f988b79SJean-Baptiste Boric 
10679f988b79SJean-Baptiste Boric 	/* fill in meta data file(s) and alloc/alignment unit sizes */
10689f988b79SJean-Baptiste Boric 	pmap->pmm.meta_file_lbn        = udf_rw32(layout.meta_file);
10699f988b79SJean-Baptiste Boric 	pmap->pmm.meta_mirror_file_lbn = udf_rw32(layout.meta_mirror);
10709f988b79SJean-Baptiste Boric 	pmap->pmm.meta_bitmap_file_lbn = udf_rw32(layout.meta_bitmap);
10719f988b79SJean-Baptiste Boric 	pmap->pmm.alloc_unit_size      = udf_rw32(layout.meta_blockingnr);
10729f988b79SJean-Baptiste Boric 	pmap->pmm.alignment_unit_size  = udf_rw16(layout.meta_alignment);
10739f988b79SJean-Baptiste Boric 	pmap->pmm.flags                = 0; /* METADATA_DUPLICATED */
10749f988b79SJean-Baptiste Boric 
10759f988b79SJean-Baptiste Boric 	context.vtop       [log_part] = phys_part;
10769f988b79SJean-Baptiste Boric 	context.vtop_tp    [log_part] = UDF_VTOP_TYPE_META;
10779f988b79SJean-Baptiste Boric 	context.vtop_offset[log_part] =
10789f988b79SJean-Baptiste Boric 		context.vtop_offset[phys_part] + layout.meta_part_start_lba;
10799f988b79SJean-Baptiste Boric 	context.part_size[log_part] = layout.meta_part_size_lba;
10809f988b79SJean-Baptiste Boric 	context.part_free[log_part] = layout.meta_part_size_lba;
10819f988b79SJean-Baptiste Boric 
10829f988b79SJean-Baptiste Boric 	/* increment number of partitions and length */
10839f988b79SJean-Baptiste Boric 	logvol->n_pm = udf_rw32(log_part + 1);
10849f988b79SJean-Baptiste Boric 	logvol->mt_l = udf_rw32(udf_rw32(logvol->mt_l) + pmapv_size);
10859f988b79SJean-Baptiste Boric 
10869f988b79SJean-Baptiste Boric 	crclen = udf_rw16(logvol->tag.desc_crc_len) + pmapv_size;
10879f988b79SJean-Baptiste Boric 	logvol->tag.desc_crc_len = udf_rw16(crclen);
10889f988b79SJean-Baptiste Boric }
10899f988b79SJean-Baptiste Boric 
10909f988b79SJean-Baptiste Boric 
10919f988b79SJean-Baptiste Boric int
udf_create_logical_dscr(int format_flags)10929f988b79SJean-Baptiste Boric udf_create_logical_dscr(int format_flags)
10939f988b79SJean-Baptiste Boric {
10949f988b79SJean-Baptiste Boric 	int error;
10959f988b79SJean-Baptiste Boric 
10969f988b79SJean-Baptiste Boric 	if ((error = udf_create_base_logical_dscr()))
10979f988b79SJean-Baptiste Boric 		return error;
10989f988b79SJean-Baptiste Boric 
10999f988b79SJean-Baptiste Boric 	/* we pass data_part for there might be a read-only part one day */
11009f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_SPARABLE) {
11019f988b79SJean-Baptiste Boric 		/* sparable partition mapping has no physical mapping */
11029f988b79SJean-Baptiste Boric 		udf_add_logvol_part_sparable(context.data_part);
11039f988b79SJean-Baptiste Boric 	} else {
11049f988b79SJean-Baptiste Boric 		udf_add_logvol_part_physical(context.data_part);
11059f988b79SJean-Baptiste Boric 	}
11069f988b79SJean-Baptiste Boric 
11079f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_VAT) {
11089f988b79SJean-Baptiste Boric 		/* add VAT virtual mapping; reflects on datapart */
11099f988b79SJean-Baptiste Boric 		udf_add_logvol_part_virtual(context.data_part);
11109f988b79SJean-Baptiste Boric 	}
11119f988b79SJean-Baptiste Boric 	if (format_flags & FORMAT_META) {
11129f988b79SJean-Baptiste Boric 		/* add META data mapping; reflects on datapart */
11139f988b79SJean-Baptiste Boric 		udf_add_logvol_part_meta(context.data_part);
11149f988b79SJean-Baptiste Boric 	}
11159f988b79SJean-Baptiste Boric 
11169f988b79SJean-Baptiste Boric 	return 0;
11179f988b79SJean-Baptiste Boric }
11189f988b79SJean-Baptiste Boric 
11199f988b79SJean-Baptiste Boric 
11209f988b79SJean-Baptiste Boric int
udf_create_impvold(char * field1,char * field2,char * field3)11219f988b79SJean-Baptiste Boric udf_create_impvold(char *field1, char *field2, char *field3)
11229f988b79SJean-Baptiste Boric {
11239f988b79SJean-Baptiste Boric 	struct impvol_desc *ivd;
11249f988b79SJean-Baptiste Boric 	struct udf_lv_info *lvi;
11259f988b79SJean-Baptiste Boric 	uint16_t crclen;
11269f988b79SJean-Baptiste Boric 
11279f988b79SJean-Baptiste Boric 	ivd = calloc(1, context.sector_size);
11289f988b79SJean-Baptiste Boric 	if (ivd == NULL)
11299f988b79SJean-Baptiste Boric 		return ENOMEM;
11309f988b79SJean-Baptiste Boric 	lvi = &ivd->_impl_use.lv_info;
11319f988b79SJean-Baptiste Boric 
11329f988b79SJean-Baptiste Boric 	udf_inittag(&ivd->tag, TAGID_IMP_VOL, /* loc */ 0);
11339f988b79SJean-Baptiste Boric 	ivd->seq_num  = udf_rw32(context.vds_seq); context.vds_seq++;
11349f988b79SJean-Baptiste Boric 
11359f988b79SJean-Baptiste Boric 	udf_set_regid(&ivd->impl_id, "*UDF LV Info");
11369f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&ivd->impl_id);
11379f988b79SJean-Baptiste Boric 
11389f988b79SJean-Baptiste Boric 	/* fill in UDF specific part */
11399f988b79SJean-Baptiste Boric 	udf_osta_charset(&lvi->lvi_charset);
11409f988b79SJean-Baptiste Boric 	udf_encode_osta_id(lvi->logvol_id, 128, context.logvol_name);
11419f988b79SJean-Baptiste Boric 
11429f988b79SJean-Baptiste Boric 	udf_encode_osta_id(lvi->lvinfo1, 36, field1);
11439f988b79SJean-Baptiste Boric 	udf_encode_osta_id(lvi->lvinfo2, 36, field2);
11449f988b79SJean-Baptiste Boric 	udf_encode_osta_id(lvi->lvinfo3, 36, field3);
11459f988b79SJean-Baptiste Boric 
11469f988b79SJean-Baptiste Boric 	udf_set_regid(&lvi->impl_id, context.impl_name);
11479f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&lvi->impl_id);
11489f988b79SJean-Baptiste Boric 
11499f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct impvol_desc) - UDF_DESC_TAG_LENGTH;
11509f988b79SJean-Baptiste Boric 	ivd->tag.desc_crc_len = udf_rw16(crclen);
11519f988b79SJean-Baptiste Boric 
11529f988b79SJean-Baptiste Boric 	context.implementation = ivd;
11539f988b79SJean-Baptiste Boric 
11549f988b79SJean-Baptiste Boric 	return 0;
11559f988b79SJean-Baptiste Boric }
11569f988b79SJean-Baptiste Boric 
11579f988b79SJean-Baptiste Boric 
11589f988b79SJean-Baptiste Boric /* XXX might need to be sanitised a bit later */
11599f988b79SJean-Baptiste Boric void
udf_update_lvintd(int type)11609f988b79SJean-Baptiste Boric udf_update_lvintd(int type)
11619f988b79SJean-Baptiste Boric {
11629f988b79SJean-Baptiste Boric 	struct logvol_int_desc *lvid;
11639f988b79SJean-Baptiste Boric 	struct udf_logvol_info *lvinfo;
11649f988b79SJean-Baptiste Boric 	struct logvol_desc     *logvol;
11659f988b79SJean-Baptiste Boric 	uint32_t *pos;
11669f988b79SJean-Baptiste Boric 	uint32_t cnt, l_iu, num_partmappings;
11679f988b79SJean-Baptiste Boric 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
11689f988b79SJean-Baptiste Boric 
11699f988b79SJean-Baptiste Boric 	lvid   = context.logvol_integrity;
11709f988b79SJean-Baptiste Boric 	logvol = context.logical_vol;
11719f988b79SJean-Baptiste Boric 
11729f988b79SJean-Baptiste Boric 	assert(lvid);
11739f988b79SJean-Baptiste Boric 	assert(logvol);
11749f988b79SJean-Baptiste Boric 
11759f988b79SJean-Baptiste Boric 	lvid->integrity_type = udf_rw32(type);
11769f988b79SJean-Baptiste Boric 
11779f988b79SJean-Baptiste Boric 	num_partmappings = udf_rw32(logvol->n_pm);
11789f988b79SJean-Baptiste Boric 
11799f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&lvid->time);
11809f988b79SJean-Baptiste Boric 
11819f988b79SJean-Baptiste Boric 	lvinfo = (struct udf_logvol_info *)
11829f988b79SJean-Baptiste Boric 		(lvid->tables + num_partmappings * 2);
11839f988b79SJean-Baptiste Boric 	udf_set_regid(&lvinfo->impl_id, context.impl_name);
11849f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&lvinfo->impl_id);
11859f988b79SJean-Baptiste Boric 
11869f988b79SJean-Baptiste Boric 	lvinfo->num_files          = udf_rw32(context.num_files);
11879f988b79SJean-Baptiste Boric 	lvinfo->num_directories    = udf_rw32(context.num_directories);
11889f988b79SJean-Baptiste Boric 
11899f988b79SJean-Baptiste Boric 	lvid->lvint_next_unique_id = udf_rw64(context.unique_id);
11909f988b79SJean-Baptiste Boric 
11919f988b79SJean-Baptiste Boric 	/* XXX sane enough ? */
11929f988b79SJean-Baptiste Boric 	lvinfo->min_udf_readver  = udf_rw16(context.min_udf);
11939f988b79SJean-Baptiste Boric 	lvinfo->min_udf_writever = udf_rw16(context.min_udf);
11949f988b79SJean-Baptiste Boric 	lvinfo->max_udf_writever = udf_rw16(context.max_udf);
11959f988b79SJean-Baptiste Boric 
11969f988b79SJean-Baptiste Boric 	lvid->num_part = udf_rw32(num_partmappings);
11979f988b79SJean-Baptiste Boric 
11989f988b79SJean-Baptiste Boric 	/* no impl. use needed */
11999f988b79SJean-Baptiste Boric 	l_iu = sizeof(struct udf_logvol_info);
12009f988b79SJean-Baptiste Boric 	lvid->l_iu = udf_rw32(l_iu);
12019f988b79SJean-Baptiste Boric 
12029f988b79SJean-Baptiste Boric 	pos = &lvid->tables[0];
12039f988b79SJean-Baptiste Boric 	for (cnt = 0; cnt < num_partmappings; cnt++) {
12049f988b79SJean-Baptiste Boric 		*pos++ = udf_rw32(context.part_free[cnt]);
12059f988b79SJean-Baptiste Boric 	}
12069f988b79SJean-Baptiste Boric 	for (cnt = 0; cnt < num_partmappings; cnt++) {
12079f988b79SJean-Baptiste Boric 		*pos++ = udf_rw32(context.part_size[cnt]);
12089f988b79SJean-Baptiste Boric 	}
12099f988b79SJean-Baptiste Boric 
12109f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct logvol_int_desc) -4 -UDF_DESC_TAG_LENGTH + l_iu;
12119f988b79SJean-Baptiste Boric 	crclen += num_partmappings * 2 * 4;
12129f988b79SJean-Baptiste Boric /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
12139f988b79SJean-Baptiste Boric 	lvid->tag.desc_crc_len = udf_rw16(crclen);
12149f988b79SJean-Baptiste Boric 
12159f988b79SJean-Baptiste Boric 	context.logvol_info = lvinfo;
12169f988b79SJean-Baptiste Boric }
12179f988b79SJean-Baptiste Boric 
12189f988b79SJean-Baptiste Boric 
12199f988b79SJean-Baptiste Boric int
udf_create_lvintd(int type)12209f988b79SJean-Baptiste Boric udf_create_lvintd(int type)
12219f988b79SJean-Baptiste Boric {
12229f988b79SJean-Baptiste Boric 	struct logvol_int_desc *lvid;
12239f988b79SJean-Baptiste Boric 
12249f988b79SJean-Baptiste Boric 	lvid = calloc(1, context.sector_size);
12259f988b79SJean-Baptiste Boric 	if (lvid == NULL)
12269f988b79SJean-Baptiste Boric 		return ENOMEM;
12279f988b79SJean-Baptiste Boric 
12289f988b79SJean-Baptiste Boric 	udf_inittag(&lvid->tag, TAGID_LOGVOL_INTEGRITY, /* loc */ 0);
12299f988b79SJean-Baptiste Boric 
12309f988b79SJean-Baptiste Boric 	context.logvol_integrity = lvid;
12319f988b79SJean-Baptiste Boric 
12329f988b79SJean-Baptiste Boric 	udf_update_lvintd(type);
12339f988b79SJean-Baptiste Boric 
12349f988b79SJean-Baptiste Boric 	return 0;
12359f988b79SJean-Baptiste Boric }
12369f988b79SJean-Baptiste Boric 
12379f988b79SJean-Baptiste Boric 
12389f988b79SJean-Baptiste Boric int
udf_create_fsd(void)12399f988b79SJean-Baptiste Boric udf_create_fsd(void)
12409f988b79SJean-Baptiste Boric {
12419f988b79SJean-Baptiste Boric 	struct fileset_desc *fsd;
12429f988b79SJean-Baptiste Boric 	uint16_t crclen;
12439f988b79SJean-Baptiste Boric 
12449f988b79SJean-Baptiste Boric 	fsd = calloc(1, context.sector_size);
12459f988b79SJean-Baptiste Boric 	if (fsd == NULL)
12469f988b79SJean-Baptiste Boric 		return ENOMEM;
12479f988b79SJean-Baptiste Boric 
12489f988b79SJean-Baptiste Boric 	udf_inittag(&fsd->tag, TAGID_FSD, /* loc */ 0);
12499f988b79SJean-Baptiste Boric 
12509f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&fsd->time);
12519f988b79SJean-Baptiste Boric 	fsd->ichg_lvl     = udf_rw16(3);		/* UDF 2.3.2.1 */
12529f988b79SJean-Baptiste Boric 	fsd->max_ichg_lvl = udf_rw16(3);		/* UDF 2.3.2.2 */
12539f988b79SJean-Baptiste Boric 
12549f988b79SJean-Baptiste Boric 	fsd->charset_list     = udf_rw32(1);		/* only CS0 */
12559f988b79SJean-Baptiste Boric 	fsd->max_charset_list = udf_rw32(1);		/* only CS0 */
12569f988b79SJean-Baptiste Boric 
12579f988b79SJean-Baptiste Boric 	fsd->fileset_num      = udf_rw32(0);		/* only one fsd */
12589f988b79SJean-Baptiste Boric 	fsd->fileset_desc_num = udf_rw32(0);		/* origional    */
12599f988b79SJean-Baptiste Boric 
12609f988b79SJean-Baptiste Boric 	udf_osta_charset(&fsd->logvol_id_charset);
12619f988b79SJean-Baptiste Boric 	udf_encode_osta_id(fsd->logvol_id, 128, context.logvol_name);
12629f988b79SJean-Baptiste Boric 
12639f988b79SJean-Baptiste Boric 	udf_osta_charset(&fsd->fileset_charset);
12649f988b79SJean-Baptiste Boric 	udf_encode_osta_id(fsd->fileset_id, 32, context.fileset_name);
12659f988b79SJean-Baptiste Boric 
12669f988b79SJean-Baptiste Boric 	/* copyright file and abstract file names obmitted */
12679f988b79SJean-Baptiste Boric 
12689f988b79SJean-Baptiste Boric 	fsd->rootdir_icb.len	      = udf_rw32(context.sector_size);
12699f988b79SJean-Baptiste Boric 	fsd->rootdir_icb.loc.lb_num   = udf_rw32(layout.rootdir);
12709f988b79SJean-Baptiste Boric 	fsd->rootdir_icb.loc.part_num = udf_rw16(context.metadata_part);
12719f988b79SJean-Baptiste Boric 
12729f988b79SJean-Baptiste Boric 	udf_set_regid(&fsd->domain_id, "*OSTA UDF Compliant");
12739f988b79SJean-Baptiste Boric 	udf_add_domain_regid(&fsd->domain_id);
12749f988b79SJean-Baptiste Boric 
12759f988b79SJean-Baptiste Boric 	/* next_ex stays zero */
12769f988b79SJean-Baptiste Boric 	/* no system streamdirs yet */
12779f988b79SJean-Baptiste Boric 
12789f988b79SJean-Baptiste Boric 	crclen = sizeof(struct fileset_desc) - UDF_DESC_TAG_LENGTH;
12799f988b79SJean-Baptiste Boric 	fsd->tag.desc_crc_len = udf_rw16(crclen);
12809f988b79SJean-Baptiste Boric 
12819f988b79SJean-Baptiste Boric 	context.fileset_desc = fsd;
12829f988b79SJean-Baptiste Boric 
12839f988b79SJean-Baptiste Boric 	return 0;
12849f988b79SJean-Baptiste Boric }
12859f988b79SJean-Baptiste Boric 
12869f988b79SJean-Baptiste Boric 
12879f988b79SJean-Baptiste Boric int
udf_create_space_bitmap(uint32_t dscr_size,uint32_t part_size_lba,struct space_bitmap_desc ** sbdp)12889f988b79SJean-Baptiste Boric udf_create_space_bitmap(uint32_t dscr_size, uint32_t part_size_lba,
12899f988b79SJean-Baptiste Boric 	struct space_bitmap_desc **sbdp)
12909f988b79SJean-Baptiste Boric {
12919f988b79SJean-Baptiste Boric 	struct space_bitmap_desc *sbd;
12929f988b79SJean-Baptiste Boric 	uint32_t cnt;
12939f988b79SJean-Baptiste Boric 	uint16_t crclen;
12949f988b79SJean-Baptiste Boric 
12959f988b79SJean-Baptiste Boric 	*sbdp = NULL;
12969f988b79SJean-Baptiste Boric 	sbd = calloc(context.sector_size, dscr_size);
12979f988b79SJean-Baptiste Boric 	if (sbd == NULL)
12989f988b79SJean-Baptiste Boric 		return ENOMEM;
12999f988b79SJean-Baptiste Boric 
13009f988b79SJean-Baptiste Boric 	udf_inittag(&sbd->tag, TAGID_SPACE_BITMAP, /* loc */ 0);
13019f988b79SJean-Baptiste Boric 
13029f988b79SJean-Baptiste Boric 	sbd->num_bits  = udf_rw32(part_size_lba);
13039f988b79SJean-Baptiste Boric 	sbd->num_bytes = udf_rw32((part_size_lba + 7)/8);
13049f988b79SJean-Baptiste Boric 
13059f988b79SJean-Baptiste Boric 	/* fill space with 0xff to indicate free */
13069f988b79SJean-Baptiste Boric 	for (cnt = 0; cnt < udf_rw32(sbd->num_bytes); cnt++)
13079f988b79SJean-Baptiste Boric 		sbd->data[cnt] = 0xff;
13089f988b79SJean-Baptiste Boric 
13099f988b79SJean-Baptiste Boric 	/* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
13109f988b79SJean-Baptiste Boric 	crclen = sizeof(struct space_bitmap_desc) -1 - UDF_DESC_TAG_LENGTH;
13119f988b79SJean-Baptiste Boric 	sbd->tag.desc_crc_len = udf_rw16(crclen);
13129f988b79SJean-Baptiste Boric 
13139f988b79SJean-Baptiste Boric 	*sbdp = sbd;
13149f988b79SJean-Baptiste Boric 	return 0;
13159f988b79SJean-Baptiste Boric }
13169f988b79SJean-Baptiste Boric 
13179f988b79SJean-Baptiste Boric 
13189f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
13199f988b79SJean-Baptiste Boric 
13209f988b79SJean-Baptiste Boric int
udf_register_bad_block(uint32_t location)13219f988b79SJean-Baptiste Boric udf_register_bad_block(uint32_t location)
13229f988b79SJean-Baptiste Boric {
13239f988b79SJean-Baptiste Boric 	struct udf_sparing_table *spt;
13249f988b79SJean-Baptiste Boric 	struct spare_map_entry   *sme, *free_sme;
13259f988b79SJean-Baptiste Boric 	uint32_t cnt;
13269f988b79SJean-Baptiste Boric 
13279f988b79SJean-Baptiste Boric 	spt = context.sparing_table;
13289f988b79SJean-Baptiste Boric 	if (spt == NULL) {
13299f988b79SJean-Baptiste Boric 		printf("internal error: adding bad block to non sparable\n");
13309f988b79SJean-Baptiste Boric 		return EINVAL;
13319f988b79SJean-Baptiste Boric 	}
13329f988b79SJean-Baptiste Boric 
13339f988b79SJean-Baptiste Boric 	/* find us a free spare map entry */
13349f988b79SJean-Baptiste Boric 	free_sme = NULL;
13359f988b79SJean-Baptiste Boric 	for (cnt = 0; cnt < layout.sparable_blocks; cnt++) {
13369f988b79SJean-Baptiste Boric 		sme = &spt->entries[cnt];
13379f988b79SJean-Baptiste Boric 		/* if we are allready in it, bail out */
13389f988b79SJean-Baptiste Boric 		if (udf_rw32(sme->org) == location)
13399f988b79SJean-Baptiste Boric 			return 0;
13409f988b79SJean-Baptiste Boric 		if (udf_rw32(sme->org) == 0xffffffff) {
13419f988b79SJean-Baptiste Boric 			free_sme = sme;
13429f988b79SJean-Baptiste Boric 			break;
13439f988b79SJean-Baptiste Boric 		}
13449f988b79SJean-Baptiste Boric 	}
13459f988b79SJean-Baptiste Boric 	if (free_sme == NULL) {
13469f988b79SJean-Baptiste Boric 		printf("Disc relocation blocks full; disc too damanged\n");
13479f988b79SJean-Baptiste Boric 		return EINVAL;
13489f988b79SJean-Baptiste Boric 	}
13499f988b79SJean-Baptiste Boric 	free_sme->org = udf_rw32(location);
13509f988b79SJean-Baptiste Boric 
13519f988b79SJean-Baptiste Boric 	return 0;
13529f988b79SJean-Baptiste Boric }
13539f988b79SJean-Baptiste Boric 
13549f988b79SJean-Baptiste Boric 
13559f988b79SJean-Baptiste Boric void
udf_mark_allocated(uint32_t start_lb,int partnr,uint32_t blocks)13569f988b79SJean-Baptiste Boric udf_mark_allocated(uint32_t start_lb, int partnr, uint32_t blocks)
13579f988b79SJean-Baptiste Boric {
13589f988b79SJean-Baptiste Boric 	union dscrptr *dscr;
13599f988b79SJean-Baptiste Boric 	uint8_t *bpos;
13609f988b79SJean-Baptiste Boric 	uint32_t cnt, bit;
13619f988b79SJean-Baptiste Boric 
13629f988b79SJean-Baptiste Boric 	/* account for space used on underlying partition */
13639f988b79SJean-Baptiste Boric 	context.part_free[partnr] -= blocks;
13649f988b79SJean-Baptiste Boric #ifdef DEBUG
13659f988b79SJean-Baptiste Boric 	printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
13669f988b79SJean-Baptiste Boric 		partnr, start_lb, blocks);
13679f988b79SJean-Baptiste Boric #endif
13689f988b79SJean-Baptiste Boric 
13699f988b79SJean-Baptiste Boric 	switch (context.vtop_tp[partnr]) {
13709f988b79SJean-Baptiste Boric 	case UDF_VTOP_TYPE_VIRT:
13719f988b79SJean-Baptiste Boric 		/* nothing */
13729f988b79SJean-Baptiste Boric 		break;
13739f988b79SJean-Baptiste Boric 	case UDF_VTOP_TYPE_PHYS:
13749f988b79SJean-Baptiste Boric 	case UDF_VTOP_TYPE_SPARABLE:
13759f988b79SJean-Baptiste Boric 	case UDF_VTOP_TYPE_META:
13769f988b79SJean-Baptiste Boric 		if (context.part_unalloc_bits[context.vtop[partnr]] == NULL) {
13779f988b79SJean-Baptiste Boric 			context.part_free[partnr] = 0;
13789f988b79SJean-Baptiste Boric 			break;
13799f988b79SJean-Baptiste Boric 		}
13809f988b79SJean-Baptiste Boric #ifdef DEBUG
13819f988b79SJean-Baptiste Boric 		printf("Marking %d+%d as used\n", start_lb, blocks);
13829f988b79SJean-Baptiste Boric #endif
13839f988b79SJean-Baptiste Boric 		dscr = (union dscrptr *) (context.part_unalloc_bits[partnr]);
13849f988b79SJean-Baptiste Boric 		for (cnt = start_lb; cnt < start_lb + blocks; cnt++) {
13859f988b79SJean-Baptiste Boric 			 bpos  = &dscr->sbd.data[cnt / 8];
13869f988b79SJean-Baptiste Boric 			 bit   = cnt % 8;
13879f988b79SJean-Baptiste Boric 			*bpos &= ~(1<< bit);
13889f988b79SJean-Baptiste Boric 		}
13899f988b79SJean-Baptiste Boric 		break;
13909f988b79SJean-Baptiste Boric 	default:
13919f988b79SJean-Baptiste Boric 		printf("internal error: reality check in mapping type %d\n",
13929f988b79SJean-Baptiste Boric 			context.vtop_tp[partnr]);
13939f988b79SJean-Baptiste Boric 		exit(EXIT_FAILURE);
13949f988b79SJean-Baptiste Boric 	}
13959f988b79SJean-Baptiste Boric }
13969f988b79SJean-Baptiste Boric 
13979f988b79SJean-Baptiste Boric 
13989f988b79SJean-Baptiste Boric void
udf_advance_uniqueid(void)13999f988b79SJean-Baptiste Boric udf_advance_uniqueid(void)
14009f988b79SJean-Baptiste Boric {
14019f988b79SJean-Baptiste Boric 	/* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
14029f988b79SJean-Baptiste Boric 	context.unique_id++;
14039f988b79SJean-Baptiste Boric 	if (context.unique_id < 0x10)
14049f988b79SJean-Baptiste Boric 		context.unique_id = 0x10;
14059f988b79SJean-Baptiste Boric }
14069f988b79SJean-Baptiste Boric 
14079f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
14089f988b79SJean-Baptiste Boric 
14099f988b79SJean-Baptiste Boric static void
unix_to_udf_name(char * result,uint8_t * result_len,char const * name,int name_len,struct charspec * chsp)14109f988b79SJean-Baptiste Boric unix_to_udf_name(char *result, uint8_t *result_len,
14119f988b79SJean-Baptiste Boric 	char const *name, int name_len, struct charspec *chsp)
14129f988b79SJean-Baptiste Boric {
14139f988b79SJean-Baptiste Boric 	uint16_t   *raw_name;
14149f988b79SJean-Baptiste Boric 	uint16_t   *outchp;
14159f988b79SJean-Baptiste Boric 	const char *inchp;
14169f988b79SJean-Baptiste Boric 	const char *osta_id = "OSTA Compressed Unicode";
14179f988b79SJean-Baptiste Boric 	int         udf_chars, is_osta_typ0, bits;
14189f988b79SJean-Baptiste Boric 	size_t      cnt;
14199f988b79SJean-Baptiste Boric 
14209f988b79SJean-Baptiste Boric 	/* allocate temporary unicode-16 buffer */
14219f988b79SJean-Baptiste Boric 	raw_name = malloc(1024);
14229f988b79SJean-Baptiste Boric 	assert(raw_name);
14239f988b79SJean-Baptiste Boric 
14249f988b79SJean-Baptiste Boric 	/* convert utf8 to unicode-16 */
14259f988b79SJean-Baptiste Boric 	*raw_name = 0;
14269f988b79SJean-Baptiste Boric 	inchp  = name;
14279f988b79SJean-Baptiste Boric 	outchp = raw_name;
14289f988b79SJean-Baptiste Boric 	bits = 8;
14299f988b79SJean-Baptiste Boric 	for (cnt = name_len, udf_chars = 0; cnt;) {
14309f988b79SJean-Baptiste Boric 		*outchp = wget_utf8(&inchp, &cnt);
14319f988b79SJean-Baptiste Boric 		if (*outchp > 0xff)
14329f988b79SJean-Baptiste Boric 			bits=16;
14339f988b79SJean-Baptiste Boric 		outchp++;
14349f988b79SJean-Baptiste Boric 		udf_chars++;
14359f988b79SJean-Baptiste Boric 	}
14369f988b79SJean-Baptiste Boric 	/* null terminate just in case */
14379f988b79SJean-Baptiste Boric 	*outchp++ = 0;
14389f988b79SJean-Baptiste Boric 
14399f988b79SJean-Baptiste Boric 	is_osta_typ0  = (chsp->type == 0);
14409f988b79SJean-Baptiste Boric 	is_osta_typ0 &= (strcmp((char *) chsp->inf, osta_id) == 0);
14419f988b79SJean-Baptiste Boric 	if (is_osta_typ0) {
14429f988b79SJean-Baptiste Boric 		udf_chars = udf_CompressUnicode(udf_chars, bits,
14439f988b79SJean-Baptiste Boric 				(unicode_t *) raw_name,
14449f988b79SJean-Baptiste Boric 				(byte *) result);
14459f988b79SJean-Baptiste Boric 	} else {
14469f988b79SJean-Baptiste Boric 		printf("unix to udf name: no CHSP0 ?\n");
14479f988b79SJean-Baptiste Boric 		/* XXX assume 8bit char length byte latin-1 */
14489f988b79SJean-Baptiste Boric 		*result++ = 8; udf_chars = 1;
14499f988b79SJean-Baptiste Boric 		strncpy(result, name + 1, name_len);
14509f988b79SJean-Baptiste Boric 		udf_chars += name_len;
14519f988b79SJean-Baptiste Boric 	}
14529f988b79SJean-Baptiste Boric 	*result_len = udf_chars;
14539f988b79SJean-Baptiste Boric 	free(raw_name);
14549f988b79SJean-Baptiste Boric }
14559f988b79SJean-Baptiste Boric 
14569f988b79SJean-Baptiste Boric 
14579f988b79SJean-Baptiste Boric #define UDF_SYMLINKBUFLEN    (64*1024)               /* picked */
14589f988b79SJean-Baptiste Boric int
udf_encode_symlink(uint8_t ** pathbufp,uint32_t * pathlenp,char * target)14599f988b79SJean-Baptiste Boric udf_encode_symlink(uint8_t **pathbufp, uint32_t *pathlenp, char *target)
14609f988b79SJean-Baptiste Boric {
14619f988b79SJean-Baptiste Boric 	struct charspec osta_charspec;
14629f988b79SJean-Baptiste Boric 	struct pathcomp pathcomp;
14639f988b79SJean-Baptiste Boric 	char *pathbuf, *pathpos, *compnamepos;
14649f988b79SJean-Baptiste Boric //	char *mntonname;
14659f988b79SJean-Baptiste Boric //	int   mntonnamelen;
14669f988b79SJean-Baptiste Boric 	int pathlen, len, compnamelen;
14679f988b79SJean-Baptiste Boric 	int error;
14689f988b79SJean-Baptiste Boric 
14699f988b79SJean-Baptiste Boric 	/* process `target' to an UDF structure */
14709f988b79SJean-Baptiste Boric 	pathbuf = malloc(UDF_SYMLINKBUFLEN);
14719f988b79SJean-Baptiste Boric 	assert(pathbuf);
14729f988b79SJean-Baptiste Boric 
14739f988b79SJean-Baptiste Boric 	*pathbufp = NULL;
14749f988b79SJean-Baptiste Boric 	*pathlenp = 0;
14759f988b79SJean-Baptiste Boric 
14769f988b79SJean-Baptiste Boric 	pathpos = pathbuf;
14779f988b79SJean-Baptiste Boric 	pathlen = 0;
14789f988b79SJean-Baptiste Boric 	udf_osta_charset(&osta_charspec);
14799f988b79SJean-Baptiste Boric 
14809f988b79SJean-Baptiste Boric 	if (*target == '/') {
14819f988b79SJean-Baptiste Boric 		/* symlink starts from the root */
14829f988b79SJean-Baptiste Boric 		len = UDF_PATH_COMP_SIZE;
14839f988b79SJean-Baptiste Boric 		memset(&pathcomp, 0, len);
14849f988b79SJean-Baptiste Boric 		pathcomp.type = UDF_PATH_COMP_ROOT;
14859f988b79SJean-Baptiste Boric 
14869f988b79SJean-Baptiste Boric #if 0
14879f988b79SJean-Baptiste Boric 		/* XXX how to check for in makefs? */
14889f988b79SJean-Baptiste Boric 		/* check if its mount-point relative! */
14899f988b79SJean-Baptiste Boric 		mntonname    = udf_node->ump->vfs_mountp->mnt_stat.f_mntonname;
14909f988b79SJean-Baptiste Boric 		mntonnamelen = strlen(mntonname);
14919f988b79SJean-Baptiste Boric 		if (strlen(target) >= mntonnamelen) {
14929f988b79SJean-Baptiste Boric 			if (strncmp(target, mntonname, mntonnamelen) == 0) {
14939f988b79SJean-Baptiste Boric 				pathcomp.type = UDF_PATH_COMP_MOUNTROOT;
14949f988b79SJean-Baptiste Boric 				target += mntonnamelen;
14959f988b79SJean-Baptiste Boric 			}
14969f988b79SJean-Baptiste Boric 		} else {
14979f988b79SJean-Baptiste Boric 			target++;
14989f988b79SJean-Baptiste Boric 		}
14999f988b79SJean-Baptiste Boric #else
15009f988b79SJean-Baptiste Boric 		target++;
15019f988b79SJean-Baptiste Boric #endif
15029f988b79SJean-Baptiste Boric 
15039f988b79SJean-Baptiste Boric 		memcpy(pathpos, &pathcomp, len);
15049f988b79SJean-Baptiste Boric 		pathpos += len;
15059f988b79SJean-Baptiste Boric 		pathlen += len;
15069f988b79SJean-Baptiste Boric 	}
15079f988b79SJean-Baptiste Boric 
15089f988b79SJean-Baptiste Boric 	error = 0;
15099f988b79SJean-Baptiste Boric 	while (*target) {
15109f988b79SJean-Baptiste Boric 		/* ignore multiple '/' */
15119f988b79SJean-Baptiste Boric 		while (*target == '/') {
15129f988b79SJean-Baptiste Boric 			target++;
15139f988b79SJean-Baptiste Boric 		}
15149f988b79SJean-Baptiste Boric 		if (!*target)
15159f988b79SJean-Baptiste Boric 			break;
15169f988b79SJean-Baptiste Boric 
15179f988b79SJean-Baptiste Boric 		/* extract component name */
15189f988b79SJean-Baptiste Boric 		compnamelen = 0;
15199f988b79SJean-Baptiste Boric 		compnamepos = target;
15209f988b79SJean-Baptiste Boric 		while ((*target) && (*target != '/')) {
15219f988b79SJean-Baptiste Boric 			target++;
15229f988b79SJean-Baptiste Boric 			compnamelen++;
15239f988b79SJean-Baptiste Boric 		}
15249f988b79SJean-Baptiste Boric 
15259f988b79SJean-Baptiste Boric 		/* just trunc if too long ?? (security issue) */
15269f988b79SJean-Baptiste Boric 		if (compnamelen >= 127) {
15279f988b79SJean-Baptiste Boric 			error = ENAMETOOLONG;
15289f988b79SJean-Baptiste Boric 			break;
15299f988b79SJean-Baptiste Boric 		}
15309f988b79SJean-Baptiste Boric 
15319f988b79SJean-Baptiste Boric 		/* convert unix name to UDF name */
15329f988b79SJean-Baptiste Boric 		len = sizeof(struct pathcomp);
15339f988b79SJean-Baptiste Boric 		memset(&pathcomp, 0, len);
15349f988b79SJean-Baptiste Boric 		pathcomp.type = UDF_PATH_COMP_NAME;
15359f988b79SJean-Baptiste Boric 		len = UDF_PATH_COMP_SIZE;
15369f988b79SJean-Baptiste Boric 
15379f988b79SJean-Baptiste Boric 		if ((compnamelen == 2) && (strncmp(compnamepos, "..", 2) == 0))
15389f988b79SJean-Baptiste Boric 			pathcomp.type = UDF_PATH_COMP_PARENTDIR;
15399f988b79SJean-Baptiste Boric 		if ((compnamelen == 1) && (*compnamepos == '.'))
15409f988b79SJean-Baptiste Boric 			pathcomp.type = UDF_PATH_COMP_CURDIR;
15419f988b79SJean-Baptiste Boric 
15429f988b79SJean-Baptiste Boric 		if (pathcomp.type == UDF_PATH_COMP_NAME) {
15439f988b79SJean-Baptiste Boric 			unix_to_udf_name(
15449f988b79SJean-Baptiste Boric 				(char *) &pathcomp.ident, &pathcomp.l_ci,
15459f988b79SJean-Baptiste Boric 				compnamepos, compnamelen,
15469f988b79SJean-Baptiste Boric 				&osta_charspec);
15479f988b79SJean-Baptiste Boric 			len = UDF_PATH_COMP_SIZE + pathcomp.l_ci;
15489f988b79SJean-Baptiste Boric 		}
15499f988b79SJean-Baptiste Boric 
15509f988b79SJean-Baptiste Boric 		if (pathlen + len >= UDF_SYMLINKBUFLEN) {
15519f988b79SJean-Baptiste Boric 			error = ENAMETOOLONG;
15529f988b79SJean-Baptiste Boric 			break;
15539f988b79SJean-Baptiste Boric 		}
15549f988b79SJean-Baptiste Boric 
15559f988b79SJean-Baptiste Boric 		memcpy(pathpos, &pathcomp, len);
15569f988b79SJean-Baptiste Boric 		pathpos += len;
15579f988b79SJean-Baptiste Boric 		pathlen += len;
15589f988b79SJean-Baptiste Boric 	}
15599f988b79SJean-Baptiste Boric 
15609f988b79SJean-Baptiste Boric 	if (error) {
15619f988b79SJean-Baptiste Boric 		/* aparently too big */
15629f988b79SJean-Baptiste Boric 		free(pathbuf);
15639f988b79SJean-Baptiste Boric 		return error;
15649f988b79SJean-Baptiste Boric 	}
15659f988b79SJean-Baptiste Boric 
15669f988b79SJean-Baptiste Boric 	/* return status of symlink contents writeout */
15679f988b79SJean-Baptiste Boric 	*pathbufp = (uint8_t *) pathbuf;
15689f988b79SJean-Baptiste Boric 	*pathlenp = pathlen;
15699f988b79SJean-Baptiste Boric 
15709f988b79SJean-Baptiste Boric 	return 0;
15719f988b79SJean-Baptiste Boric 
15729f988b79SJean-Baptiste Boric }
15739f988b79SJean-Baptiste Boric #undef UDF_SYMLINKBUFLEN
15749f988b79SJean-Baptiste Boric 
15759f988b79SJean-Baptiste Boric 
15769f988b79SJean-Baptiste Boric int
udf_fidsize(struct fileid_desc * fid)15779f988b79SJean-Baptiste Boric udf_fidsize(struct fileid_desc *fid)
15789f988b79SJean-Baptiste Boric {
15799f988b79SJean-Baptiste Boric 	uint32_t size;
15809f988b79SJean-Baptiste Boric 
15819f988b79SJean-Baptiste Boric 	if (udf_rw16(fid->tag.id) != TAGID_FID)
15820a6a1f1dSLionel Sambuc 		errx(EINVAL, "got udf_fidsize on non FID");
15839f988b79SJean-Baptiste Boric 
15849f988b79SJean-Baptiste Boric 	size = UDF_FID_SIZE + fid->l_fi + udf_rw16(fid->l_iu);
15859f988b79SJean-Baptiste Boric 	size = (size + 3) & ~3;
15869f988b79SJean-Baptiste Boric 
15879f988b79SJean-Baptiste Boric 	return size;
15889f988b79SJean-Baptiste Boric }
15899f988b79SJean-Baptiste Boric 
15909f988b79SJean-Baptiste Boric 
15919f988b79SJean-Baptiste Boric int
udf_create_parentfid(struct fileid_desc * fid,struct long_ad * parent)15929f988b79SJean-Baptiste Boric udf_create_parentfid(struct fileid_desc *fid, struct long_ad *parent)
15939f988b79SJean-Baptiste Boric {
15949f988b79SJean-Baptiste Boric 	/* the size of an empty FID is 38 but needs to be a multiple of 4 */
15959f988b79SJean-Baptiste Boric 	int fidsize = 40;
15969f988b79SJean-Baptiste Boric 
15979f988b79SJean-Baptiste Boric 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(parent->loc.lb_num));
15989f988b79SJean-Baptiste Boric 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
15999f988b79SJean-Baptiste Boric 	fid->file_char = UDF_FILE_CHAR_DIR | UDF_FILE_CHAR_PAR;
16009f988b79SJean-Baptiste Boric 	fid->icb = *parent;
16019f988b79SJean-Baptiste Boric 	fid->icb.longad_uniqueid = parent->longad_uniqueid;
16029f988b79SJean-Baptiste Boric 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
16039f988b79SJean-Baptiste Boric 
16049f988b79SJean-Baptiste Boric 	/* we have to do the fid here explicitly for simplicity */
16059f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums((union dscrptr *) fid);
16069f988b79SJean-Baptiste Boric 
16079f988b79SJean-Baptiste Boric 	return fidsize;
16089f988b79SJean-Baptiste Boric }
16099f988b79SJean-Baptiste Boric 
16109f988b79SJean-Baptiste Boric 
16119f988b79SJean-Baptiste Boric void
udf_create_fid(uint32_t diroff,struct fileid_desc * fid,char * name,int file_char,struct long_ad * ref)16129f988b79SJean-Baptiste Boric udf_create_fid(uint32_t diroff, struct fileid_desc *fid, char *name,
16139f988b79SJean-Baptiste Boric 	int file_char, struct long_ad *ref)
16149f988b79SJean-Baptiste Boric {
16159f988b79SJean-Baptiste Boric 	struct charspec osta_charspec;
16169f988b79SJean-Baptiste Boric 	uint32_t endfid;
16179f988b79SJean-Baptiste Boric 	uint32_t fidsize, lb_rest;
16189f988b79SJean-Baptiste Boric 
16199f988b79SJean-Baptiste Boric 	memset(fid, 0, sizeof(*fid));
16209f988b79SJean-Baptiste Boric 	udf_inittag(&fid->tag, TAGID_FID, udf_rw32(ref->loc.lb_num));
16219f988b79SJean-Baptiste Boric 	fid->file_version_num = udf_rw16(1);	/* UDF 2.3.4.1 */
16229f988b79SJean-Baptiste Boric 	fid->file_char = file_char;
16239f988b79SJean-Baptiste Boric 	fid->l_iu = udf_rw16(0);
16249f988b79SJean-Baptiste Boric 	fid->icb = *ref;
16259f988b79SJean-Baptiste Boric 	fid->icb.longad_uniqueid = ref->longad_uniqueid;
16269f988b79SJean-Baptiste Boric 
16279f988b79SJean-Baptiste Boric 	udf_osta_charset(&osta_charspec);
16289f988b79SJean-Baptiste Boric 	unix_to_udf_name((char *) fid->data, &fid->l_fi, name, strlen(name),
16299f988b79SJean-Baptiste Boric 			&osta_charspec);
16309f988b79SJean-Baptiste Boric 
16319f988b79SJean-Baptiste Boric 	/*
16329f988b79SJean-Baptiste Boric 	 * OK, tricky part: we need to pad so the next descriptor header won't
16339f988b79SJean-Baptiste Boric 	 * cross the sector boundary
16349f988b79SJean-Baptiste Boric 	 */
16359f988b79SJean-Baptiste Boric 	endfid = diroff + udf_fidsize(fid);
16369f988b79SJean-Baptiste Boric 	lb_rest = context.sector_size - (endfid % context.sector_size);
16379f988b79SJean-Baptiste Boric 	if (lb_rest < sizeof(struct desc_tag)) {
16389f988b79SJean-Baptiste Boric 		/* add at least 32 */
16399f988b79SJean-Baptiste Boric 		fid->l_iu = udf_rw16(32);
16409f988b79SJean-Baptiste Boric 		udf_set_regid((struct regid *) fid->data, context.impl_name);
16419f988b79SJean-Baptiste Boric 		udf_add_impl_regid((struct regid *) fid->data);
16429f988b79SJean-Baptiste Boric 
16439f988b79SJean-Baptiste Boric 		unix_to_udf_name((char *) fid->data + udf_rw16(fid->l_iu),
16449f988b79SJean-Baptiste Boric 			&fid->l_fi, name, strlen(name), &osta_charspec);
16459f988b79SJean-Baptiste Boric 	}
16469f988b79SJean-Baptiste Boric 
16479f988b79SJean-Baptiste Boric 	fidsize = udf_fidsize(fid);
16489f988b79SJean-Baptiste Boric 	fid->tag.desc_crc_len = udf_rw16(fidsize - UDF_DESC_TAG_LENGTH);
16499f988b79SJean-Baptiste Boric 
16509f988b79SJean-Baptiste Boric 	/* make sure the header sums stays correct */
16519f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums((union dscrptr *)fid);
16529f988b79SJean-Baptiste Boric }
16539f988b79SJean-Baptiste Boric 
16549f988b79SJean-Baptiste Boric 
16559f988b79SJean-Baptiste Boric static void
udf_append_parentfid(union dscrptr * dscr,struct long_ad * parent_icb)16569f988b79SJean-Baptiste Boric udf_append_parentfid(union dscrptr *dscr, struct long_ad *parent_icb)
16579f988b79SJean-Baptiste Boric {
16589f988b79SJean-Baptiste Boric 	struct file_entry      *fe;
16599f988b79SJean-Baptiste Boric 	struct extfile_entry   *efe;
16609f988b79SJean-Baptiste Boric 	struct fileid_desc     *fid;
16619f988b79SJean-Baptiste Boric 	uint32_t l_ea;
16629f988b79SJean-Baptiste Boric 	uint32_t fidsize, crclen;
16639f988b79SJean-Baptiste Boric 	uint8_t *bpos, *data;
16649f988b79SJean-Baptiste Boric 
16659f988b79SJean-Baptiste Boric 	fe = NULL;
16669f988b79SJean-Baptiste Boric 	efe = NULL;
16679f988b79SJean-Baptiste Boric 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
16689f988b79SJean-Baptiste Boric 		fe    = &dscr->fe;
16699f988b79SJean-Baptiste Boric 		data  = fe->data;
16709f988b79SJean-Baptiste Boric 		l_ea  = udf_rw32(fe->l_ea);
16719f988b79SJean-Baptiste Boric 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
16729f988b79SJean-Baptiste Boric 		efe   = &dscr->efe;
16739f988b79SJean-Baptiste Boric 		data  = efe->data;
16749f988b79SJean-Baptiste Boric 		l_ea  = udf_rw32(efe->l_ea);
16759f988b79SJean-Baptiste Boric 	} else {
16769f988b79SJean-Baptiste Boric 		errx(1, "Bad tag passed to udf_append_parentfid");
16779f988b79SJean-Baptiste Boric 	}
16789f988b79SJean-Baptiste Boric 
16799f988b79SJean-Baptiste Boric 	/* create '..' */
16809f988b79SJean-Baptiste Boric 	bpos = data + l_ea;
16819f988b79SJean-Baptiste Boric 	fid  = (struct fileid_desc *) bpos;
16829f988b79SJean-Baptiste Boric 	fidsize = udf_create_parentfid(fid, parent_icb);
16839f988b79SJean-Baptiste Boric 
16849f988b79SJean-Baptiste Boric 	/* record fidlength information */
16859f988b79SJean-Baptiste Boric 	if (fe) {
16869f988b79SJean-Baptiste Boric 		fe->inf_len     = udf_rw64(fidsize);
16879f988b79SJean-Baptiste Boric 		fe->l_ad        = udf_rw32(fidsize);
16889f988b79SJean-Baptiste Boric 		fe->logblks_rec = udf_rw64(0);		/* intern */
16899f988b79SJean-Baptiste Boric 		crclen  = sizeof(struct file_entry);
16909f988b79SJean-Baptiste Boric 	} else {
16919f988b79SJean-Baptiste Boric 		efe->inf_len     = udf_rw64(fidsize);
16929f988b79SJean-Baptiste Boric 		efe->obj_size    = udf_rw64(fidsize);
16939f988b79SJean-Baptiste Boric 		efe->l_ad        = udf_rw32(fidsize);
16949f988b79SJean-Baptiste Boric 		efe->logblks_rec = udf_rw64(0);		/* intern */
16959f988b79SJean-Baptiste Boric 		crclen  = sizeof(struct extfile_entry);
16969f988b79SJean-Baptiste Boric 	}
16979f988b79SJean-Baptiste Boric 	crclen -= 1 + UDF_DESC_TAG_LENGTH;
16989f988b79SJean-Baptiste Boric 	crclen += l_ea + fidsize;
16999f988b79SJean-Baptiste Boric 	dscr->tag.desc_crc_len = udf_rw16(crclen);
17009f988b79SJean-Baptiste Boric 
17019f988b79SJean-Baptiste Boric 	/* make sure the header sums stays correct */
17029f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums(dscr);
17039f988b79SJean-Baptiste Boric }
17049f988b79SJean-Baptiste Boric 
17059f988b79SJean-Baptiste Boric 
17069f988b79SJean-Baptiste Boric 
17079f988b79SJean-Baptiste Boric /*
17089f988b79SJean-Baptiste Boric  * Order of extended attributes :
17099f988b79SJean-Baptiste Boric  *   ECMA 167 EAs
17109f988b79SJean-Baptiste Boric  *   Non block aligned Implementation Use EAs
17119f988b79SJean-Baptiste Boric  *   Block aligned Implementation Use EAs	(not in newfs_udf)
17129f988b79SJean-Baptiste Boric  *   Application Use EAs			(not in newfs_udf)
17139f988b79SJean-Baptiste Boric  *
17149f988b79SJean-Baptiste Boric  *   no checks for doubles, must be called in-order
17159f988b79SJean-Baptiste Boric  */
17169f988b79SJean-Baptiste Boric static void
udf_extattr_append_internal(union dscrptr * dscr,struct extattr_entry * extattr)17179f988b79SJean-Baptiste Boric udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr)
17189f988b79SJean-Baptiste Boric {
17199f988b79SJean-Baptiste Boric 	struct file_entry      *fe;
17209f988b79SJean-Baptiste Boric 	struct extfile_entry   *efe;
17219f988b79SJean-Baptiste Boric 	struct extattrhdr_desc *extattrhdr;
17229f988b79SJean-Baptiste Boric 	struct impl_extattr_entry *implext;
17239f988b79SJean-Baptiste Boric 	uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len;
17249f988b79SJean-Baptiste Boric 	uint32_t *l_eap, l_ad;
17259f988b79SJean-Baptiste Boric 	uint16_t *spos;
17269f988b79SJean-Baptiste Boric 	uint8_t *bpos, *data;
17279f988b79SJean-Baptiste Boric 
17289f988b79SJean-Baptiste Boric 	if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
17299f988b79SJean-Baptiste Boric 		fe    = &dscr->fe;
17309f988b79SJean-Baptiste Boric 		data  = fe->data;
17319f988b79SJean-Baptiste Boric 		l_eap = &fe->l_ea;
17329f988b79SJean-Baptiste Boric 		l_ad  = udf_rw32(fe->l_ad);
17339f988b79SJean-Baptiste Boric 	} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
17349f988b79SJean-Baptiste Boric 		efe   = &dscr->efe;
17359f988b79SJean-Baptiste Boric 		data  = efe->data;
17369f988b79SJean-Baptiste Boric 		l_eap = &efe->l_ea;
17379f988b79SJean-Baptiste Boric 		l_ad  = udf_rw32(efe->l_ad);
17389f988b79SJean-Baptiste Boric 	} else {
17399f988b79SJean-Baptiste Boric 		errx(1, "Bad tag passed to udf_extattr_append_internal");
17409f988b79SJean-Baptiste Boric 	}
17419f988b79SJean-Baptiste Boric 
17429f988b79SJean-Baptiste Boric 	/* should have a header! */
17439f988b79SJean-Baptiste Boric 	extattrhdr = (struct extattrhdr_desc *) data;
17449f988b79SJean-Baptiste Boric 	l_ea = udf_rw32(*l_eap);
17459f988b79SJean-Baptiste Boric 	if (l_ea == 0) {
1746*e1cdaee1SLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
17479f988b79SJean-Baptiste Boric 		assert(l_ad == 0);
1748*e1cdaee1SLionel Sambuc #else
1749*e1cdaee1SLionel Sambuc 		if (l_ad != 0) {
1750*e1cdaee1SLionel Sambuc 		    printf("%s:%d: l_ad != 0\n", __func__, __LINE__);
1751*e1cdaee1SLionel Sambuc 		    abort();
1752*e1cdaee1SLionel Sambuc 		}
1753*e1cdaee1SLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
17549f988b79SJean-Baptiste Boric 		/* create empty extended attribute header */
17559f988b79SJean-Baptiste Boric 		exthdr_len = sizeof(struct extattrhdr_desc);
17569f988b79SJean-Baptiste Boric 
17579f988b79SJean-Baptiste Boric 		udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0);
17589f988b79SJean-Baptiste Boric 		extattrhdr->impl_attr_loc = udf_rw32(exthdr_len);
17599f988b79SJean-Baptiste Boric 		extattrhdr->appl_attr_loc = udf_rw32(exthdr_len);
17609f988b79SJean-Baptiste Boric 		extattrhdr->tag.desc_crc_len = udf_rw16(8);
17619f988b79SJean-Baptiste Boric 
17629f988b79SJean-Baptiste Boric 		/* record extended attribute header length */
17639f988b79SJean-Baptiste Boric 		l_ea = exthdr_len;
17649f988b79SJean-Baptiste Boric 		*l_eap = udf_rw32(l_ea);
17659f988b79SJean-Baptiste Boric 	}
17669f988b79SJean-Baptiste Boric 
17679f988b79SJean-Baptiste Boric 	/* extract locations */
17689f988b79SJean-Baptiste Boric 	impl_attr_loc = udf_rw32(extattrhdr->impl_attr_loc);
17699f988b79SJean-Baptiste Boric 	appl_attr_loc = udf_rw32(extattrhdr->appl_attr_loc);
17709f988b79SJean-Baptiste Boric 	if (impl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
17719f988b79SJean-Baptiste Boric 		impl_attr_loc = l_ea;
17729f988b79SJean-Baptiste Boric 	if (appl_attr_loc == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
17739f988b79SJean-Baptiste Boric 		appl_attr_loc = l_ea;
17749f988b79SJean-Baptiste Boric 
17759f988b79SJean-Baptiste Boric 	/* Ecma 167 EAs */
17769f988b79SJean-Baptiste Boric 	if (udf_rw32(extattr->type) < 2048) {
17779f988b79SJean-Baptiste Boric 		assert(impl_attr_loc == l_ea);
17789f988b79SJean-Baptiste Boric 		assert(appl_attr_loc == l_ea);
17799f988b79SJean-Baptiste Boric 	}
17809f988b79SJean-Baptiste Boric 
17819f988b79SJean-Baptiste Boric 	/* implementation use extended attributes */
17829f988b79SJean-Baptiste Boric 	if (udf_rw32(extattr->type) == 2048) {
17839f988b79SJean-Baptiste Boric 		assert(appl_attr_loc == l_ea);
17849f988b79SJean-Baptiste Boric 
17859f988b79SJean-Baptiste Boric 		/* calculate and write extended attribute header checksum */
17869f988b79SJean-Baptiste Boric 		implext = (struct impl_extattr_entry *) extattr;
17879f988b79SJean-Baptiste Boric 		assert(udf_rw32(implext->iu_l) == 4);	/* [UDF 3.3.4.5] */
17889f988b79SJean-Baptiste Boric 		spos = (uint16_t *) implext->data;
17899f988b79SJean-Baptiste Boric 		*spos = udf_rw16(udf_ea_cksum((uint8_t *) implext));
17909f988b79SJean-Baptiste Boric 	}
17919f988b79SJean-Baptiste Boric 
17929f988b79SJean-Baptiste Boric 	/* application use extended attributes */
17939f988b79SJean-Baptiste Boric 	assert(udf_rw32(extattr->type) != 65536);
17949f988b79SJean-Baptiste Boric 	assert(appl_attr_loc == l_ea);
17959f988b79SJean-Baptiste Boric 
17969f988b79SJean-Baptiste Boric 	/* append the attribute at the end of the current space */
17979f988b79SJean-Baptiste Boric 	bpos = data + udf_rw32(*l_eap);
17989f988b79SJean-Baptiste Boric 	a_l  = udf_rw32(extattr->a_l);
17999f988b79SJean-Baptiste Boric 
18009f988b79SJean-Baptiste Boric 	/* update impl. attribute locations */
18019f988b79SJean-Baptiste Boric 	if (udf_rw32(extattr->type) < 2048) {
18029f988b79SJean-Baptiste Boric 		impl_attr_loc = l_ea + a_l;
18039f988b79SJean-Baptiste Boric 		appl_attr_loc = l_ea + a_l;
18049f988b79SJean-Baptiste Boric 	}
18059f988b79SJean-Baptiste Boric 	if (udf_rw32(extattr->type) == 2048) {
18069f988b79SJean-Baptiste Boric 		appl_attr_loc = l_ea + a_l;
18079f988b79SJean-Baptiste Boric 	}
18089f988b79SJean-Baptiste Boric 
18099f988b79SJean-Baptiste Boric 	/* copy and advance */
18109f988b79SJean-Baptiste Boric 	memcpy(bpos, extattr, a_l);
18119f988b79SJean-Baptiste Boric 	l_ea += a_l;
18129f988b79SJean-Baptiste Boric 	*l_eap = udf_rw32(l_ea);
18139f988b79SJean-Baptiste Boric 
18149f988b79SJean-Baptiste Boric 	/* do the `dance` again backwards */
18159f988b79SJean-Baptiste Boric 	if (context.dscrver != 2) {
18169f988b79SJean-Baptiste Boric 		if (impl_attr_loc == l_ea)
18179f988b79SJean-Baptiste Boric 			impl_attr_loc = UDF_IMPL_ATTR_LOC_NOT_PRESENT;
18189f988b79SJean-Baptiste Boric 		if (appl_attr_loc == l_ea)
18199f988b79SJean-Baptiste Boric 			appl_attr_loc = UDF_APPL_ATTR_LOC_NOT_PRESENT;
18209f988b79SJean-Baptiste Boric 	}
18219f988b79SJean-Baptiste Boric 
18229f988b79SJean-Baptiste Boric 	/* store offsets */
18239f988b79SJean-Baptiste Boric 	extattrhdr->impl_attr_loc = udf_rw32(impl_attr_loc);
18249f988b79SJean-Baptiste Boric 	extattrhdr->appl_attr_loc = udf_rw32(appl_attr_loc);
18259f988b79SJean-Baptiste Boric 
18269f988b79SJean-Baptiste Boric 	/* make sure the header sums stays correct */
18279f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums((union dscrptr *) extattrhdr);
18289f988b79SJean-Baptiste Boric }
18299f988b79SJean-Baptiste Boric 
18309f988b79SJean-Baptiste Boric 
18319f988b79SJean-Baptiste Boric int
udf_create_new_fe(struct file_entry ** fep,int file_type,struct stat * st)18329f988b79SJean-Baptiste Boric udf_create_new_fe(struct file_entry **fep, int file_type, struct stat *st)
18339f988b79SJean-Baptiste Boric {
18349f988b79SJean-Baptiste Boric 	struct file_entry      *fe;
18359f988b79SJean-Baptiste Boric 	struct icb_tag         *icb;
18369f988b79SJean-Baptiste Boric 	struct timestamp        birthtime;
18379f988b79SJean-Baptiste Boric 	struct filetimes_extattr_entry *ft_extattr;
18389f988b79SJean-Baptiste Boric 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
18399f988b79SJean-Baptiste Boric 	uint16_t icbflags;
18409f988b79SJean-Baptiste Boric 
18419f988b79SJean-Baptiste Boric 	*fep = NULL;
18429f988b79SJean-Baptiste Boric 	fe = calloc(1, context.sector_size);
18439f988b79SJean-Baptiste Boric 	if (fe == NULL)
18449f988b79SJean-Baptiste Boric 		return ENOMEM;
18459f988b79SJean-Baptiste Boric 
18469f988b79SJean-Baptiste Boric 	udf_inittag(&fe->tag, TAGID_FENTRY, /* loc */ 0);
18479f988b79SJean-Baptiste Boric 	icb = &fe->icbtag;
18489f988b79SJean-Baptiste Boric 
18499f988b79SJean-Baptiste Boric 	/*
18509f988b79SJean-Baptiste Boric 	 * Always use strategy type 4 unless on WORM wich we don't support
18519f988b79SJean-Baptiste Boric 	 * (yet). Fill in defaults and set for internal allocation of data.
18529f988b79SJean-Baptiste Boric 	 */
18539f988b79SJean-Baptiste Boric 	icb->strat_type      = udf_rw16(4);
18549f988b79SJean-Baptiste Boric 	icb->max_num_entries = udf_rw16(1);
18559f988b79SJean-Baptiste Boric 	icb->file_type       = file_type;	/* 8 bit */
18569f988b79SJean-Baptiste Boric 	icb->flags           = udf_rw16(UDF_ICB_INTERN_ALLOC);
18579f988b79SJean-Baptiste Boric 
18589f988b79SJean-Baptiste Boric 	fe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
18599f988b79SJean-Baptiste Boric 	fe->link_cnt = udf_rw16(0);		/* explicit setting */
18609f988b79SJean-Baptiste Boric 
18619f988b79SJean-Baptiste Boric 	fe->ckpoint  = udf_rw32(1);		/* user supplied file version */
18629f988b79SJean-Baptiste Boric 
18639f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&birthtime);
18649f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&fe->atime);
18659f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&fe->attrtime);
18669f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&fe->mtime);
18679f988b79SJean-Baptiste Boric 
18689f988b79SJean-Baptiste Boric 	/* set attributes */
18699f988b79SJean-Baptiste Boric 	if (st) {
18709f988b79SJean-Baptiste Boric #if !HAVE_NBTOOL_CONFIG_H
18719f988b79SJean-Baptiste Boric 		udf_set_timestamp(&birthtime,    st->st_birthtime);
18729f988b79SJean-Baptiste Boric #else
18739f988b79SJean-Baptiste Boric 		udf_set_timestamp(&birthtime,    0);
18749f988b79SJean-Baptiste Boric #endif
18759f988b79SJean-Baptiste Boric 		udf_set_timestamp(&fe->atime,    st->st_atime);
18769f988b79SJean-Baptiste Boric 		udf_set_timestamp(&fe->attrtime, st->st_ctime);
18779f988b79SJean-Baptiste Boric 		udf_set_timestamp(&fe->mtime,    st->st_mtime);
18789f988b79SJean-Baptiste Boric 		fe->uid  = udf_rw32(st->st_uid);
18799f988b79SJean-Baptiste Boric 		fe->gid  = udf_rw32(st->st_gid);
18809f988b79SJean-Baptiste Boric 
18819f988b79SJean-Baptiste Boric 		fe->perm = unix_mode_to_udf_perm(st->st_mode);
18829f988b79SJean-Baptiste Boric 
18839f988b79SJean-Baptiste Boric 		icbflags = udf_rw16(fe->icbtag.flags);
18849f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
18859f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
18869f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
18879f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISUID)
18889f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
18899f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISGID)
18909f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
18919f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISVTX)
18929f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
18939f988b79SJean-Baptiste Boric 		fe->icbtag.flags  = udf_rw16(icbflags);
18949f988b79SJean-Baptiste Boric 	}
18959f988b79SJean-Baptiste Boric 
18969f988b79SJean-Baptiste Boric 	udf_set_regid(&fe->imp_id, context.impl_name);
18979f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&fe->imp_id);
18989f988b79SJean-Baptiste Boric 	fe->unique_id = udf_rw64(context.unique_id);
18999f988b79SJean-Baptiste Boric 	udf_advance_uniqueid();
19009f988b79SJean-Baptiste Boric 
19019f988b79SJean-Baptiste Boric 	fe->l_ea = udf_rw32(0);
19029f988b79SJean-Baptiste Boric 
19039f988b79SJean-Baptiste Boric 	/* create extended attribute to record our creation time */
19049f988b79SJean-Baptiste Boric 	ft_extattr = calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
19059f988b79SJean-Baptiste Boric 	ft_extattr->hdr.type = udf_rw32(UDF_FILETIMES_ATTR_NO);
19069f988b79SJean-Baptiste Boric 	ft_extattr->hdr.subtype = 1;	/* [4/48.10.5] */
19079f988b79SJean-Baptiste Boric 	ft_extattr->hdr.a_l = udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
19089f988b79SJean-Baptiste Boric 	ft_extattr->d_l     = udf_rw32(UDF_TIMESTAMP_SIZE); /* one item */
19099f988b79SJean-Baptiste Boric 	ft_extattr->existence = UDF_FILETIMES_FILE_CREATION;
19109f988b79SJean-Baptiste Boric 	ft_extattr->times[0]  = birthtime;
19119f988b79SJean-Baptiste Boric 
19129f988b79SJean-Baptiste Boric 	udf_extattr_append_internal((union dscrptr *) fe,
19139f988b79SJean-Baptiste Boric 		(struct extattr_entry *) ft_extattr);
19149f988b79SJean-Baptiste Boric 	free(ft_extattr);
19159f988b79SJean-Baptiste Boric 
19169f988b79SJean-Baptiste Boric 	/* record fidlength information */
19179f988b79SJean-Baptiste Boric 	fe->inf_len = udf_rw64(0);
19189f988b79SJean-Baptiste Boric 	fe->l_ad    = udf_rw32(0);
19199f988b79SJean-Baptiste Boric 	fe->logblks_rec = udf_rw64(0);		/* intern */
19209f988b79SJean-Baptiste Boric 
19219f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
19229f988b79SJean-Baptiste Boric 	crclen += udf_rw32(fe->l_ea);
19239f988b79SJean-Baptiste Boric 
19249f988b79SJean-Baptiste Boric 	/* make sure the header sums stays correct */
19259f988b79SJean-Baptiste Boric 	fe->tag.desc_crc_len = udf_rw16(crclen);
19269f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums((union dscrptr *) fe);
19279f988b79SJean-Baptiste Boric 
19289f988b79SJean-Baptiste Boric 	*fep = fe;
19299f988b79SJean-Baptiste Boric 	return 0;
19309f988b79SJean-Baptiste Boric }
19319f988b79SJean-Baptiste Boric 
19329f988b79SJean-Baptiste Boric 
19339f988b79SJean-Baptiste Boric int
udf_create_new_efe(struct extfile_entry ** efep,int file_type,struct stat * st)19349f988b79SJean-Baptiste Boric udf_create_new_efe(struct extfile_entry **efep, int file_type, struct stat *st)
19359f988b79SJean-Baptiste Boric {
19369f988b79SJean-Baptiste Boric 	struct extfile_entry *efe;
19379f988b79SJean-Baptiste Boric 	struct icb_tag       *icb;
19389f988b79SJean-Baptiste Boric 	uint32_t crclen;	/* XXX: should be 16; need to detect overflow */
19399f988b79SJean-Baptiste Boric 	uint16_t icbflags;
19409f988b79SJean-Baptiste Boric 
19419f988b79SJean-Baptiste Boric 	*efep = NULL;
19429f988b79SJean-Baptiste Boric 	efe = calloc(1, context.sector_size);
19439f988b79SJean-Baptiste Boric 	if (efe == NULL)
19449f988b79SJean-Baptiste Boric 		return ENOMEM;
19459f988b79SJean-Baptiste Boric 
19469f988b79SJean-Baptiste Boric 	udf_inittag(&efe->tag, TAGID_EXTFENTRY, /* loc */ 0);
19479f988b79SJean-Baptiste Boric 	icb = &efe->icbtag;
19489f988b79SJean-Baptiste Boric 
19499f988b79SJean-Baptiste Boric 	/*
19509f988b79SJean-Baptiste Boric 	 * Always use strategy type 4 unless on WORM wich we don't support
19519f988b79SJean-Baptiste Boric 	 * (yet). Fill in defaults and set for internal allocation of data.
19529f988b79SJean-Baptiste Boric 	 */
19539f988b79SJean-Baptiste Boric 	icb->strat_type      = udf_rw16(4);
19549f988b79SJean-Baptiste Boric 	icb->max_num_entries = udf_rw16(1);
19559f988b79SJean-Baptiste Boric 	icb->file_type       = file_type;	/* 8 bit */
19569f988b79SJean-Baptiste Boric 	icb->flags = udf_rw16(UDF_ICB_INTERN_ALLOC);
19579f988b79SJean-Baptiste Boric 
19589f988b79SJean-Baptiste Boric 	efe->perm     = udf_rw32(0x7fff);	/* all is allowed   */
19599f988b79SJean-Baptiste Boric 	efe->link_cnt = udf_rw16(0);		/* explicit setting */
19609f988b79SJean-Baptiste Boric 
19619f988b79SJean-Baptiste Boric 	efe->ckpoint  = udf_rw32(1);		/* user supplied file version */
19629f988b79SJean-Baptiste Boric 
19639f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&efe->ctime);
19649f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&efe->atime);
19659f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&efe->attrtime);
19669f988b79SJean-Baptiste Boric 	udf_set_timestamp_now(&efe->mtime);
19679f988b79SJean-Baptiste Boric 
19689f988b79SJean-Baptiste Boric 	/* set attributes */
19699f988b79SJean-Baptiste Boric 	if (st) {
19709f988b79SJean-Baptiste Boric #if !HAVE_NBTOOL_CONFIG_H
19719f988b79SJean-Baptiste Boric 		udf_set_timestamp(&efe->ctime,    st->st_birthtime);
19729f988b79SJean-Baptiste Boric #else
19739f988b79SJean-Baptiste Boric 		udf_set_timestamp(&efe->ctime,    0);
19749f988b79SJean-Baptiste Boric #endif
19759f988b79SJean-Baptiste Boric 		udf_set_timestamp(&efe->atime,    st->st_atime);
19769f988b79SJean-Baptiste Boric 		udf_set_timestamp(&efe->attrtime, st->st_ctime);
19779f988b79SJean-Baptiste Boric 		udf_set_timestamp(&efe->mtime,    st->st_mtime);
19789f988b79SJean-Baptiste Boric 		efe->uid = udf_rw32(st->st_uid);
19799f988b79SJean-Baptiste Boric 		efe->gid = udf_rw32(st->st_gid);
19809f988b79SJean-Baptiste Boric 
19819f988b79SJean-Baptiste Boric 		efe->perm = unix_mode_to_udf_perm(st->st_mode);
19829f988b79SJean-Baptiste Boric 
19839f988b79SJean-Baptiste Boric 		icbflags = udf_rw16(efe->icbtag.flags);
19849f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETUID;
19859f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_SETGID;
19869f988b79SJean-Baptiste Boric 		icbflags &= ~UDF_ICB_TAG_FLAGS_STICKY;
19879f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISUID)
19889f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_SETUID;
19899f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISGID)
19909f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_SETGID;
19919f988b79SJean-Baptiste Boric 		if (st->st_mode & S_ISVTX)
19929f988b79SJean-Baptiste Boric 			icbflags |= UDF_ICB_TAG_FLAGS_STICKY;
19939f988b79SJean-Baptiste Boric 		efe->icbtag.flags = udf_rw16(icbflags);
19949f988b79SJean-Baptiste Boric 	}
19959f988b79SJean-Baptiste Boric 
19969f988b79SJean-Baptiste Boric 	udf_set_regid(&efe->imp_id, context.impl_name);
19979f988b79SJean-Baptiste Boric 	udf_add_impl_regid(&efe->imp_id);
19989f988b79SJean-Baptiste Boric 
19999f988b79SJean-Baptiste Boric 	efe->unique_id = udf_rw64(context.unique_id);
20009f988b79SJean-Baptiste Boric 	udf_advance_uniqueid();
20019f988b79SJean-Baptiste Boric 
20029f988b79SJean-Baptiste Boric 	/* record fidlength information */
20039f988b79SJean-Baptiste Boric 	efe->inf_len  = udf_rw64(0);
20049f988b79SJean-Baptiste Boric 	efe->obj_size = udf_rw64(0);
20059f988b79SJean-Baptiste Boric 	efe->l_ad     = udf_rw32(0);
20069f988b79SJean-Baptiste Boric 	efe->logblks_rec = udf_rw64(0);
20079f988b79SJean-Baptiste Boric 
20089f988b79SJean-Baptiste Boric 	crclen  = sizeof(struct extfile_entry) - 1 - UDF_DESC_TAG_LENGTH;
20099f988b79SJean-Baptiste Boric 
20109f988b79SJean-Baptiste Boric 	/* make sure the header sums stays correct */
20119f988b79SJean-Baptiste Boric 	efe->tag.desc_crc_len = udf_rw16(crclen);
20129f988b79SJean-Baptiste Boric 	udf_validate_tag_and_crc_sums((union dscrptr *) efe);
20139f988b79SJean-Baptiste Boric 
20149f988b79SJean-Baptiste Boric 	*efep = efe;
20159f988b79SJean-Baptiste Boric 	return 0;
20169f988b79SJean-Baptiste Boric }
20179f988b79SJean-Baptiste Boric 
20189f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
20199f988b79SJean-Baptiste Boric 
20209f988b79SJean-Baptiste Boric /* for METADATA file appending only */
20219f988b79SJean-Baptiste Boric static void
udf_append_meta_mapping_part_to_efe(struct extfile_entry * efe,struct short_ad * mapping)20229f988b79SJean-Baptiste Boric udf_append_meta_mapping_part_to_efe(struct extfile_entry *efe,
20239f988b79SJean-Baptiste Boric 		struct short_ad *mapping)
20249f988b79SJean-Baptiste Boric {
20259f988b79SJean-Baptiste Boric 	struct icb_tag *icb;
20269f988b79SJean-Baptiste Boric 	uint64_t inf_len, obj_size, logblks_rec;
20279f988b79SJean-Baptiste Boric 	uint32_t l_ad, l_ea;
20289f988b79SJean-Baptiste Boric 	uint16_t crclen;
20299f988b79SJean-Baptiste Boric 	uint8_t *bpos;
20309f988b79SJean-Baptiste Boric 
20319f988b79SJean-Baptiste Boric 	inf_len     = udf_rw64(efe->inf_len);
20329f988b79SJean-Baptiste Boric 	obj_size    = udf_rw64(efe->obj_size);
20339f988b79SJean-Baptiste Boric 	logblks_rec = udf_rw64(efe->logblks_rec);
20349f988b79SJean-Baptiste Boric 	l_ad   = udf_rw32(efe->l_ad);
20359f988b79SJean-Baptiste Boric 	l_ea   = udf_rw32(efe->l_ea);
20369f988b79SJean-Baptiste Boric 	crclen = udf_rw16(efe->tag.desc_crc_len);
20379f988b79SJean-Baptiste Boric 	icb    = &efe->icbtag;
20389f988b79SJean-Baptiste Boric 
20399f988b79SJean-Baptiste Boric 	/* set our allocation to shorts if not already done */
20409f988b79SJean-Baptiste Boric 	icb->flags = udf_rw16(UDF_ICB_SHORT_ALLOC);
20419f988b79SJean-Baptiste Boric 
20429f988b79SJean-Baptiste Boric 	/* append short_ad */
20439f988b79SJean-Baptiste Boric 	bpos = (uint8_t *) efe->data + l_ea + l_ad;
20449f988b79SJean-Baptiste Boric 	memcpy(bpos, mapping, sizeof(struct short_ad));
20459f988b79SJean-Baptiste Boric 
20469f988b79SJean-Baptiste Boric 	l_ad   += sizeof(struct short_ad);
20479f988b79SJean-Baptiste Boric 	crclen += sizeof(struct short_ad);
20489f988b79SJean-Baptiste Boric 	inf_len  += UDF_EXT_LEN(udf_rw32(mapping->len));
20499f988b79SJean-Baptiste Boric 	obj_size += UDF_EXT_LEN(udf_rw32(mapping->len));
20509f988b79SJean-Baptiste Boric 	logblks_rec = UDF_ROUNDUP(inf_len, context.sector_size) /
20519f988b79SJean-Baptiste Boric 				context.sector_size;
20529f988b79SJean-Baptiste Boric 
20539f988b79SJean-Baptiste Boric 	efe->l_ad = udf_rw32(l_ad);
20549f988b79SJean-Baptiste Boric 	efe->inf_len     = udf_rw64(inf_len);
20559f988b79SJean-Baptiste Boric 	efe->obj_size    = udf_rw64(obj_size);
20569f988b79SJean-Baptiste Boric 	efe->logblks_rec = udf_rw64(logblks_rec);
20579f988b79SJean-Baptiste Boric 	efe->tag.desc_crc_len = udf_rw16(crclen);
20589f988b79SJean-Baptiste Boric }
20599f988b79SJean-Baptiste Boric 
20609f988b79SJean-Baptiste Boric 
20619f988b79SJean-Baptiste Boric /* for METADATA file appending only */
20629f988b79SJean-Baptiste Boric static void
udf_append_meta_mapping_to_efe(struct extfile_entry * efe,uint16_t partnr,uint32_t lb_num,uint64_t len)20639f988b79SJean-Baptiste Boric udf_append_meta_mapping_to_efe(struct extfile_entry *efe,
20649f988b79SJean-Baptiste Boric 		uint16_t partnr, uint32_t lb_num,
20659f988b79SJean-Baptiste Boric 	uint64_t len)
20669f988b79SJean-Baptiste Boric {
20679f988b79SJean-Baptiste Boric 	struct short_ad mapping;
20689f988b79SJean-Baptiste Boric 	uint64_t max_len, part_len;
20699f988b79SJean-Baptiste Boric 
20709f988b79SJean-Baptiste Boric 	/* calculate max length meta allocation sizes */
20719f988b79SJean-Baptiste Boric 	max_len = UDF_EXT_MAXLEN / context.sector_size; /* in sectors */
20729f988b79SJean-Baptiste Boric 	max_len = (max_len / layout.meta_blockingnr) * layout.meta_blockingnr;
20739f988b79SJean-Baptiste Boric 	max_len = max_len * context.sector_size;
20749f988b79SJean-Baptiste Boric 
20759f988b79SJean-Baptiste Boric 	memset(&mapping, 0, sizeof(mapping));
20769f988b79SJean-Baptiste Boric 	while (len) {
20779f988b79SJean-Baptiste Boric 		part_len = MIN(len, max_len);
20789f988b79SJean-Baptiste Boric 		mapping.lb_num   = udf_rw32(lb_num);
20799f988b79SJean-Baptiste Boric 		mapping.len      = udf_rw32(part_len);
20809f988b79SJean-Baptiste Boric 
20819f988b79SJean-Baptiste Boric 		udf_append_meta_mapping_part_to_efe(efe, &mapping);
20829f988b79SJean-Baptiste Boric 
20839f988b79SJean-Baptiste Boric 		lb_num += part_len / context.sector_size;
20849f988b79SJean-Baptiste Boric 		len    -= part_len;
20859f988b79SJean-Baptiste Boric 	}
20869f988b79SJean-Baptiste Boric }
20879f988b79SJean-Baptiste Boric 
20889f988b79SJean-Baptiste Boric 
20899f988b79SJean-Baptiste Boric int
udf_create_meta_files(void)20909f988b79SJean-Baptiste Boric udf_create_meta_files(void)
20919f988b79SJean-Baptiste Boric {
20929f988b79SJean-Baptiste Boric 	struct extfile_entry *efe;
20939f988b79SJean-Baptiste Boric 	struct long_ad meta_icb;
20949f988b79SJean-Baptiste Boric 	uint64_t bytes;
20959f988b79SJean-Baptiste Boric 	uint32_t sector_size;
20969f988b79SJean-Baptiste Boric 	int filetype, error;
20979f988b79SJean-Baptiste Boric 
20989f988b79SJean-Baptiste Boric 	sector_size = context.sector_size;
20999f988b79SJean-Baptiste Boric 
21009f988b79SJean-Baptiste Boric 	memset(&meta_icb, 0, sizeof(meta_icb));
21019f988b79SJean-Baptiste Boric 	meta_icb.len          = udf_rw32(sector_size);
21029f988b79SJean-Baptiste Boric 	meta_icb.loc.part_num = udf_rw16(context.data_part);
21039f988b79SJean-Baptiste Boric 
21049f988b79SJean-Baptiste Boric 	/* create metadata file */
21059f988b79SJean-Baptiste Boric 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_file);
21069f988b79SJean-Baptiste Boric 	filetype = UDF_ICB_FILETYPE_META_MAIN;
21079f988b79SJean-Baptiste Boric 	error = udf_create_new_efe(&efe, filetype, NULL);
21089f988b79SJean-Baptiste Boric 	if (error)
21099f988b79SJean-Baptiste Boric 		return error;
21109f988b79SJean-Baptiste Boric 	context.meta_file = efe;
21119f988b79SJean-Baptiste Boric 
21129f988b79SJean-Baptiste Boric 	/* create metadata mirror file */
21139f988b79SJean-Baptiste Boric 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_mirror);
21149f988b79SJean-Baptiste Boric 	filetype = UDF_ICB_FILETYPE_META_MIRROR;
21159f988b79SJean-Baptiste Boric 	error = udf_create_new_efe(&efe, filetype, NULL);
21169f988b79SJean-Baptiste Boric 	if (error)
21179f988b79SJean-Baptiste Boric 		return error;
21189f988b79SJean-Baptiste Boric 	context.meta_mirror = efe;
21199f988b79SJean-Baptiste Boric 
21209f988b79SJean-Baptiste Boric 	/* create metadata bitmap file */
21219f988b79SJean-Baptiste Boric 	meta_icb.loc.lb_num   = udf_rw32(layout.meta_bitmap);
21229f988b79SJean-Baptiste Boric 	filetype = UDF_ICB_FILETYPE_META_BITMAP;
21239f988b79SJean-Baptiste Boric 	error = udf_create_new_efe(&efe, filetype, NULL);
21249f988b79SJean-Baptiste Boric 	if (error)
21259f988b79SJean-Baptiste Boric 		return error;
21269f988b79SJean-Baptiste Boric 	context.meta_bitmap = efe;
21279f988b79SJean-Baptiste Boric 
21289f988b79SJean-Baptiste Boric 	/* patch up files */
21299f988b79SJean-Baptiste Boric 	context.meta_file->unique_id   = udf_rw64(0);
21309f988b79SJean-Baptiste Boric 	context.meta_mirror->unique_id = udf_rw64(0);
21319f988b79SJean-Baptiste Boric 	context.meta_bitmap->unique_id = udf_rw64(0);
21329f988b79SJean-Baptiste Boric 
21339f988b79SJean-Baptiste Boric 	/* restart unique id */
21349f988b79SJean-Baptiste Boric 	context.unique_id = 0x10;
21359f988b79SJean-Baptiste Boric 
21369f988b79SJean-Baptiste Boric 	/* XXX no support for metadata mirroring yet */
21379f988b79SJean-Baptiste Boric 	/* insert extents */
21389f988b79SJean-Baptiste Boric 	efe = context.meta_file;
21399f988b79SJean-Baptiste Boric 	udf_append_meta_mapping_to_efe(efe, context.data_part,
21409f988b79SJean-Baptiste Boric 		layout.meta_part_start_lba,
21419f988b79SJean-Baptiste Boric 		(uint64_t) layout.meta_part_size_lba * sector_size);
21429f988b79SJean-Baptiste Boric 
21439f988b79SJean-Baptiste Boric 	efe = context.meta_mirror;
21449f988b79SJean-Baptiste Boric 	udf_append_meta_mapping_to_efe(efe, context.data_part,
21459f988b79SJean-Baptiste Boric 		layout.meta_part_start_lba,
21469f988b79SJean-Baptiste Boric 		(uint64_t) layout.meta_part_size_lba * sector_size);
21479f988b79SJean-Baptiste Boric 
21489f988b79SJean-Baptiste Boric 	efe = context.meta_bitmap;
21499f988b79SJean-Baptiste Boric 	bytes = udf_space_bitmap_len(layout.meta_part_size_lba);
21509f988b79SJean-Baptiste Boric 	udf_append_meta_mapping_to_efe(efe, context.data_part,
21519f988b79SJean-Baptiste Boric 		layout.meta_bitmap_space, bytes);
21529f988b79SJean-Baptiste Boric 
21539f988b79SJean-Baptiste Boric 	return 0;
21549f988b79SJean-Baptiste Boric }
21559f988b79SJean-Baptiste Boric 
21569f988b79SJean-Baptiste Boric 
21579f988b79SJean-Baptiste Boric /* --------------------------------------------------------------------- */
21589f988b79SJean-Baptiste Boric 
21599f988b79SJean-Baptiste Boric int
udf_create_new_rootdir(union dscrptr ** dscr)21609f988b79SJean-Baptiste Boric udf_create_new_rootdir(union dscrptr **dscr)
21619f988b79SJean-Baptiste Boric {
21629f988b79SJean-Baptiste Boric 	struct file_entry *fe;
21639f988b79SJean-Baptiste Boric 	struct extfile_entry *efe;
21649f988b79SJean-Baptiste Boric 	struct long_ad root_icb;
21659f988b79SJean-Baptiste Boric 	int filetype, error;
21669f988b79SJean-Baptiste Boric 
2167*e1cdaee1SLionel Sambuc #if defined(__minix)
2168*e1cdaee1SLionel Sambuc 	/* LSC: -Werror=maybe-uninitialized when compiling with -O3 */
2169*e1cdaee1SLionel Sambuc 	fe = NULL;
2170*e1cdaee1SLionel Sambuc #endif /*defined(__minix) */
21719f988b79SJean-Baptiste Boric 	memset(&root_icb, 0, sizeof(root_icb));
21729f988b79SJean-Baptiste Boric 	root_icb.len          = udf_rw32(context.sector_size);
21739f988b79SJean-Baptiste Boric 	root_icb.loc.lb_num   = udf_rw32(layout.rootdir);
21749f988b79SJean-Baptiste Boric 	root_icb.loc.part_num = udf_rw16(context.metadata_part);
21759f988b79SJean-Baptiste Boric 
21769f988b79SJean-Baptiste Boric 	filetype = UDF_ICB_FILETYPE_DIRECTORY;
21779f988b79SJean-Baptiste Boric 	if (context.dscrver == 2) {
21789f988b79SJean-Baptiste Boric 		error = udf_create_new_fe(&fe, filetype, NULL);
21799f988b79SJean-Baptiste Boric 		*dscr = (union dscrptr *) fe;
21809f988b79SJean-Baptiste Boric 	} else {
21819f988b79SJean-Baptiste Boric 		error = udf_create_new_efe(&efe, filetype, NULL);
21829f988b79SJean-Baptiste Boric 		*dscr = (union dscrptr *) efe;
21839f988b79SJean-Baptiste Boric 	}
21849f988b79SJean-Baptiste Boric 	if (error)
21859f988b79SJean-Baptiste Boric 		return error;
21869f988b79SJean-Baptiste Boric 
21879f988b79SJean-Baptiste Boric 	/* append '..' */
21889f988b79SJean-Baptiste Boric 	udf_append_parentfid(*dscr, &root_icb);
21899f988b79SJean-Baptiste Boric 
21909f988b79SJean-Baptiste Boric 	/* rootdir has explicit only one link on creation; '..' is no link */
21919f988b79SJean-Baptiste Boric 	if (context.dscrver == 2) {
21929f988b79SJean-Baptiste Boric 		fe->link_cnt  = udf_rw16(1);
21939f988b79SJean-Baptiste Boric 	} else {
21949f988b79SJean-Baptiste Boric 		efe->link_cnt = udf_rw16(1);
21959f988b79SJean-Baptiste Boric 	}
21969f988b79SJean-Baptiste Boric 
21979f988b79SJean-Baptiste Boric 	context.num_directories++;
21989f988b79SJean-Baptiste Boric 	assert(context.num_directories == 1);
21999f988b79SJean-Baptiste Boric 
22009f988b79SJean-Baptiste Boric 	return 0;
22019f988b79SJean-Baptiste Boric }
22029f988b79SJean-Baptiste Boric 
22039f988b79SJean-Baptiste Boric 
22049f988b79SJean-Baptiste Boric void
udf_prepend_VAT_file(void)22059f988b79SJean-Baptiste Boric udf_prepend_VAT_file(void)
22069f988b79SJean-Baptiste Boric {
22079f988b79SJean-Baptiste Boric 	/* old style VAT has no prepend */
22089f988b79SJean-Baptiste Boric 	if (context.dscrver == 2) {
22099f988b79SJean-Baptiste Boric 		context.vat_start = 0;
22109f988b79SJean-Baptiste Boric 		context.vat_size  = 0;
22119f988b79SJean-Baptiste Boric 		return;
22129f988b79SJean-Baptiste Boric 	}
22139f988b79SJean-Baptiste Boric 
22149f988b79SJean-Baptiste Boric 	context.vat_start = offsetof(struct udf_vat, data);
22159f988b79SJean-Baptiste Boric 	context.vat_size  = offsetof(struct udf_vat, data);
22169f988b79SJean-Baptiste Boric }
22179f988b79SJean-Baptiste Boric 
22189f988b79SJean-Baptiste Boric 
22199f988b79SJean-Baptiste Boric void
udf_vat_update(uint32_t virt,uint32_t phys)22209f988b79SJean-Baptiste Boric udf_vat_update(uint32_t virt, uint32_t phys)
22219f988b79SJean-Baptiste Boric {
22229f988b79SJean-Baptiste Boric 	uint32_t *vatpos;
22239f988b79SJean-Baptiste Boric 	uint32_t new_size;
22249f988b79SJean-Baptiste Boric 
22259f988b79SJean-Baptiste Boric 	if (context.vtop_tp[context.metadata_part] != UDF_VTOP_TYPE_VIRT)
22269f988b79SJean-Baptiste Boric 		return;
22279f988b79SJean-Baptiste Boric 
22289f988b79SJean-Baptiste Boric 	new_size = MAX(context.vat_size,
22299f988b79SJean-Baptiste Boric 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
22309f988b79SJean-Baptiste Boric 
22319f988b79SJean-Baptiste Boric 	if (new_size > context.vat_allocated) {
22329f988b79SJean-Baptiste Boric 		context.vat_allocated =
22339f988b79SJean-Baptiste Boric 			UDF_ROUNDUP(new_size, context.sector_size);
22349f988b79SJean-Baptiste Boric 		context.vat_contents = realloc(context.vat_contents,
22359f988b79SJean-Baptiste Boric 			context.vat_allocated);
22369f988b79SJean-Baptiste Boric 		assert(context.vat_contents);
22379f988b79SJean-Baptiste Boric 		/* XXX could also report error */
22389f988b79SJean-Baptiste Boric 	}
22399f988b79SJean-Baptiste Boric 	vatpos  = (uint32_t *) (context.vat_contents + context.vat_start);
22409f988b79SJean-Baptiste Boric 	vatpos[virt] = udf_rw32(phys);
22419f988b79SJean-Baptiste Boric 
22429f988b79SJean-Baptiste Boric 	context.vat_size = MAX(context.vat_size,
22439f988b79SJean-Baptiste Boric 		(context.vat_start + (virt+1)*sizeof(uint32_t)));
22449f988b79SJean-Baptiste Boric }
22459f988b79SJean-Baptiste Boric 
22469f988b79SJean-Baptiste Boric 
22479f988b79SJean-Baptiste Boric int
udf_append_VAT_file(void)22489f988b79SJean-Baptiste Boric udf_append_VAT_file(void)
22499f988b79SJean-Baptiste Boric {
22509f988b79SJean-Baptiste Boric 	struct udf_oldvat_tail *oldvat_tail;
22519f988b79SJean-Baptiste Boric 	struct udf_vat *vathdr;
22529f988b79SJean-Baptiste Boric 	int32_t len_diff;
22539f988b79SJean-Baptiste Boric 
22549f988b79SJean-Baptiste Boric 	/* new style VAT has VAT LVInt analog in front */
22559f988b79SJean-Baptiste Boric 	if (context.dscrver == 3) {
22569f988b79SJean-Baptiste Boric 		/* set up VATv2 descriptor */
22579f988b79SJean-Baptiste Boric 		vathdr = (struct udf_vat *) context.vat_contents;
22589f988b79SJean-Baptiste Boric 		vathdr->header_len      = udf_rw16(sizeof(struct udf_vat) - 1);
22599f988b79SJean-Baptiste Boric 		vathdr->impl_use_len    = udf_rw16(0);
22609f988b79SJean-Baptiste Boric 		memcpy(vathdr->logvol_id, context.logical_vol->logvol_id, 128);
22619f988b79SJean-Baptiste Boric 		vathdr->prev_vat        = udf_rw32(UDF_NO_PREV_VAT);
22629f988b79SJean-Baptiste Boric 		vathdr->num_files       = udf_rw32(context.num_files);
22639f988b79SJean-Baptiste Boric 		vathdr->num_directories = udf_rw32(context.num_directories);
22649f988b79SJean-Baptiste Boric 
22659f988b79SJean-Baptiste Boric 		vathdr->min_udf_readver  = udf_rw16(context.min_udf);
22669f988b79SJean-Baptiste Boric 		vathdr->min_udf_writever = udf_rw16(context.min_udf);
22679f988b79SJean-Baptiste Boric 		vathdr->max_udf_writever = udf_rw16(context.max_udf);
22689f988b79SJean-Baptiste Boric 
22699f988b79SJean-Baptiste Boric 		return 0;
22709f988b79SJean-Baptiste Boric 	}
22719f988b79SJean-Baptiste Boric 
22729f988b79SJean-Baptiste Boric 	/* old style VAT has identifier appended */
22739f988b79SJean-Baptiste Boric 
22749f988b79SJean-Baptiste Boric 	/* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
22759f988b79SJean-Baptiste Boric 	len_diff = context.vat_allocated - context.vat_size;
22769f988b79SJean-Baptiste Boric 	assert(len_diff >= 0);
22779f988b79SJean-Baptiste Boric 	if (len_diff < (int32_t) sizeof(struct udf_oldvat_tail)) {
22789f988b79SJean-Baptiste Boric 		context.vat_allocated += context.sector_size;
22799f988b79SJean-Baptiste Boric 		context.vat_contents = realloc(context.vat_contents,
22809f988b79SJean-Baptiste Boric 			context.vat_allocated);
22819f988b79SJean-Baptiste Boric 		assert(context.vat_contents);
22829f988b79SJean-Baptiste Boric 		/* XXX could also report error */
22839f988b79SJean-Baptiste Boric 	}
22849f988b79SJean-Baptiste Boric 
22859f988b79SJean-Baptiste Boric 	oldvat_tail = (struct udf_oldvat_tail *) (context.vat_contents +
22869f988b79SJean-Baptiste Boric 			context.vat_size);
22879f988b79SJean-Baptiste Boric 
22889f988b79SJean-Baptiste Boric 	udf_set_regid(&oldvat_tail->id, "*UDF Virtual Alloc Tbl");
22899f988b79SJean-Baptiste Boric 	udf_add_udf_regid(&oldvat_tail->id);
22909f988b79SJean-Baptiste Boric 	oldvat_tail->prev_vat = udf_rw32(UDF_NO_PREV_VAT);
22919f988b79SJean-Baptiste Boric 
22929f988b79SJean-Baptiste Boric 	context.vat_size += sizeof(struct udf_oldvat_tail);
22939f988b79SJean-Baptiste Boric 
22949f988b79SJean-Baptiste Boric 	return 0;
22959f988b79SJean-Baptiste Boric }
22969f988b79SJean-Baptiste Boric 
22979f988b79SJean-Baptiste Boric 
22989f988b79SJean-Baptiste Boric int
udf_create_VAT(union dscrptr ** vat_dscr)22999f988b79SJean-Baptiste Boric udf_create_VAT(union dscrptr **vat_dscr)
23009f988b79SJean-Baptiste Boric {
23019f988b79SJean-Baptiste Boric 	struct file_entry *fe;
23029f988b79SJean-Baptiste Boric 	struct extfile_entry *efe;
23039f988b79SJean-Baptiste Boric 	struct impl_extattr_entry *implext;
23049f988b79SJean-Baptiste Boric 	struct vatlvext_extattr_entry *vatlvext;
23059f988b79SJean-Baptiste Boric 	struct long_ad dataloc, *allocpos;
23069f988b79SJean-Baptiste Boric 	uint8_t *bpos, *extattr;
23079f988b79SJean-Baptiste Boric 	uint32_t ea_len, inf_len, vat_len, blks;
23089f988b79SJean-Baptiste Boric 	int filetype;
23099f988b79SJean-Baptiste Boric 	int error;
23109f988b79SJean-Baptiste Boric 
23119f988b79SJean-Baptiste Boric 	assert((layout.rootdir < 2) && (layout.fsd < 2));
23129f988b79SJean-Baptiste Boric 
23139f988b79SJean-Baptiste Boric 	memset(&dataloc, 0, sizeof(dataloc));
23149f988b79SJean-Baptiste Boric 	dataloc.len = udf_rw32(context.vat_size);
23159f988b79SJean-Baptiste Boric 	dataloc.loc.part_num = udf_rw16(context.data_part);
23169f988b79SJean-Baptiste Boric 	dataloc.loc.lb_num   = udf_rw32(layout.vat);
23179f988b79SJean-Baptiste Boric 
23189f988b79SJean-Baptiste Boric 	if (context.dscrver == 2) {
23199f988b79SJean-Baptiste Boric 		/* old style VAT */
23209f988b79SJean-Baptiste Boric 		filetype = UDF_ICB_FILETYPE_UNKNOWN;
23219f988b79SJean-Baptiste Boric 		error = udf_create_new_fe(&fe, filetype, NULL);
23229f988b79SJean-Baptiste Boric 		if (error)
23239f988b79SJean-Baptiste Boric 			return error;
23249f988b79SJean-Baptiste Boric 
23259f988b79SJean-Baptiste Boric 		/* append VAT LVExtension attribute */
23269f988b79SJean-Baptiste Boric 		ea_len = sizeof(struct impl_extattr_entry) - 1 +
23279f988b79SJean-Baptiste Boric 			 sizeof(struct vatlvext_extattr_entry) + 4;
23289f988b79SJean-Baptiste Boric 
23299f988b79SJean-Baptiste Boric 		extattr = calloc(1, ea_len);
23309f988b79SJean-Baptiste Boric 
23319f988b79SJean-Baptiste Boric 		implext  = (struct impl_extattr_entry *) extattr;
23329f988b79SJean-Baptiste Boric 		implext->hdr.type = udf_rw32(2048);	/* [4/48.10.8] */
23339f988b79SJean-Baptiste Boric 		implext->hdr.subtype = 1;		/* [4/48.10.8.2] */
23349f988b79SJean-Baptiste Boric 		implext->hdr.a_l = udf_rw32(ea_len);	/* VAT LVext EA size */
23359f988b79SJean-Baptiste Boric 		/* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
23369f988b79SJean-Baptiste Boric 		implext->iu_l = udf_rw32(4);
23379f988b79SJean-Baptiste Boric 		udf_set_regid(&implext->imp_id, "*UDF VAT LVExtension");
23389f988b79SJean-Baptiste Boric 		udf_add_udf_regid(&implext->imp_id);
23399f988b79SJean-Baptiste Boric 
23409f988b79SJean-Baptiste Boric 		/* VAT LVExtension data follows UDF IU space */
23419f988b79SJean-Baptiste Boric 		bpos = ((uint8_t *) implext->data) + 4;
23429f988b79SJean-Baptiste Boric 		vatlvext = (struct vatlvext_extattr_entry *) bpos;
23439f988b79SJean-Baptiste Boric 
23449f988b79SJean-Baptiste Boric 		vatlvext->unique_id_chk = udf_rw64(fe->unique_id);
23459f988b79SJean-Baptiste Boric 		vatlvext->num_files = udf_rw32(context.num_files);
23469f988b79SJean-Baptiste Boric 		vatlvext->num_directories = udf_rw32(context.num_directories);
23479f988b79SJean-Baptiste Boric 		memcpy(vatlvext->logvol_id, context.logical_vol->logvol_id,128);
23489f988b79SJean-Baptiste Boric 
23499f988b79SJean-Baptiste Boric 		udf_extattr_append_internal((union dscrptr *) fe,
23509f988b79SJean-Baptiste Boric 			(struct extattr_entry *) extattr);
23519f988b79SJean-Baptiste Boric 
23529f988b79SJean-Baptiste Boric 		free(extattr);
23539f988b79SJean-Baptiste Boric 
23549f988b79SJean-Baptiste Boric 		fe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
23559f988b79SJean-Baptiste Boric 
23569f988b79SJean-Baptiste Boric 		allocpos = (struct long_ad *) (fe->data + udf_rw32(fe->l_ea));
23579f988b79SJean-Baptiste Boric 		*allocpos = dataloc;
23589f988b79SJean-Baptiste Boric 
23599f988b79SJean-Baptiste Boric 		/* set length */
23609f988b79SJean-Baptiste Boric 		inf_len = context.vat_size;
23619f988b79SJean-Baptiste Boric 		fe->inf_len = udf_rw64(inf_len);
23629f988b79SJean-Baptiste Boric 		fe->l_ad    = udf_rw32(sizeof(struct long_ad));
23639f988b79SJean-Baptiste Boric 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
23649f988b79SJean-Baptiste Boric 			context.sector_size;
23659f988b79SJean-Baptiste Boric 		fe->logblks_rec = udf_rw32(blks);
23669f988b79SJean-Baptiste Boric 
23679f988b79SJean-Baptiste Boric 		/* update vat descriptor's CRC length */
23689f988b79SJean-Baptiste Boric 		vat_len  = sizeof(struct file_entry) - 1 - UDF_DESC_TAG_LENGTH;
23699f988b79SJean-Baptiste Boric 		vat_len += udf_rw32(fe->l_ad) + udf_rw32(fe->l_ea);
23709f988b79SJean-Baptiste Boric 		fe->tag.desc_crc_len = udf_rw16(vat_len);
23719f988b79SJean-Baptiste Boric 
23729f988b79SJean-Baptiste Boric 		*vat_dscr = (union dscrptr *) fe;
23739f988b79SJean-Baptiste Boric 	} else {
23749f988b79SJean-Baptiste Boric 		/* new style VAT */
23759f988b79SJean-Baptiste Boric 		filetype = UDF_ICB_FILETYPE_VAT;
23769f988b79SJean-Baptiste Boric 		error = udf_create_new_efe(&efe, filetype, NULL);
23779f988b79SJean-Baptiste Boric 		if (error)
23789f988b79SJean-Baptiste Boric 			return error;
23799f988b79SJean-Baptiste Boric 
23809f988b79SJean-Baptiste Boric 		efe->icbtag.flags = udf_rw16(UDF_ICB_LONG_ALLOC);
23819f988b79SJean-Baptiste Boric 
23829f988b79SJean-Baptiste Boric 		allocpos = (struct long_ad *) efe->data;
23839f988b79SJean-Baptiste Boric 		*allocpos = dataloc;
23849f988b79SJean-Baptiste Boric 
23859f988b79SJean-Baptiste Boric 		/* set length */
23869f988b79SJean-Baptiste Boric 		inf_len = context.vat_size;
23879f988b79SJean-Baptiste Boric 		efe->inf_len     = udf_rw64(inf_len);
23889f988b79SJean-Baptiste Boric 		efe->obj_size    = udf_rw64(inf_len);
23899f988b79SJean-Baptiste Boric 		efe->l_ad        = udf_rw32(sizeof(struct long_ad));
23909f988b79SJean-Baptiste Boric 		blks = UDF_ROUNDUP(inf_len, context.sector_size) /
23919f988b79SJean-Baptiste Boric 			context.sector_size;
23929f988b79SJean-Baptiste Boric 		efe->logblks_rec = udf_rw32(blks);
23939f988b79SJean-Baptiste Boric 
23949f988b79SJean-Baptiste Boric 		vat_len  = sizeof(struct extfile_entry)-1 - UDF_DESC_TAG_LENGTH;
23959f988b79SJean-Baptiste Boric 		vat_len += udf_rw32(efe->l_ad);
23969f988b79SJean-Baptiste Boric 		efe->tag.desc_crc_len = udf_rw16(vat_len);
23979f988b79SJean-Baptiste Boric 
23989f988b79SJean-Baptiste Boric 		*vat_dscr = (union dscrptr *) efe;
23999f988b79SJean-Baptiste Boric 	}
24009f988b79SJean-Baptiste Boric 
24019f988b79SJean-Baptiste Boric 	return 0;
24029f988b79SJean-Baptiste Boric }
24039f988b79SJean-Baptiste Boric 
2404