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