1 /* $NetBSD: udf_create.c,v 1.16 2009/05/19 12:13:02 reinoud 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.
29 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: udf_create.c,v 1.16 2009/05/19 12:13:02 reinoud Exp $");
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include "udf_create.h"
54 udf_init_create_context(void)
57 memset(&context
, 0, sizeof(struct udf_create_context
));
59 /* fill with defaults currently known */
61 context
.min_udf
= 0x0102;
62 context
.max_udf
= 0x0260;
63 context
.serialnum
= 1; /* default */
66 context
.sector_size
= 512; /* minimum for UDF */
68 context
.logvol_name
= NULL
;
69 context
.primary_name
= NULL
;
70 context
.volset_name
= NULL
;
71 context
.fileset_name
= NULL
;
73 context
.app_name
= "*NetBSD newfs";
74 context
.app_version_main
= __NetBSD_Version__
/ 100000000;
75 context
.app_version_sub
= (__NetBSD_Version__
/ 1000000) % 100;
76 context
.impl_name
= "*NetBSD kernel UDF";
78 context
.vds_seq
= 0; /* first one starts with zero */
80 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
81 context
.unique_id
= 0x10;
83 context
.num_files
= 0;
84 context
.num_directories
= 0;
89 udf_space_bitmap_len(uint32_t part_size
)
91 return sizeof(struct space_bitmap_desc
)-1 +
97 udf_bytes_to_sectors(uint64_t bytes
)
99 uint32_t sector_size
= layout
.sector_size
;
100 return (bytes
+ sector_size
-1) / sector_size
;
105 udf_calculate_disc_layout(int format_flags
, int min_udf
,
106 uint32_t wrtrack_skew
,
107 uint32_t first_lba
, uint32_t last_lba
,
108 uint32_t sector_size
, uint32_t blockingnr
,
109 uint32_t sparable_blocks
, float meta_fract
)
111 uint64_t kbsize
, bytes
;
112 uint32_t sparable_blockingnr
;
113 uint32_t align_blockingnr
;
117 bzero(&layout
, sizeof(struct udf_disclayout
));
119 /* fill with parameters */
120 layout
.wrtrack_skew
= wrtrack_skew
;
121 layout
.first_lba
= first_lba
;
122 layout
.last_lba
= last_lba
;
123 layout
.sector_size
= sector_size
;
124 layout
.blockingnr
= blockingnr
;
125 layout
.sparable_blocks
= sparable_blocks
;
127 /* start disc layouting */
130 * location of iso9660 vrs is defined as first sector AFTER 32kb,
131 * minimum `sector size' 2048
133 layout
.iso9660_vrs
= ((32*1024 + sector_size
- 1) / sector_size
)
136 /* anchor starts at specified offset in sectors */
137 layout
.anchors
[0] = first_lba
+ 256;
138 if (format_flags
& FORMAT_TRACK512
)
139 layout
.anchors
[0] = first_lba
+ 512;
140 layout
.anchors
[1] = last_lba
- 256;
141 layout
.anchors
[2] = last_lba
;
143 /* update workable space */
144 first_lba
= layout
.anchors
[0] + blockingnr
;
145 last_lba
= layout
.anchors
[1] - 1;
147 /* XXX rest of anchor packet can be added to unallocated space descr */
149 /* reserve space for VRS and VRS copy and associated tables */
150 layout
.vds_size
= MAX(16, blockingnr
); /* UDF 2.2.3.1+2 */
151 layout
.vds1
= first_lba
;
152 first_lba
+= layout
.vds_size
; /* next packet */
154 if (format_flags
& FORMAT_SEQUENTIAL
) {
155 /* for sequential, append them ASAP */
156 layout
.vds2
= first_lba
;
157 first_lba
+= layout
.vds_size
;
159 layout
.vds2
= layout
.anchors
[1] - layout
.vds_size
;
160 last_lba
= layout
.vds2
- 1; /* XXX -1 ?? */
163 /* reserve space for logvol integrity sequence */
164 layout
.lvis_size
= MAX(8192/sector_size
, 2 * blockingnr
);
165 if (format_flags
& FORMAT_VAT
)
166 layout
.lvis_size
= 2;
167 if (format_flags
& FORMAT_WORM
)
168 layout
.lvis_size
= 64 * blockingnr
;
170 /* TODO skip bad blocks in LVID sequence; for now use f.e. */
172 layout
.lvis
= first_lba
;
173 first_lba
+= layout
.lvis_size
;
175 /* initial guess of UDF partition size */
176 layout
.part_start_lba
= first_lba
;
177 layout
.part_size_lba
= last_lba
- layout
.part_start_lba
;
179 /* all non sequential media needs an unallocated space bitmap */
180 layout
.alloc_bitmap_dscr_size
= 0;
181 if ((format_flags
& FORMAT_SEQUENTIAL
) == 0) {
182 bytes
= udf_space_bitmap_len(layout
.part_size_lba
);
183 layout
.alloc_bitmap_dscr_size
= udf_bytes_to_sectors(bytes
);
185 /* XXX freed space map when applicable */
189 * Note that for (bug) compatibility with version UDF 2.00 (fixed in
190 * 2.01 and higher) the blocking size needs to be 32 sectors otherwise
191 * the drive's blockingnr.
194 sparable_blockingnr
= blockingnr
;
195 if (min_udf
<= 0x200)
196 sparable_blockingnr
= 32;
198 align_blockingnr
= blockingnr
;
199 if (format_flags
& (FORMAT_SPARABLE
| FORMAT_META
))
200 align_blockingnr
= sparable_blockingnr
;
202 layout
.align_blockingnr
= align_blockingnr
;
203 layout
.sparable_blockingnr
= sparable_blockingnr
;
206 * Align partition LBA space to blocking granularity. Not strickly
207 * nessisary for non sparables but safer for the VRS data since it is
208 * not updated sporadically
211 if ((format_flags
& FORMAT_SEQUENTIAL
) == 0) {
213 printf("Lost %d slack sectors at start\n", UDF_ROUNDUP(
214 first_lba
- wrtrack_skew
, align_blockingnr
) -
215 (first_lba
- wrtrack_skew
));
216 printf("Lost %d slack sectors at end\n",
217 (first_lba
- wrtrack_skew
) - UDF_ROUNDDOWN(
218 first_lba
- wrtrack_skew
, align_blockingnr
));
221 first_lba
= UDF_ROUNDUP( first_lba
- wrtrack_skew
, align_blockingnr
);
222 last_lba
= UDF_ROUNDDOWN(last_lba
- wrtrack_skew
, align_blockingnr
);
225 if ((format_flags
& FORMAT_SPARABLE
) == 0)
226 layout
.sparable_blocks
= 0;
228 if (format_flags
& FORMAT_SPARABLE
) {
229 layout
.sparable_area_size
=
230 layout
.sparable_blocks
* sparable_blockingnr
;
232 /* a sparing table descriptor is a whole blockingnr sectors */
233 layout
.sparing_table_dscr_lbas
= sparable_blockingnr
;
235 /* place the descriptors at the start and end of the area */
236 layout
.spt_1
= first_lba
;
237 first_lba
+= layout
.sparing_table_dscr_lbas
;
239 layout
.spt_2
= last_lba
- layout
.sparing_table_dscr_lbas
;
240 last_lba
-= layout
.sparing_table_dscr_lbas
;
242 /* allocate sparable section */
243 layout
.sparable_area
= first_lba
;
244 first_lba
+= layout
.sparable_area_size
;
247 /* update guess of UDF partition size */
248 layout
.part_start_lba
= first_lba
;
249 layout
.part_size_lba
= last_lba
- layout
.part_start_lba
;
251 /* determine partition selection for data and metadata */
252 context
.data_part
= 0;
253 context
.metadata_part
= context
.data_part
;
254 if ((format_flags
& FORMAT_VAT
) || (format_flags
& FORMAT_META
))
255 context
.metadata_part
= context
.data_part
+ 1;
258 * Pick fixed logical space sector numbers for main FSD, rootdir and
259 * unallocated space. The reason for this pre-allocation is that they
260 * are referenced in the volume descriptor sequence and hence can't be
264 layout
.unalloc_space
= pos
;
265 pos
+= layout
.alloc_bitmap_dscr_size
;
267 /* claim metadata descriptors and partition space [UDF 2.2.10] */
268 if (format_flags
& FORMAT_META
) {
269 /* note: all in backing partition space */
270 layout
.meta_file
= pos
++;
271 layout
.meta_bitmap
= pos
++;;
272 layout
.meta_mirror
= layout
.part_size_lba
-1;
273 layout
.meta_alignment
= MAX(blockingnr
, sparable_blockingnr
);
274 layout
.meta_blockingnr
= MAX(layout
.meta_alignment
, 32);
276 /* calculate our partition length and store in sectors */
277 layout
.meta_part_size_lba
= layout
.part_size_lba
* meta_fract
;
278 layout
.meta_part_size_lba
= MAX(layout
.meta_part_size_lba
, 32);
279 layout
.meta_part_size_lba
=
280 UDF_ROUNDDOWN(layout
.meta_part_size_lba
, layout
.meta_blockingnr
);
282 /* calculate positions */
283 bytes
= udf_space_bitmap_len(layout
.meta_part_size_lba
);
284 layout
.meta_bitmap_dscr_size
= udf_bytes_to_sectors(bytes
);
286 layout
.meta_bitmap_space
= pos
;
287 pos
+= layout
.meta_bitmap_dscr_size
;
289 layout
.meta_part_start_lba
= UDF_ROUNDUP(pos
, layout
.meta_alignment
);
292 mpos
= (context
.metadata_part
== context
.data_part
) ? pos
: 0;
293 layout
.fsd
= mpos
; mpos
+= 1;
294 layout
.rootdir
= mpos
; mpos
+= 1;
295 layout
.vat
= mpos
; mpos
+= 1; /* if present */
298 printf("Summary so far\n");
299 printf("\tiso9660_vrs\t\t%d\n", layout
.iso9660_vrs
);
300 printf("\tanchor0\t\t\t%d\n", layout
.anchors
[0]);
301 printf("\tanchor1\t\t\t%d\n", layout
.anchors
[1]);
302 printf("\tanchor2\t\t\t%d\n", layout
.anchors
[2]);
303 printf("\tvds_size\t\t%d\n", layout
.vds_size
);
304 printf("\tvds1\t\t\t%d\n", layout
.vds1
);
305 printf("\tvds2\t\t\t%d\n", layout
.vds2
);
306 printf("\tlvis_size\t\t%d\n", layout
.lvis_size
);
307 printf("\tlvis\t\t\t%d\n", layout
.lvis
);
308 if (format_flags
& FORMAT_SPARABLE
) {
309 printf("\tsparable size\t\t%d\n", layout
.sparable_area_size
);
310 printf("\tsparable\t\t%d\n", layout
.sparable_area
);
312 printf("\tpartition start lba\t%d\n", layout
.part_start_lba
);
313 printf("\tpartition size\t\t%d KiB, %d MiB\n",
314 (layout
.part_size_lba
* sector_size
) / 1024,
315 (layout
.part_size_lba
* sector_size
) / (1024*1024));
316 if ((format_flags
& FORMAT_SEQUENTIAL
) == 0) {
317 printf("\tpart bitmap start\t%d\n", layout
.unalloc_space
);
318 printf("\t\tfor %d lba\n", layout
.alloc_bitmap_dscr_size
);
320 if (format_flags
& FORMAT_META
) {
321 printf("\tmeta blockingnr\t\t%d\n", layout
.meta_blockingnr
);
322 printf("\tmeta alignment\t\t%d\n", layout
.meta_alignment
);
323 printf("\tmeta size\t\t%d KiB, %d MiB\n",
324 (layout
.meta_part_size_lba
* sector_size
) / 1024,
325 (layout
.meta_part_size_lba
* sector_size
) / (1024*1024));
326 printf("\tmeta file\t\t%d\n", layout
.meta_file
);
327 printf("\tmeta mirror\t\t%d\n", layout
.meta_mirror
);
328 printf("\tmeta bitmap\t\t%d\n", layout
.meta_bitmap
);
329 printf("\tmeta bitmap start\t%d\n", layout
.meta_bitmap_space
);
330 printf("\t\tfor %d lba\n", layout
.meta_bitmap_dscr_size
);
331 printf("\tmeta space start\t%d\n", layout
.meta_part_start_lba
);
332 printf("\t\tfor %d lba\n", layout
.meta_part_size_lba
);
337 kbsize
= (uint64_t) last_lba
* sector_size
;
338 printf("Total space on this medium approx. %"PRIu64
" KiB, %"PRIu64
" MiB\n",
339 kbsize
/1024, kbsize
/(1024*1024));
340 kbsize
= (uint64_t) (layout
.part_size_lba
- layout
.alloc_bitmap_dscr_size
341 - layout
.meta_bitmap_dscr_size
) * sector_size
;
342 printf("Free space on this volume approx. %"PRIu64
" KiB, %"PRIu64
" MiB\n\n",
343 kbsize
/1024, kbsize
/(1024*1024));
350 udf_validate_tag_sum(union dscrptr
*dscr
)
352 struct desc_tag
*tag
= &dscr
->tag
;
353 uint8_t *pos
, sum
, cnt
;
355 /* calculate TAG header checksum */
356 pos
= (uint8_t *) tag
;
359 for(cnt
= 0; cnt
< 16; cnt
++) {
360 if (cnt
!= 4) sum
+= *pos
;
363 tag
->cksum
= sum
; /* 8 bit */
369 /* assumes sector number of descriptor to be allready present */
371 udf_validate_tag_and_crc_sums(union dscrptr
*dscr
)
373 struct desc_tag
*tag
= &dscr
->tag
;
376 /* check payload CRC if applicable */
377 if (udf_rw16(tag
->desc_crc_len
) > 0) {
378 crc
= udf_cksum(((uint8_t *) tag
) + UDF_DESC_TAG_LENGTH
,
379 udf_rw16(tag
->desc_crc_len
));
380 tag
->desc_crc
= udf_rw16(crc
);
383 /* calculate TAG header checksum */
384 return udf_validate_tag_sum(dscr
);
389 udf_inittag(struct desc_tag
*tag
, int tagid
, uint32_t loc
)
391 tag
->id
= udf_rw16(tagid
);
392 tag
->descriptor_ver
= udf_rw16(context
.dscrver
);
395 tag
->serial_num
= udf_rw16(context
.serialnum
);
396 tag
->tag_loc
= udf_rw32(loc
);
401 udf_create_anchor(int num
)
403 struct anchor_vdp
*avdp
;
404 uint32_t vds_extent_len
= layout
.vds_size
* context
.sector_size
;
406 if ((avdp
= calloc(1, context
.sector_size
)) == NULL
)
409 udf_inittag(&avdp
->tag
, TAGID_ANCHOR
, layout
.anchors
[num
]);
411 avdp
->main_vds_ex
.loc
= udf_rw32(layout
.vds1
);
412 avdp
->main_vds_ex
.len
= udf_rw32(vds_extent_len
);
414 avdp
->reserve_vds_ex
.loc
= udf_rw32(layout
.vds2
);
415 avdp
->reserve_vds_ex
.len
= udf_rw32(vds_extent_len
);
417 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
418 avdp
->tag
.desc_crc_len
= udf_rw16(512-UDF_DESC_TAG_LENGTH
);
420 context
.anchors
[num
] = avdp
;
426 udf_create_terminator(union dscrptr
*dscr
, uint32_t loc
)
428 bzero(dscr
, context
.sector_size
);
429 udf_inittag(&dscr
->tag
, TAGID_TERM
, loc
);
431 /* CRC length for an anchor is 512 - tag length; defined in Ecma 167 */
432 dscr
->tag
.desc_crc_len
= udf_rw16(512-UDF_DESC_TAG_LENGTH
);
437 udf_osta_charset(struct charspec
*charspec
)
439 bzero(charspec
, sizeof(struct charspec
));
441 strcpy((char *) charspec
->inf
, "OSTA Compressed Unicode");
446 udf_encode_osta_id(char *osta_id
, uint16_t len
, char *text
)
448 uint16_t u16_name
[1024];
453 if (!text
|| (strlen(text
) == 0)) return;
455 bzero(u16_name
, sizeof(uint16_t) * 1023);
457 /* convert ascii to 16 bits unicode */
458 pos
= (uint8_t *) text
;
466 udf_CompressUnicode(len
, 8, (unicode_t
*) u16_name
, (byte
*) osta_id
);
468 /* Ecma 167/7.2.13 states that length is recorded in the last byte */
469 osta_id
[len
-1] = strlen(text
)+1;
473 /* first call udf_set_regid and then the suffix */
475 udf_set_regid(struct regid
*regid
, char const *name
)
477 bzero(regid
, sizeof(struct regid
));
478 regid
->flags
= 0; /* not dirty and not protected */
479 strcpy((char *) regid
->id
, name
);
484 udf_add_domain_regid(struct regid
*regid
)
488 ver
= (uint16_t *) regid
->id_suffix
;
489 *ver
= udf_rw16(context
.min_udf
);
494 udf_add_udf_regid(struct regid
*regid
)
498 ver
= (uint16_t *) regid
->id_suffix
;
499 *ver
= udf_rw16(context
.min_udf
);
501 regid
->id_suffix
[2] = 4; /* unix */
502 regid
->id_suffix
[3] = 8; /* NetBSD */
507 udf_add_impl_regid(struct regid
*regid
)
509 regid
->id_suffix
[0] = 4; /* unix */
510 regid
->id_suffix
[1] = 8; /* NetBSD */
515 udf_add_app_regid(struct regid
*regid
)
517 regid
->id_suffix
[0] = context
.app_version_main
;
518 regid
->id_suffix
[1] = context
.app_version_sub
;
523 * Fill in timestamp structure based on clock_gettime(). Time is reported back as a time_t
524 * accompanied with a nano second field.
526 * The husec, usec and csec could be relaxed in type.
529 udf_timespec_to_timestamp(struct timespec
*timespec
, struct timestamp
*timestamp
)
532 uint64_t husec
, usec
, csec
;
534 bzero(timestamp
, sizeof(struct timestamp
));
535 gmtime_r(×pec
->tv_sec
, &tm
);
538 * Time type and time zone : see ECMA 1/7.3, UDF 2., 2.1.4.1, 3.1.1.
540 * Lower 12 bits are two complement signed timezone offset if bit 12
541 * (method 1) is clear. Otherwise if bit 12 is set, specify timezone
542 * offset to -2047 i.e. unsigned `zero'
545 /* set method 1 for CUT/GMT */
546 timestamp
->type_tz
= udf_rw16((1<<12) + 0);
547 timestamp
->year
= udf_rw16(tm
.tm_year
+ 1900);
548 timestamp
->month
= tm
.tm_mon
+ 1; /* `tm' uses 0..11 for months */
549 timestamp
->day
= tm
.tm_mday
;
550 timestamp
->hour
= tm
.tm_hour
;
551 timestamp
->minute
= tm
.tm_min
;
552 timestamp
->second
= tm
.tm_sec
;
554 usec
= (timespec
->tv_nsec
+ 500) / 1000; /* round */
556 usec
-= husec
* 100; /* only 0-99 in usec */
557 csec
= husec
/ 100; /* only 0-99 in csec */
558 husec
-= csec
* 100; /* only 0-99 in husec */
560 timestamp
->centisec
= csec
;
561 timestamp
->hund_usec
= husec
;
562 timestamp
->usec
= usec
;
568 udf_set_timestamp_now(struct timestamp
*timestamp
)
572 clock_gettime(CLOCK_REALTIME
, &now
);
573 udf_timespec_to_timestamp(&now
, timestamp
);
578 udf_create_primaryd(void)
580 struct pri_vol_desc
*pri
;
583 pri
= calloc(1, context
.sector_size
);
587 bzero(pri
, context
.sector_size
);
588 udf_inittag(&pri
->tag
, TAGID_PRI_VOL
, /* loc */ 0);
589 pri
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
591 pri
->pvd_num
= udf_rw32(0); /* default serial */
592 udf_encode_osta_id(pri
->vol_id
, 32, context
.primary_name
);
594 /* set defaults for single disc volumes as UDF prescribes */
595 pri
->vds_num
= udf_rw16(1);
596 pri
->max_vol_seq
= udf_rw16(1);
597 pri
->ichg_lvl
= udf_rw16(2);
598 pri
->max_ichg_lvl
= udf_rw16(3);
599 pri
->flags
= udf_rw16(0);
601 pri
->charset_list
= udf_rw32(1); /* only CS0 */
602 pri
->max_charset_list
= udf_rw32(1); /* only CS0 */
604 udf_encode_osta_id(pri
->volset_id
, 128, context
.volset_name
);
605 udf_osta_charset(&pri
->desc_charset
);
606 udf_osta_charset(&pri
->explanatory_charset
);
608 udf_set_regid(&pri
->app_id
, context
.app_name
);
609 udf_add_app_regid(&pri
->app_id
);
611 udf_set_regid(&pri
->imp_id
, context
.impl_name
);
612 udf_add_impl_regid(&pri
->imp_id
);
614 udf_set_timestamp_now(&pri
->time
);
616 crclen
= sizeof(struct pri_vol_desc
) - UDF_DESC_TAG_LENGTH
;
617 pri
->tag
.desc_crc_len
= udf_rw16(crclen
);
619 context
.primary_vol
= pri
;
625 /* XXX no support for unallocated or freed space tables yet (!) */
627 udf_create_partitiond(int part_num
, int part_accesstype
)
629 struct part_desc
*pd
;
630 struct part_hdr_desc
*phd
;
631 uint32_t sector_size
, bitmap_bytes
;
634 sector_size
= context
.sector_size
;
635 bitmap_bytes
= layout
.alloc_bitmap_dscr_size
* sector_size
;
637 if (context
.partitions
[part_num
]) {
638 printf("Internal error: partition %d allready defined\n",
643 pd
= calloc(1, context
.sector_size
);
646 phd
= &pd
->_impl_use
.part_hdr
;
648 udf_inittag(&pd
->tag
, TAGID_PARTITION
, /* loc */ 0);
649 pd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
651 pd
->flags
= udf_rw16(1); /* allocated */
652 pd
->part_num
= udf_rw16(part_num
); /* only one physical partition */
654 if (context
.dscrver
== 2) {
655 udf_set_regid(&pd
->contents
, "+NSR02");
657 udf_set_regid(&pd
->contents
, "+NSR03");
659 udf_add_app_regid(&pd
->contents
);
661 phd
->unalloc_space_bitmap
.len
= udf_rw32(bitmap_bytes
);
662 phd
->unalloc_space_bitmap
.lb_num
= udf_rw32(layout
.unalloc_space
);
664 if (layout
.freed_space
) {
665 phd
->freed_space_bitmap
.len
= udf_rw32(bitmap_bytes
);
666 phd
->freed_space_bitmap
.lb_num
= udf_rw32(layout
.freed_space
);
669 pd
->access_type
= udf_rw32(part_accesstype
);
670 pd
->start_loc
= udf_rw32(layout
.part_start_lba
);
671 pd
->part_len
= udf_rw32(layout
.part_size_lba
);
673 udf_set_regid(&pd
->imp_id
, context
.impl_name
);
674 udf_add_impl_regid(&pd
->imp_id
);
676 crclen
= sizeof(struct part_desc
) - UDF_DESC_TAG_LENGTH
;
677 pd
->tag
.desc_crc_len
= udf_rw16(crclen
);
679 context
.partitions
[part_num
] = pd
;
686 udf_create_unalloc_spaced(void)
688 struct unalloc_sp_desc
*usd
;
691 usd
= calloc(1, context
.sector_size
);
695 udf_inittag(&usd
->tag
, TAGID_UNALLOC_SPACE
, /* loc */ 0);
696 usd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
698 /* no default entries */
699 usd
->alloc_desc_num
= udf_rw32(0); /* no entries */
701 crclen
= sizeof(struct unalloc_sp_desc
) - sizeof(struct extent_ad
);
702 crclen
-= UDF_DESC_TAG_LENGTH
;
703 usd
->tag
.desc_crc_len
= udf_rw16(crclen
);
705 context
.unallocated
= usd
;
712 udf_create_base_logical_dscr(void)
714 struct logvol_desc
*lvd
;
715 uint32_t sector_size
;
718 sector_size
= context
.sector_size
;
720 lvd
= calloc(1, sector_size
);
724 udf_inittag(&lvd
->tag
, TAGID_LOGVOL
, /* loc */ 0);
725 lvd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
727 udf_osta_charset(&lvd
->desc_charset
);
728 udf_encode_osta_id(lvd
->logvol_id
, 128, context
.logvol_name
);
729 lvd
->lb_size
= udf_rw32(context
.sector_size
);
731 udf_set_regid(&lvd
->domain_id
, "*OSTA UDF Compliant");
732 udf_add_domain_regid(&lvd
->domain_id
);
734 /* no partition mappings/entries yet */
735 lvd
->mt_l
= udf_rw32(0);
736 lvd
->n_pm
= udf_rw32(0);
738 udf_set_regid(&lvd
->imp_id
, context
.impl_name
);
739 udf_add_impl_regid(&lvd
->imp_id
);
741 lvd
->integrity_seq_loc
.loc
= udf_rw32(layout
.lvis
);
742 lvd
->integrity_seq_loc
.len
= udf_rw32(layout
.lvis_size
* sector_size
);
744 /* just one fsd for now */
745 lvd
->lv_fsd_loc
.len
= udf_rw32(sector_size
);
746 lvd
->lv_fsd_loc
.loc
.part_num
= udf_rw32(context
.metadata_part
);
747 lvd
->lv_fsd_loc
.loc
.lb_num
= udf_rw32(layout
.fsd
);
749 crclen
= sizeof(struct logvol_desc
) - 1 - UDF_DESC_TAG_LENGTH
;
750 lvd
->tag
.desc_crc_len
= udf_rw16(crclen
);
752 context
.logical_vol
= lvd
;
753 context
.vtop_tp
[UDF_VTOP_RAWPART
] = UDF_VTOP_TYPE_RAW
;
754 context
.vtop_offset
[UDF_VTOP_RAWPART
] = 0;
761 udf_add_logvol_part_physical(uint16_t phys_part
)
763 struct logvol_desc
*logvol
= context
.logical_vol
;
764 union udf_pmap
*pmap
;
767 uint32_t pmap1_size
, log_part
;
769 log_part
= udf_rw32(logvol
->n_pm
);
770 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
771 pmap1_size
= sizeof(struct part_map_1
);
773 pmap
= (union udf_pmap
*) pmap_pos
;
775 pmap
->pm1
.len
= sizeof(struct part_map_1
);
776 pmap
->pm1
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
777 pmap
->pm1
.part_num
= udf_rw16(phys_part
);
779 context
.vtop
[log_part
] = phys_part
;
780 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_PHYS
;
781 context
.vtop_offset
[log_part
] = layout
.part_start_lba
;
782 context
.part_size
[log_part
] = layout
.part_size_lba
;
783 context
.part_free
[log_part
] = layout
.part_size_lba
;
785 /* increment number of partitions and length */
786 logvol
->n_pm
= udf_rw32(log_part
+ 1);
787 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmap1_size
);
789 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmap1_size
;
790 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
795 udf_add_logvol_part_virtual(uint16_t phys_part
)
797 union udf_pmap
*pmap
;
798 struct logvol_desc
*logvol
= context
.logical_vol
;
801 uint32_t pmapv_size
, log_part
;
803 log_part
= udf_rw32(logvol
->n_pm
);
804 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
805 pmapv_size
= sizeof(struct part_map_2
);
807 pmap
= (union udf_pmap
*) pmap_pos
;
809 pmap
->pmv
.len
= pmapv_size
;
811 udf_set_regid(&pmap
->pmv
.id
, "*UDF Virtual Partition");
812 udf_add_udf_regid(&pmap
->pmv
.id
);
814 pmap
->pmv
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
815 pmap
->pmv
.part_num
= udf_rw16(phys_part
);
817 context
.vtop
[log_part
] = phys_part
;
818 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_VIRT
;
819 context
.vtop_offset
[log_part
] = context
.vtop_offset
[phys_part
];
820 context
.part_size
[log_part
] = 0xffffffff;
821 context
.part_free
[log_part
] = 0xffffffff;
823 /* increment number of partitions and length */
824 logvol
->n_pm
= udf_rw32(log_part
+ 1);
825 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmapv_size
);
827 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmapv_size
;
828 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
832 /* sparing table size is in bytes */
834 udf_add_logvol_part_sparable(uint16_t phys_part
)
836 union udf_pmap
*pmap
;
837 struct logvol_desc
*logvol
= context
.logical_vol
;
838 uint32_t *st_pos
, sparable_bytes
, pmaps_size
;
839 uint8_t *pmap_pos
, num
;
843 log_part
= udf_rw32(logvol
->n_pm
);
844 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
845 pmaps_size
= sizeof(struct part_map_2
);
846 sparable_bytes
= layout
.sparable_area_size
* context
.sector_size
;
848 pmap
= (union udf_pmap
*) pmap_pos
;
850 pmap
->pms
.len
= pmaps_size
;
852 udf_set_regid(&pmap
->pmv
.id
, "*UDF Sparable Partition");
853 udf_add_udf_regid(&pmap
->pmv
.id
);
855 pmap
->pms
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
856 pmap
->pms
.part_num
= udf_rw16(phys_part
);
858 pmap
->pms
.packet_len
= udf_rw16(layout
.sparable_blockingnr
);
859 pmap
->pms
.st_size
= udf_rw32(sparable_bytes
);
861 /* enter spare tables */
862 st_pos
= &pmap
->pms
.st_loc
[0];
863 *st_pos
++ = udf_rw32(layout
.spt_1
);
864 *st_pos
++ = udf_rw32(layout
.spt_2
);
867 if (layout
.spt_2
== 0) num
--;
868 if (layout
.spt_1
== 0) num
--;
869 pmap
->pms
.n_st
= num
; /* 8 bit */
871 /* the vtop_offset needs to explicitly set since there is no phys. */
872 context
.vtop
[log_part
] = phys_part
;
873 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_SPARABLE
;
874 context
.vtop_offset
[log_part
] = layout
.part_start_lba
;
875 context
.part_size
[log_part
] = layout
.part_size_lba
;
876 context
.part_free
[log_part
] = layout
.part_size_lba
;
878 /* increment number of partitions and length */
879 logvol
->n_pm
= udf_rw32(log_part
+ 1);
880 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmaps_size
);
882 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmaps_size
;
883 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
888 udf_create_sparing_tabled(void)
890 struct udf_sparing_table
*spt
;
891 struct spare_map_entry
*sme
;
893 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
895 spt
= calloc(context
.sector_size
, layout
.sparing_table_dscr_lbas
);
899 /* a sparing table descriptor is a whole sparable_blockingnr sectors */
900 udf_inittag(&spt
->tag
, TAGID_SPARING_TABLE
, /* loc */ 0);
902 udf_set_regid(&spt
->id
, "*UDF Sparing Table");
903 udf_add_udf_regid(&spt
->id
);
905 spt
->rt_l
= udf_rw16(layout
.sparable_blocks
);
906 spt
->seq_num
= udf_rw32(0); /* first generation */
908 for (cnt
= 0; cnt
< layout
.sparable_blocks
; cnt
++) {
909 sme
= &spt
->entries
[cnt
];
910 loc
= layout
.sparable_area
+ cnt
* layout
.sparable_blockingnr
;
911 sme
->org
= udf_rw32(0xffffffff); /* open for reloc */
912 sme
->map
= udf_rw32(loc
);
915 /* calculate crc len for actual size */
916 crclen
= sizeof(struct udf_sparing_table
) - UDF_DESC_TAG_LENGTH
;
917 crclen
+= (layout
.sparable_blocks
-1) * sizeof(struct spare_map_entry
);
918 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
919 spt
->tag
.desc_crc_len
= udf_rw16((uint16_t)crclen
);
921 context
.sparing_table
= spt
;
928 udf_add_logvol_part_meta(uint16_t phys_part
)
930 union udf_pmap
*pmap
;
931 struct logvol_desc
*logvol
= context
.logical_vol
;
933 uint32_t pmapv_size
, log_part
;
936 log_part
= udf_rw32(logvol
->n_pm
);
937 pmap_pos
= logvol
->maps
+ udf_rw32(logvol
->mt_l
);
938 pmapv_size
= sizeof(struct part_map_2
);
940 pmap
= (union udf_pmap
*) pmap_pos
;
942 pmap
->pmm
.len
= pmapv_size
;
944 udf_set_regid(&pmap
->pmm
.id
, "*UDF Metadata Partition");
945 udf_add_udf_regid(&pmap
->pmm
.id
);
947 pmap
->pmm
.vol_seq_num
= udf_rw16(1); /* no multi-volume */
948 pmap
->pmm
.part_num
= udf_rw16(phys_part
);
950 /* fill in meta data file(s) and alloc/alignment unit sizes */
951 pmap
->pmm
.meta_file_lbn
= udf_rw32(layout
.meta_file
);
952 pmap
->pmm
.meta_mirror_file_lbn
= udf_rw32(layout
.meta_mirror
);
953 pmap
->pmm
.meta_bitmap_file_lbn
= udf_rw32(layout
.meta_bitmap
);
954 pmap
->pmm
.alloc_unit_size
= udf_rw32(layout
.meta_blockingnr
);
955 pmap
->pmm
.alignment_unit_size
= udf_rw16(layout
.meta_alignment
);
956 pmap
->pmm
.flags
= 0; /* METADATA_DUPLICATED */
958 context
.vtop
[log_part
] = phys_part
;
959 context
.vtop_tp
[log_part
] = UDF_VTOP_TYPE_META
;
960 context
.vtop_offset
[log_part
] =
961 context
.vtop_offset
[phys_part
] + layout
.meta_part_start_lba
;
962 context
.part_size
[log_part
] = layout
.meta_part_size_lba
;
963 context
.part_free
[log_part
] = layout
.meta_part_size_lba
;
965 /* increment number of partitions and length */
966 logvol
->n_pm
= udf_rw32(log_part
+ 1);
967 logvol
->mt_l
= udf_rw32(udf_rw32(logvol
->mt_l
) + pmapv_size
);
969 crclen
= udf_rw16(logvol
->tag
.desc_crc_len
) + pmapv_size
;
970 logvol
->tag
.desc_crc_len
= udf_rw16(crclen
);
975 udf_create_logical_dscr(int format_flags
)
979 if ((error
= udf_create_base_logical_dscr()))
982 /* we pass data_part for there might be a read-only part one day */
983 if (format_flags
& FORMAT_SPARABLE
) {
984 /* sparable partition mapping has no physical mapping */
985 udf_add_logvol_part_sparable(context
.data_part
);
987 udf_add_logvol_part_physical(context
.data_part
);
990 if (format_flags
& FORMAT_VAT
) {
991 /* add VAT virtual mapping; reflects on datapart */
992 udf_add_logvol_part_virtual(context
.data_part
);
994 if (format_flags
& FORMAT_META
) {
995 /* add META data mapping; reflects on datapart */
996 udf_add_logvol_part_meta(context
.data_part
);
1004 udf_create_impvold(char *field1
, char *field2
, char *field3
)
1006 struct impvol_desc
*ivd
;
1007 struct udf_lv_info
*lvi
;
1010 ivd
= calloc(1, context
.sector_size
);
1013 lvi
= &ivd
->_impl_use
.lv_info
;
1015 udf_inittag(&ivd
->tag
, TAGID_IMP_VOL
, /* loc */ 0);
1016 ivd
->seq_num
= udf_rw32(context
.vds_seq
); context
.vds_seq
++;
1018 udf_set_regid(&ivd
->impl_id
, "*UDF LV Info");
1019 udf_add_udf_regid(&ivd
->impl_id
);
1021 /* fill in UDF specific part */
1022 udf_osta_charset(&lvi
->lvi_charset
);
1023 udf_encode_osta_id(lvi
->logvol_id
, 128, context
.logvol_name
);
1025 udf_encode_osta_id(lvi
->lvinfo1
, 36, field1
);
1026 udf_encode_osta_id(lvi
->lvinfo2
, 36, field2
);
1027 udf_encode_osta_id(lvi
->lvinfo3
, 36, field3
);
1029 udf_set_regid(&lvi
->impl_id
, context
.impl_name
);
1030 udf_add_impl_regid(&lvi
->impl_id
);
1032 crclen
= sizeof(struct impvol_desc
) - UDF_DESC_TAG_LENGTH
;
1033 ivd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1035 context
.implementation
= ivd
;
1041 /* XXX might need to be sanitised a bit later */
1043 udf_update_lvintd(int type
)
1045 struct logvol_int_desc
*lvid
;
1046 struct udf_logvol_info
*lvinfo
;
1047 struct logvol_desc
*logvol
;
1049 uint32_t cnt
, l_iu
, num_partmappings
;
1050 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1052 lvid
= context
.logvol_integrity
;
1053 logvol
= context
.logical_vol
;
1058 lvid
->integrity_type
= udf_rw32(type
);
1060 num_partmappings
= udf_rw32(logvol
->n_pm
);
1062 udf_set_timestamp_now(&lvid
->time
);
1064 lvinfo
= (struct udf_logvol_info
*)
1065 (lvid
->tables
+ num_partmappings
* 2);
1066 udf_set_regid(&lvinfo
->impl_id
, context
.impl_name
);
1067 udf_add_impl_regid(&lvinfo
->impl_id
);
1069 lvinfo
->num_files
= udf_rw32(context
.num_files
);
1070 lvinfo
->num_directories
= udf_rw32(context
.num_directories
);
1072 lvid
->lvint_next_unique_id
= udf_rw64(context
.unique_id
);
1074 /* XXX sane enough ? */
1075 lvinfo
->min_udf_readver
= udf_rw16(context
.min_udf
);
1076 lvinfo
->min_udf_writever
= udf_rw16(context
.min_udf
);
1077 lvinfo
->max_udf_writever
= udf_rw16(context
.max_udf
);
1079 lvid
->num_part
= udf_rw32(num_partmappings
);
1081 /* no impl. use needed */
1082 l_iu
= sizeof(struct udf_logvol_info
);
1083 lvid
->l_iu
= udf_rw32(l_iu
);
1085 pos
= &lvid
->tables
[0];
1086 for (cnt
= 0; cnt
< num_partmappings
; cnt
++) {
1087 *pos
++ = udf_rw32(context
.part_free
[cnt
]);
1089 for (cnt
= 0; cnt
< num_partmappings
; cnt
++) {
1090 *pos
++ = udf_rw32(context
.part_size
[cnt
]);
1093 crclen
= sizeof(struct logvol_int_desc
) -4 -UDF_DESC_TAG_LENGTH
+ l_iu
;
1094 crclen
+= num_partmappings
* 2 * 4;
1095 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
1096 lvid
->tag
.desc_crc_len
= udf_rw16(crclen
);
1098 context
.logvol_info
= lvinfo
;
1103 udf_create_lvintd(int type
)
1105 struct logvol_int_desc
*lvid
;
1107 lvid
= calloc(1, context
.sector_size
);
1111 udf_inittag(&lvid
->tag
, TAGID_LOGVOL_INTEGRITY
, /* loc */ 0);
1113 context
.logvol_integrity
= lvid
;
1115 udf_update_lvintd(type
);
1122 udf_create_fsd(void)
1124 struct fileset_desc
*fsd
;
1127 fsd
= calloc(1, context
.sector_size
);
1131 udf_inittag(&fsd
->tag
, TAGID_FSD
, /* loc */ 0);
1133 udf_set_timestamp_now(&fsd
->time
);
1134 fsd
->ichg_lvl
= udf_rw16(3); /* UDF 2.3.2.1 */
1135 fsd
->max_ichg_lvl
= udf_rw16(3); /* UDF 2.3.2.2 */
1137 fsd
->charset_list
= udf_rw32(1); /* only CS0 */
1138 fsd
->max_charset_list
= udf_rw32(1); /* only CS0 */
1140 fsd
->fileset_num
= udf_rw32(0); /* only one fsd */
1141 fsd
->fileset_desc_num
= udf_rw32(0); /* origional */
1143 udf_osta_charset(&fsd
->logvol_id_charset
);
1144 udf_encode_osta_id(fsd
->logvol_id
, 128, context
.logvol_name
);
1146 udf_osta_charset(&fsd
->fileset_charset
);
1147 udf_encode_osta_id(fsd
->fileset_id
, 32, context
.fileset_name
);
1149 /* copyright file and abstract file names obmitted */
1151 fsd
->rootdir_icb
.len
= udf_rw32(context
.sector_size
);
1152 fsd
->rootdir_icb
.loc
.lb_num
= udf_rw32(layout
.rootdir
);
1153 fsd
->rootdir_icb
.loc
.part_num
= udf_rw16(context
.metadata_part
);
1155 udf_set_regid(&fsd
->domain_id
, "*OSTA UDF Compliant");
1156 udf_add_domain_regid(&fsd
->domain_id
);
1158 /* next_ex stays zero */
1159 /* no system streamdirs yet */
1161 crclen
= sizeof(struct fileset_desc
) - UDF_DESC_TAG_LENGTH
;
1162 fsd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1164 context
.fileset_desc
= fsd
;
1171 udf_create_space_bitmap(uint32_t dscr_size
, uint32_t part_size_lba
,
1172 struct space_bitmap_desc
**sbdp
)
1174 struct space_bitmap_desc
*sbd
;
1179 sbd
= calloc(context
.sector_size
, dscr_size
);
1183 udf_inittag(&sbd
->tag
, TAGID_SPACE_BITMAP
, /* loc */ 0);
1185 sbd
->num_bits
= udf_rw32(part_size_lba
);
1186 sbd
->num_bytes
= udf_rw32((part_size_lba
+ 7)/8);
1188 /* fill space with 0xff to indicate free */
1189 for (cnt
= 0; cnt
< udf_rw32(sbd
->num_bytes
); cnt
++)
1190 sbd
->data
[cnt
] = 0xff;
1192 /* set crc to only cover the header (UDF 2.3.1.2, 2.3.8.1) */
1193 crclen
= sizeof(struct space_bitmap_desc
) -1 - UDF_DESC_TAG_LENGTH
;
1194 sbd
->tag
.desc_crc_len
= udf_rw16(crclen
);
1201 /* --------------------------------------------------------------------- */
1204 udf_register_bad_block(uint32_t location
)
1206 struct udf_sparing_table
*spt
;
1207 struct spare_map_entry
*sme
, *free_sme
;
1210 spt
= context
.sparing_table
;
1212 printf("internal error: adding bad block to non sparable\n");
1216 /* find us a free spare map entry */
1218 for (cnt
= 0; cnt
< layout
.sparable_blocks
; cnt
++) {
1219 sme
= &spt
->entries
[cnt
];
1220 /* if we are allready in it, bail out */
1221 if (udf_rw32(sme
->org
) == location
)
1223 if (udf_rw32(sme
->org
) == 0xffffffff) {
1228 if (free_sme
== NULL
) {
1229 printf("Disc relocation blocks full; disc too damanged\n");
1232 free_sme
->org
= udf_rw32(location
);
1239 udf_mark_allocated(uint32_t start_lb
, int partnr
, uint32_t blocks
)
1241 union dscrptr
*dscr
;
1245 /* make not on space used on underlying partition */
1246 context
.part_free
[partnr
] -= blocks
;
1248 printf("mark allocated : partnr %d, start_lb %d for %d blocks\n",
1249 partnr
, start_lb
, blocks
);
1252 switch (context
.vtop_tp
[partnr
]) {
1253 case UDF_VTOP_TYPE_VIRT
:
1256 case UDF_VTOP_TYPE_PHYS
:
1257 case UDF_VTOP_TYPE_SPARABLE
:
1258 case UDF_VTOP_TYPE_META
:
1260 printf("Marking %d+%d as used\n", start_lb
, blocks
);
1262 dscr
= (union dscrptr
*) (context
.part_unalloc_bits
[partnr
]);
1263 for (cnt
= start_lb
; cnt
< start_lb
+ blocks
; cnt
++) {
1264 bpos
= &dscr
->sbd
.data
[cnt
/ 8];
1266 *bpos
&= ~(1<< bit
);
1270 printf("internal error: reality check in mapping type %d\n",
1271 context
.vtop_tp
[partnr
]);
1277 /* --------------------------------------------------------------------- */
1280 udf_advance_uniqueid(void)
1282 /* Minimum value of 16 : UDF 3.2.1.1, 3.3.3.4. */
1283 context
.unique_id
++;
1284 if (context
.unique_id
< 0x10)
1285 context
.unique_id
= 0x10;
1290 udf_create_parentfid(struct fileid_desc
*fid
, struct long_ad
*parent
,
1293 /* the size of an empty FID is 38 but needs to be a multiple of 4 */
1296 udf_inittag(&fid
->tag
, TAGID_FID
, udf_rw32(parent
->loc
.lb_num
));
1297 fid
->file_version_num
= udf_rw16(1); /* UDF 2.3.4.1 */
1298 fid
->file_char
= UDF_FILE_CHAR_DIR
| UDF_FILE_CHAR_PAR
;
1300 fid
->icb
.longad_uniqueid
= udf_rw32((uint32_t) unique_id
);
1301 fid
->tag
.desc_crc_len
= udf_rw16(fidsize
- UDF_DESC_TAG_LENGTH
);
1303 /* we have to do the fid here explicitly for simplicity */
1304 udf_validate_tag_and_crc_sums((union dscrptr
*) fid
);
1311 * Order of extended attributes :
1313 * Non block aligned Implementation Use EAs
1314 * Block aligned Implementation Use EAs (not in newfs_udf)
1315 * Application Use EAs (not in newfs_udf)
1317 * no checks for doubles, must be called in-order
1320 udf_extattr_append_internal(union dscrptr
*dscr
, struct extattr_entry
*extattr
)
1322 struct file_entry
*fe
;
1323 struct extfile_entry
*efe
;
1324 struct extattrhdr_desc
*extattrhdr
;
1325 struct impl_extattr_entry
*implext
;
1326 uint32_t impl_attr_loc
, appl_attr_loc
, l_ea
, a_l
, exthdr_len
;
1327 uint32_t *l_eap
, l_ad
;
1329 uint8_t *bpos
, *data
;
1331 if (udf_rw16(dscr
->tag
.id
) == TAGID_FENTRY
) {
1335 l_ad
= udf_rw32(fe
->l_ad
);
1336 } else if (udf_rw16(dscr
->tag
.id
) == TAGID_EXTFENTRY
) {
1340 l_ad
= udf_rw32(efe
->l_ad
);
1342 errx(1, "Bad tag passed to udf_extattr_append_internal");
1345 /* should have a header! */
1346 extattrhdr
= (struct extattrhdr_desc
*) data
;
1347 l_ea
= udf_rw32(*l_eap
);
1350 /* create empty extended attribute header */
1351 exthdr_len
= sizeof(struct extattrhdr_desc
);
1353 udf_inittag(&extattrhdr
->tag
, TAGID_EXTATTR_HDR
, /* loc */ 0);
1354 extattrhdr
->impl_attr_loc
= udf_rw32(exthdr_len
);
1355 extattrhdr
->appl_attr_loc
= udf_rw32(exthdr_len
);
1356 extattrhdr
->tag
.desc_crc_len
= udf_rw16(8);
1358 /* record extended attribute header length */
1360 *l_eap
= udf_rw32(l_ea
);
1363 /* extract locations */
1364 impl_attr_loc
= udf_rw32(extattrhdr
->impl_attr_loc
);
1365 appl_attr_loc
= udf_rw32(extattrhdr
->appl_attr_loc
);
1366 if (impl_attr_loc
== UDF_IMPL_ATTR_LOC_NOT_PRESENT
)
1367 impl_attr_loc
= l_ea
;
1368 if (appl_attr_loc
== UDF_IMPL_ATTR_LOC_NOT_PRESENT
)
1369 appl_attr_loc
= l_ea
;
1372 if (udf_rw32(extattr
->type
) < 2048) {
1373 assert(impl_attr_loc
== l_ea
);
1374 assert(appl_attr_loc
== l_ea
);
1377 /* implementation use extended attributes */
1378 if (udf_rw32(extattr
->type
) == 2048) {
1379 assert(appl_attr_loc
== l_ea
);
1381 /* calculate and write extended attribute header checksum */
1382 implext
= (struct impl_extattr_entry
*) extattr
;
1383 assert(udf_rw32(implext
->iu_l
) == 4); /* [UDF 3.3.4.5] */
1384 spos
= (uint16_t *) implext
->data
;
1385 *spos
= udf_rw16(udf_ea_cksum((uint8_t *) implext
));
1388 /* application use extended attributes */
1389 assert(udf_rw32(extattr
->type
) != 65536);
1390 assert(appl_attr_loc
== l_ea
);
1392 /* append the attribute at the end of the current space */
1393 bpos
= data
+ udf_rw32(*l_eap
);
1394 a_l
= udf_rw32(extattr
->a_l
);
1396 /* update impl. attribute locations */
1397 if (udf_rw32(extattr
->type
) < 2048) {
1398 impl_attr_loc
= l_ea
+ a_l
;
1399 appl_attr_loc
= l_ea
+ a_l
;
1401 if (udf_rw32(extattr
->type
) == 2048) {
1402 appl_attr_loc
= l_ea
+ a_l
;
1405 /* copy and advance */
1406 memcpy(bpos
, extattr
, a_l
);
1408 *l_eap
= udf_rw32(l_ea
);
1410 /* do the `dance` again backwards */
1411 if (context
.dscrver
!= 2) {
1412 if (impl_attr_loc
== l_ea
)
1413 impl_attr_loc
= UDF_IMPL_ATTR_LOC_NOT_PRESENT
;
1414 if (appl_attr_loc
== l_ea
)
1415 appl_attr_loc
= UDF_APPL_ATTR_LOC_NOT_PRESENT
;
1419 extattrhdr
->impl_attr_loc
= udf_rw32(impl_attr_loc
);
1420 extattrhdr
->appl_attr_loc
= udf_rw32(appl_attr_loc
);
1422 /* make sure the header sums stays correct */
1423 udf_validate_tag_and_crc_sums((union dscrptr
*) extattrhdr
);
1428 udf_create_new_fe(struct file_entry
**fep
, int file_type
,
1429 struct long_ad
*parent_icb
)
1431 struct file_entry
*fe
;
1432 struct icb_tag
*icb
;
1433 struct timestamp birthtime
;
1434 struct filetimes_extattr_entry
*ft_extattr
;
1437 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1440 fe
= calloc(1, context
.sector_size
);
1444 udf_inittag(&fe
->tag
, TAGID_FENTRY
, /* loc */ 0);
1448 * Always use strategy type 4 unless on WORM wich we don't support
1449 * (yet). Fill in defaults and set for internal allocation of data.
1451 icb
->strat_type
= udf_rw16(4);
1452 icb
->max_num_entries
= udf_rw16(1);
1453 icb
->file_type
= file_type
; /* 8 bit */
1454 icb
->flags
= udf_rw16(UDF_ICB_INTERN_ALLOC
);
1456 fe
->perm
= udf_rw32(0x7fff); /* all is allowed */
1457 fe
->link_cnt
= udf_rw16(0); /* explicit setting */
1459 fe
->ckpoint
= udf_rw32(1); /* user supplied file version */
1460 udf_set_timestamp_now(&birthtime
);
1461 udf_set_timestamp_now(&fe
->atime
);
1462 udf_set_timestamp_now(&fe
->attrtime
);
1463 udf_set_timestamp_now(&fe
->mtime
);
1465 udf_set_regid(&fe
->imp_id
, context
.impl_name
);
1466 udf_add_impl_regid(&fe
->imp_id
);
1467 fe
->unique_id
= udf_rw64(context
.unique_id
);
1468 fe
->l_ea
= udf_rw32(0);
1470 /* create extended attribute to record our creation time */
1471 ft_extattr
= calloc(1, UDF_FILETIMES_ATTR_SIZE(1));
1472 ft_extattr
->hdr
.type
= udf_rw32(UDF_FILETIMES_ATTR_NO
);
1473 ft_extattr
->hdr
.subtype
= 1; /* [4/48.10.5] */
1474 ft_extattr
->hdr
.a_l
= udf_rw32(UDF_FILETIMES_ATTR_SIZE(1));
1475 ft_extattr
->d_l
= udf_rw32(UDF_TIMESTAMP_SIZE
); /* one item */
1476 ft_extattr
->existence
= UDF_FILETIMES_FILE_CREATION
;
1477 ft_extattr
->times
[0] = birthtime
;
1479 udf_extattr_append_internal((union dscrptr
*) fe
,
1480 (struct extattr_entry
*) ft_extattr
);
1483 /* if its a directory, create '..' */
1484 bpos
= (uint8_t *) fe
->data
+ udf_rw32(fe
->l_ea
);
1486 if (file_type
== UDF_ICB_FILETYPE_DIRECTORY
) {
1487 fidsize
= udf_create_parentfid((struct fileid_desc
*) bpos
,
1488 parent_icb
, context
.unique_id
);
1490 udf_advance_uniqueid();
1492 /* record fidlength information */
1493 fe
->inf_len
= udf_rw64(fidsize
);
1494 fe
->l_ad
= udf_rw32(fidsize
);
1495 fe
->logblks_rec
= udf_rw64(0); /* intern */
1497 crclen
= sizeof(struct file_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
1498 crclen
+= udf_rw32(fe
->l_ea
) + fidsize
;
1499 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
1500 fe
->tag
.desc_crc_len
= udf_rw16(crclen
);
1508 udf_create_new_efe(struct extfile_entry
**efep
, int file_type
,
1509 struct long_ad
*parent_icb
)
1511 struct extfile_entry
*efe
;
1512 struct icb_tag
*icb
;
1514 uint32_t crclen
; /* XXX: should be 16; need to detect overflow */
1517 efe
= calloc(1, context
.sector_size
);
1521 udf_inittag(&efe
->tag
, TAGID_EXTFENTRY
, /* loc */ 0);
1525 * Always use strategy type 4 unless on WORM wich we don't support
1526 * (yet). Fill in defaults and set for internal allocation of data.
1528 icb
->strat_type
= udf_rw16(4);
1529 icb
->max_num_entries
= udf_rw16(1);
1530 icb
->file_type
= file_type
; /* 8 bit */
1531 icb
->flags
= udf_rw16(UDF_ICB_INTERN_ALLOC
);
1533 efe
->perm
= udf_rw32(0x7fff); /* all is allowed */
1534 efe
->link_cnt
= udf_rw16(0); /* explicit setting */
1536 efe
->ckpoint
= udf_rw32(1); /* user supplied file version */
1537 udf_set_timestamp_now(&efe
->ctime
);
1538 udf_set_timestamp_now(&efe
->atime
);
1539 udf_set_timestamp_now(&efe
->attrtime
);
1540 udf_set_timestamp_now(&efe
->mtime
);
1542 udf_set_regid(&efe
->imp_id
, context
.impl_name
);
1543 udf_add_impl_regid(&efe
->imp_id
);
1546 efe
->unique_id
= udf_rw64(context
.unique_id
);
1547 if (file_type
== UDF_ICB_FILETYPE_DIRECTORY
) {
1548 fidsize
= udf_create_parentfid((struct fileid_desc
*) efe
->data
,
1549 parent_icb
, context
.unique_id
);
1551 udf_advance_uniqueid();
1553 /* record fidlength information */
1554 efe
->inf_len
= udf_rw64(fidsize
);
1555 efe
->obj_size
= udf_rw64(fidsize
);
1556 efe
->l_ad
= udf_rw32(fidsize
);
1557 efe
->logblks_rec
= udf_rw64(0);
1559 crclen
= sizeof(struct extfile_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
1561 /* XXX ensure crclen doesn't exceed UINT16_MAX ? */
1562 efe
->tag
.desc_crc_len
= udf_rw16(crclen
);
1568 /* --------------------------------------------------------------------- */
1571 udf_append_mapping_part_to_efe(struct extfile_entry
*efe
, struct short_ad
*mapping
)
1573 struct icb_tag
*icb
;
1574 uint64_t inf_len
, obj_size
, logblks_rec
;
1575 uint32_t l_ad
, l_ea
;
1579 inf_len
= udf_rw64(efe
->inf_len
);
1580 obj_size
= udf_rw64(efe
->obj_size
);
1581 logblks_rec
= udf_rw64(efe
->logblks_rec
);
1582 l_ad
= udf_rw32(efe
->l_ad
);
1583 l_ea
= udf_rw32(efe
->l_ea
);
1584 crclen
= udf_rw16(efe
->tag
.desc_crc_len
);
1587 /* set our allocation to shorts if not already done */
1588 icb
->flags
= udf_rw16(UDF_ICB_SHORT_ALLOC
);
1590 /* append short_ad */
1591 bpos
= (uint8_t *) efe
->data
+ l_ea
+ l_ad
;
1592 memcpy(bpos
, mapping
, sizeof(struct short_ad
));
1594 l_ad
+= sizeof(struct short_ad
);
1595 crclen
+= sizeof(struct short_ad
);
1596 inf_len
+= UDF_EXT_LEN(udf_rw32(mapping
->len
));
1597 obj_size
+= UDF_EXT_LEN(udf_rw32(mapping
->len
));
1598 logblks_rec
= UDF_ROUNDUP(inf_len
, context
.sector_size
) /
1599 context
.sector_size
;
1601 efe
->l_ad
= udf_rw32(l_ad
);
1602 efe
->inf_len
= udf_rw64(inf_len
);
1603 efe
->obj_size
= udf_rw64(obj_size
);
1604 efe
->logblks_rec
= udf_rw64(logblks_rec
);
1605 efe
->tag
.desc_crc_len
= udf_rw16(crclen
);
1610 udf_append_meta_mapping_to_efe(struct extfile_entry
*efe
, uint16_t partnr
, uint32_t lb_num
,
1613 struct short_ad mapping
;
1614 uint64_t max_len
, part_len
;
1616 /* calculate max length meta allocation sizes */
1617 max_len
= UDF_EXT_MAXLEN
/ context
.sector_size
; /* in sectors */
1618 max_len
= (max_len
/ layout
.meta_blockingnr
) * layout
.meta_blockingnr
;
1619 max_len
= max_len
* context
.sector_size
;
1621 memset(&mapping
, 0, sizeof(struct short_ad
));
1623 part_len
= MIN(len
, max_len
);
1624 mapping
.lb_num
= udf_rw32(lb_num
);
1625 mapping
.len
= udf_rw32(part_len
);
1627 udf_append_mapping_part_to_efe(efe
, &mapping
);
1629 lb_num
+= part_len
/ context
.sector_size
;
1636 udf_create_meta_files(void)
1638 struct extfile_entry
*efe
;
1639 struct long_ad meta_icb
;
1641 uint32_t sector_size
;
1642 int filetype
, error
;
1644 sector_size
= context
.sector_size
;
1646 bzero(&meta_icb
, sizeof(struct long_ad
));
1647 meta_icb
.len
= udf_rw32(sector_size
);
1648 meta_icb
.loc
.part_num
= udf_rw16(context
.data_part
);
1650 /* create metadata file */
1651 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_file
);
1652 filetype
= UDF_ICB_FILETYPE_META_MAIN
;
1653 error
= udf_create_new_efe(&efe
, filetype
, &meta_icb
);
1656 context
.meta_file
= efe
;
1658 /* create metadata mirror file */
1659 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_mirror
);
1660 filetype
= UDF_ICB_FILETYPE_META_MIRROR
;
1661 error
= udf_create_new_efe(&efe
, filetype
, &meta_icb
);
1664 context
.meta_mirror
= efe
;
1666 /* create metadata bitmap file */
1667 meta_icb
.loc
.lb_num
= udf_rw32(layout
.meta_bitmap
);
1668 filetype
= UDF_ICB_FILETYPE_META_BITMAP
;
1669 error
= udf_create_new_efe(&efe
, filetype
, &meta_icb
);
1672 context
.meta_bitmap
= efe
;
1674 /* patch up files */
1675 context
.meta_file
->unique_id
= udf_rw64(0);
1676 context
.meta_mirror
->unique_id
= udf_rw64(0);
1677 context
.meta_bitmap
->unique_id
= udf_rw64(0);
1679 /* restart unique id */
1680 context
.unique_id
= 0x10;
1682 /* XXX no support for metadata mirroring yet */
1683 /* insert extents */
1684 efe
= context
.meta_file
;
1685 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
1686 layout
.meta_part_start_lba
,
1687 (uint64_t) layout
.meta_part_size_lba
* sector_size
);
1689 efe
= context
.meta_mirror
;
1690 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
1691 layout
.meta_part_start_lba
,
1692 (uint64_t) layout
.meta_part_size_lba
* sector_size
);
1694 efe
= context
.meta_bitmap
;
1695 bytes
= udf_space_bitmap_len(layout
.meta_part_size_lba
);
1696 udf_append_meta_mapping_to_efe(efe
, context
.data_part
,
1697 layout
.meta_bitmap_space
, bytes
);
1703 /* --------------------------------------------------------------------- */
1706 udf_create_new_rootdir(union dscrptr
**dscr
)
1708 struct file_entry
*fe
;
1709 struct extfile_entry
*efe
;
1710 struct long_ad root_icb
;
1711 int filetype
, error
;
1713 bzero(&root_icb
, sizeof(struct long_ad
));
1714 root_icb
.len
= udf_rw32(context
.sector_size
);
1715 root_icb
.loc
.lb_num
= udf_rw32(layout
.rootdir
);
1716 root_icb
.loc
.part_num
= udf_rw16(context
.metadata_part
);
1718 filetype
= UDF_ICB_FILETYPE_DIRECTORY
;
1719 if (context
.dscrver
== 2) {
1720 error
= udf_create_new_fe(&fe
, filetype
, &root_icb
);
1721 *dscr
= (union dscrptr
*) fe
;
1723 error
= udf_create_new_efe(&efe
, filetype
, &root_icb
);
1724 *dscr
= (union dscrptr
*) efe
;
1729 /* Rootdir has explicit only one link on creation; '..' is no link */
1730 if (context
.dscrver
== 2) {
1731 fe
->link_cnt
= udf_rw16(1);
1733 efe
->link_cnt
= udf_rw16(1);
1736 context
.num_directories
++;
1737 assert(context
.num_directories
== 1);
1744 udf_create_new_VAT(union dscrptr
**vat_dscr
)
1746 struct file_entry
*fe
;
1747 struct extfile_entry
*efe
;
1748 struct impl_extattr_entry
*implext
;
1749 struct vatlvext_extattr_entry
*vatlvext
;
1750 struct udf_oldvat_tail
*oldvat_tail
;
1751 struct udf_vat
*vathdr
;
1753 uint8_t *bpos
, *extattr
;
1754 uint32_t ea_len
, inf_len
, vat_len
;
1758 assert((layout
.rootdir
< 2) && (layout
.fsd
< 2));
1759 if (context
.dscrver
== 2) {
1761 filetype
= UDF_ICB_FILETYPE_UNKNOWN
;
1762 error
= udf_create_new_fe(&fe
, filetype
, NULL
);
1766 /* append VAT LVExtension attribute */
1767 ea_len
= sizeof(struct impl_extattr_entry
) - 1 +
1768 sizeof(struct vatlvext_extattr_entry
) + 4;
1770 extattr
= calloc(1, ea_len
);
1772 implext
= (struct impl_extattr_entry
*) extattr
;
1773 implext
->hdr
.type
= udf_rw32(2048); /* [4/48.10.8] */
1774 implext
->hdr
.subtype
= 1; /* [4/48.10.8.2] */
1775 implext
->hdr
.a_l
= udf_rw32(ea_len
); /* VAT LVext EA size */
1776 /* use 4 bytes of imp use for UDF checksum [UDF 3.3.4.5] */
1777 implext
->iu_l
= udf_rw32(4);
1778 udf_set_regid(&implext
->imp_id
, "*UDF VAT LVExtension");
1779 udf_add_udf_regid(&implext
->imp_id
);
1781 /* VAT LVExtension data follows UDF IU space */
1782 bpos
= ((uint8_t *) implext
->data
) + 4;
1783 vatlvext
= (struct vatlvext_extattr_entry
*) bpos
;
1785 vatlvext
->unique_id_chk
= udf_rw64(fe
->unique_id
);
1786 vatlvext
->num_files
= udf_rw32(context
.num_files
);
1787 vatlvext
->num_directories
= udf_rw32(context
.num_directories
);
1788 memcpy(vatlvext
->logvol_id
, context
.logical_vol
->logvol_id
, 128);
1790 udf_extattr_append_internal((union dscrptr
*) fe
,
1791 (struct extattr_entry
*) extattr
);
1795 /* writeout VAT locations (partition offsets) */
1796 vat_pos
= (uint32_t *) (fe
->data
+ udf_rw32(fe
->l_ea
));
1797 vat_pos
[layout
.rootdir
] = udf_rw32(layout
.rootdir
);
1798 vat_pos
[layout
.fsd
] = udf_rw32(layout
.fsd
);
1800 /* Append "*UDF Virtual Alloc Tbl" id and prev. VAT location */
1801 oldvat_tail
= (struct udf_oldvat_tail
*) (vat_pos
+ 2);
1802 udf_set_regid(&oldvat_tail
->id
, "*UDF Virtual Alloc Tbl");
1803 udf_add_udf_regid(&oldvat_tail
->id
);
1804 oldvat_tail
->prev_vat
= udf_rw32(UDF_NO_PREV_VAT
);
1807 inf_len
= 2 * 4 + sizeof(struct udf_oldvat_tail
);
1808 fe
->inf_len
= udf_rw64(inf_len
);
1809 fe
->l_ad
= udf_rw32(inf_len
);
1811 /* update vat descriptor's CRC length */
1812 vat_len
= inf_len
+ udf_rw32(fe
->l_ea
) +
1813 sizeof(struct file_entry
) - 1 - UDF_DESC_TAG_LENGTH
;
1814 fe
->tag
.desc_crc_len
= udf_rw16(vat_len
);
1816 *vat_dscr
= (union dscrptr
*) fe
;
1819 filetype
= UDF_ICB_FILETYPE_VAT
;
1820 error
= udf_create_new_efe(&efe
, filetype
, NULL
);
1824 /* set up VATv2 descriptor */
1825 vathdr
= (struct udf_vat
*) efe
->data
;
1826 vathdr
->header_len
= udf_rw16(sizeof(struct udf_vat
) - 1);
1827 vathdr
->impl_use_len
= udf_rw16(0);
1828 memcpy(vathdr
->logvol_id
, context
.logical_vol
->logvol_id
, 128);
1829 vathdr
->prev_vat
= udf_rw32(UDF_NO_PREV_VAT
);
1830 vathdr
->num_files
= udf_rw32(context
.num_files
);
1831 vathdr
->num_directories
= udf_rw32(context
.num_directories
);
1833 vathdr
->min_udf_readver
= udf_rw16(context
.min_udf
);
1834 vathdr
->min_udf_writever
= udf_rw16(context
.min_udf
);
1835 vathdr
->max_udf_writever
= udf_rw16(context
.max_udf
);
1837 /* writeout VAT locations */
1838 vat_pos
= (uint32_t *) vathdr
->data
;
1839 vat_pos
[layout
.rootdir
] = udf_rw32(layout
.rootdir
);
1840 vat_pos
[layout
.fsd
] = udf_rw32(layout
.fsd
);
1843 inf_len
= 2 * 4 + sizeof(struct udf_vat
) - 1;
1844 efe
->inf_len
= udf_rw64(inf_len
);
1845 efe
->obj_size
= udf_rw64(inf_len
);
1846 efe
->l_ad
= udf_rw32(inf_len
);
1847 efe
->logblks_rec
= udf_rw32(0);
1849 vat_len
= sizeof(struct extfile_entry
)-1 - UDF_DESC_TAG_LENGTH
;
1851 efe
->tag
.desc_crc_len
= udf_rw16(vat_len
);
1853 *vat_dscr
= (union dscrptr
*) efe
;