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