1 /* dvdisaster: Additional error correction for optical media.
2 * Copyright (C) 2004-2015 Carsten Gnoerlich.
3 *
4 * Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org
5 * Project homepage: http://www.dvdisaster.org
6 *
7 * This file is part of dvdisaster.
8 *
9 * dvdisaster is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * dvdisaster is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "dvdisaster.h"
24
25 #include "udf.h"
26
27 /***
28 *** Rudimentary UDF and ISO filesystem parsing.
29 ***
30 * Information about UDF and ISO was gathered from ECMA-119,
31 * ECMA-167, ECMA-167 and the UDF 2.6 standard from OSTA.org.
32 * However, no claims are made to be actually conformant to any
33 * of those standards.
34 */
35
36 /*
37 * ECMA sector indices start with 1;
38 * this definition make it easier to use the standard for reading strings
39 * from the buffer.
40 * begin and end are the bp postions of the string start and end position.
41 */
42
43 /*
44 * 8bit values
45 */
46
47 #define bp_get_byte(buf, idx) (buf[(idx)-1])
48 #define bp_set_byte(buf, idx, byte) (buf[(idx)-1] = (unsigned char)byte)
49
50 /*
51 * 16bit both byte order
52 */
53
54 #ifdef HAVE_BIG_ENDIAN
55 #define bp_get_short_bbo(buf, idx) (*((guint16*)(buf+idx+1)))
56 #else
57 #define bp_get_short_bbo(buf, idx) (*((guint16*)(buf+idx-1)))
58 #endif
59
bp_set_short_bbo(unsigned char * buf,int idx,guint16 value)60 static void bp_set_short_bbo(unsigned char *buf, int idx, guint16 value)
61 { unsigned char wx = (value >> 8) & 0xff;
62 unsigned char yz = value & 0xff;
63
64 buf = buf + idx - 1;
65 *buf++ = yz;
66 *buf++ = wx;
67 *buf++ = wx;
68 *buf++ = yz;
69 }
70
bp_set_short_lsb(unsigned char * buf,int idx,guint16 value)71 static void bp_set_short_lsb(unsigned char *buf, int idx, guint16 value)
72 { unsigned char wx = (value >> 8) & 0xff;
73 unsigned char yz = value & 0xff;
74
75 buf = buf + idx - 1;
76 *buf++ = yz;
77 *buf++ = wx;
78 }
79
bp_set_short_msb(unsigned char * buf,int idx,guint16 value)80 static void bp_set_short_msb(unsigned char *buf, int idx, guint16 value)
81 { unsigned char wx = (value >> 8) & 0xff;
82 unsigned char yz = value & 0xff;
83
84 buf = buf + idx - 1;
85 *buf++ = wx;
86 *buf++ = yz;
87 }
88
89 /*
90 * 32bit single byte order
91 */
92
93 #ifdef HAVE_BIG_ENDIAN
94 #define bp_get_long_lsb(buf, idx) (((guint32)buf[(idx)+2])<<24|((guint32)buf[(idx)+1])<<16|((guint32)buf[(idx)])<<8|((guint32)buf[(idx)-1]))
95 #else
96 #define bp_get_long_lsb(buf, idx) (*((guint32*)(buf+idx-1)))
97 #endif
98 #define bp_get_long_msb(buf, idx) (((guint32)buf[(idx)-1])<<24|((guint32)buf[idx])<<16|((guint32)buf[(idx)+1])<<8|((guint32)buf[(idx)+2]))
99
bp_set_long_lsb(unsigned char * buf,int idx,guint32 value)100 static void bp_set_long_lsb(unsigned char *buf, int idx, guint32 value)
101 { unsigned char st = (value >> 24) & 0xff;
102 unsigned char uv = (value >> 16) & 0xff;
103 unsigned char wx = (value >> 8) & 0xff;
104 unsigned char yz = value & 0xff;
105
106 buf = buf + idx - 1;
107 *buf++ = yz;
108 *buf++ = wx;
109 *buf++ = uv;
110 *buf++ = st;
111 }
112
bp_set_long_msb(unsigned char * buf,int idx,guint32 value)113 static void bp_set_long_msb(unsigned char *buf, int idx, guint32 value)
114 { unsigned char st = (value >> 24) & 0xff;
115 unsigned char uv = (value >> 16) & 0xff;
116 unsigned char wx = (value >> 8) & 0xff;
117 unsigned char yz = value & 0xff;
118
119 buf = buf + idx - 1;
120 *buf++ = st;
121 *buf++ = uv;
122 *buf++ = wx;
123 *buf++ = yz;
124 }
125
126 /*
127 * 32bit both byte order
128 */
129
130 #ifdef HAVE_BIG_ENDIAN
131 #define bp_get_long_bbo(buf, idx) (*((guint32*)(buf+idx+3)))
132 #else
133 #define bp_get_long_bbo(buf, idx) (*((guint32*)(buf+idx-1)))
134 #endif
135
bp_set_long_bbo(unsigned char * buf,int idx,guint32 value)136 static void bp_set_long_bbo(unsigned char *buf, int idx, guint32 value)
137 { unsigned char st = (value >> 24) & 0xff;
138 unsigned char uv = (value >> 16) & 0xff;
139 unsigned char wx = (value >> 8) & 0xff;
140 unsigned char yz = value & 0xff;
141
142 buf = buf + idx - 1;
143 *buf++ = yz;
144 *buf++ = wx;
145 *buf++ = uv;
146 *buf++ = st;
147 *buf++ = st;
148 *buf++ = uv;
149 *buf++ = wx;
150 *buf++ = yz;
151 }
152
bp_get(unsigned char * dest,unsigned char * src,int begin,int end)153 static void bp_get(unsigned char *dest, unsigned char *src, int begin, int end)
154 { int length = end-begin+1;
155
156 strncpy((char*)dest, (char*)src+begin-1, length);
157 }
158
159 #if 0
160 static void bp_set(unsigned char *dest, unsigned char *src, int begin, int end)
161 { int length = end-begin+1;
162
163 memcpy((char*)dest+begin-1, (char*)src, length);
164 }
165 #endif
166
167 /*
168 * String operations
169 */
170
bp_get_string(unsigned char * dest,unsigned char * src,int begin,int end)171 static void bp_get_string(unsigned char *dest, unsigned char *src, int begin, int end)
172 { int length = end-begin+1;
173
174 strncpy((char*)dest, (char*)src+begin-1, length);
175 dest[length] = 0;
176 }
177
bp_set_string(unsigned char * dest,char * src,int begin,int end)178 static void bp_set_string(unsigned char *dest, char *src, int begin, int end)
179 { int length = end-begin+1;
180
181 strncpy((char*)(dest+begin-1), src, length);
182 }
183
184 /*
185 * D1 string conversion currently simply expands the string to 16bit characters.
186 */
187
bp_set_d1_string(unsigned char * dest,char * src,int begin,int end)188 static void bp_set_d1_string(unsigned char *dest, char *src, int begin, int end)
189 {
190 dest = dest + begin - 1;
191
192 while(begin<=end-2 && *src)
193 { *dest++ = 0;
194 *dest++ = (unsigned char)*src++;
195 begin += 2;
196 }
197 }
198
199 /*
200 * Date values
201 */
202
get_date(unsigned char * date,unsigned char * buf,int idx)203 static void get_date(unsigned char *date, unsigned char *buf, int idx)
204 {
205 idx--;
206 sprintf((char*)date, "dd-mm-yyyy hh:mm:ss.ss");
207 bp_get(date+ 6, buf, idx+ 1, idx+ 4);
208 bp_get(date+ 3, buf, idx+ 5, idx+ 6);
209 bp_get(date+ 0, buf, idx+ 7, idx+ 8);
210 bp_get(date+11, buf, idx+ 9, idx+10);
211 bp_get(date+14, buf, idx+11, idx+12);
212 bp_get(date+17, buf, idx+13, idx+14);
213 bp_get(date+20, buf, idx+15, idx+16);
214 }
215
set_date(unsigned char * date,int idx,int year,int month,int day,int hour,int minute,int second,int hsecond,int gmt_offset)216 static void set_date(unsigned char *date, int idx,
217 int year, int month, int day,
218 int hour, int minute, int second, int hsecond,
219 int gmt_offset)
220 {
221 sprintf((char*)(date+idx-1), "%04d%02d%02d%02d%02d%02d%02d",
222 year, month, day, hour, minute, second, hsecond);
223
224 *(date+idx+15) = (unsigned char)gmt_offset;
225 }
226
set_binary_date(unsigned char * dest,int idx,int year,int month,int day,int hour,int minute,int second,int gmt_offset)227 static void set_binary_date(unsigned char *dest, int idx,
228 int year, int month, int day,
229 int hour, int minute, int second,
230 int gmt_offset)
231 {
232 dest = dest + idx - 1;
233
234 *dest++ = (unsigned char)year;
235 *dest++ = (unsigned char)month;
236 *dest++ = (unsigned char)day;
237 *dest++ = (unsigned char)hour;
238 *dest++ = (unsigned char)minute;
239 *dest++ = (unsigned char)second;
240 *dest++ = (unsigned char)gmt_offset;
241 }
242
beautify_dchar(char * dchar)243 static void beautify_dchar(char *dchar)
244 { int idx = strlen(dchar)-1;
245
246 while(idx>=0)
247 { if(dchar[idx] != ' ') break;
248 dchar[idx--] = 0;
249 }
250
251 while(idx>0)
252 { if(dchar[idx-1] != ' ')
253 dchar[idx] = tolower((int)dchar[idx]);
254 idx--;
255 }
256
257 if(!*dchar) strcpy(dchar, _("Unnamed"));
258 }
259
260 /***
261 *** Extract some useful information from the ISO file system
262 ***/
263
FreeIsoInfo(IsoInfo * ii)264 void FreeIsoInfo(IsoInfo *ii)
265 {
266 g_free(ii);
267 }
268
examine_primary_vd(unsigned char * buf)269 static IsoInfo* examine_primary_vd(unsigned char *buf)
270 { IsoInfo *ii = g_malloc(sizeof(IsoInfo));
271 unsigned char vlabel[33];
272 unsigned char str[80];
273 guint32 x,vss;
274 unsigned char date[32];
275
276 bp_get_string(str, buf, 9, 40);
277 Verbose(" System identifier : |%s|\n", str);
278
279 bp_get_string(vlabel, buf, 41, 72);
280 Verbose(" Volume identifier : |%s|\n", vlabel);
281
282 vss = bp_get_long_bbo(buf, 81);
283 Verbose(" Volume space size : %d sectors\n", vss);
284
285 x = bp_get_short_bbo(buf, 121);
286 Verbose(" Volume set size : %d\n", x);
287
288 x = bp_get_short_bbo(buf, 125);
289 Verbose(" Volume sequence size : %d\n", x);
290
291 x = bp_get_short_bbo(buf, 129);
292 Verbose(" Logical block size : %d\n", x);
293
294 x = bp_get_long_bbo(buf, 133);
295 Verbose(" Path table size : %d bytes\n", x);
296
297 x = bp_get_long_lsb(buf, 141);
298 Verbose(" L-Path table location : %d\n", x);
299
300 x = bp_get_long_lsb(buf, 145);
301 Verbose(" Opt L-Path table location : %d\n", x);
302
303 x = bp_get_long_msb(buf, 149);
304 Verbose(" M-Path table location : %d\n", x);
305
306 x = bp_get_long_msb(buf, 153);
307 Verbose(" Opt M-Path table location : %d\n", x);
308
309 /* 157 .. 190 directory record */
310
311 /* 191 .. 318 Volume set identifier */
312
313 /* 319 .. 446 Publisher Identifier */
314
315 /* 447 .. 574 Data Preparer Identifier */
316
317 /* 575 .. 702 Application Identfier */
318
319 /* 703 .. 739 Copyright File Identifier */
320
321 /* 740 .. 776 Abstract File Identifier */
322
323 /* 777 .. 813 Bibliographic File Identifier */
324
325 get_date(date, buf, 814);
326 Verbose(" Volume creation date/time : %s\n", date);
327
328 get_date(str, buf, 831);
329 Verbose(" Volume modification d/t : %s\n", str);
330
331 get_date(str, buf, 848);
332 Verbose(" Volume expiration d/t : %s\n", str);
333
334 get_date(str, buf, 865);
335 Verbose(" Volume effective d/t : %s\n", str);
336
337 x = bp_get_byte(buf,882);
338 Verbose(" File structure version : %d\n", x);
339
340 /* Extract information for IsoInfo */
341
342 ii->volumeSize = vss;
343
344 if(!Closure->screenShotMode)
345 { strcpy(ii->volumeLabel, (char*)vlabel);
346 beautify_dchar(ii->volumeLabel);
347 }
348 else strcpy(ii->volumeLabel, _("Example disc"));
349 strcpy(ii->creationDate, (char*)date);
350 ii->creationDate[10] = 0;
351 return ii;
352 }
353
examine_iso(Image * image)354 static IsoInfo* examine_iso(Image *image)
355 { AlignedBuffer *ab = CreateAlignedBuffer(2048);
356 unsigned char *buf = ab->buf;
357 IsoInfo *ii = NULL;
358 int sector;
359 int vdt,vdt_ver;
360 unsigned char sid[6];
361
362 Verbose(" Examining the ISO file system...\n");
363
364 /*** Iterate over the volume decriptors */
365
366 for(sector=16; sector<32; sector++)
367 { if(Closure->stopActions)
368 continue;
369
370 if(ImageReadSectors(image, buf, sector, 1) != 1)
371 { Verbose(" Sector %2d: unreadable\n", sector);
372 continue;
373 }
374
375 vdt = bp_get_byte(buf, 1); /* Volume descriptor type */
376 bp_get_string(sid, buf, 2, 6); /* Standard identifier */
377 vdt_ver = bp_get_byte(buf,7); /* Volume descriptor version */
378
379 Verbose(" Sector %2d:\n"
380 " Volume descriptor type = %d\n"
381 " Volume descriptor version = %d\n"
382 " Standard identifier = %s\n",
383 sector, vdt, vdt_ver, sid);
384
385 if(strncmp((char*)sid,"CD001",5))
386 { Verbose(" * Wrong or missing standard identifier.\n");
387 continue;
388 }
389
390 switch(vdt)
391 { case 0: Verbose(" -> boot record: *skipped*\n");
392 break;
393 case 1: Verbose(" -> primary volume descriptor:\n");
394 ii = examine_primary_vd(buf);
395 break;
396 case 2: Verbose(" -> supplementary volume descriptor: *skipped*\n");
397 break;
398 case 255: Verbose(" -> volume descriptor set terminator;\n"
399 " end of ISO file system parsing.\n");
400 goto finished;
401 break;
402 default : Verbose(" -> unknown volume descriptor: *skipped*\n");
403 break;
404 }
405 }
406
407 finished:
408 FreeAlignedBuffer(ab);
409 return ii;
410 }
411
412 /***
413 *** The main wrapper for visiting the ISO and UDF file system structures
414 ***/
415
416
ExamineUDF(Image * image)417 void ExamineUDF(Image *image)
418 {
419 if(!image) return;
420
421 if(image->type == IMAGE_MEDIUM) Verbose("\nExamineUDF(Device: %s)\n", image->dh->devinfo);
422 if(image->type == IMAGE_FILE ) Verbose("\nExamineUDF(File: %s)\n", image->file->path);
423
424 image->isoInfo = examine_iso(image);
425
426 Verbose(" Examining the UDF file system...\n");
427 Verbose(" not yet implemented.\n\n");
428 }
429
430 /***
431 *** Rudimentary support for creating .iso images.
432 *** Currently only used for creating the random image;
433 * can only create .iso images containing exactly one file.
434 */
435
436 /*
437 * Directory record writing
438 */
439
create_iso_dir()440 static IsoDir* create_iso_dir()
441 { IsoDir *id = g_malloc0(sizeof(IsoDir));
442
443 id->dir = g_malloc0(2048);
444 id->nSectors = 1;
445
446 return id;
447 }
448
free_iso_dir(IsoDir * id)449 static void free_iso_dir(IsoDir *id)
450 { g_free(id->dir);
451 g_free(id);
452 }
453
add_directory_record(IsoDir * iso_dir,int extent,int file_flags,int file_identifier,int year,int month,int day,int hour,int minute,int second,int gmt_offset)454 static void add_directory_record(IsoDir *iso_dir,
455 int extent, int file_flags, int file_identifier,
456 int year, int month, int day,
457 int hour, int minute, int second, int gmt_offset)
458 { unsigned char *dir = iso_dir->dir + iso_dir->tail;
459
460 iso_dir->tail += 34;
461
462 bp_set_byte(dir, 1, 34); /* Length of directory record */
463 bp_set_byte(dir, 2, 0); /* Extended attribute length */
464 bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
465 bp_set_long_bbo(dir, 11, 2048); /* Data length of file section */
466 set_binary_date(dir, 19, /* Binary date rep of creation time */
467 year,month,day,hour,minute,second,gmt_offset);
468 bp_set_byte(dir, 26, file_flags); /* File flags (we are a directory) */
469 bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
470 bp_set_byte(dir, 28, 0); /* Interleave gap size */
471 bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
472 bp_set_byte(dir, 33, 1); /* Length of file identifier */
473 bp_set_byte(dir, 34, file_identifier); /* File identifier */
474 }
475
add_file_record(IsoDir * iso_dir,char * filename,guint64 size,int extent,int year,int month,int day,int hour,int minute,int second,int gmt_offset)476 static void add_file_record(IsoDir *iso_dir, char *filename, guint64 size, int extent,
477 int year, int month, int day,
478 int hour, int minute, int second, int gmt_offset)
479 { unsigned char *dir = iso_dir->dir + iso_dir->tail;
480 int sl = strlen(filename);
481 int entry_len = 34+sl;
482
483 iso_dir->tail += entry_len;
484
485 bp_set_byte(dir, 1, entry_len); /* Length of directory record */
486 bp_set_byte(dir, 2, 0); /* Extended attribute length */
487 bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
488 bp_set_long_bbo(dir, 11, size); /* Data length of file section */
489 set_binary_date(dir, 19, /* Binary date rep of creation time */
490 year,month,day,hour,minute,second,gmt_offset);
491 bp_set_byte(dir, 26, 0); /* File flags (we are a file) */
492 bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
493 bp_set_byte(dir, 28, 0); /* Interleave gap size */
494 bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
495 bp_set_byte(dir, 33, sl); /* Length of file identifier */
496 bp_set_string(dir, filename, 34, 34+sl); /* File name */
497 }
498
add_d1_file_record(IsoDir * iso_dir,char * filename,guint64 size,int extent,int year,int month,int day,int hour,int minute,int second,int gmt_offset)499 static void add_d1_file_record(IsoDir *iso_dir, char *filename, guint64 size, int extent,
500 int year, int month, int day,
501 int hour, int minute, int second, int gmt_offset)
502 { unsigned char *dir = iso_dir->dir + iso_dir->tail;
503 int sl = 2*strlen(filename);
504 int entry_len = 34+sl;
505
506 iso_dir->tail += entry_len;
507
508 bp_set_byte(dir, 1, entry_len); /* Length of directory record */
509 bp_set_byte(dir, 2, 0); /* Extended attribute length */
510 bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
511 bp_set_long_bbo(dir, 11, size); /* Data length of file section */
512 set_binary_date(dir, 19, /* Binary date rep of creation time */
513 year,month,day,hour,minute,second,gmt_offset);
514 bp_set_byte(dir, 26, 0); /* File flags (we are a file) */
515 bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
516 bp_set_byte(dir, 28, 0); /* Interleave gap size */
517 bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
518 bp_set_byte(dir, 33, sl); /* Length of file identifier */
519 bp_set_d1_string(dir, filename, 34, 34+sl); /* File name */
520 }
521
522
523 /*
524 * Path tables
525 */
526
create_iso_path_table()527 static IsoPathTable* create_iso_path_table()
528 { IsoPathTable *ipt = g_malloc0(sizeof(IsoPathTable));
529
530 ipt->lpath = g_malloc0(2048);
531 ipt->mpath = g_malloc0(2048);
532 ipt->nSectors = 1;
533
534 return ipt;
535 }
536
free_iso_path_table(IsoPathTable * ipt)537 static void free_iso_path_table(IsoPathTable *ipt)
538 { g_free(ipt->lpath);
539 g_free(ipt->mpath);
540 g_free(ipt);
541 }
542
add_path(IsoPathTable * ipt,int extent)543 static void add_path(IsoPathTable *ipt, int extent)
544 { unsigned char *lpath = ipt->lpath + ipt->tail;
545 unsigned char *mpath = ipt->mpath + ipt->tail;
546
547 bp_set_byte(lpath, 1, 1); /* Length of directory identifier (root=1) */
548 bp_set_byte(mpath, 1, 1);
549
550 bp_set_byte(lpath, 2, 0); /* Extended attribute length */
551 bp_set_byte(mpath, 2, 0); /* Extended attribute length */
552
553 bp_set_long_lsb(lpath, 3, extent); /* Location of extent */
554 bp_set_long_msb(mpath, 3, extent);
555
556 bp_set_short_lsb(lpath, 7, 1); /* Parent directory number */
557 bp_set_short_msb(mpath, 7, 1);
558
559 bp_set_byte(lpath, 9, 0); /* Directory identifier (root=0) */
560 bp_set_byte(mpath, 9, 0);
561 }
562
563 /*
564 * Initialize the IsoHeader structure
565 */
566
InitIsoHeader(void)567 IsoHeader* InitIsoHeader(void)
568 { IsoHeader *ih = g_malloc0(sizeof(IsoHeader));
569 unsigned char *pvd,*svd;
570 char blank[128], string[128];
571
572 memset(blank, ' ', 128);
573
574 /*** Initialize primary volume descriptor (sector 16). */
575
576 ih->pvd = pvd = g_malloc0(2048);
577 ih->dirSectors = 1;
578
579 /* 1..8: Standard identifier */
580
581 bp_set_byte(pvd, 1, 1); /* Volume descriptor type 1 */
582 bp_set_string(pvd, "CD001", 2, 6); /* Standard identifier */
583 bp_set_byte(pvd, 7, 1); /* Volume descriptor version 1 */
584
585 /* 9..40: System identifier */
586
587 bp_set_string(pvd, blank, 9, 40);
588
589 /* 41..72: Volume identifier */
590
591 memcpy(string, blank, 128);
592 memcpy(string, "RANDOM IMAGE", 12);
593 bp_set_string(pvd, string, 41, 72);
594
595 /* 73.. 80: Unused, zero bytes */
596 /* 81.. 88: Volume space size, filled in at WriteIsoHeader() */
597 /* 89..120: Unused, zero bytes */
598
599 /* 121..124: Volume set size */
600
601 bp_set_short_bbo(pvd, 121, 1);
602
603 /* 125..128: Volume sequence number */
604
605 bp_set_short_bbo(pvd, 125, 1);
606
607 /* 129..132: Logical block size */
608
609 bp_set_short_bbo(pvd, 129, 2048);
610
611 /* 133..140: Path table size, filled in at WriteIsoHeader() */
612 /* 141..144: L Path table location, filled in at WriteIsoHeader() */
613 /* 145..148: Optional L Path table location, filled in at WriteIsoHeader() */
614 /* 149..152: M Path table location, filled in at WriteIsoHeader() */
615 /* 153..156: Optional M Path table location, filled in at WriteIsoHeader() */
616
617 /* 157..190: Directory record for root dir, filled in at WriteIsoHeader() */
618
619 /* 191..318: Volume set identifier */
620
621 bp_set_string(pvd, blank, 191, 318);
622
623 /* 319..446: Publisher identifier */
624
625 bp_set_string(pvd, blank, 319, 446);
626
627 /* 447..574: Data preparer identifier */
628
629 bp_set_string(pvd, blank, 447, 574);
630
631 /* 575..702 Application Identfier */
632
633 bp_set_string(pvd, blank, 575, 702);
634
635 /* 703..739 Copyright File Identifier */
636
637 bp_set_string(pvd, blank, 703, 739);
638
639 /* 740..776 Abstract File Identifier */
640
641 bp_set_string(pvd, blank, 740, 776);
642
643 /* 777..813 Bibliographic File Identifier */
644
645 bp_set_string(pvd, blank, 777, 813);
646
647 /* 814..830 Volume creation time, filled in by WriteIsoHeader() */
648 /* 831..847 Volume modification time, filled in by WriteIsoHeader() */
649 /* 848..864 Volume expiration time, filled in by WriteIsoHeader() */
650 /* 865..881 Volume effective time, filled in by WriteIsoHeader() */
651
652 /* 882 File structure version */
653
654 bp_set_byte(pvd, 882, 1);
655
656 /* 883 Reserved, zero */
657 /* 884..1395 for application use */
658 /* 1396..2048 Reserved, zero */
659
660 /*** Initialize supplementary volume descriptor (sector 17). */
661
662 ih->svd = svd = g_malloc0(2048);
663 ih->dirSectors = 2;
664
665 /* 1..8: Standard identifier */
666
667 bp_set_byte(svd, 1, 2); /* Volume descriptor type 1 */
668 bp_set_string(svd, "CD001", 2, 6); /* Standard identifier */
669 bp_set_byte(svd, 7, 1); /* Volume descriptor version 1 */
670 bp_set_byte(svd, 8, 0); /* Volume flags */
671
672 /* 9..40: System identifier (zero filled) */
673
674 /* 41..72: Volume identifier */
675
676 bp_set_d1_string(svd, "random image", 41, 72);
677
678 /* 73.. 80: Unused, zero bytes */
679 /* 81.. 88: Volume space size, filled in at WriteIsoHeader() */
680 /* 89..120: Escape sequences */
681
682 bp_set_byte(svd, 89, 37);
683 bp_set_byte(svd, 90, 47);
684 bp_set_byte(svd, 91, 64);
685
686 /* 121..124: Volume set size */
687
688 bp_set_short_bbo(svd, 121, 1);
689
690 /* 125..128: Volume sequence number */
691
692 bp_set_short_bbo(svd, 125, 1);
693
694 /* 129..132: Logical block size */
695
696 bp_set_short_bbo(svd, 129, 2048);
697
698 /* 133..140: Path table size, filled in at WriteIsoHeader() */
699 /* 141..144: L Path table location, filled in at WriteIsoHeader() */
700 /* 145..148: Optional L Path table location, filled in at WriteIsoHeader() */
701 /* 149..152: M Path table location, filled in at WriteIsoHeader() */
702 /* 153..156: Optional M Path table location, filled in at WriteIsoHeader() */
703
704 /* 157..190: Directory record for root dir, filled in at WriteIsoHeader() */
705
706 /* The standard says to fill the identifier field with blanks,
707 but actual writing software seems to use zeroes. */
708
709 /* 191..318: Volume set identifier */
710
711 //bp_set_string(svd, blank, 191, 318);
712
713 /* 319..446: Publisher identifier */
714
715 //bp_set_string(svd, blank, 319, 446);
716
717 /* 447..574: Data preparer identifier */
718
719 //bp_set_string(svd, blank, 447, 574);
720
721 /* 575..702 Application Identfier */
722
723 //bp_set_string(svd, blank, 575, 702);
724
725 /* 703..739 Copyright File Identifier */
726
727 //bp_set_string(svd, blank, 703, 739);
728
729 /* 740..776 Abstract File Identifier */
730
731 //bp_set_string(svd, blank, 740, 776);
732
733 /* 777..813 Bibliographic File Identifier */
734
735 //bp_set_string(svd, blank, 777, 813);
736
737 /* 814..830 Volume creation time, filled in by WriteIsoHeader() */
738 /* 831..847 Volume modification time, filled in by WriteIsoHeader() */
739 /* 848..864 Volume expiration time, filled in by WriteIsoHeader() */
740 /* 865..881 Volume effective time, filled in by WriteIsoHeader() */
741
742 /* 882 File structure version */
743
744 bp_set_byte(svd, 882, 1);
745
746 /* 883 Reserved, zero */
747 /* 884..1395 for application use */
748 /* 1396..2048 Reserved, zero */
749
750 /*** The volume descriptor set terminator (sector 17)
751 is trivial and created during WriteIsoHeader() */
752
753 ih->dirSectors = 3;
754
755 /*** Allocate space for directories and path tables */
756
757 ih->proot = create_iso_dir();
758 add_directory_record(ih->proot, 21, 2, 0,
759 106, 7, 16, 12, 35, 46, 8);
760 add_directory_record(ih->proot, 21, 2, 1,
761 106, 7, 16, 12, 35, 46, 8);
762
763 ih->ppath = create_iso_path_table();
764 add_path(ih->ppath, 21);
765
766 ih->sroot = create_iso_dir();
767 add_directory_record(ih->sroot, 24, 2, 0,
768 106, 7, 16, 12, 35, 46, 8);
769 add_directory_record(ih->sroot, 24, 2, 1,
770 106, 7, 16, 12, 35, 46, 8);
771
772 ih->spath = create_iso_path_table();
773 add_path(ih->spath, 24);
774
775 ih->dirSectors += 6;
776
777 return ih;
778 }
779
FreeIsoHeader(IsoHeader * ih)780 void FreeIsoHeader(IsoHeader *ih)
781 {
782 free_iso_dir(ih->proot);
783 free_iso_dir(ih->sroot);
784 free_iso_path_table(ih->ppath);
785 free_iso_path_table(ih->spath);
786 g_free(ih->pvd);
787 g_free(ih->svd);
788 g_free(ih);
789 }
790
791 /*
792 * Add file to iso image (works currently only for one file!)
793 */
794
AddFile(IsoHeader * ih,char * name,guint64 size)795 void AddFile(IsoHeader *ih, char *name, guint64 size)
796 { static int n;
797 char iso[20], joliet[strlen(name)+3];
798
799 n++;
800 sprintf(iso,"RAN_%04d.DAT;1", n);
801 add_file_record(ih->proot, iso, size, 25,
802 106, 7, 16, 12, 28, 10, 8);
803 sprintf(joliet,"%s;1", name);
804 add_d1_file_record(ih->sroot, joliet, size, 25,
805 106, 7, 16, 12, 28, 10, 8);
806
807 ih->volumeSpace += (size+2047)/2048;
808 }
809
810 /*
811 * Write out the IsoHeader, return number of sectors written
812 */
813
WriteIsoHeader(IsoHeader * ih,LargeFile * image)814 void WriteIsoHeader(IsoHeader *ih, LargeFile *image)
815 { unsigned char zero[2048], sector[2048];
816 unsigned char *pvd,*svd;
817 int i;
818
819 /* The first 16 sectors are zeroed out */
820
821 memset(zero, 0, 2048);
822
823 for(i=0; i<16; i++)
824 { int n = LargeWrite(image, zero, 2048);
825
826 if(n != 2048)
827 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)i, strerror(errno));
828 }
829
830 /* Complete the primary volume descriptor */
831
832 pvd = ih->pvd;
833
834 /* 81..88: Volume space size */
835
836 ih->volumeSpace += 16 + ih->dirSectors;
837 bp_set_long_bbo(pvd, 81, ih->volumeSpace);
838
839 /* 133..140: Path table size, Fixme: use real values */
840 /* 141..144: L Path table location */
841 /* 145..148: Optional L Path table location */
842 /* 149..152: M Path table location */
843 /* 153..156: Optional M Path table location */
844
845 bp_set_long_bbo(pvd, 133, 10);
846 bp_set_long_lsb(pvd, 141, 19);
847 bp_set_long_lsb(pvd, 145, 0);
848 bp_set_long_msb(pvd, 149, 20);
849 bp_set_long_msb(pvd, 153, 0);
850
851 /* 157..190: Directory record for root directory, Fixme: use real values */
852
853 bp_set_byte(pvd, 157, 34); /* Length of directory record */
854 bp_set_byte(pvd, 158, 0); /* Extended atribute length */
855 bp_set_long_bbo(pvd, 159, 21); /* Location of Extent */
856 bp_set_long_bbo(pvd, 167, 2048); /* Data length of file section */
857 set_binary_date(pvd, 175, /* Binary date rep of creation time */
858 106, 7, 16, 10, 35, 46, 8);
859 bp_set_byte(pvd, 182, 2); /* File flags (we are a directory) */
860 bp_set_byte(pvd, 183, 0); /* File unit size if interleaved */
861 bp_set_byte(pvd, 184, 0); /* Interleave gap size */
862 bp_set_short_bbo(pvd, 185, 1); /* Volume sequence number */
863 bp_set_byte(pvd, 189, 1); /* Length of file identifier */
864 bp_set_byte(pvd, 190, 0); /* File identifier */
865
866 /* 814..830 Volume creation time */
867
868 set_date(pvd, 814, 2006, 7, 16, 10, 35, 46, 23, 8);
869
870 /* 831..847 Volume modification time */
871
872 set_date(pvd, 831, 2006, 7, 16, 10, 35, 46, 23, 8);
873
874 /* 848..864 Volume expiration time */
875
876 set_date(pvd, 848, 2106, 7, 16, 10, 35, 46, 23, 8);
877
878 /* 865..881 Volume effective time */
879
880 set_date(pvd, 865, 2006, 7, 16, 10, 35, 46, 23, 8);
881
882 /* Write the pvd */
883
884 if(LargeWrite(image, pvd, 2048) != 2048)
885 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)16, strerror(errno));
886
887
888 /* Create the supplementary volume descriptor */
889
890 svd = ih->svd;
891
892 /* 81..88: Volume space size */
893
894 bp_set_long_bbo(svd, 81, ih->volumeSpace);
895
896 /* 133..140: Path table size, Fixme: use real values */
897 /* 141..144: L Path table location */
898 /* 145..148: Optional L Path table location */
899 /* 149..152: M Path table location */
900 /* 153..156: Optional M Path table location */
901
902 bp_set_long_bbo(svd, 133, 10);
903 bp_set_long_lsb(svd, 141, 22);
904 bp_set_long_lsb(svd, 145, 0);
905 bp_set_long_msb(svd, 149, 23);
906 bp_set_long_msb(svd, 153, 0);
907
908 /* 157..190: Directory record for root directory, Fixme: use real values */
909
910 bp_set_byte(svd, 157, 34); /* Length of directory record */
911 bp_set_byte(svd, 158, 0); /* Extended attribute length */
912 bp_set_long_bbo(svd, 159, 24); /* Location of Extent */
913 bp_set_long_bbo(svd, 167, 2048); /* Data length of file section */
914 set_binary_date(svd, 175, /* Binary date rep of creation time */
915 106, 7, 16, 10, 35, 46, 8);
916 bp_set_byte(svd, 182, 2); /* File flags (we are a directory) */
917 bp_set_byte(svd, 183, 0); /* File unit size if interleaved */
918 bp_set_byte(svd, 184, 0); /* Interleave gap size */
919 bp_set_short_bbo(svd, 185, 1); /* Volume sequence number */
920 bp_set_byte(svd, 189, 1); /* Length of file identifier */
921 bp_set_byte(svd, 190, 0); /* File identifier */
922
923 /* 814..830 Volume creation time */
924
925 set_date(svd, 814, 2006, 7, 16, 10, 35, 46, 23, 8);
926
927 /* 831..847 Volume modification time */
928
929 set_date(svd, 831, 2006, 7, 16, 10, 35, 46, 23, 8);
930
931 /* 848..864 Volume expiration time */
932
933 set_date(svd, 848, 2106, 7, 16, 10, 35, 46, 23, 8);
934
935 /* 865..881 Volume effective time */
936
937 set_date(svd, 865, 2006, 7, 16, 10, 35, 46, 23, 8);
938
939 /* Write the svd */
940
941 if(LargeWrite(image, svd, 2048) != 2048)
942 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)17, strerror(errno));
943
944 /*** Create and write the volume descriptor set terminator */
945
946 /* 1..8: Standard identifier */
947
948 memset(sector, 0, 2048);
949
950 bp_set_byte(sector, 1, 255); /* Volume descriptor set terminator */
951 bp_set_string(sector, "CD001", 2, 6); /* Standard identifier */
952 bp_set_byte(sector, 7, 1); /* Volume descriptor version 1 */
953
954 if(LargeWrite(image, sector, 2048) != 2048)
955 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)18, strerror(errno));
956
957 /*** Write the primary and supplementary path tables and root directories */
958
959 if(LargeWrite(image, ih->ppath->lpath, 2048) != 2048)
960 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)19, strerror(errno));
961
962 if(LargeWrite(image, ih->ppath->mpath, 2048) != 2048)
963 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)20, strerror(errno));
964
965 if(LargeWrite(image, ih->proot->dir, 2048) != 2048)
966 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)21, strerror(errno));
967
968 if(LargeWrite(image, ih->spath->lpath, 2048) != 2048)
969 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)22, strerror(errno));
970
971 if(LargeWrite(image, ih->spath->mpath, 2048) != 2048)
972 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)23, strerror(errno));
973
974 if(LargeWrite(image, ih->sroot->dir, 2048) != 2048)
975 Stop(_("Failed writing to sector %lld in image: %s"), (gint64)24, strerror(errno));
976
977 }
978