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