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