scripts

misc scripts and tools
git clone git://git.2f30.org/scripts
Log | Files | Refs

isofix.c (9760B)


      1 /******************************************************/
      2 /*                                                    */
      3 /*            ISO start LBA fixing utility            */
      4 /*                                                    */
      5 /* This tool will take an ISO image with PVD pointing */
      6 /* to bad DR offset and add padding data so actual DR */
      7 /* gets located in right absolute address.            */
      8 /*                                                    */
      9 /* Original boot area, PVD, SVD and VDT are copied to */
     10 /* the start of new, fixed ISO image.                 */
     11 /*                                                    */
     12 /* Supported input image formats are: 2048, 2336,     */
     13 /* 2352 and 2056 bytes per sector. All of them are    */
     14 /* converted to 2048 bytes per sector when writing    */
     15 /* excluding 2056 format which is needed by Mac users.*/
     16 /*                                                    */
     17 /******************************************************/
     18 
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include "isofix.h"
     24 
     25 
     26 int main( int argc, char **argv )
     27 {
     28 	int sector_size = 2048, mode = 1;
     29 	long image_length, remaining_length, progress, last_pos, start_lba, i;
     30 	char lba_parameter = 0;
     31 
     32 	char destfname[256];
     33 	char string[256];
     34 	char buffer[4096];
     35 
     36 	struct opts_s opts = { false, false, false, false, false };
     37 
     38 	FILE *fsource, *fdest, *fboot, *fheader;
     39 
     40 
     41 printf("ISO LBA fixer 1.3 - (C) 2001 by DeXT\n\n");
     42 
     43 // process command line
     44 
     45 strcpy(destfname,"fixed.iso");
     46 
     47 if (argc < 2)
     48    opts.askforimage = true;
     49 else
     50    {
     51    for (i = 1; i < argc; i++)
     52        {
     53        if (atol(argv[i]) <= 0)    // not a number, or negative one
     54           {
     55           if (!stricmp(argv[i], "/boot"))
     56              {
     57              opts.extractbootonly = true;
     58              if (i == 1) opts.askforimage = true;
     59              }
     60           else if (!stricmp(argv[i], "/header"))
     61              {
     62              opts.extractheaderonly = true;
     63              if (i == 1) opts.askforimage = true;
     64              }
     65           else if (!stricmp(argv[i], "/mac"))
     66              {
     67              opts.macformat = true;
     68              if (i == 1) opts.askforimage = true;
     69              }
     70           else if (!stricmp(argv[i], "/iso"))
     71              {
     72              opts.isoformat = true;
     73              if (i == 1) opts.askforimage = true;
     74              }
     75           else
     76              {
     77              if (i == 1) strcpy(string, argv[i]);
     78              else strcpy(destfname, argv[i]);
     79              }
     80           }
     81        else lba_parameter = i;
     82        }
     83    }
     84 
     85 if (opts.askforimage == true)
     86    {
     87    printf("\nPlease enter name of image to fix (Return to exit): ");
     88    gets(string);
     89    if (strlen(string) == 0) exit(1);
     90    }
     91 
     92 printf("Processing file: '%s'\n",string);
     93 
     94 fsource = fopen(string,"rb");
     95 
     96 if (fsource == NULL) { printf("Image not found!"); exit(1); }
     97 
     98 fseek(fsource, 0L, SEEK_END);
     99 image_length = ftell(fsource);
    100 fseek(fsource, 0L, SEEK_SET);
    101 
    102 // detect format
    103 
    104 printf("Scanning image...\n");
    105 
    106 fread(buffer, 1, 16, fsource);
    107 if (!memcmp(SYNC_DATA, buffer, 12)) // raw (2352)
    108    {
    109    sector_size = 2352;
    110    switch(buffer[15])
    111          {
    112          case 2: mode = 2; break;
    113          case 1: mode = 1; break;
    114          default: { printf("Unsupported track mode (%d)", buffer[15]); exit (1); }
    115          }
    116    if (seek_pvd(buffer, 2352, mode, fsource) == 0) { printf("Could not find PVD!\n"); exit(1); }
    117    }
    118 else if (seek_pvd(buffer, 2048, 1, fsource))
    119    {
    120    sector_size = 2048;
    121    mode = 1;
    122    }
    123 else if (seek_pvd(buffer, 2336, 2, fsource))
    124    {
    125    sector_size = 2336;
    126    mode = 2;
    127    }
    128 else if (seek_pvd(buffer, 2056, 2, fsource))
    129    {
    130    sector_size = 2056;
    131    mode = 2;
    132    opts.macformat = true;
    133    }
    134 else { printf("Could not find PVD!\n"); exit(1); }
    135 
    136 if (opts.isoformat == true) opts.macformat = false;
    137 
    138 printf("sector size = %d, mode = %d\n", sector_size, mode);
    139 
    140 if (opts.extractbootonly == false && opts.extractheaderonly == false)
    141    {
    142    if (lba_parameter != 0)
    143       start_lba = atol(argv[lba_parameter]);
    144    else
    145       {
    146       printf("\nPlease enter starting LBA value: ");
    147       gets(string);
    148       start_lba = atol(string);
    149       if (start_lba <= 0) { printf("Bad LBA value"); exit(1); }
    150       }
    151 
    152    printf("Creating destination file '%s'...\n",destfname);
    153    fdest = fopen(destfname, "wb");
    154    if (fdest == NULL) { printf("Can't open destination file!"); exit(1); }
    155    }
    156 
    157 if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
    158    {
    159    printf("Saving boot area to file 'bootfile.bin'...\n");
    160    fboot = fopen("bootfile.bin", "wb");
    161    }
    162 if (opts.extractbootonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
    163    {
    164    printf("Saving ISO header to file 'header.iso'...\n");
    165    fheader = fopen("header.iso", "wb");
    166    }
    167 
    168 // save boot area
    169 
    170 fseek(fsource, 0L, SEEK_SET);
    171 for (i = 0; i < 16 ; i++)
    172     {
    173     sector_read(buffer, sector_size, mode, fsource);
    174     if (opts.extractbootonly == false && opts.extractheaderonly == false)
    175        {
    176        if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
    177        fwrite(buffer, 2048, 1, fdest);
    178        }
    179     if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
    180        {
    181        if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fboot);
    182        fwrite(buffer, 2048, 1, fboot);
    183        }
    184     if (opts.extractbootonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
    185        {
    186        if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
    187        fwrite(buffer, 2048, 1, fheader);
    188        }
    189     }
    190 
    191 if (opts.extractheaderonly == false || (opts.extractheaderonly == true && opts.extractbootonly == true))
    192    fclose(fboot);
    193 if (opts.extractbootonly == true && opts.extractheaderonly == false) exit(0); // boot saved, exit
    194 
    195 // seek & copy pvd etc.
    196 
    197 last_pos = ftell(fsource); // start of pvd
    198 
    199 do {
    200    sector_read(buffer, sector_size, mode, fsource);
    201 
    202    if      (!memcmp(PVD_STRING, buffer, 8)) { printf("Found PVD at sector %ld\n", last_pos/sector_size); }
    203    else if (!memcmp(SVD_STRING, buffer, 8)) { printf("Found SVD at sector %ld\n", last_pos/sector_size); }
    204    else if (!memcmp(VDT_STRING, buffer, 8)) { printf("Found VDT at sector %ld\n", last_pos/sector_size); opts.last_vd = true; }
    205    else    { printf("Error: Found unknown Volume Descriptor"); exit(1); }
    206 
    207    if (opts.extractbootonly == false && opts.extractheaderonly == false)
    208       {
    209       if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
    210       fwrite(buffer, 2048, 1, fdest);
    211       }
    212    if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
    213    fwrite(buffer, 2048, 1, fheader);
    214    last_pos = ftell(fsource);
    215    }
    216    while (opts.last_vd == false);
    217 
    218 // add padding data to header file
    219 
    220 for(i = 0; i < (long)sizeof(buffer); i++)  // clear buffer
    221    buffer[i] = 0;
    222 
    223 remaining_length = 300 - (last_pos/sector_size);
    224 for(i = 0; i < remaining_length; i++)
    225    {
    226    if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fheader);
    227    fwrite(buffer, 2048, 1, fheader);
    228    }
    229 
    230 fclose(fheader);
    231 if (opts.extractheaderonly == true) exit(0); // header saved, exit
    232 
    233 // add padding data to iso image
    234 
    235 if (last_pos > start_lba*sector_size)
    236    { printf("Sorry, LBA value is too small...\nIt should be at least %d for current ISO image (probably greater)", last_pos/sector_size); exit(1); }
    237 if (start_lba < 11700)
    238    printf("Warning! LBA value should be greater or equal to 11700 for multisession images\n");
    239 
    240 printf("Adding padding data up to start LBA value...");
    241 
    242 remaining_length = start_lba - (last_pos/sector_size);
    243 
    244 printf("   ");
    245 for(i = 0; i < remaining_length; i++)
    246    {
    247    if (!(i%512))
    248       {
    249       progress = i*100/remaining_length;
    250       printf("\b\b\b%02d%%", progress);
    251       }
    252    if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
    253    if (!fwrite(buffer, 2048, 1, fdest))  { printf("\nCan't write file! (disk full?)"); exit(1); }
    254    }
    255 printf("\b\b\b   \b\b\b");
    256 
    257 printf("Done!\n");
    258 
    259 // append original iso image
    260 
    261 printf("Appending ISO image...");
    262 
    263 fseek(fsource, 0L, SEEK_SET);
    264 
    265 remaining_length = image_length/sector_size;
    266 
    267 printf("   ");
    268 for(i = 0; i < remaining_length; i++)
    269    {
    270    if (!(i%512))
    271       {
    272       progress = i*100/remaining_length;
    273       printf("\b\b\b%02d%%", progress);
    274       }
    275       if (!sector_read(buffer, sector_size, mode, fsource)) { printf("\nCan't read image!"); exit(1); }
    276       if (opts.macformat == true) fwrite (SUB_HEADER, 8, 1, fdest);
    277       if (!fwrite(buffer, 2048, 1, fdest))  { printf("\nCan't write file! (disk full?)"); exit(1); }
    278    }
    279 printf("\b\b\b   \b\b\b");
    280 
    281 printf("Done!\n");
    282 
    283 printf("\nImage is now fixed!\n");
    284 
    285 fclose(fsource);
    286 fclose(fdest);
    287 
    288 return 0;
    289 }
    290 
    291 
    292 //////////////////////////////////////////////////////////////////////////////
    293 
    294 // seek_pvd() will search for valid PVD in sector 16 of source image
    295 
    296 int seek_pvd(char *buffer, int sector_size, int mode, FILE *fsource)
    297 {
    298    fseek(fsource, 0L, SEEK_SET);   
    299    fseek(fsource, 16*sector_size, SEEK_CUR);              // boot area
    300    if (sector_size == 2352) fseek(fsource, 16, SEEK_CUR); // header
    301    if (mode == 2) fseek(fsource, 8, SEEK_CUR);            // subheader
    302    fread(buffer, 1, 8, fsource);
    303    if (!memcmp(PVD_STRING, buffer, 8)) return 1;
    304 
    305 return 0;
    306 }
    307 
    308 // sector_read() will put user data into buffer no matter the source format
    309 
    310 int sector_read(char *buffer, int sector_size, int mode, FILE *fsource)
    311 {
    312 int status;
    313 
    314    if (sector_size == 2352) fseek(fsource, 16, SEEK_CUR); // header
    315    if (mode == 2) fseek(fsource, 8, SEEK_CUR);            // subheader
    316    status = fread(buffer, 2048, 1, fsource);
    317    if (sector_size >= 2336)
    318       {
    319       fseek(fsource, 280, SEEK_CUR);
    320       if (mode == 1) fseek(fsource, 8, SEEK_CUR);
    321       }
    322 
    323 return status;
    324 }
    325