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(×pec->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