Advertisement
MSM

ISO Can Parse

MSM
Aug 24th, 2012
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.44 KB | None | 0 0
  1. /*                         Created by MSM                              */
  2. /* Licensed under a Creative Commons Attribution 3.0 Unported License. */
  3.  
  4. /*          Parse and dump .iso files                      */
  5.  
  6. #include <stdlib.h>         // screw it
  7. #include <string.h>         // screw char*s
  8. #include <stdint.h>         // screw ints
  9. #include <stdbool.h>        // screw ints
  10. #include <stdio.h>          // screw iostream
  11. #include <stdarg.h>         // screw good code
  12. #include <io.h>             // screw portability
  13.  
  14. #define RESERVED(X) _reserved ## X
  15. #define UNUSED(X) ((void)(X))
  16.  
  17. #pragma pack(1)
  18.  
  19. const size_t sector_size = 0x800;
  20. const unsigned ignored_sectors = 0x10;
  21.  
  22. struct date_time_t;
  23. struct directory_record_t;
  24. struct volume_descriptor_common_t;
  25. struct volume_descriptor_generic_t;
  26. struct boot_descriptor_t;
  27. struct primary_descriptor_t;
  28. enum dir_flags;
  29. enum volume_type;
  30.  
  31. void iso_dump_record_list(FILE *image, const char *relpath, int sector, size_t size);
  32. void iso_dump_record(FILE *image, const char *relpath, const struct directory_record_t *current, bool recorsive);
  33. void iso_dump_file(FILE *image, const char *relpath, int sector, size_t size);
  34. void iso_dump_descriptor(FILE *image, struct volume_descriptor_generic_t *desc);
  35. void iso_dump_primary_descriptor(FILE *image, struct primary_descriptor_t *desc);
  36. void iso_dump_boot_descriptor(FILE *image, struct boot_descriptor_t *desc);
  37. void iso_inspect_descriptors(FILE *image);
  38.  
  39. const char *record_get_hr_name(const struct directory_record_t *record);
  40. void record_free_hr_name(const char *name);
  41.  
  42. const char *path_combine(const char *dir, const char *sub);
  43. void path_free(const char *path);
  44.  
  45. void fread_at(void *ptr, fpos_t from, size_t bytes, FILE *file);
  46.  
  47. void iprintf(char *fmt, ...);
  48. void iindent();
  49. void iundent();
  50. void isetstr(const char *new_indent_str);
  51.  
  52. enum dir_flags {
  53.     df_hidden = 0x01,
  54.     df_directory = 0x02,
  55.     df_associated = 0x04,
  56.     df_format_specified = 0x08,
  57.     df_permissions_specified = 0x10,
  58.     df_continue = 0x80
  59. };
  60.  
  61. enum volume_type {
  62.     vt_boot_descriptor,
  63.     vt_primary_descriptor,
  64.     vt_supplementart_descriptor,
  65.     vt_partition_descriptor,
  66.     vt_end = 0xFF
  67. };
  68.  
  69. struct date_time_t {
  70.     uint8_t years;
  71.     uint8_t month;
  72.     uint8_t day;
  73.     uint8_t hour;
  74.     uint8_t minute;
  75.     uint8_t second;
  76.     int8_t greenwich_offset;
  77. };
  78.  
  79. struct directory_record_t {
  80.     uint8_t length;
  81.     uint8_t ext_attrib_length;
  82.     uint32_t extent_le;
  83.     uint32_t extent_be;
  84.     uint32_t data_length_le;
  85.     uint32_t data_length_be;
  86.     struct date_time_t recording_time;
  87.     uint8_t flags;
  88.     uint8_t file_unit_size;
  89.     uint8_t interleave_gap_size;
  90.     uint32_t volume_seq_number;
  91.     uint8_t file_id_length;
  92.     char file_id[];
  93. };
  94.  
  95. struct volume_descriptor_common_t {
  96.     uint8_t type;
  97.     char magic[5];
  98.     uint8_t version;
  99. };
  100.  
  101. struct volume_descriptor_generic_t {
  102.     struct volume_descriptor_common_t volume_data;
  103.     char RESERVED(0)[2041];
  104. };
  105.  
  106. struct boot_descriptor_t {
  107.     struct volume_descriptor_common_t volume_data;
  108.     char boot_system_id[32];
  109.     char boot_id[32];
  110.     char boot_system_use[1976];
  111. };
  112.  
  113. struct primary_descriptor_t {
  114.     struct volume_descriptor_common_t volume_data;
  115.     uint8_t RESERVED(0);
  116.     char system_id[32];
  117.     char volume_id[32];
  118.     char RESERVED(1)[8];
  119.     uint64_t volume_space_size;
  120.     char RESERVED(2)[32];
  121.     uint32_t volume_set_size;
  122.     uint32_t volume_seq_number;
  123.     uint16_t logical_block_size_le;
  124.     uint16_t logical_block_size_be;
  125.     uint64_t path_table_size;
  126.     uint32_t path_table_l_occurence;
  127.     uint32_t path_table_l_optional_occurence;
  128.     uint32_t path_table_m_occurence;
  129.     uint32_t path_table_m_optional_occurence;
  130.     struct directory_record_t root_directory;
  131.     char ignored_rest[];
  132. };
  133.  
  134. void fread_at(void *ptr, fpos_t from, size_t bytes, FILE *file) {
  135.     fpos_t old_pos = ftell(file);
  136.     fseek(file, from, SEEK_SET);
  137.     fread(ptr, bytes, 1, file);
  138.     fseek(file, old_pos, SEEK_SET);
  139. }
  140.  
  141. const char *record_get_hr_name(const struct directory_record_t *record) {
  142.     static const int self_dir_id = 0;
  143.     static const int parent_dir_id = 1;
  144.  
  145.     size_t name_len;
  146.     const char *name;
  147.     if (record->file_id[0] == self_dir_id) {
  148.         name_len = 1;
  149.         name = ".";
  150.     } else if (record->file_id[0] == parent_dir_id) {
  151.         name_len = 2;
  152.         name = "..";
  153.     } else {
  154.         name_len = record->file_id_length;
  155.         name = record->file_id;
  156.        
  157.         for(int i = 0; i < (int)name_len; i++) {
  158.             if (name[i] == ';') {
  159.                 name_len = i;
  160.                 break;
  161.             }
  162.         }
  163.  
  164.         if (name[name_len - 1] == '.') {
  165.             name_len--;
  166.         }
  167.     }
  168.  
  169.     char *dyn_name = malloc(name_len + 1);
  170.     sprintf(dyn_name, "%.*s", name_len, name);
  171.  
  172.     return dyn_name;
  173. }
  174.  
  175. void record_free_hr_name(const char *record_name) {
  176.     free((char*)record_name);
  177. }
  178.  
  179. const char *path_combine(const char *dir, const char *sub) {
  180.     int dir_len = strlen(dir);
  181.     static const int slash_len = 1;
  182.     int sub_len = strlen(sub);
  183.     int total_len = dir_len + slash_len + sub_len;
  184.  
  185.     char *memory = malloc(total_len + 1);
  186.  
  187.     strcpy(memory, dir);
  188.     memory[dir_len] = '/';
  189.     strcpy(memory + dir_len + 1, sub);
  190.     memory[total_len] = 0;
  191.  
  192.     return memory;
  193. }
  194.  
  195. void path_free(const char *path) {
  196.     free((char*)path);
  197. }
  198.  
  199. unsigned iindent_level; // Teh ugly global variables
  200. const char *iindent_str;
  201.  
  202. void iindent() {
  203.     iindent_level++;
  204. }
  205.  
  206. void iundent() {
  207.     iindent_level--;
  208. }
  209.  
  210. void isetstr(const char *new_indent_str) {
  211.     iindent_str = new_indent_str;
  212. }
  213.  
  214. void iprintf(char *fmt, ...) {
  215.     for(int i = 0; i < (int)iindent_level; i++) {
  216.         printf(iindent_str);
  217.     }
  218.    
  219.     va_list args;
  220.     va_start(args, fmt);
  221.     vprintf(fmt, args);
  222.     va_end(args);
  223. }
  224.  
  225. void iso_dump_file(FILE *image, const char *relpath, int sector, size_t data_size) {
  226.     FILE *newf = fopen(relpath, "wb");
  227.  
  228.     uint8_t *const file_data = malloc(data_size);
  229.     fread_at(file_data, sector * sector_size, data_size, image);
  230.  
  231.     fwrite(file_data, data_size, 1, newf);
  232.  
  233.     fclose(newf);
  234. }
  235.  
  236. void iso_dump_record_list(FILE *image, const char *relpath, int sector, size_t data_size) {
  237.     uint8_t *const sector_data = malloc(sector_size);
  238.     fread_at(sector_data, sector * sector_size, data_size, image);
  239.    
  240.     mkdir(relpath);
  241.  
  242.     uint8_t *current_record_ptr = sector_data;
  243.     struct directory_record_t *current = (struct directory_record_t*)current_record_ptr;
  244.  
  245.     for(int ndx = 0; current->length != 0; ndx++) {
  246.         iso_dump_record(image, relpath, current, ndx > 1);
  247.  
  248.         current_record_ptr += current->length;
  249.         current = (struct directory_record_t*)current_record_ptr;
  250.     }
  251.  
  252.     free(sector_data);
  253. }
  254.  
  255. void iso_dump_record(FILE *image, const char *relpath, const struct directory_record_t *current, bool recursive) {
  256.     const char *name = record_get_hr_name(current);
  257.     bool is_dir = current->flags & df_directory;
  258.  
  259.     iprintf("- %s%s%s\n",
  260.             is_dir ? "[" : "",
  261.             name,
  262.             is_dir ? "]" : "");
  263.  
  264.     if (recursive) {
  265.         iindent();
  266.         const char *childpath = path_combine(relpath, name);
  267.  
  268.         if (is_dir) {
  269.             iso_dump_record_list(image, childpath, current->extent_le, current->data_length_le);
  270.         } else {
  271.             iso_dump_file(image, childpath, current->extent_le, current->data_length_le);
  272.         }
  273.  
  274.         path_free(childpath);
  275.         iundent();
  276.     }
  277.  
  278.     record_free_hr_name(name);
  279. }
  280.  
  281. void iso_dump_boot_descriptor(FILE *image, struct boot_descriptor_t *desc) {
  282.     UNUSED(image);
  283.  
  284.     iprintf("Known Type: Boot Descriptor\n");
  285.     iprintf("Boot System ID: %.32s\n", desc->boot_system_id);
  286.     iprintf("Boot ID: %.32s\n", desc->boot_id);
  287. }
  288.  
  289. void iso_dump_primary_descriptor(FILE *image, struct primary_descriptor_t *desc) {
  290.     iprintf("Known Type: Primary Descriptor\n");
  291.     iprintf("System ID: %.32s\n", desc->system_id);
  292.     iprintf("Volume ID: %.32s\n", desc->volume_id);
  293.     iprintf("Logical Block Size: %x\n", desc->logical_block_size_le);
  294.     iprintf("Filesystem Dump\n");
  295.  
  296.     iso_dump_record(image, "Root", &desc->root_directory, true);
  297. }
  298.  
  299. void iso_dump_descriptor(FILE *image, struct volume_descriptor_generic_t *desc) {
  300.     struct volume_descriptor_common_t common = desc->volume_data;
  301.     printf("\nFound Descriptor <type=%X> <magic=%.5s> <version=%X>\n",
  302.             common.type, common.magic, common.version);
  303.  
  304.     isetstr("    ");
  305.     iindent();
  306.     if (common.type == vt_primary_descriptor) {
  307.         iso_dump_primary_descriptor(image, (struct primary_descriptor_t*)desc);
  308.     } else if (common.type == vt_boot_descriptor) {
  309.         iso_dump_boot_descriptor(image, (struct boot_descriptor_t*)desc);
  310.     }
  311.     iundent();
  312. }
  313.  
  314. void iso_inspect_descriptors(FILE *image) {
  315.     struct volume_descriptor_generic_t generic_desc;
  316.    
  317.     fseek(image, ignored_sectors * sector_size, SEEK_SET);
  318.     do  {
  319.         fread(&generic_desc, sizeof(generic_desc), 1, image);
  320.         iso_dump_descriptor(image, &generic_desc);
  321.     } while(generic_desc.volume_data.type != vt_end);
  322. }
  323.  
  324. int main() {
  325.     FILE *test = fopen("iso.iso", "rb");
  326.     iso_inspect_descriptors(test);
  327.  
  328.     return 0;
  329. }
  330.  
  331. /* You might also want to have a look at (my forum post, in polish)
  332.    http://forum.4programmers.net/Newbie/203080-montowanie_obrazow_plyt?p=874744#id874744
  333. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement