1 /* $NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $ */
4 * Copyright (c) 2006, 2008 Reinoud Zandijk
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
28 #if HAVE_NBTOOL_CONFIG_H
29 #include "nbtool_config.h"
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $");
43 #include <sys/types.h>
44 #include <sys/param.h>
46 #include "udf_create.h"
56 * NOTE that there is some overlap between this code and the udf kernel fs.
57 * This is intentially though it might better be factored out one day.
61 udf_init_create_context(void)
64 memset(&context
, 0, sizeof(struct udf_create_context
));
66 /* fill with defaults currently known */
68 context
.min_udf
= 0x0102;
69 context
.max_udf
= 0x0260;
70 context
.serialnum
= 1; /* default */
73 context
.sector_size
= 512; /* minimum for UDF */
75 context
.logvol_name
= NULL
;
76 context
.primary_name
= NULL
;
77 context
.volset_name
= NULL
;
78 context
.fileset_name
= NULL
;
80 /* most basic identification */
81 context
.app_name
= "*NetBSD";
82 context
.app_version_main
= 0;
83 context
.app_version_sub
= 0;
84 context
.impl_name
= "*NetBSD";
86 context
.vds_seq
= 0; /* first one starts with zero */
88 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
89 context
.unique_id
= 0x10;
91 context
.num_files
= 0;
92 context
.num_directories
= 0;
94 context
.data_part
= 0;
95 context
.metadata_part
= 0;
96 context
.metadata_alloc_pos
= 0;
97 context
.data_alloc_pos
= 0;
101 /* version can be specified as 0xabc or a.bc */
103 parse_udfversion(const char *pos
, uint32_t *version
) {
110 /* expect hex format */
117 if (c1
< '0' || c1
> '9')
127 if (c2
< '0' || c2
> '9')
132 if (c3
< '0' || c3
> '9')
140 *version
= c1
* 0x100 + c2
* 0x10 + c3
;
145 /* parse a given string for an udf version */
147 a_udf_version(const char *s
, const char *id_type
)
151 if (parse_udfversion(s
, &version
))
152 errx(1, "unknown %s id %s; specify as hex or float", id_type
, s
);
158 udf_space_bitmap_len(uint32_t part_size
)
160 return sizeof(struct space_bitmap_desc
)-1 +
166 udf_bytes_to_sectors(uint64_t bytes
)
168 uint32_t sector_size
= layout
.sector_size
;
169 return (bytes
+ sector_size
-1) / sector_size
;
174 udf_calculate_disc_layout(int format_flags
, int min_udf
,
175 uint32_t wrtrack_skew
,
176 uint32_t first_lba
, uint32_t last_lba
,
177 uint32_t sector_size
, uint32_t blockingnr
,
178 uint32_t sparable_blocks
, float meta_fract
)
180 uint64_t kbsize
, bytes
;
181 uint32_t sparable_blockingnr
;
182 uint32_t align_blockingnr
;
186 memset(&layout
, 0, sizeof(layout
));
188 /* fill with parameters */
189 layout
.wrtrack_skew
= wrtrack_skew
;
190 layout
.first_lba
= first_lba
;
191 layout
.last_lba
= last_lba
;
192 layout
.sector_size
= sector_size
;
193 layout
.blockingnr
= blockingnr
;
194 layout
.sparable_blocks
= sparable_blocks
;
196 /* start disc layouting */
199 * location of iso9660 vrs is defined as first sector AFTER 32kb,
200 * minimum `sector size' 2048
202 layout
.iso9660_vrs
= ((32*1024 + sector_size
- 1) / sector_size
)
205 /* anchor starts at specified offset in sectors */
206 layout
.anchors
[0] = first_lba
+ 256;
207 if (format_flags
& FORMAT_TRACK512
)
208 layout
.anchors
[0] = first_lba
+ 512;
209 layout
.anchors
[1] = last_lba
- 256;
210 layout
.anchors
[2] = last_lba
;
212 /* update workable space */
213 first_lba
= layout
.anchors
[0] + blockingnr
;
214 last_lba
= layout
.anchors
[1] - 1;
216 /* XXX rest of anchor packet can be added to unallocated space descr */
218 /* reserve space for VRS and VRS copy and associated tables */
219 layout
.vds_size
= MAX(16, blockingnr
); /* UDF 2.2.3.1+2 */
220 layout
.vds1
= first_lba
;
221 first_lba
+= layout
.vds_size
; /* next packet */
223 if (format_flags
& FORMAT_SEQUENTIAL
) {
224 /* for sequential, append them ASAP */
225 layout
.vds2
= first_lba
;
226 first_lba
+= layout
.vds_size
;
228 layout
.vds2
= layout
.anchors
[1] - layout
.vds_size
;
229 last_lba
= layout
.vds2
- 1; /* XXX -1 ?? */
232 /* reserve space for logvol integrity sequence */
233 layout
.lvis_size
= MAX(8192/sector_size
, 2 * blockingnr
);
234 if (format_flags
& FORMAT_VAT
)
235 layout
.lvis_size
= 2;
236 if (format_flags
& FORMAT_WORM
)
237 layout
.lvis_size
= 64 * blockingnr
;
239 /* TODO skip bad blocks in LVID sequence; for now use f.e. */
241 layout
.lvis
= first_lba
;
242 first_lba
+= layout
.lvis_size
;
244 /* initial guess of UDF partition size */
245 layout
.part_start_lba
= first_lba
;
246 layout
.part_size_lba
= last_lba
- layout
.part_start_lba
;
248 /* all non sequential media needs an unallocated space bitmap */
249 layout
.alloc_bitmap_dscr_size
= 0;
250 if ((format_flags
& (FORMAT_SEQUENTIAL
| FORMAT_READONLY
)) == 0) {
251 bytes
= udf_space_bitmap_len(layout
.part_size_lba
);
252 layout
.alloc_bitmap_dscr_size
= udf_bytes_to_sectors(bytes
);
254 /* XXX freed space map when applicable */
258 * Note that for (bug) compatibility with version UDF 2.00 (fixed in
259 * 2.01 and higher) the blocking size needs to be 32 sectors otherwise
260 * the drive's blockingnr.
263 sparable_blockingnr
= blockingnr
;
264 if (min_udf
<= 0x200)
265 sparable_blockingnr
= 32;
267 align_blockingnr
= blockingnr
;
268 if (format_flags
& (FORMAT_SPARABLE
| FORMAT_META
))
269 align_blockingnr
= sparable_blockingnr
;
271 layout
.align_blockingnr
= align_blockingnr
;
272 layout
.sparable_blockingnr
= sparable_blockingnr
;
275 * Align partition LBA space to blocking granularity. Not strickly
276 * nessisary for non sparables but safer for the VRS data since it is
277 * not updated sporadically
280 if ((format_flags
& (FORMAT_SEQUENTIAL
| FORMAT_READONLY
)) == 0) {
282 printf("Lost %d slack sectors at start\n", UDF_ROUNDUP(
283 first_lba
- wrtrack_skew
, align_blockingnr
) -
284 (first_lba
- wrtrack_skew
));
285 printf("Lost %d slack sectors at end\n",
286 (first_lba
- wrtrack_skew
) - UDF_ROUNDDOWN(
287 first_lba
- wrtrack_skew
, align_blockingnr
));
290 first_lba
= UDF_ROUNDUP( first_lba
- wrtrack_skew
,
292 last_lba
= UDF_ROUNDDOWN(last_lba
- wrtrack_skew
,
296 if ((format_flags
& FORMAT_SPARABLE
) == 0)
297 layout
.sparable_blocks
= 0;
299 if (format_flags
& FORMAT_SPARABLE
) {
300 layout
.sparable_area_size
=
301 layout
.sparable_blocks
* sparable_blockingnr
;
303 /* a sparing table descriptor is a whole blockingnr sectors */
304 layout
.sparing_table_dscr_lbas
= sparable_blockingnr
;
306 /* place the descriptors at the start and end of the area */
307 layout
.spt_1
= first_lba
;
308 first_lba
+= layout
.sparing_table_dscr_lbas
;
310 layout
.spt_2
= last_lba
- layout
.sparing_table_dscr_lbas
;
311 last_lba
-= layout
.sparing_table_dscr_lbas
;
313 /* allocate sparable section */
314 layout
.sparable_area
= first_lba
;
315 first_lba
+= layout
.sparable_area_size
;
318 /* update guess of UDF partition size */
319 layout
.part_start_lba
= first_lba
;
320 layout
.part_size_lba
= last_lba
- layout
.part_start_lba
;
322 /* determine partition selection for data and metadata */
323 context
.data_part
= 0;
324 context
.metadata_part
= context
.data_part
;
325 if ((format_flags
& FORMAT_VAT
) || (format_flags
& FORMAT_META
))
326 context
.metadata_part
= context
.data_part
+ 1;
329 * Pick fixed logical space sector numbers for main FSD, rootdir and
330 * unallocated space. The reason for this pre-allocation is that they
331 * are referenced in the volume descriptor sequence and hence can't be
335 layout
.unalloc_space
= pos
;
336 pos
+= layout
.alloc_bitmap_dscr_size
;
338 /* claim metadata descriptors and partition space [UDF 2.2.10] */
339 if (format_flags
& FORMAT_META
) {
340 /* note: all in backing partition space */
341 layout
.meta_file
= pos
++;
342 layout
.meta_bitmap
= pos
++;;
343 layout
.meta_mirror
= layout
.part_size_lba
-1;
344 layout
.meta_alignment
= MAX(blockingnr
, sparable_blockingnr
);
345 layout
.meta_blockingnr
= MAX(layout
.meta_alignment
, 32);
347 /* calculate our partition length and store in sectors */
348 layout
.meta_part_size_lba
= layout
.part_size_lba
* meta_fract
;
349 layout
.meta_part_size_lba
= MAX(layout
.meta_part_size_lba
, 32);
350 layout
.meta_part_size_lba
=
351 UDF_ROUNDDOWN(layout
.meta_part_size_lba
, layout
.meta_blockingnr
);
353 /* calculate positions */
354 bytes
= udf_space_bitmap_len(layout
.meta_part_size_lba
);
355 layout
.meta_bitmap_dscr_size
= udf_bytes_to_sectors(bytes
);
357 layout
.meta_bitmap_space
= pos
;
358 pos
+= layout
.meta_bitmap_dscr_size
;
360 layout
.meta_part_start_lba
= UDF_ROUNDUP(pos
, layout
.meta_alignment
);
363 mpos
= (context
.metadata_part
== context
.data_part
) ? pos
: 0;
364 layout
.fsd
= mpos
; mpos
+= 1;
365 layout
.rootdir
= mpos
; mpos
+= 1;
366 layout
.vat
= mpos
; mpos
+= 1; /* if present */
369 printf("Summary so far\n");
370 printf("\tiso9660_vrs\t\t%d\n", layout
.iso9660_vrs
);
371 printf("\tanchor0\t\t\t%d\n", layout
.anchors
[0]);
372 printf("\tanchor1\t\t\t%d\n", layout
.anchors
[1]);
373 printf("\tanchor2\t\t\t%d\n", layout
.anchors
[2]);
374 printf("\tvds_size\t\t%d\n", layout
.vds_size
);
375 printf("\tvds1\t\t\t%d\n", layout
.vds1
);
376 printf("\tvds2\t\t\t%d\n", layout
.vds2
);
377 printf("\tlvis_size\t\t%d\n", layout
.lvis_size
);
378 printf("\tlvis\t\t\t%d\n", layout
.lvis
);
379 if (format_flags
& FORMAT_SPARABLE
) {
380 printf("\tsparable size\t\t%d\n", layout
.sparable_area_size
);
381 printf("\tsparable\t\t%d\n", layout
.sparable_area
);
383 printf("\tpartition start lba\t%d\n", layout
.part_start_lba
);
384 printf("\tpartition size\t\t%d KiB, %d MiB\n",
385 (layout
.part_size_lba
* sector_size
) / 1024,
386 (layout
.part_size_lba
* sector_size
) / (1024*1024));
387 if ((format_flags
& FORMAT_SEQUENTIAL
) == 0) {
388 printf("\tpart bitmap start\t%d\n", layout
.unalloc_space
);
389 printf("\t\tfor %d lba\n", layout
.alloc_bitmap_dscr_size
);
391 if (format_flags
& FORMAT_META
) {
392 printf("\tmeta blockingnr\t\t%d\n", layout
.meta_blockingnr
);
393 printf("\tmeta alignment\t\t%d\n", layout
.meta_alignment
);
394 printf("\tmeta size\t\t%d KiB, %d MiB\n",
395 (layout
.meta_part_size_lba
* sector_size
) / 1024,
396 (layout
.meta_part_size_lba
* sector_size
) / (1024*1024));
397 printf("\tmeta file\t\t%d\n", layout
.meta_file
);
398 printf("\tmeta mirror\t\t%d\n", layout
.meta_mirror
);
399 printf("\tmeta bitmap\t\t%d\n", layout
.meta_bitmap
);
400 printf("\tmeta bitmap start\t%d\n", layout
.meta_bitmap_space
);
401 printf("\t\tfor %d lba\n", layout
.meta_bitmap_dscr_size
);
402 printf("\tmeta space start\t%d\n", layout
.meta_part_start_lba
);
403 printf("\t\tfor %d lba\n", layout
.meta_part_size_lba
);
408 kbsize
= (uint64_t) last_lba
* sector_size
;
409 printf("Total space on this medium approx. "
410 "%"PRIu64
" KiB, %"PRIu64
" MiB\n",
411 kbsize
/1024, kbsize
/(1024*1024));
412 kbsize
= (uint64_t)(layout
.part_size_lba
- layout
.alloc_bitmap_dscr_size
413 - layout
.meta_bitmap_dscr_size
) * sector_size
;
414 printf("Free space on this volume approx. "
415 "%"PRIu64
" KiB, %"PRIu64
" MiB\n\n",
416 kbsize
/1024, kbsize
/(1024*1024));
423 udf_validate_tag_sum(union dscrptr
*dscr
)
425 struct desc_tag
*tag
= &dscr
->tag
;
426 uint8_t *pos
, sum
, cnt
;
428 /* calculate TAG header checksum */
429 pos
= (uint8_t *) tag
;
432 for(cnt
= 0; cnt
< 16; cnt
++) {
433 if (cnt
!= 4) sum
+= *pos
;
436 tag
->cksum
= sum
; /* 8 bit */
442 /* assumes sector number of descriptor to be allready present */
444 udf_validate_tag_and_crc_sums(union dscrptr
*dscr
)
446 struct desc_tag
*tag
= &dscr
->tag
;
449 /* check payload CRC if applicable */
450 if (udf_rw16(tag
->desc_crc_len
) > 0) {
451 crc
= udf_cksum(((uint8_t *) tag
) + UDF_DESC_TAG_LENGTH
,
452 udf_rw16(tag
->desc_crc_len
));
453 tag
->desc_crc
= udf_rw16(crc
);
456 /* calculate TAG header checksum */
457 return udf_validate_tag_sum(dscr
);
462 udf_inittag(struct desc_tag
*tag
, int tagid
, uint32_t loc
)
464 tag
->id
= udf_rw16(tagid
);
465 tag
->descriptor_ver
= udf_rw16(context
.dscrver
);
468 tag
->serial_num
= udf_rw16(context
.serialnum
);
469 tag
->tag_loc
= udf_rw32(loc
);
474 udf_create_anchor(int num
)
476 struct anchor_vdp
*avdp
;
477 uint32_t vds_extent_len
= layout
.vds_size
* context
.sector_size
;
479 if ((avdp
= calloc(1, context
.sector_size
)) == NULL
)
482 udf_inittag(&avdp
->tag
, TAGID_ANCHOR
, layout
.anchors
[num
]);
484 avdp
->main_vds_ex
.loc
= udf_rw32(layout
.vds1
);
485 avdp
->main_vds_ex
.len
= udf_rw32(vds_extent_len
);
487 avdp
->reserve_vds_ex
.loc
= udf_rw32(layout
.vds2
);
488 avdp
->reserve_vds_ex
.len
= udf_rw32(vds_extent_len
);
490 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
491 avdp
->tag
.desc_crc_len
= udf_rw16(512-UDF_DESC_TAG_LENGTH
);
493 context
.anchors
[num
] = avdp
;
499 udf_create_terminator(union dscrptr
*dscr
, uint32_t loc
)
501 memset(dscr
, 0, context
.sector_size
);
502 udf_inittag(&dscr
->tag
, TAGID_TERM
, loc
);
504 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
505 dscr
->tag
.desc_crc_len
= udf_rw16(512-UDF_DESC_TAG_LENGTH
);
510 udf_osta_charset(struct charspec
*charspec
)
512 memset(charspec
, 0, sizeof(*charspec
));
514 strcpy((char *) charspec
->inf
, "OSTA Compressed Unicode");
519 udf_encode_osta_id(char *osta_id
, uint16_t len
, char *text
)
521 uint16_t u16_name
[1024];
525 memset(osta_id
, 0, len
);
526 if (!text
|| (strlen(text
) == 0)) return;
528 memset(u16_name
, 0, sizeof(uint16_t) * 1023);
530 /* convert ascii to 16 bits unicode */
531 pos
= (uint8_t *) text
;
539 udf_CompressUnicode(len
, 8, (unicode_t
*) u16_name
, (byte
*) osta_id
);
541 /* Ecma 167/7.2.13 states that length is recorded in the last byte */
542 osta_id
[len
-1] = strlen(text
)+1;
546 /* first call udf_set_regid and then the suffix */
548 udf_set_regid(struct regid
*regid
, char const *name
)
550 memset(regid
, 0, sizeof(*regid
));
551 regid
->flags
= 0; /* not dirty and not protected */
552 strcpy((char *) regid
->id
, name
);
557 udf_add_domain_regid(struct regid
*regid
)
561 ver
= (uint16_t *) regid
->id_suffix
;
562 *ver
= udf_rw16(context
.min_udf
);
567 udf_add_udf_regid(struct regid
*regid
)
571 ver
= (uint16_t *) regid
->id_suffix
;
572 *ver
= udf_rw16(context
.min_udf
);
574 regid
->id_suffix
[2] = 4; /* unix */
575 regid
->id_suffix
[3] = 8; /* NetBSD */
580 udf_add_impl_regid(struct regid
*regid
)
582 regid
->id_suffix
[0] = 4; /* unix */
583 regid
->id_suffix
[1] = 8; /* NetBSD */
588 udf_add_app_regid(struct regid
*regid
)
590 regid
->id_suffix
[0] = context
.app_version_main
;
591 regid
->id_suffix
[1] = context
.app_version_sub
;
596 * Fill in timestamp structure based on clock_gettime(). Time is reported back
597 * as a time_t accompanied with a nano second field.
599 * The husec, usec and csec could be relaxed in type.
602 udf_timespec_to_timestamp(struct timespec
*timespec
, struct timestamp
*timestamp
)
605 uint64_t husec
, usec
, csec
;
607 memset(timestamp
, 0, sizeof(*timestamp
));
608 gmtime_r(×pec
->tv_sec
, &tm
);
611 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
613 * Lower 12 bits are two complement signed timezone offset if bit 12
614 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
615 * offset to -2047 i.e. unsigned `zero'
618 /* set method 1 for CUT/GMT */
619 timestamp
->type_tz
= udf_rw16((1<<12) + 0);
620 timestamp
->year
= udf_rw16(tm
.tm_year
+ 1900);
621 timestamp
->month
= tm
.tm_mon
+ 1; /* `tm' uses 0..11 for months */
622 timestamp
->day
= tm
.tm_mday
;
623 timestamp
->hour
= tm
.tm_hour
;
624 timestamp
->minute
= tm
.tm_min
;
625 timestamp
->second
= tm
.tm_sec
;
627 usec
= (timespec
->tv_nsec
+ 500) / 1000; /* round */
629 usec
-= husec
* 100; /* only 0-99 in usec */
630 csec
= husec
/ 100; /* only 0-99 in csec */
631 husec
-= csec
* 100; /* only 0-99 in husec */
633 /* in rare cases there is overflow in csec */
634 csec
= MIN(99, csec
);
635 husec
= MIN(99, husec
);
636 usec
= MIN(99, usec
);
638 timestamp
->centisec
= csec
;
639 timestamp
->hund_usec
= husec
;
640 timestamp
->usec
= usec
;
645 udf_set_timestamp_now(struct timestamp
*timestamp
)
649 #ifdef CLOCK_REALTIME
650 (void)clock_gettime(CLOCK_REALTIME
, &now
);
652 struct timeval time_of_day
;
654 (void)gettimeofday(&time_of_day
, NULL
);
655 now
.tv_sec
= time_of_day
.tv_sec
;
656 now
.tv_nsec
= time_of_day
.tv_usec
* 1000;
658 udf_timespec_to_timestamp(&now
, timestamp
);
662 /* some code copied from sys/fs/udf */
665 udf_set_timestamp(struct timestamp
*timestamp
, time_t value
)
669 memset(&t
, 0, sizeof(struct timespec
));
672 udf_timespec_to_timestamp(&t
, timestamp
);
677 unix_mode_to_udf_perm(mode_t mode
)
681 perm
= ((mode
& S_IRWXO
) );
682 perm
|= ((mode
& S_IRWXG
) << 2);
683 perm
|= ((mode
& S_IRWXU
) << 4);
684 perm
|= ((mode
& S_IWOTH
) << 3);
685 perm
|= ((mode
& S_IWGRP
) << 5);
686 perm
|= ((mode
& S_IWUSR
) << 7);
691 /* end of copied code */
695 udf_create_primaryd(void)
697 struct pri_vol_desc
*pri
;
700 pri
= calloc(1, context
.sector_size
);
704 memset(pri
, 0, context
.sector_size
);
705 udf_inittag(&pri
->tag
, TAGID_PRI_VOL
, /* loc */ 0);
706 pri
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
708 pri
->pvd_num
= udf_rw32(0); /* default serial */
709 udf_encode_osta_id(pri
->vol_id
, 32, context
.primary_name
);
711 /* set defaults for single disc volumes as UDF prescribes */
712 pri
->vds_num
= udf_rw16(1);
713 pri
->max_vol_seq
= udf_rw16(1);
714 pri
->ichg_lvl
= udf_rw16(2);
715 pri
->max_ichg_lvl
= udf_rw16(3);
716 pri
->flags
= udf_rw16(0);
718 pri
->charset_list
= udf_rw32(1); /* only CS0 */
719 pri
->max_charset_list
= udf_rw32(1); /* only CS0 */
721 udf_encode_osta_id(pri
->volset_id
, 128, context
.volset_name
);
722 udf_osta_charset(&pri
->desc_charset
);
723 udf_osta_charset(&pri
->explanatory_charset
);
725 udf_set_regid(&pri
->app_id
, context
.app_name
);
726 udf_add_app_regid(&pri
->app_id
);
728 udf_set_regid(&pri
->imp_id
, context
.impl_name
);
729 udf_add_impl_regid(&pri
->imp_id
);
731 udf_set_timestamp_now(&pri
->time
);
733 crclen
= sizeof(struct pri_vol_desc
) - UDF_DESC_TAG_LENGTH
;
734 pri
->tag
.desc_crc_len
= udf_rw16(crclen
);
736 context
.primary_vol
= pri
;
742 /* XXX no support for unallocated or freed space tables yet (!) */
744 udf_create_partitiond(int part_num
, int part_accesstype
)
746 struct part_desc
*pd
;
747 struct part_hdr_desc
*phd
;
748 uint32_t sector_size
, bitmap_bytes
;
751 sector_size
= context
.sector_size
;
752 bitmap_bytes
= layout
.alloc_bitmap_dscr_size
* sector_size
;
754 if (context
.partitions
[part_num
]) {
755 printf("Internal error: partition %d allready defined\n",
760 pd
= calloc(1, context
.sector_size
);
763 phd
= &pd
->_impl_use
.part_hdr
;
765 udf_inittag(&pd
->tag
, TAGID_PARTITION
, /* loc */ 0);
766 pd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
768 pd
->flags
= udf_rw16(1); /* allocated */
769 pd
->part_num
= udf_rw16(part_num
); /* only one physical partition */
771 if (context
.dscrver
== 2) {
772 udf_set_regid(&pd
->contents
, "+NSR02");
774 udf_set_regid(&pd
->contents
, "+NSR03");
776 udf_add_app_regid(&pd
->contents
);
778 phd
->unalloc_space_bitmap
.len
= udf_rw32(bitmap_bytes
);
779 phd
->unalloc_space_bitmap
.lb_num
= udf_rw32(layout
.unalloc_space
);
781 if (layout
.freed_space
) {
782 phd
->freed_space_bitmap
.len
= udf_rw32(bitmap_bytes
);
783 phd
->freed_space_bitmap
.lb_num
= udf_rw32(layout
.freed_space
);
786 pd
->access_type
= udf_rw32(part_accesstype
);
787 pd
->start_loc
= udf_rw32(layout
.part_start_lba
);
788 pd
->part_len
= udf_rw32(layout
.part_size_lba
);
790 udf_set_regid(&pd
->imp_id
, context
.impl_name
);
791 udf_add_impl_regid(&pd
->imp_id
);
793 crclen
= sizeof(struct part_desc
) - UDF_DESC_TAG_LENGTH
;
794 pd
->tag
.desc_crc_len
= udf_rw16(crclen
);
796 context
.partitions
[part_num
] = pd
;
803 udf_create_unalloc_spaced(void)
805 struct unalloc_sp_desc
*usd
;
808 usd
= calloc(1, context
.sector_size
);
812 udf_inittag(&usd
->tag
, TAGID_UNALLOC_SPACE
, /* loc */ 0);
813 usd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
815 /* no default entries */
816 usd
->alloc_desc_num
= udf_rw32(0); /* no entries */
818 crclen
= sizeof(struct unalloc_sp_desc
) - sizeof(struct extent_ad
);
819 crclen
-= UDF_DESC_TAG_LENGTH
;
820 usd
->tag
.desc_crc_len
= udf_rw16(crclen
);
822 context
.unallocated
= usd
;
829 udf_create_base_logical_dscr(void)
831 struct logvol_desc
*lvd
;
832 uint32_t sector_size
;
835 sector_size
= context
.sector_size
;
837 lvd
= calloc(1, sector_size
);
841 udf_inittag(&lvd
->tag
, TAGID_LOGVOL
, /* loc */ 0);
842 lvd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
844 udf_osta_charset(&lvd
->desc_charset
);
845 udf_encode_osta_id(lvd
->logvol_id
, 128, context
.logvol_name
);
846 lvd
->lb_size
= udf_rw32(context
.sector_size
);
848 udf_set_regid(&lvd
->domain_id
, "*OSTA UDF Compliant");
849 udf_add_domain_regid(&lvd
->domain_id
);
851 /* no partition mappings/entries yet */
852 lvd
->mt_l
= udf_rw32(0);
853 lvd
->n_pm
= udf_rw32(0);
855 udf_set_regid(&lvd
->imp_id
, context
.impl_name
);
856 udf_add_impl_regid(&lvd
->imp_id
);
858 lvd
->integrity_seq_loc
.loc
= udf_rw32(layout
.lvis
);
859 lvd
->integrity_seq_loc
.len
= udf_rw32(layout
.lvis_size
* sector_size
);
861 /* just one fsd for now */
862 lvd
->lv_fsd_loc
.len
= udf_rw32(sector_size
);
863 lvd
->lv_fsd_loc
.loc
.part_num
= udf_rw32(context
.metadata_part
);
864 lvd
->lv_fsd_loc
.loc
.lb_num
= udf_rw32(layout
.fsd
);
866 crclen
= sizeof(struct logvol_desc
) - 1 - UDF_DESC_TAG_LENGTH
;
867 lvd
->tag
.desc_crc_len
= udf_rw16(crclen
);
869 context
.logical_vol
= lvd
;
870 context
.vtop_tp
[UDF_VTOP_RAWPART
] = UDF_VTOP_TYPE_RAW
;
871 context
.vtop_offset
[UDF_VTOP_RAWPART
] = 0;
878 udf_add_logvol_part_physical(uint16_t phys_part
)
880 struct logvol_desc
*logvol
= context
.logical_vol
;
881 union udf_pmap
*pmap
;
884 uint32_t pmap1_size
, log_part
;
886 log_part
= udf_rw32(logvol
->n_pm
);
887 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
888 pmap1_size
= sizeof(struct part_map_1
);
890 pmap
= (union udf_pmap
*) pmap_pos
;
892 pmap
->pm1
.len
= sizeof(struct part_map_1
);
893 pmap
->pm1
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
894 pmap
->pm1
.part_num
= udf_rw16(phys_part
);
896 context
.vtop
[log_part
] = phys_part
;
897 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_PHYS
;
898 context
.vtop_offset
[log_part
] = layout
.part_start_lba
;
899 context
.part_size
[log_part
] = layout
.part_size_lba
;
900 context
.part_free
[log_part
] = layout
.part_size_lba
;
902 /* increment number of partitions and length */
903 logvol
->n_pm
= udf_rw32(log_part
+ 1);
904 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmap1_size
);
906 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmap1_size
;
907 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
912 udf_add_logvol_part_virtual(uint16_t phys_part
)
914 union udf_pmap
*pmap
;
915 struct logvol_desc
*logvol
= context
.logical_vol
;
918 uint32_t pmapv_size
, log_part
;
920 log_part
= udf_rw32(logvol
->n_pm
);
921 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
922 pmapv_size
= sizeof(struct part_map_2
);
924 pmap
= (union udf_pmap
*) pmap_pos
;
926 pmap
->pmv
.len
= pmapv_size
;
928 udf_set_regid(&pmap
->pmv
.id
, "*UDF Virtual Partition");
929 udf_add_udf_regid(&pmap
->pmv
.id
);
931 pmap
->pmv
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
932 pmap
->pmv
.part_num
= udf_rw16(phys_part
);
934 context
.vtop
[log_part
] = phys_part
;
935 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_VIRT
;
936 context
.vtop_offset
[log_part
] = context
.vtop_offset
[phys_part
];
937 context
.part_size
[log_part
] = 0xffffffff;
938 context
.part_free
[log_part
] = 0xffffffff;
940 /* increment number of partitions and length */
941 logvol
->n_pm
= udf_rw32(log_part
+ 1);
942 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmapv_size
);
944 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmapv_size
;
945 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
949 /* sparing table size is in bytes */
951 udf_add_logvol_part_sparable(uint16_t phys_part
)
953 union udf_pmap
*pmap
;
954 struct logvol_desc
*logvol
= context
.logical_vol
;
955 uint32_t *st_pos
, sparable_bytes
, pmaps_size
;
956 uint8_t *pmap_pos
, num
;
960 log_part
= udf_rw32(logvol
->n_pm
);
961 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
962 pmaps_size
= sizeof(struct part_map_2
);
963 sparable_bytes
= layout
.sparable_area_size
* context
.sector_size
;
965 pmap
= (union udf_pmap
*) pmap_pos
;
967 pmap
->pms
.len
= pmaps_size
;
969 udf_set_regid(&pmap
->pmv
.id
, "*UDF Sparable Partition");
970 udf_add_udf_regid(&pmap
->pmv
.id
);
972 pmap
->pms
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
973 pmap
->pms
.part_num
= udf_rw16(phys_part
);
975 pmap
->pms
.packet_len
= udf_rw16(layout
.sparable_blockingnr
);
976 pmap
->pms
.st_size
= udf_rw32(sparable_bytes
);
978 /* enter spare tables */
979 st_pos
= &pmap
->pms
.st_loc
[0];
980 *st_pos
++ = udf_rw32(layout
.spt_1
);
981 *st_pos
++ = udf_rw32(layout
.spt_2
);
984 if (layout
.spt_2
== 0) num
--;
985 if (layout
.spt_1
== 0) num
--;
986 pmap
->pms
.n_st
= num
; /* 8 bit */
988 /* the vtop_offset needs to explicitly set since there is no phys. */
989 context
.vtop
[log_part
] = phys_part
;
990 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_SPARABLE
;
991 context
.vtop_offset
[log_part
] = layout
.part_start_lba
;
992 context
.part_size
[log_part
] = layout
.part_size_lba
;
993 context
.part_free
[log_part
] = layout
.part_size_lba
;
995 /* increment number of partitions and length */
996 logvol
->n_pm
= udf_rw32(log_part
+ 1);
997 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmaps_size
);
999 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmaps_size
;
1000 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
1005 udf_create_sparing_tabled(void)
1007 struct udf_sparing_table
*spt
;
1008 struct spare_map_entry
*sme
;
1010 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1012 spt
= calloc(context
.sector_size
, layout
.sparing_table_dscr_lbas
);
1016 /* a sparing table descriptor is a whole sparable_blockingnr sectors */
1017 udf_inittag(&spt
->tag
, TAGID_SPARING_TABLE
, /* loc */ 0);
1019 udf_set_regid(&spt
->id
, "*UDF Sparing Table");
1020 udf_add_udf_regid(&spt
->id
);
1022 spt
->rt_l
= udf_rw16(layout
.sparable_blocks
);
1023 spt
->seq_num
= udf_rw32(0); /* first generation */
1025 for (cnt
= 0; cnt
< layout
.sparable_blocks
; cnt
++) {
1026 sme
= &spt
->entries
[cnt
];
1027 loc
= layout
.sparable_area
+ cnt
* layout
.sparable_blockingnr
;
1028 sme
->org
= udf_rw32(0xffffffff); /* open for reloc */
1029 sme
->map
= udf_rw32(loc
);
1032 /* calculate crc len for actual size */
1033 crclen
= sizeof(struct udf_sparing_table
) - UDF_DESC_TAG_LENGTH
;
1034 crclen
+= (layout
.sparable_blocks
-1) * sizeof(struct spare_map_entry
);
1035 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
1036 spt
->tag
.desc_crc_len
= udf_rw16((uint16_t)crclen
);
1038 context
.sparing_table
= spt
;
1045 udf_add_logvol_part_meta(uint16_t phys_part
)
1047 union udf_pmap
*pmap
;
1048 struct logvol_desc
*logvol
= context
.logical_vol
;
1050 uint32_t pmapv_size
, log_part
;
1053 log_part
= udf_rw32(logvol
->n_pm
);
1054 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
1055 pmapv_size
= sizeof(struct part_map_2
);
1057 pmap
= (union udf_pmap
*) pmap_pos
;
1059 pmap
->pmm
.len
= pmapv_size
;
1061 udf_set_regid(&pmap
->pmm
.id
, "*UDF Metadata Partition");
1062 udf_add_udf_regid(&pmap
->pmm
.id
);
1064 pmap
->pmm
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
1065 pmap
->pmm
.part_num
= udf_rw16(phys_part
);
1067 /* fill in meta data file(s) and alloc/alignment unit sizes */
1068 pmap
->pmm
.meta_file_lbn
= udf_rw32(layout
.meta_file
);
1069 pmap
->pmm
.meta_mirror_file_lbn
= udf_rw32(layout
.meta_mirror
);
1070 pmap
->pmm
.meta_bitmap_file_lbn
= udf_rw32(layout
.meta_bitmap
);
1071 pmap
->pmm
.alloc_unit_size
= udf_rw32(layout
.meta_blockingnr
);
1072 pmap
->pmm
.alignment_unit_size
= udf_rw16(layout
.meta_alignment
);
1073 pmap
->pmm
.flags
= 0; /* METADATA_DUPLICATED */
1075 context
.vtop
[log_part
] = phys_part
;
1076 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_META
;
1077 context
.vtop_offset
[log_part
] =
1078 context
.vtop_offset
[phys_part
] + layout
.meta_part_start_lba
;
1079 context
.part_size
[log_part
] = layout
.meta_part_size_lba
;
1080 context
.part_free
[log_part
] = layout
.meta_part_size_lba
;
1082 /* increment number of partitions and length */
1083 logvol
->n_pm
= udf_rw32(log_part
+ 1);
1084 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmapv_size
);
1086 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmapv_size
;
1087 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
1092 udf_create_logical_dscr(int format_flags
)
1096 if ((error
= udf_create_base_logical_dscr()))
1099 /* we pass data_part for there might be a read-only part one day */
1100 if (format_flags
& FORMAT_SPARABLE
) {
1101 /* sparable partition mapping has no physical mapping */
1102 udf_add_logvol_part_sparable(context
.data_part
);
1104 udf_add_logvol_part_physical(context
.data_part
);
1107 if (format_flags
& FORMAT_VAT
) {
1108 /* add VAT virtual mapping; reflects on datapart */
1109 udf_add_logvol_part_virtual(context
.data_part
);
1111 if (format_flags
& FORMAT_META
) {
1112 /* add META data mapping; reflects on datapart */
1113 udf_add_logvol_part_meta(context
.data_part
);
1121 udf_create_impvold(char *field1
, char *field2
, char *field3
)
1123 struct impvol_desc
*ivd
;
1124 struct udf_lv_info
*lvi
;
1127 ivd
= calloc(1, context
.sector_size
);
1130 lvi
= &ivd
->_impl_use
.lv_info
;
1132 udf_inittag(&ivd
->tag
, TAGID_IMP_VOL
, /* loc */ 0);
1133 ivd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
1135 udf_set_regid(&ivd
->impl_id
, "*UDF LV Info");
1136 udf_add_udf_regid(&ivd
->impl_id
);
1138 /* fill in UDF specific part */
1139 udf_osta_charset(&lvi
->lvi_charset
);
1140 udf_encode_osta_id(lvi
->logvol_id
, 128, context
.logvol_name
);
1142 udf_encode_osta_id(lvi
->lvinfo1
, 36, field1
);
1143 udf_encode_osta_id(lvi
->lvinfo2
, 36, field2
);
1144 udf_encode_osta_id(lvi
->lvinfo3
, 36, field3
);
1146 udf_set_regid(&lvi
->impl_id
, context
.impl_name
);
1147 udf_add_impl_regid(&lvi
->impl_id
);
1149 crclen
= sizeof(struct impvol_desc
) - UDF_DESC_TAG_LENGTH
;
1150 ivd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1152 context
.implementation
= ivd
;
1158 /* XXX might need to be sanitised a bit later */
1160 udf_update_lvintd(int type
)
1162 struct logvol_int_desc
*lvid
;
1163 struct udf_logvol_info
*lvinfo
;
1164 struct logvol_desc
*logvol
;
1166 uint32_t cnt
, l_iu
, num_partmappings
;
1167 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1169 lvid
= context
.logvol_integrity
;
1170 logvol
= context
.logical_vol
;
1175 lvid
->integrity_type
= udf_rw32(type
);
1177 num_partmappings
= udf_rw32(logvol
->n_pm
);
1179 udf_set_timestamp_now(&lvid
->time
);
1181 lvinfo
= (struct udf_logvol_info
*)
1182 (lvid
->tables
+ num_partmappings
* 2);
1183 udf_set_regid(&lvinfo
->impl_id
, context
.impl_name
);
1184 udf_add_impl_regid(&lvinfo
->impl_id
);
1186 lvinfo
->num_files
= udf_rw32(context
.num_files
);
1187 lvinfo
->num_directories
= udf_rw32(context
.num_directories
);
1189 lvid
->lvint_next_unique_id
= udf_rw64(context
.unique_id
);
1191 /* XXX sane enough ? */
1192 lvinfo
->min_udf_readver
= udf_rw16(context
.min_udf
);
1193 lvinfo
->min_udf_writever
= udf_rw16(context
.min_udf
);
1194 lvinfo
->max_udf_writever
= udf_rw16(context
.max_udf
);
1196 lvid
->num_part
= udf_rw32(num_partmappings
);
1198 /* no impl. use needed */
1199 l_iu
= sizeof(struct udf_logvol_info
);
1200 lvid
->l_iu
= udf_rw32(l_iu
);
1202 pos
= &lvid
->tables
[0];
1203 for (cnt
= 0; cnt
< num_partmappings
; cnt
++) {
1204 *pos
++ = udf_rw32(context
.part_free
[cnt
]);
1206 for (cnt
= 0; cnt
< num_partmappings
; cnt
++) {
1207 *pos
++ = udf_rw32(context
.part_size
[cnt
]);
1210 crclen
= sizeof(struct logvol_int_desc
) -4 -UDF_DESC_TAG_LENGTH
+ l_iu
;
1211 crclen
+= num_partmappings
* 2 * 4;
1212 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
1213 lvid
->tag
.desc_crc_len
= udf_rw16(crclen
);
1215 context
.logvol_info
= lvinfo
;
1220 udf_create_lvintd(int type
)
1222 struct logvol_int_desc
*lvid
;
1224 lvid
= calloc(1, context
.sector_size
);
1228 udf_inittag(&lvid
->tag
, TAGID_LOGVOL_INTEGRITY
, /* loc */ 0);
1230 context
.logvol_integrity
= lvid
;
1232 udf_update_lvintd(type
);
1239 udf_create_fsd(void)
1241 struct fileset_desc
*fsd
;
1244 fsd
= calloc(1, context
.sector_size
);
1248 udf_inittag(&fsd
->tag
, TAGID_FSD
, /* loc */ 0);
1250 udf_set_timestamp_now(&fsd
->time
);
1251 fsd
->ichg_lvl
= udf_rw16(3); /* UDF 2.3.2.1 */
1252 fsd
->max_ichg_lvl
= udf_rw16(3); /* UDF 2.3.2.2 */
1254 fsd
->charset_list
= udf_rw32(1); /* only CS0 */
1255 fsd
->max_charset_list
= udf_rw32(1); /* only CS0 */
1257 fsd
->fileset_num
= udf_rw32(0); /* only one fsd */
1258 fsd
->fileset_desc_num
= udf_rw32(0); /* origional */
1260 udf_osta_charset(&fsd
->logvol_id_charset
);
1261 udf_encode_osta_id(fsd
->logvol_id
, 128, context
.logvol_name
);
1263 udf_osta_charset(&fsd
->fileset_charset
);
1264 udf_encode_osta_id(fsd
->fileset_id
, 32, context
.fileset_name
);
1266 /* copyright file and abstract file names obmitted */
1268 fsd
->rootdir_icb
.len
= udf_rw32(context
.sector_size
);
1269 fsd
->rootdir_icb
.loc
.lb_num
= udf_rw32(layout
.rootdir
);
1270 fsd
->rootdir_icb
.loc
.part_num
= udf_rw16(context
.metadata_part
);
1272 udf_set_regid(&fsd
->domain_id
, "*OSTA UDF Compliant");
1273 udf_add_domain_regid(&fsd
->domain_id
);
1275 /* next_ex stays zero */
1276 /* no system streamdirs yet */
1278 crclen
= sizeof(struct fileset_desc
) - UDF_DESC_TAG_LENGTH
;
1279 fsd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1281 context
.fileset_desc
= fsd
;
1288 udf_create_space_bitmap(uint32_t dscr_size
, uint32_t part_size_lba
,
1289 struct space_bitmap_desc
**sbdp
)
1291 struct space_bitmap_desc
*sbd
;
1296 sbd
= calloc(context
.sector_size
, dscr_size
);
1300 udf_inittag(&sbd
->tag
, TAGID_SPACE_BITMAP
, /* loc */ 0);
1302 sbd
->num_bits
= udf_rw32(part_size_lba
);
1303 sbd
->num_bytes
= udf_rw32((part_size_lba
+ 7)/8);
1305 /* fill space with 0xff to indicate free */
1306 for (cnt
= 0; cnt
< udf_rw32(sbd
->num_bytes
); cnt
++)
1307 sbd
->data
[cnt
] = 0xff;
1309 /* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
1310 crclen
= sizeof(struct space_bitmap_desc
) -1 - UDF_DESC_TAG_LENGTH
;
1311 sbd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1318 /* --------------------------------------------------------------------- */
1321 udf_register_bad_block(uint32_t location
)
1323 struct udf_sparing_table
*spt
;
1324 struct spare_map_entry
*sme
, *free_sme
;
1327 spt
= context
.sparing_table
;
1329 printf("internal error: adding bad block to non sparable\n");
1333 /* find us a free spare map entry */
1335 for (cnt
= 0; cnt
< layout
.sparable_blocks
; cnt
++) {
1336 sme
= &spt
->entries
[cnt
];
1337 /* if we are allready in it, bail out */
1338 if (udf_rw32(sme
->org
) == location
)
1340 if (udf_rw32(sme
->org
) == 0xffffffff) {
1345 if (free_sme
== NULL
) {
1346 printf("Disc relocation blocks full; disc too damanged\n");
1349 free_sme
->org
= udf_rw32(location
);
1356 udf_mark_allocated(uint32_t start_lb
, int partnr
, uint32_t blocks
)
1358 union dscrptr
*dscr
;
1362 /* account for space used on underlying partition */
1363 context
.part_free
[partnr
] -= blocks
;
1365 printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
1366 partnr
, start_lb
, blocks
);
1369 switch (context
.vtop_tp
[partnr
]) {
1370 case UDF_VTOP_TYPE_VIRT
:
1373 case UDF_VTOP_TYPE_PHYS
:
1374 case UDF_VTOP_TYPE_SPARABLE
:
1375 case UDF_VTOP_TYPE_META
:
1376 if (context
.part_unalloc_bits
[context
.vtop
[partnr
]] == NULL
) {
1377 context
.part_free
[partnr
] = 0;
1381 printf("Marking %d+%d as used\n", start_lb
, blocks
);
1383 dscr
= (union dscrptr
*) (context
.part_unalloc_bits
[partnr
]);
1384 for (cnt
= start_lb
; cnt
< start_lb
+ blocks
; cnt
++) {
1385 bpos
= &dscr
->sbd
.data
[cnt
/ 8];
1387 *bpos
&= ~(1<< bit
);
1391 printf("internal error: reality check in mapping type %d\n",
1392 context
.vtop_tp
[partnr
]);
1399 udf_advance_uniqueid(void)
1401 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
1402 context
.unique_id
++;
1403 if (context
.unique_id
< 0x10)
1404 context
.unique_id
= 0x10;
1407 /* --------------------------------------------------------------------- */
1410 unix_to_udf_name(char *result
, uint8_t *result_len
,
1411 char const *name
, int name_len
, struct charspec
*chsp
)
1416 const char *osta_id
= "OSTA Compressed Unicode";
1417 int udf_chars
, is_osta_typ0
, bits
;
1420 /* allocate temporary unicode-16 buffer */
1421 raw_name
= malloc(1024);
1424 /* convert utf8 to unicode-16 */
1429 for (cnt
= name_len
, udf_chars
= 0; cnt
;) {
1430 *outchp
= wget_utf8(&inchp
, &cnt
);
1436 /* null terminate just in case */
1439 is_osta_typ0
= (chsp
->type
== 0);
1440 is_osta_typ0
&= (strcmp((char *) chsp
->inf
, osta_id
) == 0);
1442 udf_chars
= udf_CompressUnicode(udf_chars
, bits
,
1443 (unicode_t
*) raw_name
,
1446 printf("unix to udf name: no CHSP0 ?\n");
1447 /* XXX assume 8bit char length byte latin-1 */
1448 *result
++ = 8; udf_chars
= 1;
1449 strncpy(result
, name
+ 1, name_len
);
1450 udf_chars
+= name_len
;
1452 *result_len
= udf_chars
;
1457 #define UDF_SYMLINKBUFLEN (64*1024) /* picked */
1459 udf_encode_symlink(uint8_t **pathbufp
, uint32_t *pathlenp
, char *target
)
1461 struct charspec osta_charspec
;
1462 struct pathcomp pathcomp
;
1463 char *pathbuf
, *pathpos
, *compnamepos
;
1465 // int mntonnamelen;
1466 int pathlen
, len
, compnamelen
;
1469 /* process `target' to an UDF structure */
1470 pathbuf
= malloc(UDF_SYMLINKBUFLEN
);
1478 udf_osta_charset(&osta_charspec
);
1480 if (*target
== '/') {
1481 /* symlink starts from the root */
1482 len
= UDF_PATH_COMP_SIZE
;
1483 memset(&pathcomp
, 0, len
);
1484 pathcomp
.type
= UDF_PATH_COMP_ROOT
;
1487 /* XXX how to check for in makefs? */
1488 /* check if its mount-point relative! */
1489 mntonname
= udf_node
->ump
->vfs_mountp
->mnt_stat
.f_mntonname
;
1490 mntonnamelen
= strlen(mntonname
);
1491 if (strlen(target
) >= mntonnamelen
) {
1492 if (strncmp(target
, mntonname
, mntonnamelen
) == 0) {
1493 pathcomp
.type
= UDF_PATH_COMP_MOUNTROOT
;
1494 target
+= mntonnamelen
;
1503 memcpy(pathpos
, &pathcomp
, len
);
1510 /* ignore multiple '/' */
1511 while (*target
== '/') {
1517 /* extract component name */
1519 compnamepos
= target
;
1520 while ((*target
) && (*target
!= '/')) {
1525 /* just trunc if too long ?? (security issue) */
1526 if (compnamelen
>= 127) {
1527 error
= ENAMETOOLONG
;
1531 /* convert unix name to UDF name */
1532 len
= sizeof(struct pathcomp
);
1533 memset(&pathcomp
, 0, len
);
1534 pathcomp
.type
= UDF_PATH_COMP_NAME
;
1535 len
= UDF_PATH_COMP_SIZE
;
1537 if ((compnamelen
== 2) && (strncmp(compnamepos
, "..", 2) == 0))
1538 pathcomp
.type
= UDF_PATH_COMP_PARENTDIR
;
1539 if ((compnamelen
== 1) && (*compnamepos
== '.'))
1540 pathcomp
.type
= UDF_PATH_COMP_CURDIR
;
1542 if (pathcomp
.type
== UDF_PATH_COMP_NAME
) {
1544 (char *) &pathcomp
.ident
, &pathcomp
.l_ci
,
1545 compnamepos
, compnamelen
,
1547 len
= UDF_PATH_COMP_SIZE
+ pathcomp
.l_ci
;
1550 if (pathlen
+ len
>= UDF_SYMLINKBUFLEN
) {
1551 error
= ENAMETOOLONG
;
1555 memcpy(pathpos
, &pathcomp
, len
);
1561 /* aparently too big */
1566 /* return status of symlink contents writeout */
1567 *pathbufp
= (uint8_t *) pathbuf
;
1568 *pathlenp
= pathlen
;
1573 #undef UDF_SYMLINKBUFLEN
1577 udf_fidsize(struct fileid_desc
*fid
)
1581 if (udf_rw16(fid
->tag
.id
) != TAGID_FID
)
1582 errx(EINVAL
, "got udf_fidsize on non FID");
1584 size
= UDF_FID_SIZE
+ fid
->l_fi
+ udf_rw16(fid
->l_iu
);
1585 size
= (size
+ 3) & ~3;
1592 udf_create_parentfid(struct fileid_desc
*fid
, struct long_ad
*parent
)
1594 /* the size of an empty FID is 38 but needs to be a multiple of 4 */
1597 udf_inittag(&fid
->tag
, TAGID_FID
, udf_rw32(parent
->loc
.lb_num
));
1598 fid
->file_version_num
= udf_rw16(1); /* UDF 2.3.4.1 */
1599 fid
->file_char
= UDF_FILE_CHAR_DIR
| UDF_FILE_CHAR_PAR
;
1601 fid
->icb
.longad_uniqueid
= parent
->longad_uniqueid
;
1602 fid
->tag
.desc_crc_len
= udf_rw16(fidsize
- UDF_DESC_TAG_LENGTH
);
1604 /* we have to do the fid here explicitly for simplicity */
1605 udf_validate_tag_and_crc_sums((union dscrptr
*) fid
);
1612 udf_create_fid(uint32_t diroff
, struct fileid_desc
*fid
, char *name
,
1613 int file_char
, struct long_ad
*ref
)
1615 struct charspec osta_charspec
;
1617 uint32_t fidsize
, lb_rest
;
1619 memset(fid
, 0, sizeof(*fid
));
1620 udf_inittag(&fid
->tag
, TAGID_FID
, udf_rw32(ref
->loc
.lb_num
));
1621 fid
->file_version_num
= udf_rw16(1); /* UDF 2.3.4.1 */
1622 fid
->file_char
= file_char
;
1623 fid
->l_iu
= udf_rw16(0);
1625 fid
->icb
.longad_uniqueid
= ref
->longad_uniqueid
;
1627 udf_osta_charset(&osta_charspec
);
1628 unix_to_udf_name((char *) fid
->data
, &fid
->l_fi
, name
, strlen(name
),
1632 * OK, tricky part: we need to pad so the next descriptor header won't
1633 * cross the sector boundary
1635 endfid
= diroff
+ udf_fidsize(fid
);
1636 lb_rest
= context
.sector_size
- (endfid
% context
.sector_size
);
1637 if (lb_rest
< sizeof(struct desc_tag
)) {
1638 /* add at least 32 */
1639 fid
->l_iu
= udf_rw16(32);
1640 udf_set_regid((struct regid
*) fid
->data
, context
.impl_name
);
1641 udf_add_impl_regid((struct regid
*) fid
->data
);
1643 unix_to_udf_name((char *) fid
->data
+ udf_rw16(fid
->l_iu
),
1644 &fid
->l_fi
, name
, strlen(name
), &osta_charspec
);
1647 fidsize
= udf_fidsize(fid
);
1648 fid
->tag
.desc_crc_len
= udf_rw16(fidsize
- UDF_DESC_TAG_LENGTH
);
1650 /* make sure the header sums stays correct */
1651 udf_validate_tag_and_crc_sums((union dscrptr
*)fid
);
1656 udf_append_parentfid(union dscrptr
*dscr
, struct long_ad
*parent_icb
)
1658 struct file_entry
*fe
;
1659 struct extfile_entry
*efe
;
1660 struct fileid_desc
*fid
;
1662 uint32_t fidsize
, crclen
;
1663 uint8_t *bpos
, *data
;
1667 if (udf_rw16(dscr
->tag
.id
) == TAGID_FENTRY
) {
1670 l_ea
= udf_rw32(fe
->l_ea
);
1671 } else if (udf_rw16(dscr
->tag
.id
) == TAGID_EXTFENTRY
) {
1674 l_ea
= udf_rw32(efe
->l_ea
);
1676 errx(1, "Bad tag passed to udf_append_parentfid");
1681 fid
= (struct fileid_desc
*) bpos
;
1682 fidsize
= udf_create_parentfid(fid
, parent_icb
);
1684 /* record fidlength information */
1686 fe
->inf_len
= udf_rw64(fidsize
);
1687 fe
->l_ad
= udf_rw32(fidsize
);
1688 fe
->logblks_rec
= udf_rw64(0); /* intern */
1689 crclen
= sizeof(struct file_entry
);
1691 efe
->inf_len
= udf_rw64(fidsize
);
1692 efe
->obj_size
= udf_rw64(fidsize
);
1693 efe
->l_ad
= udf_rw32(fidsize
);
1694 efe
->logblks_rec
= udf_rw64(0); /* intern */
1695 crclen
= sizeof(struct extfile_entry
);
1697 crclen
-= 1 + UDF_DESC_TAG_LENGTH
;
1698 crclen
+= l_ea
+ fidsize
;
1699 dscr
->tag
.desc_crc_len
= udf_rw16(crclen
);
1701 /* make sure the header sums stays correct */
1702 udf_validate_tag_and_crc_sums(dscr
);
1708 * Order of extended attributes :
1710 * Non block aligned Implementation Use EAs
1711 * Block aligned Implementation Use EAs (not in newfs_udf)
1712 * Application Use EAs (not in newfs_udf)
1714 * no checks for doubles, must be called in-order
1717 udf_extattr_append_internal(union dscrptr
*dscr
, struct extattr_entry
*extattr
)
1719 struct file_entry
*fe
;
1720 struct extfile_entry
*efe
;
1721 struct extattrhdr_desc
*extattrhdr
;
1722 struct impl_extattr_entry
*implext
;
1723 uint32_t impl_attr_loc
, appl_attr_loc
, l_ea
, a_l
, exthdr_len
;
1724 uint32_t *l_eap
, l_ad
;
1726 uint8_t *bpos
, *data
;
1728 if (udf_rw16(dscr
->tag
.id
) == TAGID_FENTRY
) {
1732 l_ad
= udf_rw32(fe
->l_ad
);
1733 } else if (udf_rw16(dscr
->tag
.id
) == TAGID_EXTFENTRY
) {
1737 l_ad
= udf_rw32(efe
->l_ad
);
1739 errx(1, "Bad tag passed to udf_extattr_append_internal");
1742 /* should have a header! */
1743 extattrhdr
= (struct extattrhdr_desc
*) data
;
1744 l_ea
= udf_rw32(*l_eap
);
1746 #if !defined(NDEBUG) && defined(__minix)
1750 printf("%s:%d: l_ad != 0\n", __func__
, __LINE__
);
1753 #endif /* !defined(NDEBUG) && defined(__minix) */
1754 /* create empty extended attribute header */
1755 exthdr_len
= sizeof(struct extattrhdr_desc
);
1757 udf_inittag(&extattrhdr
->tag
, TAGID_EXTATTR_HDR
, /* loc */ 0);
1758 extattrhdr
->impl_attr_loc
= udf_rw32(exthdr_len
);
1759 extattrhdr
->appl_attr_loc
= udf_rw32(exthdr_len
);
1760 extattrhdr
->tag
.desc_crc_len
= udf_rw16(8);
1762 /* record extended attribute header length */
1764 *l_eap
= udf_rw32(l_ea
);
1767 /* extract locations */
1768 impl_attr_loc
= udf_rw32(extattrhdr
->impl_attr_loc
);
1769 appl_attr_loc
= udf_rw32(extattrhdr
->appl_attr_loc
);
1770 if (impl_attr_loc
== UDF_IMPL_ATTR_LOC_NOT_PRESENT
)
1771 impl_attr_loc
= l_ea
;
1772 if (appl_attr_loc
== UDF_IMPL_ATTR_LOC_NOT_PRESENT
)
1773 appl_attr_loc
= l_ea
;
1776 if (udf_rw32(extattr
->type
) < 2048) {
1777 assert(impl_attr_loc
== l_ea
);
1778 assert(appl_attr_loc
== l_ea
);
1781 /* implementation use extended attributes */
1782 if (udf_rw32(extattr
->type
) == 2048) {
1783 assert(appl_attr_loc
== l_ea
);
1785 /* calculate and write extended attribute header checksum */
1786 implext
= (struct impl_extattr_entry
*) extattr
;
1787 assert(udf_rw32(implext
->iu_l
) == 4); /* [UDF 3.3.4.5] */
1788 spos
= (uint16_t *) implext
->data
;
1789 *spos
= udf_rw16(udf_ea_cksum((uint8_t *) implext
));
1792 /* application use extended attributes */
1793 assert(udf_rw32(extattr
->type
) != 65536);
1794 assert(appl_attr_loc
== l_ea
);
1796 /* append the attribute at the end of the current space */
1797 bpos
= data
+ udf_rw32(*l_eap
);
1798 a_l
= udf_rw32(extattr
->a_l
);
1800 /* update impl. attribute locations */
1801 if (udf_rw32(extattr
->type
) < 2048) {
1802 impl_attr_loc
= l_ea
+ a_l
;
1803 appl_attr_loc
= l_ea
+ a_l
;
1805 if (udf_rw32(extattr
->type
) == 2048) {
1806 appl_attr_loc
= l_ea
+ a_l
;
1809 /* copy and advance */
1810 memcpy(bpos
, extattr
, a_l
);
1812 *l_eap
= udf_rw32(l_ea
);
1814 /* do the `dance` again backwards */
1815 if (context
.dscrver
!= 2) {
1816 if (impl_attr_loc
== l_ea
)
1817 impl_attr_loc
= UDF_IMPL_ATTR_LOC_NOT_PRESENT
;
1818 if (appl_attr_loc
== l_ea
)
1819 appl_attr_loc
= UDF_APPL_ATTR_LOC_NOT_PRESENT
;
1823 extattrhdr
->impl_attr_loc
= udf_rw32(impl_attr_loc
);
1824 extattrhdr
->appl_attr_loc
= udf_rw32(appl_attr_loc
);
1826 /* make sure the header sums stays correct */
1827 udf_validate_tag_and_crc_sums((union dscrptr
*) extattrhdr
);
1832 udf_create_new_fe(struct file_entry
**fep
, int file_type
, struct stat
*st
)
1834 struct file_entry
*fe
;
1835 struct icb_tag
*icb
;
1836 struct timestamp birthtime
;
1837 struct filetimes_extattr_entry
*ft_extattr
;
1838 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1842 fe
= calloc(1, context
.sector_size
);
1846 udf_inittag(&fe
->tag
, TAGID_FENTRY
, /* loc */ 0);
1850 * Always use strategy type 4 unless on WORM wich we don't support
1851 * (yet). Fill in defaults and set for internal allocation of data.
1853 icb
->strat_type
= udf_rw16(4);
1854 icb
->max_num_entries
= udf_rw16(1);
1855 icb
->file_type
= file_type
; /* 8 bit */
1856 icb
->flags
= udf_rw16(UDF_ICB_INTERN_ALLOC
);
1858 fe
->perm
= udf_rw32(0x7fff); /* all is allowed */
1859 fe
->link_cnt
= udf_rw16(0); /* explicit setting */
1861 fe
->ckpoint
= udf_rw32(1); /* user supplied file version */
1863 udf_set_timestamp_now(&birthtime
);
1864 udf_set_timestamp_now(&fe
->atime
);
1865 udf_set_timestamp_now(&fe
->attrtime
);
1866 udf_set_timestamp_now(&fe
->mtime
);
1868 /* set attributes */
1870 #if !HAVE_NBTOOL_CONFIG_H
1871 udf_set_timestamp(&birthtime
, st
->st_birthtime
);
1873 udf_set_timestamp(&birthtime
, 0);
1875 udf_set_timestamp(&fe
->atime
, st
->st_atime
);
1876 udf_set_timestamp(&fe
->attrtime
, st
->st_ctime
);
1877 udf_set_timestamp(&fe
->mtime
, st
->st_mtime
);
1878 fe
->uid
= udf_rw32(st
->st_uid
);
1879 fe
->gid
= udf_rw32(st
->st_gid
);
1881 fe
->perm
= unix_mode_to_udf_perm(st
->st_mode
);
1883 icbflags
= udf_rw16(fe
->icbtag
.flags
);
1884 icbflags
&= ~UDF_ICB_TAG_FLAGS_SETUID
;
1885 icbflags
&= ~UDF_ICB_TAG_FLAGS_SETGID
;
1886 icbflags
&= ~UDF_ICB_TAG_FLAGS_STICKY
;
1887 if (st
->st_mode
& S_ISUID
)
1888 icbflags
|= UDF_ICB_TAG_FLAGS_SETUID
;
1889 if (st
->st_mode
& S_ISGID
)
1890 icbflags
|= UDF_ICB_TAG_FLAGS_SETGID
;
1891 if (st
->st_mode
& S_ISVTX
)
1892 icbflags
|= UDF_ICB_TAG_FLAGS_STICKY
;
1893 fe
->icbtag
.flags
= udf_rw16(icbflags
);
1896 udf_set_regid(&fe
->imp_id
, context
.impl_name
);
1897 udf_add_impl_regid(&fe
->imp_id
);
1898 fe
->unique_id
= udf_rw64(context
.unique_id
);
1899 udf_advance_uniqueid();
1901 fe
->l_ea
= udf_rw32(0);
1903 /* create extended attribute to record our creation time */
1904 ft_extattr
= calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
1905 ft_extattr
->hdr
.type
= udf_rw32(UDF_FILETIMES_ATTR_NO
);
1906 ft_extattr
->hdr
.subtype
= 1; /* [4/48.10.5] */
1907 ft_extattr
->hdr
.a_l
= udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
1908 ft_extattr
->d_l
= udf_rw32(UDF_TIMESTAMP_SIZE
); /* one item */
1909 ft_extattr
->existence
= UDF_FILETIMES_FILE_CREATION
;
1910 ft_extattr
->times
[0] = birthtime
;
1912 udf_extattr_append_internal((union dscrptr
*) fe
,
1913 (struct extattr_entry
*) ft_extattr
);
1916 /* record fidlength information */
1917 fe
->inf_len
= udf_rw64(0);
1918 fe
->l_ad
= udf_rw32(0);
1919 fe
->logblks_rec
= udf_rw64(0); /* intern */
1921 crclen
= sizeof(struct file_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
1922 crclen
+= udf_rw32(fe
->l_ea
);
1924 /* make sure the header sums stays correct */
1925 fe
->tag
.desc_crc_len
= udf_rw16(crclen
);
1926 udf_validate_tag_and_crc_sums((union dscrptr
*) fe
);
1934 udf_create_new_efe(struct extfile_entry
**efep
, int file_type
, struct stat
*st
)
1936 struct extfile_entry
*efe
;
1937 struct icb_tag
*icb
;
1938 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1942 efe
= calloc(1, context
.sector_size
);
1946 udf_inittag(&efe
->tag
, TAGID_EXTFENTRY
, /* loc */ 0);
1950 * Always use strategy type 4 unless on WORM wich we don't support
1951 * (yet). Fill in defaults and set for internal allocation of data.
1953 icb
->strat_type
= udf_rw16(4);
1954 icb
->max_num_entries
= udf_rw16(1);
1955 icb
->file_type
= file_type
; /* 8 bit */
1956 icb
->flags
= udf_rw16(UDF_ICB_INTERN_ALLOC
);
1958 efe
->perm
= udf_rw32(0x7fff); /* all is allowed */
1959 efe
->link_cnt
= udf_rw16(0); /* explicit setting */
1961 efe
->ckpoint
= udf_rw32(1); /* user supplied file version */
1963 udf_set_timestamp_now(&efe
->ctime
);
1964 udf_set_timestamp_now(&efe
->atime
);
1965 udf_set_timestamp_now(&efe
->attrtime
);
1966 udf_set_timestamp_now(&efe
->mtime
);
1968 /* set attributes */
1970 #if !HAVE_NBTOOL_CONFIG_H
1971 udf_set_timestamp(&efe
->ctime
, st
->st_birthtime
);
1973 udf_set_timestamp(&efe
->ctime
, 0);
1975 udf_set_timestamp(&efe
->atime
, st
->st_atime
);
1976 udf_set_timestamp(&efe
->attrtime
, st
->st_ctime
);
1977 udf_set_timestamp(&efe
->mtime
, st
->st_mtime
);
1978 efe
->uid
= udf_rw32(st
->st_uid
);
1979 efe
->gid
= udf_rw32(st
->st_gid
);
1981 efe
->perm
= unix_mode_to_udf_perm(st
->st_mode
);
1983 icbflags
= udf_rw16(efe
->icbtag
.flags
);
1984 icbflags
&= ~UDF_ICB_TAG_FLAGS_SETUID
;
1985 icbflags
&= ~UDF_ICB_TAG_FLAGS_SETGID
;
1986 icbflags
&= ~UDF_ICB_TAG_FLAGS_STICKY
;
1987 if (st
->st_mode
& S_ISUID
)
1988 icbflags
|= UDF_ICB_TAG_FLAGS_SETUID
;
1989 if (st
->st_mode
& S_ISGID
)
1990 icbflags
|= UDF_ICB_TAG_FLAGS_SETGID
;
1991 if (st
->st_mode
& S_ISVTX
)
1992 icbflags
|= UDF_ICB_TAG_FLAGS_STICKY
;
1993 efe
->icbtag
.flags
= udf_rw16(icbflags
);
1996 udf_set_regid(&efe
->imp_id
, context
.impl_name
);
1997 udf_add_impl_regid(&efe
->imp_id
);
1999 efe
->unique_id
= udf_rw64(context
.unique_id
);
2000 udf_advance_uniqueid();
2002 /* record fidlength information */
2003 efe
->inf_len
= udf_rw64(0);
2004 efe
->obj_size
= udf_rw64(0);
2005 efe
->l_ad
= udf_rw32(0);
2006 efe
->logblks_rec
= udf_rw64(0);
2008 crclen
= sizeof(struct extfile_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
2010 /* make sure the header sums stays correct */
2011 efe
->tag
.desc_crc_len
= udf_rw16(crclen
);
2012 udf_validate_tag_and_crc_sums((union dscrptr
*) efe
);
2018 /* --------------------------------------------------------------------- */
2020 /* for METADATA file appending only */
2022 udf_append_meta_mapping_part_to_efe(struct extfile_entry
*efe
,
2023 struct short_ad
*mapping
)
2025 struct icb_tag
*icb
;
2026 uint64_t inf_len
, obj_size
, logblks_rec
;
2027 uint32_t l_ad
, l_ea
;
2031 inf_len
= udf_rw64(efe
->inf_len
);
2032 obj_size
= udf_rw64(efe
->obj_size
);
2033 logblks_rec
= udf_rw64(efe
->logblks_rec
);
2034 l_ad
= udf_rw32(efe
->l_ad
);
2035 l_ea
= udf_rw32(efe
->l_ea
);
2036 crclen
= udf_rw16(efe
->tag
.desc_crc_len
);
2039 /* set our allocation to shorts if not already done */
2040 icb
->flags
= udf_rw16(UDF_ICB_SHORT_ALLOC
);
2042 /* append short_ad */
2043 bpos
= (uint8_t *) efe
->data
+ l_ea
+ l_ad
;
2044 memcpy(bpos
, mapping
, sizeof(struct short_ad
));
2046 l_ad
+= sizeof(struct short_ad
);
2047 crclen
+= sizeof(struct short_ad
);
2048 inf_len
+= UDF_EXT_LEN(udf_rw32(mapping
->len
));
2049 obj_size
+= UDF_EXT_LEN(udf_rw32(mapping
->len
));
2050 logblks_rec
= UDF_ROUNDUP(inf_len
, context
.sector_size
) /
2051 context
.sector_size
;
2053 efe
->l_ad
= udf_rw32(l_ad
);
2054 efe
->inf_len
= udf_rw64(inf_len
);
2055 efe
->obj_size
= udf_rw64(obj_size
);
2056 efe
->logblks_rec
= udf_rw64(logblks_rec
);
2057 efe
->tag
.desc_crc_len
= udf_rw16(crclen
);
2061 /* for METADATA file appending only */
2063 udf_append_meta_mapping_to_efe(struct extfile_entry
*efe
,
2064 uint16_t partnr
, uint32_t lb_num
,
2067 struct short_ad mapping
;
2068 uint64_t max_len
, part_len
;
2070 /* calculate max length meta allocation sizes */
2071 max_len
= UDF_EXT_MAXLEN
/ context
.sector_size
; /* in sectors */
2072 max_len
= (max_len
/ layout
.meta_blockingnr
) * layout
.meta_blockingnr
;
2073 max_len
= max_len
* context
.sector_size
;
2075 memset(&mapping
, 0, sizeof(mapping
));
2077 part_len
= MIN(len
, max_len
);
2078 mapping
.lb_num
= udf_rw32(lb_num
);
2079 mapping
.len
= udf_rw32(part_len
);
2081 udf_append_meta_mapping_part_to_efe(efe
, &mapping
);
2083 lb_num
+= part_len
/ context
.sector_size
;
2090 udf_create_meta_files(void)
2092 struct extfile_entry
*efe
;
2093 struct long_ad meta_icb
;
2095 uint32_t sector_size
;
2096 int filetype
, error
;
2098 sector_size
= context
.sector_size
;
2100 memset(&meta_icb
, 0, sizeof(meta_icb
));
2101 meta_icb
.len
= udf_rw32(sector_size
);
2102 meta_icb
.loc
.part_num
= udf_rw16(context
.data_part
);
2104 /* create metadata file */
2105 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_file
);
2106 filetype
= UDF_ICB_FILETYPE_META_MAIN
;
2107 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
2110 context
.meta_file
= efe
;
2112 /* create metadata mirror file */
2113 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_mirror
);
2114 filetype
= UDF_ICB_FILETYPE_META_MIRROR
;
2115 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
2118 context
.meta_mirror
= efe
;
2120 /* create metadata bitmap file */
2121 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_bitmap
);
2122 filetype
= UDF_ICB_FILETYPE_META_BITMAP
;
2123 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
2126 context
.meta_bitmap
= efe
;
2128 /* patch up files */
2129 context
.meta_file
->unique_id
= udf_rw64(0);
2130 context
.meta_mirror
->unique_id
= udf_rw64(0);
2131 context
.meta_bitmap
->unique_id
= udf_rw64(0);
2133 /* restart unique id */
2134 context
.unique_id
= 0x10;
2136 /* XXX no support for metadata mirroring yet */
2137 /* insert extents */
2138 efe
= context
.meta_file
;
2139 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
2140 layout
.meta_part_start_lba
,
2141 (uint64_t) layout
.meta_part_size_lba
* sector_size
);
2143 efe
= context
.meta_mirror
;
2144 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
2145 layout
.meta_part_start_lba
,
2146 (uint64_t) layout
.meta_part_size_lba
* sector_size
);
2148 efe
= context
.meta_bitmap
;
2149 bytes
= udf_space_bitmap_len(layout
.meta_part_size_lba
);
2150 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
2151 layout
.meta_bitmap_space
, bytes
);
2157 /* --------------------------------------------------------------------- */
2160 udf_create_new_rootdir(union dscrptr
**dscr
)
2162 struct file_entry
*fe
;
2163 struct extfile_entry
*efe
;
2164 struct long_ad root_icb
;
2165 int filetype
, error
;
2167 #if defined(__minix)
2168 /* LSC: -Werror=maybe-uninitialized when compiling with -O3 */
2170 #endif /*defined(__minix) */
2171 memset(&root_icb
, 0, sizeof(root_icb
));
2172 root_icb
.len
= udf_rw32(context
.sector_size
);
2173 root_icb
.loc
.lb_num
= udf_rw32(layout
.rootdir
);
2174 root_icb
.loc
.part_num
= udf_rw16(context
.metadata_part
);
2176 filetype
= UDF_ICB_FILETYPE_DIRECTORY
;
2177 if (context
.dscrver
== 2) {
2178 error
= udf_create_new_fe(&fe
, filetype
, NULL
);
2179 *dscr
= (union dscrptr
*) fe
;
2181 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
2182 *dscr
= (union dscrptr
*) efe
;
2188 udf_append_parentfid(*dscr
, &root_icb
);
2190 /* rootdir has explicit only one link on creation; '..' is no link */
2191 if (context
.dscrver
== 2) {
2192 fe
->link_cnt
= udf_rw16(1);
2194 efe
->link_cnt
= udf_rw16(1);
2197 context
.num_directories
++;
2198 assert(context
.num_directories
== 1);
2205 udf_prepend_VAT_file(void)
2207 /* old style VAT has no prepend */
2208 if (context
.dscrver
== 2) {
2209 context
.vat_start
= 0;
2210 context
.vat_size
= 0;
2214 context
.vat_start
= offsetof(struct udf_vat
, data
);
2215 context
.vat_size
= offsetof(struct udf_vat
, data
);
2220 udf_vat_update(uint32_t virt
, uint32_t phys
)
2225 if (context
.vtop_tp
[context
.metadata_part
] != UDF_VTOP_TYPE_VIRT
)
2228 new_size
= MAX(context
.vat_size
,
2229 (context
.vat_start
+ (virt
+1)*sizeof(uint32_t)));
2231 if (new_size
> context
.vat_allocated
) {
2232 context
.vat_allocated
=
2233 UDF_ROUNDUP(new_size
, context
.sector_size
);
2234 context
.vat_contents
= realloc(context
.vat_contents
,
2235 context
.vat_allocated
);
2236 assert(context
.vat_contents
);
2237 /* XXX could also report error */
2239 vatpos
= (uint32_t *) (context
.vat_contents
+ context
.vat_start
);
2240 vatpos
[virt
] = udf_rw32(phys
);
2242 context
.vat_size
= MAX(context
.vat_size
,
2243 (context
.vat_start
+ (virt
+1)*sizeof(uint32_t)));
2248 udf_append_VAT_file(void)
2250 struct udf_oldvat_tail
*oldvat_tail
;
2251 struct udf_vat
*vathdr
;
2254 /* new style VAT has VAT LVInt analog in front */
2255 if (context
.dscrver
== 3) {
2256 /* set up VATv2 descriptor */
2257 vathdr
= (struct udf_vat
*) context
.vat_contents
;
2258 vathdr
->header_len
= udf_rw16(sizeof(struct udf_vat
) - 1);
2259 vathdr
->impl_use_len
= udf_rw16(0);
2260 memcpy(vathdr
->logvol_id
, context
.logical_vol
->logvol_id
, 128);
2261 vathdr
->prev_vat
= udf_rw32(UDF_NO_PREV_VAT
);
2262 vathdr
->num_files
= udf_rw32(context
.num_files
);
2263 vathdr
->num_directories
= udf_rw32(context
.num_directories
);
2265 vathdr
->min_udf_readver
= udf_rw16(context
.min_udf
);
2266 vathdr
->min_udf_writever
= udf_rw16(context
.min_udf
);
2267 vathdr
->max_udf_writever
= udf_rw16(context
.max_udf
);
2272 /* old style VAT has identifier appended */
2274 /* append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
2275 len_diff
= context
.vat_allocated
- context
.vat_size
;
2276 assert(len_diff
>= 0);
2277 if (len_diff
< (int32_t) sizeof(struct udf_oldvat_tail
)) {
2278 context
.vat_allocated
+= context
.sector_size
;
2279 context
.vat_contents
= realloc(context
.vat_contents
,
2280 context
.vat_allocated
);
2281 assert(context
.vat_contents
);
2282 /* XXX could also report error */
2285 oldvat_tail
= (struct udf_oldvat_tail
*) (context
.vat_contents
+
2288 udf_set_regid(&oldvat_tail
->id
, "*UDF Virtual Alloc Tbl");
2289 udf_add_udf_regid(&oldvat_tail
->id
);
2290 oldvat_tail
->prev_vat
= udf_rw32(UDF_NO_PREV_VAT
);
2292 context
.vat_size
+= sizeof(struct udf_oldvat_tail
);
2299 udf_create_VAT(union dscrptr
**vat_dscr
)
2301 struct file_entry
*fe
;
2302 struct extfile_entry
*efe
;
2303 struct impl_extattr_entry
*implext
;
2304 struct vatlvext_extattr_entry
*vatlvext
;
2305 struct long_ad dataloc
, *allocpos
;
2306 uint8_t *bpos
, *extattr
;
2307 uint32_t ea_len
, inf_len
, vat_len
, blks
;
2311 assert((layout
.rootdir
< 2) && (layout
.fsd
< 2));
2313 memset(&dataloc
, 0, sizeof(dataloc
));
2314 dataloc
.len
= udf_rw32(context
.vat_size
);
2315 dataloc
.loc
.part_num
= udf_rw16(context
.data_part
);
2316 dataloc
.loc
.lb_num
= udf_rw32(layout
.vat
);
2318 if (context
.dscrver
== 2) {
2320 filetype
= UDF_ICB_FILETYPE_UNKNOWN
;
2321 error
= udf_create_new_fe(&fe
, filetype
, NULL
);
2325 /* append VAT LVExtension attribute */
2326 ea_len
= sizeof(struct impl_extattr_entry
) - 1 +
2327 sizeof(struct vatlvext_extattr_entry
) + 4;
2329 extattr
= calloc(1, ea_len
);
2331 implext
= (struct impl_extattr_entry
*) extattr
;
2332 implext
->hdr
.type
= udf_rw32(2048); /* [4/48.10.8] */
2333 implext
->hdr
.subtype
= 1; /* [4/48.10.8.2] */
2334 implext
->hdr
.a_l
= udf_rw32(ea_len
); /* VAT LVext EA size */
2335 /* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
2336 implext
->iu_l
= udf_rw32(4);
2337 udf_set_regid(&implext
->imp_id
, "*UDF VAT LVExtension");
2338 udf_add_udf_regid(&implext
->imp_id
);
2340 /* VAT LVExtension data follows UDF IU space */
2341 bpos
= ((uint8_t *) implext
->data
) + 4;
2342 vatlvext
= (struct vatlvext_extattr_entry
*) bpos
;
2344 vatlvext
->unique_id_chk
= udf_rw64(fe
->unique_id
);
2345 vatlvext
->num_files
= udf_rw32(context
.num_files
);
2346 vatlvext
->num_directories
= udf_rw32(context
.num_directories
);
2347 memcpy(vatlvext
->logvol_id
, context
.logical_vol
->logvol_id
,128);
2349 udf_extattr_append_internal((union dscrptr
*) fe
,
2350 (struct extattr_entry
*) extattr
);
2354 fe
->icbtag
.flags
= udf_rw16(UDF_ICB_LONG_ALLOC
);
2356 allocpos
= (struct long_ad
*) (fe
->data
+ udf_rw32(fe
->l_ea
));
2357 *allocpos
= dataloc
;
2360 inf_len
= context
.vat_size
;
2361 fe
->inf_len
= udf_rw64(inf_len
);
2362 fe
->l_ad
= udf_rw32(sizeof(struct long_ad
));
2363 blks
= UDF_ROUNDUP(inf_len
, context
.sector_size
) /
2364 context
.sector_size
;
2365 fe
->logblks_rec
= udf_rw32(blks
);
2367 /* update vat descriptor's CRC length */
2368 vat_len
= sizeof(struct file_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
2369 vat_len
+= udf_rw32(fe
->l_ad
) + udf_rw32(fe
->l_ea
);
2370 fe
->tag
.desc_crc_len
= udf_rw16(vat_len
);
2372 *vat_dscr
= (union dscrptr
*) fe
;
2375 filetype
= UDF_ICB_FILETYPE_VAT
;
2376 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
2380 efe
->icbtag
.flags
= udf_rw16(UDF_ICB_LONG_ALLOC
);
2382 allocpos
= (struct long_ad
*) efe
->data
;
2383 *allocpos
= dataloc
;
2386 inf_len
= context
.vat_size
;
2387 efe
->inf_len
= udf_rw64(inf_len
);
2388 efe
->obj_size
= udf_rw64(inf_len
);
2389 efe
->l_ad
= udf_rw32(sizeof(struct long_ad
));
2390 blks
= UDF_ROUNDUP(inf_len
, context
.sector_size
) /
2391 context
.sector_size
;
2392 efe
->logblks_rec
= udf_rw32(blks
);
2394 vat_len
= sizeof(struct extfile_entry
)-1 - UDF_DESC_TAG_LENGTH
;
2395 vat_len
+= udf_rw32(efe
->l_ad
);
2396 efe
->tag
.desc_crc_len
= udf_rw16(vat_len
);
2398 *vat_dscr
= (union dscrptr
*) efe
;