1/* $NetBSD: cd9660_debug.c,v 1.14 2023/12/28 12:13:55 tsutsui Exp $ */ 2 3/* 4 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan 5 * Perez-Rathke and Ram Vedam. All rights reserved. 6 * 7 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys, 8 * Alan Perez-Rathke and Ram Vedam. 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN 21 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN 25 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 28 * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 * OF SUCH DAMAGE. 33 */ 34 35#if HAVE_NBTOOL_CONFIG_H 36#include "nbtool_config.h" 37#endif 38 39#include <sys/cdefs.h> 40#include <sys/param.h> 41 42#if defined(__RCSID) && !defined(__lint) 43__RCSID("$NetBSD: cd9660_debug.c,v 1.14 2023/12/28 12:13:55 tsutsui Exp $"); 44#endif /* !__lint */ 45 46#if !HAVE_NBTOOL_CONFIG_H 47#include <sys/mount.h> 48#endif 49 50#include "makefs.h" 51#include "cd9660.h" 52#include "iso9660_rrip.h" 53 54static void debug_print_susp_attrs(cd9660node *, int); 55static void debug_dump_to_xml_padded_hex_output(const char *, unsigned char *, 56 int); 57 58static inline void 59print_n_tabs(int n) 60{ 61 int i; 62 63 for (i = 1; i <= n; i ++) 64 printf("\t"); 65} 66 67#if 0 68void 69debug_print_rrip_info(n) 70cd9660node *n; 71{ 72 struct ISO_SUSP_ATTRIBUTES *t; 73 TAILQ_FOREACH(t, &node->head, rr_ll) { 74 75 } 76} 77#endif 78 79static void 80debug_print_susp_attrs(cd9660node *n, int indent) 81{ 82 struct ISO_SUSP_ATTRIBUTES *t; 83 84 TAILQ_FOREACH(t, &n->head, rr_ll) { 85 print_n_tabs(indent); 86 printf("-"); 87 printf("%c%c: L:%i",t->attr.su_entry.SP.h.type[0], 88 t->attr.su_entry.SP.h.type[1], 89 (int)t->attr.su_entry.SP.h.length[0]); 90 printf("\n"); 91 } 92} 93 94void 95debug_print_tree(iso9660_disk *diskStructure, cd9660node *node, int level) 96{ 97#if !HAVE_NBTOOL_CONFIG_H 98 cd9660node *cn; 99 100 print_n_tabs(level); 101 if (node->type & CD9660_TYPE_DOT) { 102 printf(". (%i)\n", 103 isonum_733(node->isoDirRecord->extent)); 104 } else if (node->type & CD9660_TYPE_DOTDOT) { 105 printf("..(%i)\n", 106 isonum_733(node->isoDirRecord->extent)); 107 } else if (node->isoDirRecord->name[0]=='\0') { 108 printf("(ROOT) (%" PRIu32 " to %" PRId64 ")\n", 109 node->fileDataSector, 110 node->fileDataSector + 111 node->fileSectorsUsed - 1); 112 } else { 113 printf("%s (%s) (%" PRIu32 " to %" PRId64 ")\n", 114 node->isoDirRecord->name, 115 (node->isoDirRecord->flags[0] 116 & ISO_FLAG_DIRECTORY) ? "DIR" : "FILE", 117 node->fileDataSector, 118 (node->fileSectorsUsed == 0) ? 119 node->fileDataSector : 120 node->fileDataSector 121 + node->fileSectorsUsed - 1); 122 } 123 if (diskStructure->rock_ridge_enabled) 124 debug_print_susp_attrs(node, level + 1); 125 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) 126 debug_print_tree(diskStructure, cn, level + 1); 127#else 128 printf("Sorry, debugging is not supported in host-tools mode.\n"); 129#endif 130} 131 132void 133debug_print_path_tree(cd9660node *n) 134{ 135 cd9660node *iterator = n; 136 137 /* Only display this message when called with the root node */ 138 if (n->parent == NULL) 139 printf("debug_print_path_table: Dumping path table contents\n"); 140 141 while (iterator != NULL) { 142 if (iterator->isoDirRecord->name[0] == '\0') 143 printf("0) (ROOT)\n"); 144 else 145 printf("%i) %s\n", iterator->level, 146 iterator->isoDirRecord->name); 147 148 iterator = iterator->ptnext; 149 } 150} 151 152void 153debug_print_volume_descriptor_information(iso9660_disk *diskStructure) 154{ 155 volume_descriptor *tmp = diskStructure->firstVolumeDescriptor; 156 char temp[CD9660_SECTOR_SIZE]; 157 158 printf("==Listing Volume Descriptors==\n"); 159 160 while (tmp != NULL) { 161 memset(temp, 0, CD9660_SECTOR_SIZE); 162 memcpy(temp, tmp->volumeDescriptorData + 1, 5); 163 printf("Volume descriptor in sector %" PRId64 164 ": type %i, ID %s\n", 165 tmp->sector, tmp->volumeDescriptorData[0], temp); 166 switch(tmp->volumeDescriptorData[0]) { 167 case 0:/*boot record*/ 168 break; 169 170 case 1: /* PVD */ 171 break; 172 173 case 2: /* SVD */ 174 break; 175 176 case 3: /* Volume Partition Descriptor */ 177 break; 178 179 case 255: /* terminator */ 180 break; 181 } 182 tmp = tmp->next; 183 } 184 185 printf("==Done Listing Volume Descriptors==\n"); 186} 187 188void 189debug_dump_to_xml_ptentry(path_table_entry *pttemp, int num, int mode) 190{ 191 printf("<ptentry num=\"%i\">\n" ,num); 192 printf("<length>%i</length>\n", pttemp->length[0]); 193 printf("<extended_attribute_length>%i</extended_attribute_length>\n", 194 pttemp->extended_attribute_length[0]); 195 printf("<parent_number>%i</parent_number>\n", 196 debug_get_encoded_number(pttemp->parent_number,mode)); 197 debug_dump_to_xml_padded_hex_output("name", 198 pttemp->name, pttemp->length[0]); 199 printf("</ptentry>\n"); 200} 201 202void 203debug_dump_to_xml_path_table(FILE *fd, off_t sector, int size, int mode) 204{ 205 path_table_entry pttemp; 206 int t = 0; 207 int n = 0; 208 209 if (fseeko(fd, CD9660_SECTOR_SIZE * sector, SEEK_SET) == -1) 210 err(EXIT_FAILURE, "fseeko"); 211 212 while (t < size) { 213 /* Read fixed data first */ 214 fread(&pttemp, 1, 8, fd); 215 t += 8; 216 /* Read variable */ 217 fread(((unsigned char*)&pttemp) + 8, 1, pttemp.length[0], fd); 218 t += pttemp.length[0]; 219 debug_dump_to_xml_ptentry(&pttemp, n, mode); 220 n++; 221 } 222 223} 224 225/* 226 * XML Debug output functions 227 * Dump hierarchy of CD, as well as volume info, to XML 228 * Can be used later to diff against a standard, 229 * or just provide easy to read detailed debug output 230 */ 231void 232debug_dump_to_xml(FILE *fd) 233{ 234 unsigned char buf[CD9660_SECTOR_SIZE]; 235 off_t sector; 236 int t, t2; 237 struct iso_primary_descriptor primaryVD; 238 struct _boot_volume_descriptor bootVD; 239 240 memset(&primaryVD, 0, sizeof(primaryVD)); 241 printf("<cd9660dump>\n"); 242 243 /* Display Volume Descriptors */ 244 sector = 16; 245 do { 246 if (fseeko(fd, CD9660_SECTOR_SIZE * sector, SEEK_SET) == -1) 247 err(EXIT_FAILURE, "fseeko"); 248 fread(buf, 1, CD9660_SECTOR_SIZE, fd); 249 t = (int)((unsigned char)buf[0]); 250 switch (t) { 251 case 0: 252 memcpy(&bootVD, buf, CD9660_SECTOR_SIZE); 253 break; 254 case 1: 255 memcpy(&primaryVD, buf, CD9660_SECTOR_SIZE); 256 break; 257 } 258 debug_dump_to_xml_volume_descriptor(buf, sector); 259 sector++; 260 } while (t != 255); 261 262 t = debug_get_encoded_number((u_char *)primaryVD.type_l_path_table, 263 731); 264 t2 = debug_get_encoded_number((u_char *)primaryVD.path_table_size, 733); 265 printf("Path table 1 located at sector %i and is %i bytes long\n", 266 t,t2); 267 debug_dump_to_xml_path_table(fd, t, t2, 721); 268 269 t = debug_get_encoded_number((u_char *)primaryVD.type_m_path_table, 270 731); 271 debug_dump_to_xml_path_table(fd, t, t2, 722); 272 273 printf("</cd9660dump>\n"); 274} 275 276static void 277debug_dump_to_xml_padded_hex_output(const char *element, unsigned char *buf, 278 int len) 279{ 280 int i; 281 int t; 282 283 printf("<%s>",element); 284 for (i = 0; i < len; i++) { 285 t = (unsigned char)buf[i]; 286 if (t >= 32 && t < 127) 287 printf("%c",t); 288 } 289 printf("</%s>\n",element); 290 291 printf("<%s:hex>",element); 292 for (i = 0; i < len; i++) { 293 t = (unsigned char)buf[i]; 294 printf(" %x",t); 295 } 296 printf("</%s:hex>\n",element); 297} 298 299int 300debug_get_encoded_number(unsigned char* buf, int mode) 301{ 302#if !HAVE_NBTOOL_CONFIG_H 303 switch (mode) { 304 /* 711: Single bite */ 305 case 711: 306 return isonum_711(buf); 307 308 /* 712: Single signed byte */ 309 case 712: 310 return isonum_712((signed char *)buf); 311 312 /* 721: 16 bit LE */ 313 case 721: 314 return isonum_721(buf); 315 316 /* 731: 32 bit LE */ 317 case 731: 318 return isonum_731(buf); 319 320 /* 722: 16 bit BE */ 321 case 722: 322 return isonum_722(buf); 323 324 /* 732: 32 bit BE */ 325 case 732: 326 return isonum_732(buf); 327 328 /* 723: 16 bit bothE */ 329 case 723: 330 return isonum_723(buf); 331 332 /* 733: 32 bit bothE */ 333 case 733: 334 return isonum_733(buf); 335 } 336#endif 337 return 0; 338} 339 340void 341debug_dump_integer(const char *element, char* buf, int mode) 342{ 343 printf("<%s>%i</%s>\n", element, 344 debug_get_encoded_number((unsigned char *)buf, mode), element); 345} 346 347void 348debug_dump_string(const char *element __unused, unsigned char *buf __unused, int len __unused) 349{ 350 351} 352 353void 354debug_dump_directory_record_9_1(unsigned char* buf) 355{ 356 printf("<directoryrecord>\n"); 357 debug_dump_integer("length", 358 ((struct iso_directory_record*) buf)->length, 711); 359 debug_dump_integer("ext_attr_length", 360 ((struct iso_directory_record*) buf)->ext_attr_length,711); 361 debug_dump_integer("extent", 362 (char *)((struct iso_directory_record*) buf)->extent, 733); 363 debug_dump_integer("size", 364 (char *)((struct iso_directory_record*) buf)->size, 733); 365 debug_dump_integer("flags", 366 ((struct iso_directory_record*) buf)->flags, 711); 367 debug_dump_integer("file_unit_size", 368 ((struct iso_directory_record*) buf)->file_unit_size,711); 369 debug_dump_integer("interleave", 370 ((struct iso_directory_record*) buf)->interleave, 711); 371 debug_dump_integer("volume_sequence_number", 372 ((struct iso_directory_record*) buf)->volume_sequence_number, 373 723); 374 debug_dump_integer("name_len", 375 ((struct iso_directory_record*) buf)->name_len, 711); 376 debug_dump_to_xml_padded_hex_output("name", 377 (u_char *)((struct iso_directory_record*) buf)->name, 378 debug_get_encoded_number((u_char *) 379 ((struct iso_directory_record*) buf)->length, 711)); 380 printf("</directoryrecord>\n"); 381} 382 383 384void 385debug_dump_to_xml_volume_descriptor(unsigned char* buf, int sector) 386{ 387 printf("<volumedescriptor sector=\"%i\">\n", sector); 388 printf("<vdtype>"); 389 switch(buf[0]) { 390 case 0: 391 printf("boot"); 392 break; 393 394 case 1: 395 printf("primary"); 396 break; 397 398 case 2: 399 printf("supplementary"); 400 break; 401 402 case 3: 403 printf("volume partition descriptor"); 404 break; 405 406 case 255: 407 printf("terminator"); 408 break; 409 } 410 411 printf("</vdtype>\n"); 412 switch(buf[0]) { 413 case 1: 414 debug_dump_integer("type", 415 ((struct iso_primary_descriptor*)buf)->type, 711); 416 debug_dump_to_xml_padded_hex_output("id", 417 (u_char *)((struct iso_primary_descriptor*) buf)->id, 418 ISODCL ( 2, 6)); 419 debug_dump_integer("version", 420 ((struct iso_primary_descriptor*)buf)->version, 421 711); 422 debug_dump_to_xml_padded_hex_output("system_id", 423 (u_char *)((struct iso_primary_descriptor*)buf)->system_id, 424 ISODCL(9,40)); 425 debug_dump_to_xml_padded_hex_output("volume_id", 426 (u_char *)((struct iso_primary_descriptor*)buf)->volume_id, 427 ISODCL(41,72)); 428 debug_dump_integer("volume_space_size", 429 ((struct iso_primary_descriptor*)buf)->volume_space_size, 430 733); 431 debug_dump_integer("volume_set_size", 432 ((struct iso_primary_descriptor*)buf)->volume_set_size, 433 733); 434 debug_dump_integer("volume_sequence_number", 435 ((struct iso_primary_descriptor*)buf)->volume_sequence_number, 436 723); 437 debug_dump_integer("logical_block_size", 438 ((struct iso_primary_descriptor*)buf)->logical_block_size, 439 723); 440 debug_dump_integer("path_table_size", 441 ((struct iso_primary_descriptor*)buf)->path_table_size, 442 733); 443 debug_dump_integer("type_l_path_table", 444 ((struct iso_primary_descriptor*)buf)->type_l_path_table, 445 731); 446 debug_dump_integer("opt_type_l_path_table", 447 ((struct iso_primary_descriptor*)buf)->opt_type_l_path_table, 448 731); 449 debug_dump_integer("type_m_path_table", 450 ((struct iso_primary_descriptor*)buf)->type_m_path_table, 451 732); 452 debug_dump_integer("opt_type_m_path_table", 453 ((struct iso_primary_descriptor*)buf)->opt_type_m_path_table,732); 454 debug_dump_directory_record_9_1( 455 (u_char *)((struct iso_primary_descriptor*)buf)->root_directory_record); 456 debug_dump_to_xml_padded_hex_output("volume_set_id", 457 (u_char *)((struct iso_primary_descriptor*) buf)->volume_set_id, 458 ISODCL (191, 318)); 459 debug_dump_to_xml_padded_hex_output("publisher_id", 460 (u_char *)((struct iso_primary_descriptor*) buf)->publisher_id, 461 ISODCL (319, 446)); 462 debug_dump_to_xml_padded_hex_output("preparer_id", 463 (u_char *)((struct iso_primary_descriptor*) buf)->preparer_id, 464 ISODCL (447, 574)); 465 debug_dump_to_xml_padded_hex_output("application_id", 466 (u_char *)((struct iso_primary_descriptor*) buf)->application_id, 467 ISODCL (575, 702)); 468 debug_dump_to_xml_padded_hex_output("copyright_file_id", 469 (u_char *)((struct iso_primary_descriptor*) buf)->copyright_file_id, 470 ISODCL (703, 739)); 471 debug_dump_to_xml_padded_hex_output("abstract_file_id", 472 (u_char *)((struct iso_primary_descriptor*) buf)->abstract_file_id, 473 ISODCL (740, 776)); 474 debug_dump_to_xml_padded_hex_output("bibliographic_file_id", 475 (u_char *)((struct iso_primary_descriptor*) buf)->bibliographic_file_id, 476 ISODCL (777, 813)); 477 478 debug_dump_to_xml_padded_hex_output("creation_date", 479 (u_char *)((struct iso_primary_descriptor*) buf)->creation_date, 480 ISODCL (814, 830)); 481 debug_dump_to_xml_padded_hex_output("modification_date", 482 (u_char *)((struct iso_primary_descriptor*) buf)->modification_date, 483 ISODCL (831, 847)); 484 debug_dump_to_xml_padded_hex_output("expiration_date", 485 (u_char *)((struct iso_primary_descriptor*) buf)->expiration_date, 486 ISODCL (848, 864)); 487 debug_dump_to_xml_padded_hex_output("effective_date", 488 (u_char *)((struct iso_primary_descriptor*) buf)->effective_date, 489 ISODCL (865, 881)); 490 491 debug_dump_to_xml_padded_hex_output("file_structure_version", 492 (u_char *)((struct iso_primary_descriptor*) buf)->file_structure_version, 493 ISODCL(882,882)); 494 break; 495 } 496 printf("</volumedescriptor>\n"); 497} 498 499