Files
dvdisaster/udf.c
Stéphane Lesimple 38defdf7aa Apply (most) debian patches
Apply debian patch 02-encryption
Apply debian patch 03-dvdrom
Apply a modified version of patch 05-help-dialog
Apply debian patch 08-fix-gnu-make-detection
Apply debian patch 10-use-non-size-specific-icon-and-add-keywords-to-desktop-file
Apply debian patch 12-fix-spelling-of-up-to
Apply debian patch 13-fix-missing-language-field-in-po-files
Apply a modified version of debian patch 14-make-builds-reproducible
Apply debian patch 17-fix-all-but-deprecated-api-warnings
Apply a modified version of debian patch 18-update-copyright-in-about-dialog
Apply debian patch 19-show-text-files-with-abs-path
Apply debian patch 22-fix-hurd-i386-ftbfs
Apply debian patch 23-add-bdrom-support
Apply debian patch 25-fix-man-pages
Apply debian patch 27-allow-opening-in-browser-again
Apply debian patch 28-pdftex-reproducibility
Apply debian patch 29-fix-more-typos
Apply debian patch 30-hurd-kfreebsd-ftbfs
Apply debian patch 31-improve-hurd-and-kfreebsd-support
Apply debian patch 33-honour-LDFLAGS
Apply debian patch 34-gcc8-format-security.patch
Apply debian patch 35-archived-homepage
Apply debian patch 36-fix-parallelism
2020-08-20 14:17:35 +02:00

981 lines
29 KiB
C

