legacy/libisoburn/trunk/src/isofs_wrap.c

280 lines
7.1 KiB
C
Raw Normal View History

2007-09-01 18:20:53 +00:00
/*
cc -g -c isofs_wrap.c
*/
/*
libisofs related functions of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
2007-09-01 18:20:53 +00:00
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
2007-09-21 15:15:38 +00:00
#include <libburn.h>
#include <libisofs.h>
#include "isoburn.h"
2007-09-01 18:20:53 +00:00
/* Vreixo:
This is now all yours. My text here is only a snapshot
of what i think we discussed in the last days.
If you change the prototypes of the functions listed
in this initial stub, then you have to change isoburn.h
and eventually libisoburn.h. And you have to tell me so
i can adjust burn_wrap.c .
*/
#define BP(a,b) [(b) - (a) + 1]
struct ecma119_pri_vol_desc
{
uint8_t vol_desc_type BP(1, 1);
uint8_t std_identifier BP(2, 6);
uint8_t vol_desc_version BP(7, 7);
uint8_t unused1 BP(8, 8);
uint8_t system_id BP(9, 40);
uint8_t volume_id BP(41, 72);
uint8_t unused2 BP(73, 80);
uint8_t vol_space_size BP(81, 88);
uint8_t unused3 BP(89, 120);
uint8_t vol_set_size BP(121, 124);
uint8_t vol_seq_number BP(125, 128);
uint8_t block_size BP(129, 132);
uint8_t path_table_size BP(133, 140);
uint8_t l_path_table_pos BP(141, 144);
uint8_t opt_l_path_table_pos BP(145, 148);
uint8_t m_path_table_pos BP(149, 152);
uint8_t opt_m_path_table_pos BP(153, 156);
uint8_t root_dir_record BP(157, 190);
uint8_t vol_set_id BP(191, 318);
uint8_t publisher_id BP(319, 446);
uint8_t data_prep_id BP(447, 574);
uint8_t application_id BP(575, 702);
uint8_t copyright_file_id BP(703, 739);
uint8_t abstract_file_id BP(740, 776);
uint8_t bibliographic_file_id BP(777, 813);
uint8_t vol_creation_time BP(814, 830);
uint8_t vol_modification_time BP(831, 847);
uint8_t vol_expiration_time BP(848, 864);
uint8_t vol_effective_time BP(865, 881);
uint8_t file_structure_version BP(882, 882);
uint8_t reserved1 BP(883, 883);
uint8_t app_use BP(884, 1395);
uint8_t reserved2 BP(1396, 2048);
};
static
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
{
int i;
uint32_t ret = 0;
for (i=0; i<bytes; i++) {
ret += ((uint32_t) buf[i]) << (i*8);
}
return ret;
}
/* API function. See libisoburn.h
*/
int isoburn_read_volset(struct burn_drive *d, struct isoburn_read_opts *read_opts,
struct iso_volset **volset)
{
int ret;
struct ecma119_read_opts ropts;
struct data_source *src;
struct isoburn *o;
assert(d && read_opts && volset);
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0)
return 0;
2007-09-13 10:29:49 +00:00
if (o->fabricated_disc_status == BURN_DISC_BLANK) {
// FIXME construct an empty volset!!
*volset = NULL;
return 1;
}
ret = isoburn_disc_get_msc1(d, &ropts.block);
if (ret < 0)
return -1;
ropts.norock = read_opts->norock;
ropts.nojoliet = read_opts->nojoliet;
ropts.preferjoliet = read_opts->preferjoliet;
ropts.mode = read_opts->mode;
ropts.uid = read_opts->uid;
ropts.gid = read_opts->gid;
src = isoburn_data_source_new(d);
if (!src)
return -2;
*volset = iso_volset_read(src, &ropts);
data_source_free(src);
if (!(*volset))
return -3;
o->target_volset = *volset;
read_opts->hasRR = ropts.hasRR;
read_opts->hasJoliet = ropts.hasJoliet;
return 1;
}
2007-09-01 18:20:53 +00:00
/* API function. See libisoburn.h
*/
int isoburn_activate_session(struct burn_drive *drive)
2007-09-01 18:20:53 +00:00
{
int ret;
struct isoburn *o;
2007-09-01 18:20:53 +00:00
ret = isoburn_find_emulator(&o, drive, 0);
if (ret < 0)
return -1;
2007-09-01 18:20:53 +00:00
if (o->emulation_mode != 1)
return 1; /* don't need to activate session */
ret = burn_random_access_write(drive, 0, o->target_iso_head, 64*2048, 0);
return ret;
2007-09-01 18:20:53 +00:00
}
/** Allocate and initialize memory for libisofs related objects in
struct isoburn.
@param o A freshly created isoburn object with NULL pointers
@return <=0 error , 1 = success
*/
int isoburn_new_rwopts(struct isoburn *o)
{
struct ecma119_source_opts *wopts;
2007-09-01 18:20:53 +00:00
/* create and initialize target_ropts read options */
o->target_ropts = calloc(1, sizeof(struct ecma119_read_opts));
if (!p->target_ropts)
return -1;
/* TODO mmm, maybe we don't need struct ecma119_read_opts in libisoburn */
2007-09-01 18:20:53 +00:00
/* create and initialize new_wopts write options for new image */
wopts = calloc(1, sizeof(struct ecma119_source_opts));
if (!wopts)
return -1;
wopts->overwrite = o->target_iso_head;
o->new_wopts = wopts;
return 1;
2007-09-01 18:20:53 +00:00
}
/** Dispose memory objects created by isoburn_new_rwopts(). This function
expect that the pointers in struct isoburn might still be NULL, i.e.
that isoburn_new_rwopts() was not called before.
@return <=0 error , 1 = success
*/
int isoburn_free_rwopts(struct isoburn *o)
{
free(o->target_ropts);
free(o->new_wopts);
return 1;
2007-09-01 18:20:53 +00:00
}
/** Initialize the emulation of multi-session on random access media.
The need for emulation is confirmed already.
@param o A freshly created isoburn object. isoburn_new_rwopts() was
already called, nevertheless.
@return <=0 error , 1 = success
*/
int isoburn_start_emulation(struct isoburn *o, int flag)
{
int ret, i;
off_t *data_count;
struct burn_drive *drive;
struct ecma119_pri_vol_desc *pvm;
drive= o->drive;
/* we can assume 0 as start block for image */
// TODO what about ms? where we validate valid iso image in ms disc?
ret = burn_read_data(drive, (off_t) 0, o->target_iso_head,
sizeof(o->target_iso_head), &data_count, 0);
// TODO mmm, can a read error mean an empty disc (e.g. CD-R)?
if (ret <= 0)
return -1;
/* check first 64K. If 0's, the disc is treated as a blank disc, and thus
overwritten without extra check. */
i = sizeof(o->target_iso_head);
while (i && !o->target_iso_head[i-1])
--i;
if (!i) {
o->fabricated_disc_status= BURN_DISC_BLANK;
2007-09-13 10:29:49 +00:00
return 1;
}
pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048);
if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) {
off_t size;
/* sanity check */
if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1
|| pvm->file_structure_version[0] != 1 ) {
// TODO for now I treat this as a full disc
o->fabricated_disc_status= BURN_DISC_FULL;
return 1;
}
/* ok, PVM found, set size */
size = (off_t) iso_read_lsb(pvm->vol_space_size, 4);
size *= (off_t) 2048; /* block size in bytes */
isoburn_set_start_byte(o, size, 0);
2007-09-13 10:29:49 +00:00
o->fabricated_disc_status= BURN_DISC_APPENDABLE;
} else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) {
/* empty image */
isoburn_set_start_byte(o, (off_t) 0, 0);
2007-09-13 10:29:49 +00:00
o->fabricated_disc_status= BURN_DISC_BLANK;
} else {
/* treat any disc in an unknown format as full */
o->fabricated_disc_status= BURN_DISC_FULL;
}
return 1;
2007-09-01 18:20:53 +00:00
}
/** Alters and writes the first 64 kB of a "media" to invalidate
2007-09-01 18:20:53 +00:00
an ISO image. (It shall stay restorable by skilled humans, though).
The result shall especially keep libisoburn from accepting the media
2007-09-01 18:20:53 +00:00
image as ISO filesystem.
@param o A fully activated isoburn object. isoburn_start_emulation()
was already called.
@return <=0 error , 1 = success
*/
int isoburn_invalidate_iso(struct isoburn *o, int flag)
{
/*
* replace CD001 with CDXX1 in PVM.
* I think this is enought for invalidating an iso image
*/
strncpy(o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5);
return isoburn_activate_session(o->drive);
2007-09-01 18:20:53 +00:00
}