1 /* $NetBSD$ */
2
3 /*
4 * File "udf_verbose.c" is part of the UDFclient toolkit.
5 * File $Id: udf_verbose.c,v 1.120 2018/08/09 20:28:46 reinoud Exp $ $Name: $
6 *
7 * Copyright (c) 2003, 2004, 2005, 2006, 2011
8 * Reinoud Zandijk <reinoud@netbsd.org>
9 * All rights reserved.
10 *
11 * The UDFclient toolkit is distributed under the Clarified Artistic Licence.
12 * A copy of the licence is included in the distribution as
13 * `LICENCE.clearified.artistic' and a copy of the licence can also be
14 * requested at the GNU foundantion's website.
15 *
16 * Visit the UDFclient toolkit homepage http://www.13thmonkey.org/udftoolkit/
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <errno.h>
39
40 #include <sys/types.h>
41
42 #include "udf.h"
43 #include "udf_bswap.h"
44
45
46 /* globals */
47 void udf_dump_id(char *prefix, int len, char *id, struct charspec *chsp);
48 void udf_dump_long_ad(char *prefix, struct long_ad *adr);
49 void udf_dump_descriptor(union dscrptr *dscrpt);
50 void udf_dump_vat_table(struct udf_part_mapping *udf_part_mapping);
51
52
udf_dump_unimpl(union dscrptr * dscrpt,char * name)53 void udf_dump_unimpl(union dscrptr *dscrpt, char *name) {
54 dscrpt = dscrpt;
55 printf("\t\t(unimplemented dump of `%s` tag)\n", name);
56 }
57
58
udf_dump_desc(struct desc_tag * tag)59 void udf_dump_desc(struct desc_tag *tag) {
60 printf("\tTAG: descriptor %d, serial_num %d at sector %d, crc length %d bytes\n",
61 udf_rw16(tag->id), udf_rw16(tag->serial_num), udf_rw32(tag->tag_loc), udf_rw16(tag->desc_crc_len));
62 }
63
64
udf_dump_anchor(struct anchor_vdp * vdp)65 void udf_dump_anchor(struct anchor_vdp *vdp) {
66 printf("\t\tAnchor\n");
67 printf("\t\t\tMain volume descriptor set at %d for %d bytes\n",
68 udf_rw32(vdp->main_vds_ex.loc), udf_rw32(vdp->main_vds_ex.len));
69 printf("\t\t\tReserve volume descriptor set at %d for %d bytes\n",
70 udf_rw32(vdp->reserve_vds_ex.loc), udf_rw32(vdp->reserve_vds_ex.len));
71 }
72
73
udf_dump_disc_anchors(struct udf_discinfo * disc)74 void udf_dump_disc_anchors(struct udf_discinfo *disc) {
75 int session;
76
77 printf("\nUDF Dump of disc in device %s\n", disc->dev->dev_name);
78 printf("UDF sessions : ");
79 for (session = 0; session < disc->num_sessions; session++) {
80 if (disc->session_is_UDF[session]) {
81 printf("Yes");
82 #if 0
83 if (disc->session_quirks[session] & CD_SESS_QUIRK_SESSION_LOCAL) {
84 printf("(local)");
85 }
86 #endif
87 printf(" ");
88 } else {
89 printf("No ");
90 }
91 }
92 printf("\n\n");
93 UDF_VERBOSE_TABLES(
94 struct udf_session *udf_session;
95 /* Dump anchors */
96 STAILQ_FOREACH(udf_session, &disc->sessions, next_session) {
97 printf("UDF session %d (lba %d + %d sectors) anchor dump : \n", udf_session->session_num,
98 (uint32_t) disc->session_start[udf_session->session_num], (uint32_t) udf_session->session_length);
99 udf_dump_descriptor((union dscrptr *) &udf_session->anchor);
100 }
101 )
102 }
103
104
udf_messy_unicode_conv(char * buf)105 char *udf_messy_unicode_conv(char *buf) {
106 static char out_buf[1024];
107 uint16_t *uni_pos, uni_char;
108 char *pos;
109
110 pos = out_buf;
111 uni_pos = (uint16_t *) buf;
112
113 while ((uni_char = *uni_pos++)) {
114 if (uni_char & 0xff00) uni_char='_';
115 *pos++ = uni_char;
116 }
117
118 return out_buf;
119 }
120
121
udf_get_osname(int os_class,int os_id)122 char *udf_get_osname(int os_class, int os_id) {
123 static char buffer[40];
124
125 switch (os_class) {
126 case 0 : return "undefined OS";
127 case 1 : return "DOS/Windows 3.x";
128 case 2 : return "OS/2";
129 case 3 : return "MacOS";
130 case 4 :
131 switch (os_id) {
132 case 0 : return "UNIX";
133 case 1 : return "IBM AIX";
134 case 2 : return "SunOS/Solaris";
135 case 3 : return "HP/UX";
136 case 4 : return "Silicon Graphics Irix";
137 case 5 : return "Linux";
138 case 6 : return "MKLinux";
139 case 7 : return "FreeBSD";
140 case 8 : return "NetBSD";
141 default :
142 sprintf(buffer, "unknown UNIX (%d)", os_id);
143 return buffer;
144 }
145 case 5 : return "MS Windows 9x";
146 case 6 : return "MS Windows NT";
147 case 7 : return "OS/400";
148 case 8 : return "BeOS";
149 case 9 : return "MS Windows CE";
150 default :
151 break;
152 }
153 sprintf(buffer, "unknown OS (%d, %d)", os_class, os_id);
154 return buffer;
155 }
156
157
udf_dump_regid(char * prefix,struct regid * id,int regid_type)158 void udf_dump_regid(char *prefix, struct regid *id, int regid_type) {
159 char buffer[UDF_REGID_ID_SIZE+1];
160 int cnt, version;
161 uint8_t *pos;
162
163 memcpy(buffer, id->id, UDF_REGID_ID_SIZE);
164 buffer[UDF_REGID_ID_SIZE] = 0;
165
166 printf("%s `%s`", prefix, buffer);
167 if (regid_type == UDF_REGID_NAME) {
168 printf("\n");
169 return;
170 }
171 printf(" (");
172 pos = id->id_suffix;
173 switch (regid_type) {
174 case UDF_REGID_DOMAIN :
175 version = udf_rw16(*((uint16_t *) pos));
176 printf("UDFv %x; ", version);
177 if ((pos[2]) & UDF_DOMAIN_FLAG_HARD_WRITE_PROTECT) printf("HARD ");
178 if ((pos[2]) & UDF_DOMAIN_FLAG_SOFT_WRITE_PROTECT) printf("SOFT");
179 if (((pos[2]) & 3) == 0) printf("no");
180 printf(" write protect ");
181 if ((pos[2]) & ~3) printf("; also undefined flags 0x%d", pos[2] & ~3);
182 break;
183 case UDF_REGID_UDF :
184 version = udf_rw16(*((uint16_t *) pos));
185 printf("UDFv %x; ", version);
186 printf("%s ", udf_get_osname(pos[2], pos[3]));
187 break;
188 case UDF_REGID_IMPLEMENTATION :
189 printf("%s [", udf_get_osname(pos[0], pos[1]));
190 for(cnt=2; cnt < 8; cnt++) {
191 printf("%02x ", *pos++);
192 }
193 printf("]");
194 break;
195 case UDF_REGID_NAME :
196 break;
197 case UDF_REGID_APPLICATION :
198 default :
199 printf("[");
200 for(cnt=0; cnt < 8; cnt++) {
201 printf("%02x ", *pos++);
202 }
203 printf("]");
204 break;
205 }
206 printf(") (flags=%d)\n", id->flags);
207 }
208
209
udf_dump_timestamp(char * prefix,struct timestamp * t)210 void udf_dump_timestamp(char *prefix, struct timestamp *t) {
211 printf("%s (%4d %02d %02d at %02d:%02d:%02d.%02d.%02d.%02d)\n", prefix, udf_rw16(t->year), t->month, t->day,
212 t->hour, t->minute, t->second, t->centisec, t->hund_usec, t->usec);
213 }
214
215
216 #if 0
217 void udf_dump_charspec(char *prefix, struct charspec *chsp) {
218 int cnt, ch;
219
220 printf("%s type CS%d (", prefix, chsp->type);
221 for (cnt=0; cnt<63; cnt++) {
222 ch = chsp->inf[cnt];
223 if (ch < 32 || ch > 126) {
224 printf(".");
225 } else {
226 printf("%c", ch);
227 }
228 }
229 printf(")\n");
230 }
231 #endif
232
233
udf_dump_sparing_table(struct udf_sparing_table * spt)234 void udf_dump_sparing_table(struct udf_sparing_table *spt) {
235 struct spare_map_entry *sp_entry;
236 uint32_t entry, entries;
237
238 printf("\t\tSparing table descriptor\n");
239 udf_dump_regid("\t\t\tSparing table Id ", &spt->id, UDF_REGID_UDF);
240 printf("\t\t\tRelocation table entries %d\n", udf_rw16(spt->rt_l));
241 printf("\t\t\tSequence number %d\n", udf_rw32(spt->seq_num));
242 printf("\t\t\tMappings :");
243
244 entries = udf_rw16(spt->rt_l);
245 for(entry = 0; entry < entries; entry++) {
246 if (entry % 4 == 0) printf("\n\t\t\t\t");
247 sp_entry = &spt->entries[entry];
248 printf("[%08x -> %08x] ", udf_rw32(sp_entry->org), udf_rw32(sp_entry->map));
249 }
250 printf("\n");
251 }
252
253
udf_dump_pri_vol(struct pri_vol_desc * pvd)254 void udf_dump_pri_vol(struct pri_vol_desc *pvd) {
255 struct extent_ad *ext;
256
257 printf("\t\tPrimary volume descriptor\n");
258 printf("\t\t\tVolume descriptor sequence number %d\n", udf_rw32(pvd->seq_num));
259 printf("\t\t\tPrimary volume descriptor number %d\n", udf_rw32(pvd->pvd_num));
260 udf_dump_id("\t\t\tVolume Id ", 32, pvd->vol_id, &pvd->desc_charset);
261 printf("\t\t\tVolume sequence number %d\n", udf_rw16(pvd->vds_num));
262 printf("\t\t\tMaximum volume sequence number %d\n", udf_rw16(pvd->max_vol_seq));
263 printf("\t\t\tInterchange level %d\n", udf_rw16(pvd->ichg_lvl));
264 printf("\t\t\tMaximum interchange level %d\n", udf_rw16(pvd->max_ichg_lvl));
265 udf_dump_id("\t\t\tVolume set Id ", 128, pvd->volset_id, &pvd->desc_charset);
266 /* udf_dump_charspec("\t\t\tCharspec for this descriptor ", &pvd->desc_charset); */
267 /* udf_dump_charspec("\t\t\tCharspec for the explaination ", &pvd->explanatory_charset); */
268 ext = &pvd->vol_abstract;
269 printf("\t\t\tVolume abstract at %d for %d bytes\n", udf_rw32(ext->loc), udf_rw32(ext->len));
270 ext = &pvd->vol_copyright;
271 printf("\t\t\tVolume copyright at %d for %d bytes\n", udf_rw32(ext->loc), udf_rw32(ext->len));
272 udf_dump_regid("\t\t\tApplication id", &pvd->app_id, UDF_REGID_APPLICATION);
273 udf_dump_timestamp("\t\t\tTimestamp", &pvd->time);
274 udf_dump_regid("\t\t\tImplementator id", &pvd->imp_id, UDF_REGID_IMPLEMENTATION);
275 printf("\t\t\tPrevious volume descriptor sequence locator at sector %d\n", udf_rw32(pvd->prev_vds_loc));
276 printf("\t\t\tFlags %d\n", udf_rw16(pvd->flags));
277 }
278
279
udf_dump_implementation_volume(struct impvol_desc * ivd)280 void udf_dump_implementation_volume(struct impvol_desc *ivd) {
281 struct charspec *charspec;
282
283 printf("\t\tImplementation use volume descriptor\n");
284 printf("\t\t\tVolume descriptor sequence number %d\n", udf_rw32(ivd->seq_num));
285 udf_dump_regid("\t\t\tImplementator identifier", &ivd->impl_id, UDF_REGID_UDF);
286
287 /* check on UDF implementation info ... */
288 if (strcmp((char *) ivd->impl_id.id, "*UDF LV Info") == 0) {
289 charspec = &ivd->_impl_use.lv_info.lvi_charset;
290 /* udf_dump_charspec("\t\t\tLV info charspec ", charspec); */
291 udf_dump_id("\t\t\tLogical volume identifier ", 128, ivd->_impl_use.lv_info.logvol_id, charspec);
292 udf_dump_id("\t\t\tLV info 1 ", 36, ivd->_impl_use.lv_info.lvinfo1, charspec);
293 udf_dump_id("\t\t\tLV info 2 ", 36, ivd->_impl_use.lv_info.lvinfo2, charspec);
294 udf_dump_id("\t\t\tLV info 3 ", 36, ivd->_impl_use.lv_info.lvinfo3, charspec);
295 udf_dump_regid("\t\t\tImplementation identifier", &ivd->_impl_use.lv_info.impl_id, UDF_REGID_IMPLEMENTATION);
296 }
297 }
298
299
udf_dump_partition_access_type(int type)300 char *udf_dump_partition_access_type(int type) {
301 switch (type) {
302 case UDF_ACCESSTYPE_PSEUDO_OVERWITE : return "Pseudo overwiteable";
303 case UDF_ACCESSTYPE_READ_ONLY : return "Read only";
304 case UDF_ACCESSTYPE_WRITE_ONCE : return "Write once";
305 case UDF_ACCESSTYPE_REWRITEABLE : return "Rewritable (blocked or with erase)";
306 case UDF_ACCESSTYPE_OVERWRITABLE : return "Overwritable";
307 }
308 return "Unknown partion access type";
309 }
310
311
udf_dump_part(struct part_desc * pd)312 void udf_dump_part(struct part_desc *pd) {
313 struct part_hdr_desc *part_hdr_desc;
314
315 printf("\t\tPartition descriptor\n");
316 printf("\t\t\tVolume descriptor sequence number %d\n", udf_rw32(pd->seq_num));
317 printf("\t\t\tFlags %d\n", udf_rw16(pd->flags));
318 printf("\t\t\tPartition number %d\n", udf_rw16(pd->part_num));
319 udf_dump_regid("\t\t\tContents", &pd->contents, UDF_REGID_APPLICATION);
320 printf("\t\t\tAccessType %s\n", udf_dump_partition_access_type(udf_rw32(pd->access_type)));
321 printf("\t\t\tPartition starts at sector %u for %u sectors\n", udf_rw32(pd->start_loc), udf_rw32(pd->part_len));
322 udf_dump_regid("\t\t\tImplementator id", &pd->imp_id, UDF_REGID_IMPLEMENTATION);
323
324 printf("\t\t\tPartition contents use (file) descriptors:\n");
325 if (strncmp((char *) pd->contents.id, "+NSR0", 5) == 0) {
326 part_hdr_desc = &pd->pd_part_hdr;
327 printf("\t\t\t\tUnallocated space table at logic block %u for %u bytes\n",
328 udf_rw32(part_hdr_desc->unalloc_space_table.lb_num),
329 udf_rw32(part_hdr_desc->unalloc_space_table.len)
330 );
331 printf("\t\t\t\tUnallocated space bitmap at logic block %u for %u bytes\n",
332 udf_rw32(part_hdr_desc->unalloc_space_bitmap.lb_num),
333 udf_rw32(part_hdr_desc->unalloc_space_bitmap.len)
334 );
335 printf("\t\t\t\tPartition integrity table at logic block %u for %u bytes\n",
336 udf_rw32(part_hdr_desc->part_integrity_table.lb_num),
337 udf_rw32(part_hdr_desc->part_integrity_table.len)
338 );
339 printf("\t\t\t\tReusable (freed) space table at logic block %u for %u bytes\n",
340 udf_rw32(part_hdr_desc->freed_space_table.lb_num),
341 udf_rw32(part_hdr_desc->freed_space_table.len)
342 );
343 printf("\t\t\t\tReusable (freed) space bitmap at logic block %u for %u bytes\n",
344 udf_rw32(part_hdr_desc->freed_space_bitmap.lb_num),
345 udf_rw32(part_hdr_desc->freed_space_bitmap.len)
346 );
347 } else {
348 printf("\t\t\t\tWARNING: Unknown or unused contents\n");
349 }
350 }
351
352
udf_dump_log_vol(struct logvol_desc * lvd)353 void udf_dump_log_vol(struct logvol_desc *lvd) {
354 union udf_pmap *pmap;
355 uint8_t pmap_type, pmap_size;
356 uint8_t *pmap_pos;
357 uint32_t map, sparing_table;
358 uint32_t lb_size, packet_len;
359
360 lb_size = udf_rw32(lvd->lb_size);
361
362 printf("\t\tLogical volume descriptor\n");
363 printf("\t\t\tVolume descriptor sequence number %d\n", udf_rw32(lvd->seq_num));
364 udf_dump_id("\t\t\tLogical volume id ", 128, lvd->logvol_id, &lvd->desc_charset);
365 printf("\t\t\tLogical block size %d\n", udf_rw32(lvd->lb_size));
366 udf_dump_regid("\t\t\tDomainId", &lvd->domain_id, UDF_REGID_DOMAIN);
367 udf_dump_long_ad("\t\t\tFileset descriptor at", &lvd->_lvd_use.fsd_loc);
368 printf("\t\t\tMap table length %d\n", udf_rw32(lvd->mt_l));
369 printf("\t\t\tNumber of part maps %d\n", udf_rw32(lvd->n_pm));
370 udf_dump_regid("\t\t\tImplementation id", &lvd->imp_id, UDF_REGID_IMPLEMENTATION);
371 printf("\t\t\tIntegrety sequence at %d for %d bytes\n",
372 udf_rw32(lvd->integrity_seq_loc.loc), udf_rw32(lvd->integrity_seq_loc.len));
373 printf("\t\t\tPartion maps follow\n");
374
375 pmap_pos = &lvd->maps[0];
376 for (map = 0; map < udf_rw32(lvd->n_pm); map++) {
377 pmap = (union udf_pmap *) pmap_pos;
378 pmap_type = pmap->data[0];
379 pmap_size = pmap->data[1];
380
381 printf("\t\t\t\tPartion map type %d length %d \n", pmap_type, pmap_size);
382 /* only pmap types 1 and pmap types 2 are to be used */
383 printf("\t\t\t\t\tLogical %d maps to ", map);
384 switch (pmap_type) {
385 case 1 :
386 printf("partition %d on volume seq. number %d directly\n",
387 udf_rw16(pmap->pm1.part_num), udf_rw16(pmap->pm1.vol_seq_num));
388 break;
389 case 2 :
390 printf("partition %d on volume seq. number %d using\n",
391 udf_rw16(pmap->pm2.part_num), udf_rw16(pmap->pm2.vol_seq_num));
392 udf_dump_regid("\t\t\t\t\tmapping type", &pmap->pm2.part_id, UDF_REGID_UDF);
393 if (strncmp((char *) pmap->pm2.part_id.id, "*UDF Virtual Partition", UDF_REGID_ID_SIZE) == 0) {
394 /* nothing to print... */
395 }
396 if (strncmp((char *) pmap->pm2.part_id.id, "*UDF Sparable Partition", UDF_REGID_ID_SIZE) == 0) {
397 packet_len = udf_rw16(pmap->pms.packet_len);
398 printf("\t\t\t\t\t\tPacket length %d sectors (%d bytes)\n",
399 packet_len, packet_len * lb_size);
400 printf("\t\t\t\t\t\tNumber of sparing tables %d\n", pmap->pms.n_st);
401 printf("\t\t\t\t\t\tSize of each sparing table %d\n", udf_rw32(pmap->pms.st_size));
402 if (pmap->pms.n_st) {
403 printf("\t\t\t\t\t\tSparing tables at sectors ");
404 for (sparing_table = 0; sparing_table < pmap->pms.n_st; sparing_table++) {
405 printf("%d ", udf_rw32(pmap->pms.st_loc[sparing_table]));
406 }
407 printf("\n");
408 }
409 }
410 if (strncmp((char *) pmap->pm2.part_id.id, "*UDF Metadata Partition", UDF_REGID_ID_SIZE) == 0) {
411 printf("\t\t\t\t\t\tMetadata is %sduplicated on disc\n", pmap->pmm.flags & METADATA_DUPLICATED ? "":"NOT ");
412 printf("\t\t\t\t\t\tAllocation unit size %d sectors\n", udf_rw32(pmap->pmm.alloc_unit_size));
413 printf("\t\t\t\t\t\tAlignment unit size %d sectors\n", udf_rw32(pmap->pmm.alignment_unit_size));
414 printf("\t\t\t\t\t\tMetadata file at part. sector %d\n", udf_rw32(pmap->pmm.meta_file_lbn));
415 if (udf_rw32(pmap->pmm.meta_mirror_file_lbn) != (uint32_t) -1)
416 printf("\t\t\t\t\t\tMetadata mirror file at part. sector %d\n", udf_rw32(pmap->pmm.meta_mirror_file_lbn));
417 if (udf_rw32(pmap->pmm.meta_bitmap_file_lbn) != (uint32_t) -1)
418 printf("\t\t\t\t\t\tMetadata bitmap file at part. sector %d\n", udf_rw32(pmap->pmm.meta_bitmap_file_lbn));
419 }
420 break;
421 default :
422 break;
423 }
424 pmap_pos += pmap_size;
425 }
426 }
427
428
udf_dump_unalloc_space(struct unalloc_sp_desc * usd)429 void udf_dump_unalloc_space(struct unalloc_sp_desc *usd) {
430 struct extent_ad *alloc_desc;
431 uint32_t desc_num;
432
433 printf("\t\tUnallocated space descriptor\n");
434 printf("\t\t\tVolume descriptor sequence number %d\n", udf_rw32(usd->seq_num));
435 printf("\t\t\tNumber of free space slots %d\n", udf_rw32(usd->alloc_desc_num));
436 if (udf_rw32(usd->alloc_desc_num)) {
437 printf("\t\t\tFree space at : ");
438 for (desc_num = 0; desc_num < udf_rw32(usd->alloc_desc_num); desc_num++) {
439 alloc_desc = &usd->alloc_desc[desc_num];
440 printf("[%d %d] ", udf_rw32(alloc_desc->loc), udf_rw32(alloc_desc->loc)+udf_rw32(alloc_desc->len));
441 }
442 printf("\n");
443 }
444 }
445
446
udf_dump_terminating_desc(union dscrptr * desc)447 void udf_dump_terminating_desc(union dscrptr *desc) {
448 desc = desc;
449
450 printf("\t\tTerminating descriptor\n");
451 }
452
453
udf_dump_logvol_integrity(struct logvol_int_desc * lvid)454 void udf_dump_logvol_integrity(struct logvol_int_desc *lvid) {
455 struct udf_logvol_info *impl;
456 uint32_t part, num_part;
457 uint32_t *pos1, *pos2;
458 uint32_t free, size, rest_bytes;
459 uint32_t version;
460 const char *inttp;
461
462 printf("\t\tLogical volume integrity descriptor\n");
463 udf_dump_timestamp("\t\t\tTimestamp ", &lvid->time);
464
465 inttp = "UNKNOWN/INVALID";
466 if (udf_rw32(lvid->integrity_type) == UDF_INTEGRITY_CLOSED)
467 inttp = "closed";
468 if (udf_rw32(lvid->integrity_type) == UDF_INTEGRITY_OPEN)
469 inttp = "closed";
470 printf("\t\t\tIntegrity type %s\n", inttp);
471 printf("\t\t\tNext integrity sequence at %d for %d bytes\n",
472 udf_rw32(lvid->next_extent.loc), udf_rw32(lvid->next_extent.len));
473 printf("\t\t\tNext free unique file ID %d\n", (uint32_t) udf_rw64(lvid->lvint_next_unique_id));
474 printf("\t\t\tLength of implementation use area %d bytes\n", udf_rw32(lvid->l_iu));
475
476 num_part = udf_rw32(lvid->num_part);
477 printf("\t\t\tNumber of partitions %d\n", num_part);
478 for (part=0; part < num_part; part++) {
479 pos1 = &lvid->tables[0] + part;
480 pos2 = &lvid->tables[0] + num_part + part;
481 free = udf_rw32(*pos1);
482 size = udf_rw32(*pos2);
483 printf("\t\t\tPartition %d : %u blocks free space out of %u blocks\n", part, free, size);
484 }
485
486 /* printout the implementation use field */
487 impl = (struct udf_logvol_info *) (lvid->tables + 2*num_part);
488
489 udf_dump_regid("\t\t\tImplemenator Id", &impl->impl_id, UDF_REGID_IMPLEMENTATION );
490 printf("\t\t\tNumber of files %d\n", udf_rw32(impl->num_files));
491 printf("\t\t\tNumber of directories %d\n", udf_rw32(impl->num_directories));
492 version = udf_rw16(impl->min_udf_readver);
493 printf("\t\t\tMinimum readversion UDFv %x\n", version);
494 version = udf_rw16(impl->min_udf_writever);
495 printf("\t\t\tMinimum writeversion UDFv %x\n", version);
496 version = udf_rw16(impl->max_udf_writever);
497 printf("\t\t\tMaximum writeversion UDFv %x\n", version);
498 rest_bytes = udf_rw32(lvid->l_iu)-sizeof(struct udf_logvol_info);
499 if (rest_bytes > 0) printf("\t\t\t<%d bytes of undumped extra implementation use area>", rest_bytes);
500 printf("\n");
501 }
502
503
udf_dump_fileset_desc(struct fileset_desc * fsd)504 void udf_dump_fileset_desc(struct fileset_desc *fsd) {
505 printf("\t\tFileset descriptor\n");
506 udf_dump_timestamp("\t\t\tTimestamp ", &fsd->time);
507 printf("\t\t\tInterchange level %d\n", udf_rw16(fsd->ichg_lvl));
508 printf("\t\t\tMax interchange level %d\n", udf_rw16(fsd->max_ichg_lvl));
509 printf("\t\t\tCharset lists %d\n", udf_rw32(fsd->charset_list));
510 printf("\t\t\tMax charset lists %d\n", udf_rw32(fsd->max_charset_list));
511 printf("\t\t\tFileset number %d\n", udf_rw32(fsd->fileset_num));
512 printf("\t\t\tFileset descriptor number %d\n", udf_rw32(fsd->fileset_desc_num));
513 /* udf_dump_charspec("\t\t\tLogical volume id charspec ", &fsd->logvol_id_charset); */
514 /* udf_dump_charspec("\t\t\tFileset id charspec ", &fsd->fileset_charset); */
515 udf_dump_id("\t\t\tLogical volume id ", 128, fsd->logvol_id, &fsd->logvol_id_charset);
516 udf_dump_id("\t\t\tFileset id ", 32, fsd->fileset_id, &fsd->fileset_charset);
517 udf_dump_id("\t\t\tCopyright file id ", 32, fsd->copyright_file_id, &fsd->fileset_charset);
518 udf_dump_id("\t\t\tAbstract file id ", 32, fsd->abstract_file_id, &fsd->fileset_charset);
519 udf_dump_regid("\t\t\tDomainId", &fsd->domain_id, UDF_REGID_DOMAIN);
520 udf_dump_long_ad("\t\t\tRootdir ICB found ", &fsd->rootdir_icb);
521 udf_dump_long_ad("\t\t\tNext extend for fileset ", &fsd->next_ex);
522 udf_dump_long_ad("\t\t\tStreamdir ICB found ", &fsd->streamdir_icb);
523 }
524
525
udf_dump_fileid_in_charspec(struct fileid_desc * fid,struct charspec * chsp)526 void udf_dump_fileid_in_charspec(struct fileid_desc *fid, struct charspec *chsp) {
527 char *pos, file_char;
528
529 printf("\tFile id entry\n");
530 printf("\t\tFile version number %d\n", udf_rw16(fid->file_version_num));
531 file_char = fid->file_char;
532 printf("\t\tFile characteristics %d :\t", file_char);
533 if (file_char & UDF_FILE_CHAR_VIS) printf("hidden ");
534 if (file_char & UDF_FILE_CHAR_DEL) printf("deleted ");
535 if (file_char & UDF_FILE_CHAR_PAR) printf("parent(..) ");
536 if (file_char & UDF_FILE_CHAR_DIR) printf("directory ");
537 if (file_char & UDF_FILE_CHAR_META) printf("METADATA ");
538 printf("\n");
539 udf_dump_long_ad("\t\tFile ICB", &fid->icb);
540 printf("\t\tLength of file identifier area %d\n", fid->l_fi);
541 printf("\t\tOSTA UDF Unique ID %d\n", udf_rw32(fid->icb.impl.im_used.unique_id));
542 printf("\t\tOSTA UDF fileflags %d\n", udf_rw16(fid->icb.impl.im_used.flags));
543 printf("\t\tImplementation use length %d\n", udf_rw16(fid->l_iu));
544
545 if (udf_rw16(fid->l_iu)) {
546 /* Ecma 1/7.4 demands a (padded if wanted) implementation identifier */
547 if (udf_rw16(fid->l_iu) >= sizeof(struct regid)) {
548 udf_dump_regid("\t\t\tModified by", (struct regid *) &fid->data, UDF_REGID_IMPLEMENTATION);
549 } else {
550 printf("\t\t\tBROKEN fid, expected at least enough space for implementation regid\n");
551 }
552 }
553
554 pos = (char *) fid->data + udf_rw16(fid->l_iu);
555 if (file_char & UDF_FILE_CHAR_PAR) {
556 printf("\t\tParent directory ..\n");
557 } else {
558 udf_dump_id("\t\tFilename", fid->l_fi, pos, chsp);
559 }
560 }
561
562
udf_dump_fileid(struct fileid_desc * fid)563 void udf_dump_fileid(struct fileid_desc *fid) {
564 struct charspec chsp;
565
566 /* prolly OSTA compressed unicode anyway */
567 chsp.type = 0;
568 strcpy((char *) chsp.inf, "OSTA Compressed Unicode");
569
570 udf_dump_fileid_in_charspec(fid, &chsp);
571 }
572
573
udf_dump_icb_tag(struct icb_tag * icb_tag)574 void udf_dump_icb_tag(struct icb_tag *icb_tag) {
575 uint32_t flags, strat_param16;
576
577 flags = udf_rw16(icb_tag->flags);
578 strat_param16 = udf_rw16(icb_tag->strat_param16);
579 printf("\t\tICB Prior direct entries recorded (excl.) %d\n", udf_rw32(icb_tag->prev_num_dirs));
580 printf("\t\tICB Strategy type %d\n", udf_rw16(icb_tag->strat_type));
581 printf("\t\tICB Strategy type flags %d %d\n", icb_tag->strat_param[0], icb_tag->strat_param[1]);
582 printf("\t\tICB Maximum number of entries (non strat 4) %d\n", udf_rw16(icb_tag->max_num_entries));
583 printf("\t\tICB indirect entries/depth %d\n", strat_param16);
584 printf("\t\tICB File type %d\n", icb_tag->file_type);
585 printf("\t\tICB Parent ICB in logical block %d of mapped partition %d\n",
586 udf_rw32(icb_tag->parent_icb.lb_num), udf_rw16(icb_tag->parent_icb.part_num));
587 printf("\t\tICB Flags %d\n", udf_rw16(icb_tag->flags));
588 printf("\t\t\tFile/directory information using : ");
589 switch (flags & UDF_ICB_TAG_FLAGS_ALLOC_MASK) {
590 case UDF_ICB_SHORT_ALLOC :
591 printf("short allocation descriptor\n");
592 break;
593 case UDF_ICB_LONG_ALLOC :
594 printf("long allocation descriptor\n");
595 break;
596 case UDF_ICB_EXT_ALLOC :
597 printf("extended allocation descriptor (out of specs)\n");
598 break;
599 case UDF_ICB_INTERN_ALLOC :
600 printf("internal in the ICB\n");
601 break;
602 }
603 if (icb_tag->file_type == UDF_ICB_FILETYPE_DIRECTORY)
604 if (flags & UDF_ICB_TAG_FLAGS_DIRORDERED)
605 printf("\t\t\tOrdered directory\n");
606 if (flags & UDF_ICB_TAG_FLAGS_NONRELOC) printf("\t\t\tNot relocatable\n");
607 printf("\t\t\tFile flags :");
608 if (flags & UDF_ICB_TAG_FLAGS_SETUID) printf("setuid() ");
609 if (flags & UDF_ICB_TAG_FLAGS_SETGID) printf("setgid() ");
610 if (flags & UDF_ICB_TAG_FLAGS_STICKY) printf("sticky ");
611 printf("\n");
612 if (flags & UDF_ICB_TAG_FLAGS_CONTIGUES)
613 printf("\t\t\tFile is contigues i.e. in one piece effectively \n");
614 if (flags & UDF_ICB_TAG_FLAGS_MULTIPLEVERS)
615 printf("\t\t\tExpect multiple versions of a file in this directory\n");
616 }
617
618
udf_dump_indirect_entry(struct indirect_entry * inde)619 void udf_dump_indirect_entry(struct indirect_entry *inde) {
620 printf("\tIndirect (ICB) entry\n");
621 udf_dump_icb_tag(&inde->icbtag);
622 udf_dump_long_ad("\t\tPointing at", &inde->indirect_icb);
623 printf("\n");
624 }
625
626
udf_dump_allocation_entries(uint8_t addr_type,uint8_t * pos,uint32_t data_length)627 void udf_dump_allocation_entries(uint8_t addr_type, uint8_t *pos, uint32_t data_length) {
628 union icb *icb;
629 uint32_t size, piece_length, piece_flags;
630 uint32_t entry;
631
632 entry = 0;
633 size = 0;
634 while (data_length) {
635 if (entry % 1 == 0) printf("\n\t");
636 printf(" [ ");
637 printf("blob at ");
638 /* what to do with strat type == 3 ? or is all set up ok then ? */
639 icb = (union icb *) pos;
640 switch (addr_type) {
641 case UDF_ICB_SHORT_ALLOC :
642 piece_length = udf_rw32(icb->s_ad.len) & (((uint32_t) 1<<30)-1);
643 piece_flags = udf_rw32(icb->s_ad.len) >> 30; /* XXX ecma167 48.14.1.1 XXX */
644 printf("sector %8u for %8d bytes", udf_rw32(icb->s_ad.lb_num), piece_length);
645 if (piece_flags) printf(" flags %d", piece_flags);
646 size = sizeof(struct short_ad);
647 if (piece_length == 0) size = data_length;
648 break;
649 case UDF_ICB_LONG_ALLOC :
650 piece_length = udf_rw32(icb->l_ad.len) & (((uint32_t) 1<<30)-1);
651 piece_flags = udf_rw32(icb->l_ad.len) >> 30; /* XXX ecma167 48.14.1.1 XXX */
652 printf("sector %8d for %8d bytes in logical partion %d", udf_rw32(icb->l_ad.loc.lb_num), piece_length,
653 udf_rw16(icb->l_ad.loc.part_num));
654 if (piece_flags) printf(" flags %d", piece_flags);
655 size = sizeof(struct long_ad);
656 if (piece_length == 0) size = data_length;
657 break;
658 case UDF_ICB_EXT_ALLOC :
659 printf("extended alloc (help)");
660 size = sizeof(struct ext_ad);
661 break;
662 case UDF_ICB_INTERN_ALLOC :
663 printf("internal blob here for %d bytes", data_length);
664 size = data_length;
665 break;
666 }
667 printf(" ] ");
668 entry++;
669 pos += size;
670 data_length -=size;
671 }
672 printf("\n");
673
674 }
675
676
677 /* TODO create a read-in/insert/cleanup etc. for extra attributes */
udf_dump_extattrseq(uint8_t * start,uint32_t offset,uint32_t impl_offset,uint32_t appl_offset,uint32_t length)678 void udf_dump_extattrseq(uint8_t *start, uint32_t offset, uint32_t impl_offset, uint32_t appl_offset, uint32_t length) {
679 struct impl_extattr_entry *impl_extattr;
680 struct appl_extattr_entry *appl_extattr;
681 struct filetimes_extattr_entry *filetimes_extattr;
682 struct device_extattr_entry *device_extattr;
683 struct vatlvext_extattr_entry *vatlvext_extattr;
684 struct extattr_entry *extattr;
685 struct timestamp *timestamp;
686 struct charspec chsp;
687 uint32_t extattr_len, au_l, iu_l, d_l;
688 uint32_t type, subtype, chksum, attr_space, print_attr_space;
689 uint32_t existence;
690 uint8_t *pos;
691 char *type_txt, what[256];
692 int is_free_ea_space, is_free_app_ea_space, is_vatlvext_space, bit;
693
694 /* if used its OSTA compressed unicode anyway */
695 chsp.type = 0;
696 strcpy((char *) chsp.inf, "OSTA Compressed Unicode");
697
698 /* if one of the offsets is `-1' (0xffffffff), it indicates that its not present; God i hate magic values */
699 if (impl_offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
700 printf("\t\tNOTE: indicated no implementation related attributes are recorded in this extent\n");
701 if (appl_offset == UDF_IMPL_ATTR_LOC_NOT_PRESENT)
702 printf("\t\tNOTE: indicated no application related attributes are recorded in this extent\n");
703
704 pos = start;
705 attr_space = UDF_REGID_UDF; /* really? */
706 while (length > 0) {
707 extattr = (struct extattr_entry *) pos;
708 extattr_len = udf_rw32(extattr->a_l);
709 type = udf_rw32(extattr->type);
710 subtype = extattr->subtype;
711
712 if (pos == start) printf("\t\tStart of extended file related attributes area\n");
713 if (offset == impl_offset) printf("\t\tStart of implementation related attributes area\n");
714 if (offset == appl_offset) printf("\t\tStart of application related attributes area\n");
715
716 if (pos == start) attr_space = UDF_REGID_UDF;
717 if (offset == impl_offset) attr_space = UDF_REGID_IMPLEMENTATION;
718 if (offset == appl_offset) attr_space = UDF_REGID_APPLICATION;
719
720 if (subtype != 1) printf("\t\t\tWARNING: unknown subtype %d\n", subtype);
721
722 print_attr_space = attr_space;
723 switch (type) {
724 case 65536 : /* [4/48.10.8] application use extended attributes */
725 appl_extattr = (struct appl_extattr_entry *) pos;
726 au_l = udf_rw32(appl_extattr->au_l);
727 printf("\t\t\tApplication use extended attribute\n");
728 if (attr_space != UDF_REGID_APPLICATION)
729 printf("\t\t\t\t*** application use extended attribute found in non application use area ***\n");
730 printf("\t\t\t\tLength of application use space %d\n", au_l);
731 udf_dump_regid("\t\t\t\tApplication use Id", &appl_extattr->appl_id, attr_space);
732 break;
733 case 2048 : /* [4/48.10.9] implementation use extended attributes */
734 impl_extattr = (struct impl_extattr_entry *) pos;
735 iu_l = udf_rw32(impl_extattr->iu_l);
736 chksum = udf_rw16(impl_extattr->data16);
737
738 printf("\t\t\tImplementation use extended attribute\n");
739 if (chksum != udf_ea_cksum(pos))
740 printf("\t\t\t\t*** header checksum failed (%d should be %d) ***\n", chksum, udf_ea_cksum(pos));
741 if (attr_space != UDF_REGID_IMPLEMENTATION)
742 printf("\t\t\t\t*** implementation use extended attribute found in non implementation use area ***\n");
743
744 if (strncmp((char *) impl_extattr->imp_id.id, "*UDF", 4) == 0)
745 print_attr_space = UDF_REGID_UDF;
746 printf("\t\t\t\tLength of implementation use space %d\n", iu_l);
747 udf_dump_regid("\t\t\t\tImplementation use Id", &impl_extattr->imp_id, print_attr_space);
748 is_free_ea_space = (strcmp((char *) impl_extattr->imp_id.id, "*UDF FreeEASpace") == 0);
749 is_free_app_ea_space = (strcmp((char *) impl_extattr->imp_id.id, "*UDF FreeAppEASpace") == 0);
750 is_vatlvext_space = (strcmp((char *) impl_extattr->imp_id.id, "*UDF VAT LVExtension") == 0);
751 if (is_free_ea_space || is_free_app_ea_space) {
752 printf("\t\t\t\tFree space for new extended attributes (%d bytes total)\n", extattr_len);
753 } else if (is_vatlvext_space) {
754 vatlvext_extattr = (struct vatlvext_extattr_entry *) (impl_extattr->data + iu_l);
755 printf("\t\t\t\t\tUniqueID check %"PRIu64"\n", udf_rw64(vatlvext_extattr->unique_id_chk));
756 printf("\t\t\t\t\tNumber of files %d\n", udf_rw32(vatlvext_extattr->num_files));
757 printf("\t\t\t\t\tNumber of directories %d\n", udf_rw32(vatlvext_extattr->num_directories));
758 udf_dump_id("\t\t\t\t\tLogical volume id ", 128, vatlvext_extattr->logvol_id, &chsp);
759 } else {
760 printf("\t\t\t\t<Undumped %d bytes of implementation use data>\n", iu_l);
761 }
762 break;
763 case 1 : /* [4/48.10.3] : Character set information; UDF does allow/disallow explicitly */
764 printf("\t\t\tCharacter set information attribute\n");
765 printf("\t\t\t\t<Undumped %d bytes attribute>\n", extattr_len);
766 break;
767 case 3 : /* [4/48.10.4] : Alternate permissions; UDF 3.3.4.2: not to be recorded */
768 printf("\t\t\tAlternate permission attribute\n");
769 printf("\t\t\t\t<Undumped %d bytes attribute>\n", extattr_len);
770 break;
771 case 5 : /* [4/48.10.5] : File Times Extended Attribute */
772 case 6 : /* [4/48.10.6] : Information Times Extended Attribute; recorded in UDF ? */
773 /* ASSUMPTION : bit fields are not exlusive */
774 filetimes_extattr = (struct filetimes_extattr_entry *) pos;
775 d_l = udf_rw32(filetimes_extattr->d_l);
776 existence = udf_rw32(filetimes_extattr->existence);
777 type_txt = "File";
778 if (type == 6) type_txt = "File information";
779
780 printf("\t\t\t%s times extended attribute\n", type_txt);
781 timestamp = &filetimes_extattr->times[0];
782 for (bit = 0; bit < 32; bit++) {
783 if (d_l == 0) break;
784 if ((existence & (1 << bit)) == 0)
785 continue;
786 switch (bit) {
787 case 0 : /* File Creation Date and Time: the date and time of the day at which the file was created. */
788 sprintf(what, "\t\t\t\t%s created at ", type_txt);
789 break;
790 case 1 : /* Information Last Modification Date and Time: the date and time of the day at which the information in the file was last modified. */
791 sprintf(what, "\t\t\t\t%s last modified at ", type_txt);
792 break;
793 case 2 : /* File Deletion Date and Time: the date and time of the day after which the file may be deleted. */
794 sprintf(what, "\t\t\t\t%s may be deleted after ", type_txt);
795 break;
796 case 3 : /* File Effective Date and Time: the date and time of the day after which the file may be used. */
797 sprintf(what, "\t\t\t\t%s may only be used after ", type_txt);
798 break;
799 case 5 : /* File Last Backup Date and Time: the date and time of the day at which the file was last backed up. */
800 sprintf(what, "\t\t\t\t%s last backuped at ", type_txt);
801 break;
802 default : /* unspec */
803 sprintf(what, "\t\t\t\tUndefined meaning for %s time stamp ", type_txt);
804 break;
805 }
806 udf_dump_timestamp(what, timestamp);
807 d_l -= sizeof(struct timestamp);
808 timestamp++; /* advance */
809 }
810 break;
811 case 12 : /* [4/48.10.7] : Device Specification Extended Attribute */
812 device_extattr = (struct device_extattr_entry *) pos;
813 iu_l = udf_rw32(device_extattr->iu_l);
814 printf("\t\t\tDevice node extended attribute\n");
815 printf("\t\t\t\tMajor %d\n", udf_rw32(device_extattr->major));
816 printf("\t\t\t\tMinor %d\n", udf_rw32(device_extattr->minor));
817 if (iu_l >= sizeof(struct regid)) {
818 udf_dump_regid("\t\t\t\tImplementator", (struct regid *) (device_extattr->data), UDF_REGID_IMPLEMENTATION);
819 }
820 break;
821 default :
822 printf("\t\t\tUndumped extended attribute type %d\n", type);
823 printf("\t\t\t\tSubtype %d\n", subtype);
824 printf("\t\t\t\tLength %d\n", extattr_len);
825 break;
826 }
827 if (extattr_len == 0) {
828 printf("\t\t\tABORTing dump\n");
829 break;
830 }
831 pos += extattr_len;
832 offset += extattr_len;
833 length -= extattr_len;
834 }
835 printf("\n");
836 }
837
838
udf_dump_extattr_hdr(struct extattrhdr_desc * eahd,uint32_t length)839 void udf_dump_extattr_hdr(struct extattrhdr_desc *eahd, uint32_t length) {
840 uint32_t hdr_len, impl_attr_loc, appl_attr_loc;
841 uint8_t *pos;
842
843 hdr_len = (uint32_t) sizeof(struct extattrhdr_desc);
844 impl_attr_loc = udf_rw32(eahd->impl_attr_loc);
845 appl_attr_loc = udf_rw32(eahd->appl_attr_loc);
846
847 printf("\t\tExtended attributes header:\n");
848 printf("\t\t\tLength %d bytes\n", length);
849 printf("\t\t\tImplementation attributes at offset %d\n", impl_attr_loc);
850 printf("\t\t\tApplication attributes at offset %d\n", appl_attr_loc);
851 printf("\t\t\tBytes remaining after header %d\n", length - hdr_len);
852
853 /* determine length of file related attributes space */
854 pos = (uint8_t *) eahd;
855 pos += hdr_len;
856 length -= hdr_len;
857
858 udf_dump_extattrseq(pos, hdr_len, impl_attr_loc, appl_attr_loc, length);
859 }
860
861
udf_dump_file_entry(struct file_entry * fe)862 void udf_dump_file_entry(struct file_entry *fe) {
863 uint8_t *pos;
864 uint32_t length;
865 uint8_t addr_type;
866
867 /* direct_entries = udf_rw32(fe->icbtag.prev_num_dirs); */
868 //strat_param16 = udf_rw16(* (uint16_t *) (fe->icbtag.strat_param));
869 //entries = udf_rw16(fe->icbtag.max_num_entries);
870 //strategy = udf_rw16(fe->icbtag.strat_type);
871 addr_type = udf_rw16(fe->icbtag.flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
872
873 printf("\tFile entry\n");
874 udf_dump_icb_tag(&fe->icbtag);
875 printf("\t\tUid %d\n", udf_rw32(fe->uid));
876 printf("\t\tGid %d\n", udf_rw32(fe->gid));
877 printf("\t\tPermissions %x\n", udf_rw32(fe->perm));
878 printf("\t\tLink count %d\n", udf_rw16(fe->link_cnt));
879 printf("\t\tRecord format %d\n", fe->rec_format);
880 printf("\t\tRecord display attributes %d\n", fe->rec_disp_attr);
881 printf("\t\tRecord length %d\n", fe->rec_len);
882 printf("\t\tInformation length %"PRIu64"\n", (uint64_t) udf_rw64(fe->inf_len));
883 printf("\t\tLogical blocks recorded %"PRIu64"\n", (uint64_t) udf_rw64(fe->logblks_rec));
884 udf_dump_timestamp("\t\tAccess time ", &fe->atime);
885 udf_dump_timestamp("\t\tModification time ", &fe->mtime);
886 udf_dump_timestamp("\t\tAttribute time ", &fe->attrtime);
887 printf("\t\tCheckpoint %d\n", udf_rw32(fe->ckpoint));
888 udf_dump_long_ad("\t\tExtended attributes ICB at", &fe->ex_attr_icb);
889 udf_dump_regid("\t\tImplementation", &fe->imp_id, UDF_REGID_IMPLEMENTATION);
890 printf("\t\tUniqueID %d\n", (uint32_t) udf_rw64(fe->unique_id));
891 printf("\t\tLength of extended attribute area %d\n", udf_rw32(fe->l_ea));
892 printf("\t\tLength of allocation descriptors %d\n", udf_rw32(fe->l_ad));
893
894 if (udf_rw32(fe->l_ea)) {
895 udf_dump_extattr_hdr((struct extattrhdr_desc *) &fe->data[0], udf_rw32(fe->l_ea));
896 }
897 if (udf_rw32(fe->ex_attr_icb.len)) {
898 printf("\t\t<Undumped %d bytes of extended attributes descriptor\n", udf_rw32(fe->ex_attr_icb.len));
899 }
900
901 printf("\t\tAllocation descriptors : \n");
902
903 pos = &fe->data[0] + udf_rw32(fe->l_ea);
904 length = udf_rw32(fe->l_ad);
905
906 udf_dump_allocation_entries(addr_type, pos, length);
907 }
908
909
udf_dump_extfile_entry(struct extfile_entry * efe)910 void udf_dump_extfile_entry(struct extfile_entry *efe) {
911 uint8_t *pos;
912 uint32_t length;
913 uint8_t addr_type;
914
915 /* direct_entries = udf_rw32(efe->icbtag.prev_num_dirs); */
916 //strat_param16 = udf_rw16(* (uint16_t *) (efe->icbtag.strat_param));
917 //entries = udf_rw16(efe->icbtag.max_num_entries);
918 //strategy = udf_rw16(efe->icbtag.strat_type);
919 addr_type = udf_rw16(efe->icbtag.flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
920
921 printf("\tExtended file entry\n");
922 udf_dump_icb_tag(&efe->icbtag);
923 printf("\t\tUid %d\n", udf_rw32(efe->uid));
924 printf("\t\tGid %d\n", udf_rw32(efe->gid));
925 printf("\t\tPermissions %x\n", udf_rw32(efe->perm));
926 printf("\t\tLink count %d\n", udf_rw16(efe->link_cnt));
927 printf("\t\tRecord format %d\n", efe->rec_format);
928 printf("\t\tRecord display attributes %d\n", efe->rec_disp_attr);
929 printf("\t\tRecord length %d\n", efe->rec_len);
930 printf("\t\tInformation length %"PRIu64"\n", (uint64_t) udf_rw64(efe->inf_len));
931 printf("\t\tObject size %"PRIu64"\n", (uint64_t) udf_rw64(efe->obj_size));
932 printf("\t\tLogical blocks recorded %"PRIu64"\n", (uint64_t) udf_rw64(efe->logblks_rec));
933 udf_dump_timestamp("\t\tAccess time ", &efe->atime);
934 udf_dump_timestamp("\t\tModification time ", &efe->mtime);
935 udf_dump_timestamp("\t\tCreation time ", &efe->ctime);
936 udf_dump_timestamp("\t\tAttribute time ", &efe->attrtime);
937 printf("\t\tCheckpoint %d\n", udf_rw32(efe->ckpoint));
938 udf_dump_long_ad("\t\tExtended attributes ICB at", &efe->ex_attr_icb);
939 udf_dump_long_ad("\t\tStreamdir ICB at", &efe->streamdir_icb);
940 udf_dump_regid("\t\tImplementation", &efe->imp_id, UDF_REGID_IMPLEMENTATION);
941 printf("\t\tUniqueID %d\n", (uint32_t) udf_rw64(efe->unique_id));
942 printf("\t\tLength of extended attribute area %d\n", udf_rw32(efe->l_ea));
943 printf("\t\tLength of allocation descriptors %d\n", udf_rw32(efe->l_ad));
944
945 if (udf_rw32(efe->l_ea)) {
946 udf_dump_extattr_hdr((struct extattrhdr_desc *) &efe->data[0], udf_rw32(efe->l_ea));
947 }
948 if (udf_rw32(efe->ex_attr_icb.len)) {
949 printf("\t\t<Undumped %d bytes of extended attributes descriptor\n", udf_rw32(efe->ex_attr_icb.len));
950 }
951
952 printf("\t\tAllocation descriptors : \n");
953
954 pos = &efe->data[0] + udf_rw32(efe->l_ea);
955 length = udf_rw32(efe->l_ad);
956
957 udf_dump_allocation_entries(addr_type, pos, length);
958 }
959
960
961 /* dump allocation extention descriptor */
udf_dump_alloc_extent(struct alloc_ext_entry * ext,int addr_type)962 void udf_dump_alloc_extent(struct alloc_ext_entry *ext, int addr_type) {
963 uint8_t *pos;
964 uint32_t length;
965 int isshort, islong;
966
967 /* note we DONT know if its filled with short_ad's or long_ad's! */
968 printf("\tAllocation Extent descriptor\n");
969 printf("\t\tPrevious entry %d\n", udf_rw32(ext->prev_entry));
970 printf("\t\tLength of allocation descriptors %d\n", udf_rw32(ext->l_ad));
971
972 pos = &ext->data[0];
973 length = udf_rw32(ext->l_ad);
974
975 if (addr_type < 0) {
976 isshort = ((length % sizeof(struct short_ad)) == 0);
977 islong = ((length % sizeof(struct long_ad)) == 0);
978 if (isshort)
979 addr_type = UDF_ICB_SHORT_ALLOC;
980 if (islong)
981 addr_type = UDF_ICB_LONG_ALLOC;
982 if (!(isshort ^ islong)) {
983 printf("\t\tCan't determine if its filled with long_ad's or short_ad's !\n");
984 return;
985 }
986 }
987
988 udf_dump_allocation_entries(addr_type, pos, length);
989 }
990
991
992 /* dump a space table(entry) descriptor */
udf_dump_space_entry(struct space_entry_desc * sed)993 void udf_dump_space_entry(struct space_entry_desc *sed) {
994 union icb *icb;
995 uint32_t addr_type, size, bytes;
996 uint32_t piece_sector, piece_length, piece_part;
997 uint8_t *pos;
998
999 printf("\tSpace entry table\n");
1000 udf_dump_icb_tag(&sed->icbtag);
1001 printf("\t\tSize in bytes %d\n", udf_rw32(sed->l_ad));
1002
1003 pos = &sed->entry[0];
1004 bytes = udf_rw32(sed->l_ad);
1005
1006 addr_type = udf_rw16(sed->icbtag.flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
1007 while (bytes) {
1008 size = piece_length = piece_sector = piece_part = 0;
1009 icb = (union icb *) pos;
1010 switch (addr_type) {
1011 case UDF_ICB_SHORT_ALLOC :
1012 piece_length = udf_rw32(icb->s_ad.len) & (((uint32_t) 1<<31)-1);
1013 piece_sector = udf_rw32(icb->s_ad.lb_num);
1014 printf("[at sec %u for %d bytes] ", piece_sector, piece_length);
1015 size = sizeof(struct short_ad);
1016 break;
1017 case UDF_ICB_LONG_ALLOC :
1018 piece_length = udf_rw32(icb->l_ad.len) & (((uint32_t) 1<<31)-1);
1019 piece_sector = udf_rw32(icb->l_ad.loc.lb_num);
1020 piece_part = udf_rw16(icb->l_ad.loc.part_num);
1021 size = sizeof(struct long_ad);
1022 printf("[at sec %u for %d bytes at partition %d] ", piece_sector, piece_length, piece_part);
1023 break;
1024 case UDF_ICB_EXT_ALLOC :
1025 case UDF_ICB_INTERN_ALLOC :
1026 printf("\t\t\tWARNING : an internal alloc in a space entry?\n");
1027 return;
1028 }
1029 bytes -= size;
1030 }
1031 }
1032
1033
1034 /* dump a space bitmap descriptor */
udf_dump_space_bitmap(struct space_bitmap_desc * sbd)1035 void udf_dump_space_bitmap(struct space_bitmap_desc *sbd) {
1036 uint32_t bits, from, now, cnt;
1037 uint8_t byte, bit, bitpos, state, *pos;
1038
1039 printf("\t\tSpace bitmap\n");
1040 printf("\t\t\tNumber of bits %u\n", udf_rw32(sbd->num_bits));
1041 printf("\t\t\tNumber of bytes %u\n", udf_rw32(sbd->num_bytes));
1042 printf("\t\t\tMarked parts at :\n");
1043
1044 pos = sbd->data;
1045 bits = udf_rw32(sbd->num_bits);
1046
1047 /* shield */
1048 /* if (bits > 2000*8) bits = 2000*8; */
1049
1050 printf("\t\t\t\t");
1051 cnt = 0; from = 0; now = 0; bitpos = 0; byte = *pos; state = byte & 1;
1052 while (now < bits) {
1053 if (bitpos == 0) {
1054 byte = *pos++;
1055 }
1056 bit = byte & 1;
1057 if (bit != state) {
1058 if (state) {
1059 printf("[%08u - %08u]", from, now-1);
1060 if (cnt % 4 == 3) printf("\n\t\t\t\t"); else printf(" ");
1061 cnt++;
1062 }
1063 from = now;
1064 state = bit;
1065 }
1066 byte >>= 1;
1067 bitpos = (bitpos+1) & 7;
1068 now++;
1069 }
1070 if (state) printf("[%08u - %08u]", from, now);
1071 if (bits < udf_rw32(sbd->num_bits)) printf(" .... <trimmed>\n");
1072 }
1073
1074
1075 /* main descriptor `dump' function */
udf_dump_descriptor(union dscrptr * dscrpt)1076 void udf_dump_descriptor(union dscrptr *dscrpt) {
1077 struct desc_tag *tag = &dscrpt->tag;
1078 int error;
1079
1080 if (!dscrpt)
1081 return;
1082
1083 /* check if its a valid descritor */
1084 if (udf_rw16(tag->id == 0) && udf_rw16(tag->descriptor_ver) == 0) return;
1085
1086 udf_dump_desc(tag);
1087
1088 error = udf_check_tag(dscrpt);
1089 if (error) {
1090 printf("\tBAD TAG\n");
1091 return;
1092 }
1093 switch (udf_rw16(tag->id)) {
1094 case TAGID_SPARING_TABLE :
1095 udf_dump_sparing_table(&dscrpt->spt);
1096 break;
1097 case TAGID_PRI_VOL :
1098 udf_dump_pri_vol(&dscrpt->pvd);
1099 break;
1100 case TAGID_ANCHOR :
1101 udf_dump_anchor(&dscrpt->avdp);
1102 break;
1103 case TAGID_VOL :
1104 udf_dump_unimpl(dscrpt, "volume descriptor");
1105 break;
1106 case TAGID_IMP_VOL :
1107 udf_dump_implementation_volume(&dscrpt->ivd);
1108 break;
1109 case TAGID_PARTITION :
1110 udf_dump_part(&dscrpt->pd);
1111 break;
1112 case TAGID_LOGVOL :
1113 udf_dump_log_vol(&dscrpt->lvd);
1114 break;
1115 case TAGID_UNALLOC_SPACE :
1116 udf_dump_unalloc_space(&dscrpt->usd);
1117 break;
1118 case TAGID_TERM :
1119 udf_dump_terminating_desc(dscrpt);
1120 break;
1121 case TAGID_LOGVOL_INTEGRITY :
1122 udf_dump_logvol_integrity(&dscrpt->lvid);
1123 break;
1124 case TAGID_FSD :
1125 udf_dump_fileset_desc(&dscrpt->fsd);
1126 break;
1127 case TAGID_FID :
1128 udf_dump_fileid(&dscrpt->fid);
1129 break;
1130 case TAGID_ALLOCEXTENT :
1131 udf_dump_alloc_extent(&dscrpt->aee, -1);
1132 break;
1133 case TAGID_INDIRECTENTRY :
1134 udf_dump_indirect_entry(&dscrpt->inde);
1135 break;
1136 case TAGID_FENTRY :
1137 udf_dump_file_entry(&dscrpt->fe);
1138 break;
1139 case TAGID_EXTATTR_HDR :
1140 udf_dump_extattr_hdr(&dscrpt->eahd, sizeof(struct extattrhdr_desc));
1141 break;
1142 case TAGID_UNALL_SP_ENTRY :
1143 udf_dump_space_entry(&dscrpt->sed);
1144 break;
1145 case TAGID_SPACE_BITMAP :
1146 udf_dump_space_bitmap(&dscrpt->sbd);
1147 break;
1148 case TAGID_PART_INTEGRITY :
1149 udf_dump_unimpl(dscrpt, "partition integrity");
1150 break;
1151 case TAGID_EXTFENTRY :
1152 udf_dump_extfile_entry(&dscrpt->efe);
1153 break;
1154 default :
1155 break;
1156 }
1157 printf("\n");
1158 }
1159
1160
1161 /* this one is special since the VAT table has no tag but is a file */
udf_dump_vat_table(struct udf_part_mapping * udf_part_mapping)1162 void udf_dump_vat_table(struct udf_part_mapping *udf_part_mapping) {
1163 struct charspec chsp;
1164 struct udf_vat *vat;
1165 uint32_t previous_vat, entry, vat_entries, *vat_pos, version;
1166
1167 /* prolly OSTA compressed unicode anyway */
1168 chsp.type = 0;
1169 strcpy((char *) chsp.inf, "OSTA Compressed Unicode");
1170
1171 vat = udf_part_mapping->vat;
1172 printf("\tVAT table: ");
1173 printf("%s UDF 2.00 format\n", vat?"post":"pre");
1174
1175 vat_entries = udf_part_mapping->vat_entries;
1176 vat_pos = (uint32_t *) udf_part_mapping->vat_translation;
1177 if (vat) {
1178 printf("\t\tHeader length %d\n", udf_rw16(vat->header_len));
1179 printf("\t\tImplementation use length %d\n", udf_rw16(vat->impl_use_len));
1180 udf_dump_id("\t\tLogical volume id ", 128, vat->logvol_id, &chsp);
1181 printf("\t\tNumber of files %d\n", udf_rw32(vat->num_files));
1182 printf("\t\tNumber of directories %d\n", udf_rw32(vat->num_directories));
1183 version = udf_rw16(vat->min_udf_readver);
1184 printf("\t\tMinimum readversion UDFv %x\n", version);
1185 version = udf_rw16(vat->min_udf_writever);
1186 printf("\t\tMinimum writeversion UDFv %x\n", version);
1187 version = udf_rw16(vat->max_udf_writever);
1188 printf("\t\tMaximum writeversion UDFv %x\n", version);
1189 if (udf_rw16(vat->impl_use_len)) printf("\t\t<undumped implementation use area>");
1190 previous_vat = udf_rw32(vat->prev_vat);
1191 } else {
1192 udf_dump_regid("\t\tIdentifier id (can be wrong) ", (struct regid *) (vat_pos+vat_entries), UDF_REGID_NAME);
1193 previous_vat = udf_rw32(*(vat_pos + vat_entries + 32/4)); /* definition */
1194 }
1195 if (previous_vat == 0xffffffff) {
1196 printf("\t\tNo previous VAT recorded\n");
1197 } else {
1198 printf("\t\tPrevious VAT recorded at offset %d\n", previous_vat);
1199 }
1200
1201 printf("\t\tNumber of VAT entries %d\n", vat_entries);
1202 printf("\t\tVAT dump :");
1203 for (entry=0; entry < vat_entries; entry++) {
1204 if ((entry % 4) == 0) printf("\n\t");
1205 printf("[0x%08x -> 0x%08x] ", entry, *vat_pos++);
1206 }
1207 printf("\n");
1208 }
1209
1210
udf_dump_volumeset_info(struct udf_volumeset * udf_volumeset)1211 void udf_dump_volumeset_info(struct udf_volumeset *udf_volumeset) {
1212 struct udf_pri_vol *primary;
1213 struct udf_log_vol *logical;
1214 struct udf_partition *udf_partition;
1215 struct udf_part_mapping *udf_part_mapping;
1216 struct udf_discinfo *disc;
1217 char *name;
1218 int num_volumes, num_partitions;
1219 int subvolume, part_num, track_num;
1220
1221 num_volumes = 0; /* shut up gcc */
1222 if (udf_volumeset->obsolete) return;
1223
1224 primary = STAILQ_FIRST(&udf_volumeset->primaries);
1225 if (primary) {
1226 num_volumes = udf_rw16(primary->pri_vol->max_vol_seq);
1227 if (udf_volumeset->obsolete) printf("OBSOLETE\n"); /* XXX */
1228
1229 printf("Volume set ");
1230 udf_dump_id(NULL, 32, primary->pri_vol->volset_id, &primary->pri_vol->desc_charset);
1231 printf(" (%d volume%s) ", num_volumes, num_volumes>1?"s":"");
1232
1233 num_partitions = udf_volumeset->max_partnum;
1234 printf("with %d partition%s\n", num_partitions, (num_partitions!=1)?"s":"");
1235
1236 /* better loop trough the partition numbers to display them in a defined order */
1237 SLIST_FOREACH(udf_partition, &udf_volumeset->parts, next_partition) {
1238 part_num = udf_rw16(udf_partition->partition->part_num);
1239 if (udf_partition) {
1240 /* there is information */
1241 assert(udf_partition->udf_session);
1242 assert(udf_partition->udf_session->disc);
1243 assert(udf_partition->partition);
1244 assert(part_num == udf_rw16(udf_partition->partition->part_num));
1245 track_num = udf_partition->udf_session->session_num;
1246 disc = udf_partition->udf_session->disc;
1247
1248 printf("\tPartition number %d at device `%s' session %d from sector %d(+%d) for %u sectors\n",
1249 part_num,
1250 disc->dev->dev_name,
1251 track_num,
1252 udf_rw32(udf_partition->partition->start_loc),
1253 udf_partition->udf_session->session_offset,
1254 udf_rw32(udf_partition->partition->part_len)
1255 );
1256 } else {
1257 printf("\tUnknown partition %d [unknown]\n", part_num);
1258 }
1259 }
1260 }
1261
1262 STAILQ_FOREACH(primary, &udf_volumeset->primaries, next_primary) {
1263 subvolume = udf_rw16(primary->pri_vol->vds_num);
1264
1265 printf("\tPrimary volume ");
1266 udf_dump_id(NULL, 32, primary->pri_vol->vol_id, &primary->pri_vol->desc_charset);
1267 printf(" (part %d/%d) ", subvolume, num_volumes);
1268
1269 printf("created by implementator `%s' ", primary->pri_vol->imp_id.id);
1270 if (*primary->pri_vol->app_id.id)
1271 printf("by/for application `%s' ",primary->pri_vol->app_id.id);
1272 printf("\n");
1273
1274 SLIST_FOREACH(logical, &primary->log_vols, next_logvol) {
1275 name = logical->log_vol->logvol_id;
1276 udf_dump_id("\t\tcontains logical volume ", 128, name, &logical->log_vol->desc_charset);
1277 if (logical->broken) {
1278 printf("\t\t\tBROKEN\n");
1279 continue;
1280 }
1281
1282 SLIST_FOREACH(udf_part_mapping, &logical->part_mappings, next_mapping) {
1283 printf("\t\t\tmapping %d on %d as ", udf_part_mapping->udf_virt_part_num,
1284 udf_part_mapping->udf_phys_part_num);
1285 switch (udf_part_mapping->udf_part_mapping_type) {
1286 case UDF_PART_MAPPING_ERROR :
1287 printf("bad partition");
1288 break;
1289 case UDF_PART_MAPPING_PHYSICAL :
1290 printf("direct");
1291 break;
1292 case UDF_PART_MAPPING_VIRTUAL :
1293 printf("virtual partition");
1294 break;
1295 case UDF_PART_MAPPING_SPARABLE :
1296 printf("sparable");
1297 break;
1298 case UDF_PART_MAPPING_META :
1299 printf("metadata only");
1300 }
1301 printf(" recording");
1302 if (udf_part_mapping->data_writable) printf(" data");
1303 if (udf_part_mapping->metadata_writable) printf(" metadata");
1304 if (!udf_part_mapping->data_writable && !udf_part_mapping->metadata_writable) printf(" nothing");
1305 printf("\n");
1306 }
1307 }
1308 printf("\n");
1309 }
1310 }
1311
1312
udf_dump_alive_sets(void)1313 void udf_dump_alive_sets(void) {
1314 struct udf_volumeset *udf_volumeset;
1315
1316 printf("UDF volume sets marked alive :\n");
1317 SLIST_FOREACH(udf_volumeset, &udf_volumeset_list, next_volumeset) {
1318 udf_dump_volumeset_info(udf_volumeset);
1319 }
1320 printf("\n");
1321 }
1322
1323
1324 /*
1325 * extern defined read_logvol_descriptor breaks splitting rules but how
1326 * otherwise to provide a detailed description of the file entry udf_node
1327 */
1328
1329 #define DUMP_DIRBUFFER_SIZE (16*1024)
udf_dump_file_entry_node(struct udf_node * udf_node,char * prefix)1330 void udf_dump_file_entry_node(struct udf_node *udf_node, char *prefix) {
1331 struct long_ad udf_icbptr;
1332 struct uio dir_uio;
1333 struct iovec dir_iovec;
1334 struct dirent *dirent;
1335 struct fileid_desc *fid;
1336 struct udf_node *entry_node;
1337 uint32_t pos, lb_size;
1338 uint8_t *buffer;
1339 char fullpath[1024]; /* XXX arbitrary length XXX */
1340 int isdot, isdotdot, isdir, found, eof;
1341 int error;
1342
1343 if (!udf_node)
1344 return;
1345
1346 /* XXX could pass on dirent XXX */
1347 isdir = (udf_node->udf_filetype == UDF_ICB_FILETYPE_DIRECTORY);
1348 isdir |= (udf_node->udf_filetype == UDF_ICB_FILETYPE_STREAMDIR);
1349 if (isdir) {
1350 buffer = malloc(DUMP_DIRBUFFER_SIZE);
1351 if (!buffer)
1352 return;
1353 lb_size = udf_node->udf_log_vol->lb_size;
1354 fid = malloc(lb_size);
1355 assert(fid); /* or just return? */
1356
1357 /* recurse into this directory */
1358 dir_uio.uio_offset = 0; /* begin at start */
1359 do {
1360 dir_iovec.iov_base = buffer;
1361 dir_iovec.iov_len = DUMP_DIRBUFFER_SIZE;
1362 dir_uio.uio_resid = DUMP_DIRBUFFER_SIZE;
1363 dir_uio.uio_iovcnt = 1;
1364 dir_uio.uio_iov = &dir_iovec;
1365 dir_uio.uio_rw = UIO_WRITE;
1366
1367 error = udf_readdir(udf_node, &dir_uio, &eof);
1368 if (error) {
1369 printf("While reading in dirbuffer for dumping file entry udf_node : %s\n", strerror(error));
1370 break;
1371 }
1372 pos = 0;
1373 while (pos < DUMP_DIRBUFFER_SIZE - dir_uio.uio_resid) {
1374 dirent = (struct dirent *) (buffer + pos);
1375
1376 sprintf(fullpath, "%s/%s", prefix, dirent->d_name);
1377
1378 /* looking for '.' or '..' ? */
1379 isdot = (strncmp(dirent->d_name, ".", DIRENT_NAMLEN(dirent)) == 0);
1380 isdotdot = (strncmp(dirent->d_name, "..", DIRENT_NAMLEN(dirent)) == 0);
1381
1382 pos += sizeof(struct dirent); /* XXX variable size dirents possible XXX */
1383
1384 if (isdotdot)
1385 continue;
1386
1387 if (isdot)
1388 continue;
1389
1390 error = udf_lookup_name_in_dir(udf_node, dirent->d_name, DIRENT_NAMLEN(dirent), &udf_icbptr, fid, &found);
1391 if (!error) {
1392 error = ENOENT;
1393 if (found)
1394 error = udf_readin_udf_node(udf_node, &udf_icbptr, fid, &entry_node);
1395 }
1396 if (!error)
1397 udf_dump_file_entry_node(entry_node, fullpath);
1398 }
1399 } while (!eof);
1400
1401 free(fid);
1402 free(buffer);
1403 return;
1404 }
1405 /* leaf udf_node */
1406 printf("%s\n", prefix);
1407 }
1408 #undef DUMP_DIRBUFFER_SIZE
1409
1410
udf_dump_root_dir(struct udf_mountpoint * mountpoint)1411 void udf_dump_root_dir(struct udf_mountpoint *mountpoint) {
1412 printf("\n\nRoot dir dump\n");
1413 if (mountpoint->rootdir_node) udf_dump_file_entry_node(mountpoint->rootdir_node, ":Rootdir");
1414
1415 printf("\n\nStreamdir dump\n");
1416 if (mountpoint->streamdir_node) udf_dump_file_entry_node(mountpoint->streamdir_node, ":Streamdir");
1417 }
1418
1419
1420 /* XXX These should move to form one cd verbose file with cd_discect XXX */
print_disc_state(int state)1421 static char *print_disc_state(int state) {
1422 switch (state) {
1423 case 0: return "empty disc";
1424 case 1: return "incomplete (appendable)";
1425 case 2: return "full (not appendable)";
1426 case 3: return "random writable";
1427 }
1428 return "unknown disc state";
1429 }
1430
1431
print_session_state(int state)1432 static char *print_session_state(int state) {
1433 switch (state) {
1434 case 0 : return "empty";
1435 case 1 : return "incomplete";
1436 case 2 : return "reserved/damaged";
1437 case 3 : return "complete/closed disc";
1438 }
1439 return "unknown session_state";
1440 }
1441
1442
print_mmc_profile(int profile)1443 static char *print_mmc_profile(int profile) {
1444 static char scrap[100];
1445
1446 switch (profile) {
1447 case 0x00 : return "Unknown[0] profile";
1448 case 0x01 : return "Non removable disc";
1449 case 0x02 : return "Removable disc";
1450 case 0x03 : return "Magneto Optical with sector erase";
1451 case 0x04 : return "Magneto Optical write once";
1452 case 0x05 : return "Advance Storage Magneto Optical";
1453 case 0x08 : return "CD-ROM";
1454 case 0x09 : return "CD-R recordable";
1455 case 0x0a : return "CD-RW rewritable";
1456 case 0x10 : return "DVD-ROM";
1457 case 0x11 : return "DVD-R sequential";
1458 case 0x12 : return "DVD-RAM rewritable";
1459 case 0x13 : return "DVD-RW restricted overwrite";
1460 case 0x14 : return "DVD-RW sequential";
1461 case 0x1a : return "DVD+RW rewritable";
1462 case 0x1b : return "DVD+R recordable";
1463 case 0x20 : return "DDCD readonly";
1464 case 0x21 : return "DDCD-R recodable";
1465 case 0x22 : return "DDCD-RW rewritable";
1466 case 0x2b : return "DVD+R double layer";
1467 case 0x40 : return "BD-ROM";
1468 case 0x41 : return "BD-R Sequential Recording (SRM)";
1469 case 0x42 : return "BD-R Random Recording (RRM)";
1470 case 0x43 : return "BD-RE rewritable";
1471 }
1472 sprintf(scrap, "Reserved profile 0x%02x", profile);
1473 return scrap;
1474 }
1475
1476
udf_dump_discinfo(struct udf_discinfo * disc)1477 void udf_dump_discinfo(struct udf_discinfo *disc) {
1478 int session;
1479
1480 printf("Disc info for disc in device %s\n", disc->dev->dev_name);
1481 printf("\tMMC profile : %s\n", print_mmc_profile(disc->mmc_profile));
1482 printf("\tsequential : %s\n", disc->sequential ?"yes":" no");
1483 printf("\trecordable : %s\n", disc->recordable ?"yes":" no");
1484 printf("\terasable : %s\n", disc->erasable ?"yes":" no");
1485 printf("\tblankable : %s\n", disc->blankable ?"yes":" no");
1486 printf("\tformattable : %s\n", disc->formattable ?"yes":" no");
1487 printf("\trewritable : %s\n", disc->rewritable ?"yes":" no");
1488 printf("\tmount raineer : %s\n", disc->mrw ?"yes":" no");
1489 printf("\tpacket writing : %s\n", disc->packet ?"yes":" no");
1490 printf("\tstrict overwrite : %s\n", disc->strict_overwrite ?"yes":" no");
1491 printf("\tblocking number : %d\n", disc->blockingnr);
1492 printf("\tdisc state : %s\n", print_disc_state(disc->disc_state));
1493 printf("\tlast session state : %s\n", print_session_state(disc->last_session_state));
1494 printf("\tsectorsize : %d\n", disc->sector_size);
1495 printf("\tNumber of sessions %d\n", disc->num_sessions);
1496 for (session = 0; session < disc->num_sessions; session++) {
1497 printf("\tSession %d\n", session);
1498 printf("\t\tstart at %u\n", (uint32_t) disc->session_start[session]);
1499 printf("\t\tends at %u\n", (uint32_t) disc->session_end[session]);
1500 printf("\t\tlength for %u\n", (uint32_t) (disc->session_end[session] - disc->session_start[session]));
1501 printf("\t\tnext writable at %u\n", disc->next_writable[session]);
1502 printf("\t\tfree blocks %u\n", disc->free_blocks[session]);
1503 printf("\t\tpacket size %u\n", disc->packet_size[session]);
1504 printf("\n");
1505 }
1506 }
1507
1508 /* end of udf_verbose.c */
1509
1510