/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2017 Carsten Gnoerlich.
*
* Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org
* Project homepage: http://www.dvdisaster.org
*
* This file is part of dvdisaster.
*
* dvdisaster is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dvdisaster is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dvdisaster.h"
#include "udf.h"
/***
*** Rudimentary UDF and ISO filesystem parsing.
***
* Information about UDF and ISO was gathered from ECMA-119,
* ECMA-167, ECMA-167 and the UDF 2.6 standard from OSTA.org.
* However, no claims are made to be actually conformant to any
* of those standards.
*/
/*
* ECMA sector indices start with 1;
* this definition make it easier to use the standard for reading strings
* from the buffer.
* begin and end are the bp postions of the string start and end position.
*/
/*
* 8bit values
*/
#define bp_get_byte(buf, idx) (buf[(idx)-1])
#define bp_set_byte(buf, idx, byte) (buf[(idx)-1] = (unsigned char)byte)
/*
* 16bit both byte order
*/
#ifdef HAVE_BIG_ENDIAN
#define bp_get_short_bbo(buf, idx) (*((guint16*)(buf+idx+1)))
#else
#define bp_get_short_bbo(buf, idx) (*((guint16*)(buf+idx-1)))
#endif
static void bp_set_short_bbo(unsigned char *buf, int idx, guint16 value)
{ unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = yz;
*buf++ = wx;
*buf++ = wx;
*buf++ = yz;
}
static void bp_set_short_lsb(unsigned char *buf, int idx, guint16 value)
{ unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = yz;
*buf++ = wx;
}
static void bp_set_short_msb(unsigned char *buf, int idx, guint16 value)
{ unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = wx;
*buf++ = yz;
}
/*
* 32bit single byte order
*/
#ifdef HAVE_BIG_ENDIAN
#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]))
#else
#define bp_get_long_lsb(buf, idx) (*((guint32*)(buf+idx-1)))
#endif
#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]))
static void bp_set_long_lsb(unsigned char *buf, int idx, guint32 value)
{ unsigned char st = (value >> 24) & 0xff;
unsigned char uv = (value >> 16) & 0xff;
unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = yz;
*buf++ = wx;
*buf++ = uv;
*buf++ = st;
}
static void bp_set_long_msb(unsigned char *buf, int idx, guint32 value)
{ unsigned char st = (value >> 24) & 0xff;
unsigned char uv = (value >> 16) & 0xff;
unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = st;
*buf++ = uv;
*buf++ = wx;
*buf++ = yz;
}
/*
* 32bit both byte order
*/
#ifdef HAVE_BIG_ENDIAN
#define bp_get_long_bbo(buf, idx) (*((guint32*)(buf+idx+3)))
#else
#define bp_get_long_bbo(buf, idx) (*((guint32*)(buf+idx-1)))
#endif
static void bp_set_long_bbo(unsigned char *buf, int idx, guint32 value)
{ unsigned char st = (value >> 24) & 0xff;
unsigned char uv = (value >> 16) & 0xff;
unsigned char wx = (value >> 8) & 0xff;
unsigned char yz = value & 0xff;
buf = buf + idx - 1;
*buf++ = yz;
*buf++ = wx;
*buf++ = uv;
*buf++ = st;
*buf++ = st;
*buf++ = uv;
*buf++ = wx;
*buf++ = yz;
}
static void bp_get(unsigned char *dest, unsigned char *src, int begin, int end)
{ int length = end-begin+1;
strncpy((char*)dest, (char*)src+begin-1, length);
}
#if 0
static void bp_set(unsigned char *dest, unsigned char *src, int begin, int end)
{ int length = end-begin+1;
memcpy((char*)dest+begin-1, (char*)src, length);
}
#endif
/*
* String operations
*/
static void bp_get_string(unsigned char *dest, unsigned char *src, int begin, int end)
{ int length = end-begin+1;
strncpy((char*)dest, (char*)src+begin-1, length);
dest[length] = 0;
}
static void bp_set_string(unsigned char *dest, char *src, int begin, int end)
{ int length = end-begin+1;
strncpy((char*)(dest+begin-1), src, length);
}
/*
* D1 string conversion currently simply expands the string to 16bit characters.
*/
static void bp_set_d1_string(unsigned char *dest, char *src, int begin, int end)
{
dest = dest + begin - 1;
while(begin<=end-2 && *src)
{ *dest++ = 0;
*dest++ = (unsigned char)*src++;
begin += 2;
}
}
/*
* Date values
*/
static void get_date(unsigned char *date, unsigned char *buf, int idx)
{
idx--;
sprintf((char*)date, "dd-mm-yyyy hh:mm:ss.ss");
bp_get(date+ 6, buf, idx+ 1, idx+ 4);
bp_get(date+ 3, buf, idx+ 5, idx+ 6);
bp_get(date+ 0, buf, idx+ 7, idx+ 8);
bp_get(date+11, buf, idx+ 9, idx+10);
bp_get(date+14, buf, idx+11, idx+12);
bp_get(date+17, buf, idx+13, idx+14);
bp_get(date+20, buf, idx+15, idx+16);
}
static void set_date(unsigned char *date, int idx,
int year, int month, int day,
int hour, int minute, int second, int hsecond,
int gmt_offset)
{
sprintf((char*)(date+idx-1), "%04d%02d%02d%02d%02d%02d%02d",
year, month, day, hour, minute, second, hsecond);
*(date+idx+15) = (unsigned char)gmt_offset;
}
static void set_binary_date(unsigned char *dest, int idx,
int year, int month, int day,
int hour, int minute, int second,
int gmt_offset)
{
dest = dest + idx - 1;
*dest++ = (unsigned char)year;
*dest++ = (unsigned char)month;
*dest++ = (unsigned char)day;
*dest++ = (unsigned char)hour;
*dest++ = (unsigned char)minute;
*dest++ = (unsigned char)second;
*dest++ = (unsigned char)gmt_offset;
}
static void beautify_dchar(char *dchar)
{ int idx = strlen(dchar)-1;
while(idx>=0)
{ if(dchar[idx] != ' ') break;
dchar[idx--] = 0;
}
while(idx>0)
{ if(dchar[idx-1] != ' ')
dchar[idx] = tolower((int)dchar[idx]);
idx--;
}
if(!*dchar) strcpy(dchar, _("Unnamed"));
}
/***
*** Extract some useful information from the ISO file system
***/
void FreeIsoInfo(IsoInfo *ii)
{
g_free(ii);
}
static IsoInfo* examine_primary_vd(unsigned char *buf)
{ IsoInfo *ii = g_malloc(sizeof(IsoInfo));
unsigned char vlabel[33];
unsigned char str[80];
guint32 x,vss;
unsigned char date[32];
bp_get_string(str, buf, 9, 40);
Verbose(" System identifier : |%s|\n", str);
bp_get_string(vlabel, buf, 41, 72);
Verbose(" Volume identifier : |%s|\n", vlabel);
vss = bp_get_long_bbo(buf, 81);
Verbose(" Volume space size : %d sectors\n", vss);
x = bp_get_short_bbo(buf, 121);
Verbose(" Volume set size : %d\n", x);
x = bp_get_short_bbo(buf, 125);
Verbose(" Volume sequence size : %d\n", x);
x = bp_get_short_bbo(buf, 129);
Verbose(" Logical block size : %d\n", x);
x = bp_get_long_bbo(buf, 133);
Verbose(" Path table size : %d bytes\n", x);
x = bp_get_long_lsb(buf, 141);
Verbose(" L-Path table location : %d\n", x);
x = bp_get_long_lsb(buf, 145);
Verbose(" Opt L-Path table location : %d\n", x);
x = bp_get_long_msb(buf, 149);
Verbose(" M-Path table location : %d\n", x);
x = bp_get_long_msb(buf, 153);
Verbose(" Opt M-Path table location : %d\n", x);
/* 157 .. 190 directory record */
/* 191 .. 318 Volume set identifier */
/* 319 .. 446 Publisher Identifier */
/* 447 .. 574 Data Preparer Identifier */
/* 575 .. 702 Application Identfier */
/* 703 .. 739 Copyright File Identifier */
/* 740 .. 776 Abstract File Identifier */
/* 777 .. 813 Bibliographic File Identifier */
get_date(date, buf, 814);
Verbose(" Volume creation date/time : %s\n", date);
get_date(str, buf, 831);
Verbose(" Volume modification d/t : %s\n", str);
get_date(str, buf, 848);
Verbose(" Volume expiration d/t : %s\n", str);
get_date(str, buf, 865);
Verbose(" Volume effective d/t : %s\n", str);
x = bp_get_byte(buf,882);
Verbose(" File structure version : %d\n", x);
/* Extract information for IsoInfo */
ii->volumeSize = vss;
if(!Closure->screenShotMode)
{ strcpy(ii->volumeLabel, (char*)vlabel);
beautify_dchar(ii->volumeLabel);
}
else strcpy(ii->volumeLabel, _("Example disc"));
strcpy(ii->creationDate, (char*)date);
ii->creationDate[10] = 0;
return ii;
}
static IsoInfo* examine_iso(Image *image)
{ AlignedBuffer *ab = CreateAlignedBuffer(2048);
unsigned char *buf = ab->buf;
IsoInfo *ii = NULL;
int sector;
int vdt,vdt_ver;
unsigned char sid[6];
Verbose(" Examining the ISO file system...\n");
/*** Iterate over the volume decriptors */
for(sector=16; sector<32; sector++)
{
#ifndef CLI
if(Closure->stopActions)
continue;
#endif
if(ImageReadSectors(image, buf, sector, 1) != 1)
{ Verbose(" Sector %2d: unreadable\n", sector);
continue;
}
vdt = bp_get_byte(buf, 1); /* Volume descriptor type */
bp_get_string(sid, buf, 2, 6); /* Standard identifier */
vdt_ver = bp_get_byte(buf,7); /* Volume descriptor version */
Verbose(" Sector %2d:\n"
" Volume descriptor type = %d\n"
" Volume descriptor version = %d\n"
" Standard identifier = %s\n",
sector, vdt, vdt_ver, sid);
if(strncmp((char*)sid,"CD001",5))
{ Verbose(" * Wrong or missing standard identifier.\n");
continue;
}
switch(vdt)
{ case 0: Verbose(" -> boot record: *skipped*\n");
break;
case 1: Verbose(" -> primary volume descriptor:\n");
ii = examine_primary_vd(buf);
break;
case 2: Verbose(" -> supplementary volume descriptor: *skipped*\n");
break;
case 255: Verbose(" -> volume descriptor set terminator;\n"
" end of ISO file system parsing.\n");
goto finished;
break;
default : Verbose(" -> unknown volume descriptor: *skipped*\n");
break;
}
}
finished:
FreeAlignedBuffer(ab);
return ii;
}
/***
*** The main wrapper for visiting the ISO and UDF file system structures
***/
void ExamineUDF(Image *image)
{
if(!image) return;
if(image->type == IMAGE_MEDIUM) Verbose("\nExamineUDF(Device: %s)\n", image->dh->devinfo);
if(image->type == IMAGE_FILE ) Verbose("\nExamineUDF(File: %s)\n", image->file->path);
image->isoInfo = examine_iso(image);
Verbose(" Examining the UDF file system...\n");
Verbose(" not yet implemented.\n\n");
}
/***
*** Rudimentary support for creating .iso images.
*** Currently only used for creating the random image;
* can only create .iso images containing exactly one file.
*/
/*
* Directory record writing
*/
static IsoDir* create_iso_dir()
{ IsoDir *id = g_malloc0(sizeof(IsoDir));
id->dir = g_malloc0(2048);
id->nSectors = 1;
return id;
}
static void free_iso_dir(IsoDir *id)
{ g_free(id->dir);
g_free(id);
}
static void 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)
{ unsigned char *dir = iso_dir->dir + iso_dir->tail;
iso_dir->tail += 34;
bp_set_byte(dir, 1, 34); /* Length of directory record */
bp_set_byte(dir, 2, 0); /* Extended attribute length */
bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
bp_set_long_bbo(dir, 11, 2048); /* Data length of file section */
set_binary_date(dir, 19, /* Binary date rep of creation time */
year,month,day,hour,minute,second,gmt_offset);
bp_set_byte(dir, 26, file_flags); /* File flags (we are a directory) */
bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
bp_set_byte(dir, 28, 0); /* Interleave gap size */
bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
bp_set_byte(dir, 33, 1); /* Length of file identifier */
bp_set_byte(dir, 34, file_identifier); /* File identifier */
}
static void 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)
{ unsigned char *dir = iso_dir->dir + iso_dir->tail;
int sl = strlen(filename);
int entry_len = 34+sl;
iso_dir->tail += entry_len;
bp_set_byte(dir, 1, entry_len); /* Length of directory record */
bp_set_byte(dir, 2, 0); /* Extended attribute length */
bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
bp_set_long_bbo(dir, 11, size); /* Data length of file section */
set_binary_date(dir, 19, /* Binary date rep of creation time */
year,month,day,hour,minute,second,gmt_offset);
bp_set_byte(dir, 26, 0); /* File flags (we are a file) */
bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
bp_set_byte(dir, 28, 0); /* Interleave gap size */
bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
bp_set_byte(dir, 33, sl); /* Length of file identifier */
bp_set_string(dir, filename, 34, 34+sl); /* File name */
}
static void 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)
{ unsigned char *dir = iso_dir->dir + iso_dir->tail;
int sl = 2*strlen(filename);
int entry_len = 34+sl;
iso_dir->tail += entry_len;
bp_set_byte(dir, 1, entry_len); /* Length of directory record */
bp_set_byte(dir, 2, 0); /* Extended attribute length */
bp_set_long_bbo(dir, 3, extent); /* Location of Extent */
bp_set_long_bbo(dir, 11, size); /* Data length of file section */
set_binary_date(dir, 19, /* Binary date rep of creation time */
year,month,day,hour,minute,second,gmt_offset);
bp_set_byte(dir, 26, 0); /* File flags (we are a file) */
bp_set_byte(dir, 27, 0); /* File unit size if interleaved */
bp_set_byte(dir, 28, 0); /* Interleave gap size */
bp_set_short_bbo(dir, 29, 1); /* Volume sequence number */
bp_set_byte(dir, 33, sl); /* Length of file identifier */
bp_set_d1_string(dir, filename, 34, 34+sl); /* File name */
}
/*
* Path tables
*/
static IsoPathTable* create_iso_path_table()
{ IsoPathTable *ipt = g_malloc0(sizeof(IsoPathTable));
ipt->lpath = g_malloc0(2048);
ipt->mpath = g_malloc0(2048);
ipt->nSectors = 1;
return ipt;
}
static void free_iso_path_table(IsoPathTable *ipt)
{ g_free(ipt->lpath);
g_free(ipt->mpath);
g_free(ipt);
}
static void add_path(IsoPathTable *ipt, int extent)
{ unsigned char *lpath = ipt->lpath + ipt->tail;
unsigned char *mpath = ipt->mpath + ipt->tail;
bp_set_byte(lpath, 1, 1); /* Length of directory identifier (root=1) */
bp_set_byte(mpath, 1, 1);
bp_set_byte(lpath, 2, 0); /* Extended attribute length */
bp_set_byte(mpath, 2, 0); /* Extended attribute length */
bp_set_long_lsb(lpath, 3, extent); /* Location of extent */
bp_set_long_msb(mpath, 3, extent);
bp_set_short_lsb(lpath, 7, 1); /* Parent directory number */
bp_set_short_msb(mpath, 7, 1);
bp_set_byte(lpath, 9, 0); /* Directory identifier (root=0) */
bp_set_byte(mpath, 9, 0);
}
/*
* Initialize the IsoHeader structure
*/
IsoHeader* InitIsoHeader(void)
{ IsoHeader *ih = g_malloc0(sizeof(IsoHeader));
unsigned char *pvd,*svd;
char blank[128], string[128];
memset(blank, ' ', 128);
/*** Initialize primary volume descriptor (sector 16). */
ih->pvd = pvd = g_malloc0(2048);
ih->dirSectors = 1;
/* 1..8: Standard identifier */
bp_set_byte(pvd, 1, 1); /* Volume descriptor type 1 */
bp_set_string(pvd, "CD001", 2, 6); /* Standard identifier */
bp_set_byte(pvd, 7, 1); /* Volume descriptor version 1 */
/* 9..40: System identifier */
bp_set_string(pvd, blank, 9, 40);
/* 41..72: Volume identifier */
memcpy(string, blank, 128);
memcpy(string, "RANDOM IMAGE", 12);
bp_set_string(pvd, string, 41, 72);
/* 73.. 80: Unused, zero bytes */
/* 81.. 88: Volume space size, filled in at WriteIsoHeader() */
/* 89..120: Unused, zero bytes */
/* 121..124: Volume set size */
bp_set_short_bbo(pvd, 121, 1);
/* 125..128: Volume sequence number */
bp_set_short_bbo(pvd, 125, 1);
/* 129..132: Logical block size */
bp_set_short_bbo(pvd, 129, 2048);
/* 133..140: Path table size, filled in at WriteIsoHeader() */
/* 141..144: L Path table location, filled in at WriteIsoHeader() */
/* 145..148: Optional L Path table location, filled in at WriteIsoHeader() */
/* 149..152: M Path table location, filled in at WriteIsoHeader() */
/* 153..156: Optional M Path table location, filled in at WriteIsoHeader() */
/* 157..190: Directory record for root dir, filled in at WriteIsoHeader() */
/* 191..318: Volume set identifier */
bp_set_string(pvd, blank, 191, 318);
/* 319..446: Publisher identifier */
bp_set_string(pvd, blank, 319, 446);
/* 447..574: Data preparer identifier */
bp_set_string(pvd, blank, 447, 574);
/* 575..702 Application Identfier */
bp_set_string(pvd, blank, 575, 702);
/* 703..739 Copyright File Identifier */
bp_set_string(pvd, blank, 703, 739);
/* 740..776 Abstract File Identifier */
bp_set_string(pvd, blank, 740, 776);
/* 777..813 Bibliographic File Identifier */
bp_set_string(pvd, blank, 777, 813);
/* 814..830 Volume creation time, filled in by WriteIsoHeader() */
/* 831..847 Volume modification time, filled in by WriteIsoHeader() */
/* 848..864 Volume expiration time, filled in by WriteIsoHeader() */
/* 865..881 Volume effective time, filled in by WriteIsoHeader() */
/* 882 File structure version */
bp_set_byte(pvd, 882, 1);
/* 883 Reserved, zero */
/* 884..1395 for application use */
/* 1396..2048 Reserved, zero */
/*** Initialize supplementary volume descriptor (sector 17). */
ih->svd = svd = g_malloc0(2048);
ih->dirSectors = 2;
/* 1..8: Standard identifier */
bp_set_byte(svd, 1, 2); /* Volume descriptor type 1 */
bp_set_string(svd, "CD001", 2, 6); /* Standard identifier */
bp_set_byte(svd, 7, 1); /* Volume descriptor version 1 */
bp_set_byte(svd, 8, 0); /* Volume flags */
/* 9..40: System identifier (zero filled) */
/* 41..72: Volume identifier */
bp_set_d1_string(svd, "random image", 41, 72);
/* 73.. 80: Unused, zero bytes */
/* 81.. 88: Volume space size, filled in at WriteIsoHeader() */
/* 89..120: Escape sequences */
bp_set_byte(svd, 89, 37);
bp_set_byte(svd, 90, 47);
bp_set_byte(svd, 91, 64);
/* 121..124: Volume set size */
bp_set_short_bbo(svd, 121, 1);
/* 125..128: Volume sequence number */
bp_set_short_bbo(svd, 125, 1);
/* 129..132: Logical block size */
bp_set_short_bbo(svd, 129, 2048);
/* 133..140: Path table size, filled in at WriteIsoHeader() */
/* 141..144: L Path table location, filled in at WriteIsoHeader() */
/* 145..148: Optional L Path table location, filled in at WriteIsoHeader() */
/* 149..152: M Path table location, filled in at WriteIsoHeader() */
/* 153..156: Optional M Path table location, filled in at WriteIsoHeader() */
/* 157..190: Directory record for root dir, filled in at WriteIsoHeader() */
/* The standard says to fill the identifier field with blanks,
but actual writing software seems to use zeroes. */
/* 191..318: Volume set identifier */
//bp_set_string(svd, blank, 191, 318);
/* 319..446: Publisher identifier */
//bp_set_string(svd, blank, 319, 446);
/* 447..574: Data preparer identifier */
//bp_set_string(svd, blank, 447, 574);
/* 575..702 Application Identfier */
//bp_set_string(svd, blank, 575, 702);
/* 703..739 Copyright File Identifier */
//bp_set_string(svd, blank, 703, 739);
/* 740..776 Abstract File Identifier */
//bp_set_string(svd, blank, 740, 776);
/* 777..813 Bibliographic File Identifier */
//bp_set_string(svd, blank, 777, 813);
/* 814..830 Volume creation time, filled in by WriteIsoHeader() */
/* 831..847 Volume modification time, filled in by WriteIsoHeader() */
/* 848..864 Volume expiration time, filled in by WriteIsoHeader() */
/* 865..881 Volume effective time, filled in by WriteIsoHeader() */
/* 882 File structure version */
bp_set_byte(svd, 882, 1);
/* 883 Reserved, zero */
/* 884..1395 for application use */
/* 1396..2048 Reserved, zero */
/*** The volume descriptor set terminator (sector 17)
is trivial and created during WriteIsoHeader() */
ih->dirSectors = 3;
/*** Allocate space for directories and path tables */
ih->proot = create_iso_dir();
add_directory_record(ih->proot, 21, 2, 0,
106, 7, 16, 12, 35, 46, 8);
add_directory_record(ih->proot, 21, 2, 1,
106, 7, 16, 12, 35, 46, 8);
ih->ppath = create_iso_path_table();
add_path(ih->ppath, 21);
ih->sroot = create_iso_dir();
add_directory_record(ih->sroot, 24, 2, 0,
106, 7, 16, 12, 35, 46, 8);
add_directory_record(ih->sroot, 24, 2, 1,
106, 7, 16, 12, 35, 46, 8);
ih->spath = create_iso_path_table();
add_path(ih->spath, 24);
ih->dirSectors += 6;
return ih;
}
void FreeIsoHeader(IsoHeader *ih)
{
free_iso_dir(ih->proot);
free_iso_dir(ih->sroot);
free_iso_path_table(ih->ppath);
free_iso_path_table(ih->spath);
g_free(ih->pvd);
g_free(ih->svd);
g_free(ih);
}
/*
* Add file to iso image (works currently only for one file!)
*/
void AddFile(IsoHeader *ih, char *name, guint64 size)
{ static int n;
char iso[22], joliet[strlen(name)+3];
n++;
sprintf(iso,"RAN_%04d.DAT;1", n);
add_file_record(ih->proot, iso, size, 25,
106, 7, 16, 12, 28, 10, 8);
sprintf(joliet,"%s;1", name);
add_d1_file_record(ih->sroot, joliet, size, 25,
106, 7, 16, 12, 28, 10, 8);
ih->volumeSpace += (size+2047)/2048;
}
/*
* Write out the IsoHeader, return number of sectors written
*/
void WriteIsoHeader(IsoHeader *ih, LargeFile *image)
{ unsigned char zero[2048], sector[2048];
unsigned char *pvd,*svd;
int i;
/* The first 16 sectors are zeroed out */
memset(zero, 0, 2048);
for(i=0; i<16; i++)
{ int n = LargeWrite(image, zero, 2048);
if(n != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)i, strerror(errno));
}
/* Complete the primary volume descriptor */
pvd = ih->pvd;
/* 81..88: Volume space size */
ih->volumeSpace += 16 + ih->dirSectors;
bp_set_long_bbo(pvd, 81, ih->volumeSpace);
/* 133..140: Path table size, Fixme: use real values */
/* 141..144: L Path table location */
/* 145..148: Optional L Path table location */
/* 149..152: M Path table location */
/* 153..156: Optional M Path table location */
bp_set_long_bbo(pvd, 133, 10);
bp_set_long_lsb(pvd, 141, 19);
bp_set_long_lsb(pvd, 145, 0);
bp_set_long_msb(pvd, 149, 20);
bp_set_long_msb(pvd, 153, 0);
/* 157..190: Directory record for root directory, Fixme: use real values */
bp_set_byte(pvd, 157, 34); /* Length of directory record */
bp_set_byte(pvd, 158, 0); /* Extended atribute length */
bp_set_long_bbo(pvd, 159, 21); /* Location of Extent */
bp_set_long_bbo(pvd, 167, 2048); /* Data length of file section */
set_binary_date(pvd, 175, /* Binary date rep of creation time */
106, 7, 16, 10, 35, 46, 8);
bp_set_byte(pvd, 182, 2); /* File flags (we are a directory) */
bp_set_byte(pvd, 183, 0); /* File unit size if interleaved */
bp_set_byte(pvd, 184, 0); /* Interleave gap size */
bp_set_short_bbo(pvd, 185, 1); /* Volume sequence number */
bp_set_byte(pvd, 189, 1); /* Length of file identifier */
bp_set_byte(pvd, 190, 0); /* File identifier */
/* 814..830 Volume creation time */
set_date(pvd, 814, 2006, 7, 16, 10, 35, 46, 23, 8);
/* 831..847 Volume modification time */
set_date(pvd, 831, 2006, 7, 16, 10, 35, 46, 23, 8);
/* 848..864 Volume expiration time */
set_date(pvd, 848, 2106, 7, 16, 10, 35, 46, 23, 8);
/* 865..881 Volume effective time */
set_date(pvd, 865, 2006, 7, 16, 10, 35, 46, 23, 8);
/* Write the pvd */
if(LargeWrite(image, pvd, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)16, strerror(errno));
/* Create the supplementary volume descriptor */
svd = ih->svd;
/* 81..88: Volume space size */
bp_set_long_bbo(svd, 81, ih->volumeSpace);
/* 133..140: Path table size, Fixme: use real values */
/* 141..144: L Path table location */
/* 145..148: Optional L Path table location */
/* 149..152: M Path table location */
/* 153..156: Optional M Path table location */
bp_set_long_bbo(svd, 133, 10);
bp_set_long_lsb(svd, 141, 22);
bp_set_long_lsb(svd, 145, 0);
bp_set_long_msb(svd, 149, 23);
bp_set_long_msb(svd, 153, 0);
/* 157..190: Directory record for root directory, Fixme: use real values */
bp_set_byte(svd, 157, 34); /* Length of directory record */
bp_set_byte(svd, 158, 0); /* Extended attribute length */
bp_set_long_bbo(svd, 159, 24); /* Location of Extent */
bp_set_long_bbo(svd, 167, 2048); /* Data length of file section */
set_binary_date(svd, 175, /* Binary date rep of creation time */
106, 7, 16, 10, 35, 46, 8);
bp_set_byte(svd, 182, 2); /* File flags (we are a directory) */
bp_set_byte(svd, 183, 0); /* File unit size if interleaved */
bp_set_byte(svd, 184, 0); /* Interleave gap size */
bp_set_short_bbo(svd, 185, 1); /* Volume sequence number */
bp_set_byte(svd, 189, 1); /* Length of file identifier */
bp_set_byte(svd, 190, 0); /* File identifier */
/* 814..830 Volume creation time */
set_date(svd, 814, 2006, 7, 16, 10, 35, 46, 23, 8);
/* 831..847 Volume modification time */
set_date(svd, 831, 2006, 7, 16, 10, 35, 46, 23, 8);
/* 848..864 Volume expiration time */
set_date(svd, 848, 2106, 7, 16, 10, 35, 46, 23, 8);
/* 865..881 Volume effective time */
set_date(svd, 865, 2006, 7, 16, 10, 35, 46, 23, 8);
/* Write the svd */
if(LargeWrite(image, svd, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)17, strerror(errno));
/*** Create and write the volume descriptor set terminator */
/* 1..8: Standard identifier */
memset(sector, 0, 2048);
bp_set_byte(sector, 1, 255); /* Volume descriptor set terminator */
bp_set_string(sector, "CD001", 2, 6); /* Standard identifier */
bp_set_byte(sector, 7, 1); /* Volume descriptor version 1 */
if(LargeWrite(image, sector, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)18, strerror(errno));
/*** Write the primary and supplementary path tables and root directories */
if(LargeWrite(image, ih->ppath->lpath, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)19, strerror(errno));
if(LargeWrite(image, ih->ppath->mpath, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)20, strerror(errno));
if(LargeWrite(image, ih->proot->dir, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)21, strerror(errno));
if(LargeWrite(image, ih->spath->lpath, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)22, strerror(errno));
if(LargeWrite(image, ih->spath->mpath, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)23, strerror(errno));
if(LargeWrite(image, ih->sroot->dir, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), (gint64)24, strerror(errno));
}