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