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