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