Implemented basic eltorito
This commit is contained in:
parent
f3f835f2be
commit
a3f32e1093
@ -31,7 +31,9 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/hash.h \
|
||||
libisofs/hash.c \
|
||||
libisofs/file.h \
|
||||
libisofs/file.c
|
||||
libisofs/file.c \
|
||||
libisofs/eltorito.h \
|
||||
libisofs/eltorito.c
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libisofs/libisofs.h
|
||||
|
29
libisofs/trunk/TODO
Normal file
29
libisofs/trunk/TODO
Normal file
@ -0,0 +1,29 @@
|
||||
FEATURES
|
||||
========
|
||||
|
||||
El-Torito
|
||||
Support for multiple images
|
||||
HFS/HFS+
|
||||
CD reading
|
||||
Multisession
|
||||
UDF
|
||||
ISO relaxed contraints
|
||||
ISO 9660:1998
|
||||
|
||||
Support for special files (only dirs, reg. files and symlinks are supported).
|
||||
|
||||
TESTS
|
||||
=====
|
||||
|
||||
For all
|
||||
|
||||
IMPLEMENTATION
|
||||
==============
|
||||
|
||||
a way to return NULL sources meaning a failure!!
|
||||
Error message queue
|
||||
Public API for all things already implemented
|
||||
Better charset support
|
||||
default input charset to locale one, no always UTF-8
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "file.h"
|
||||
#include "libisofs.h"
|
||||
#include "libburn/libburn.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
/* burn-source compatible stuff */
|
||||
static int
|
||||
@ -78,6 +79,7 @@ static const write_fn writers[] =
|
||||
NULL,
|
||||
wr_system_area,
|
||||
wr_pri_vol_desc,
|
||||
el_torito_wr_boot_vol_desc,
|
||||
joliet_wr_sup_vol_desc,
|
||||
wr_vol_desc_term,
|
||||
wr_l_path_table,
|
||||
@ -86,6 +88,7 @@ static const write_fn writers[] =
|
||||
joliet_wr_m_path_table,
|
||||
wr_dir_records,
|
||||
joliet_wr_dir_records,
|
||||
el_torito_wr_catalog,
|
||||
wr_files
|
||||
};
|
||||
|
||||
@ -297,6 +300,9 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
|
||||
t->catalog = volset->volume[volnum]->bootcat;
|
||||
t->eltorito = t->catalog ? 1 : 0;
|
||||
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
if (t->joliet)
|
||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||
@ -337,6 +343,8 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
+ 1 /* volume desc */
|
||||
+ 1; /* volume desc terminator */
|
||||
|
||||
if (t->eltorito)
|
||||
t->curblock += 1; /* boot record volume descriptor */
|
||||
if (t->joliet) /* supplementary vol desc */
|
||||
t->curblock += div_up (2048, t->block_size);
|
||||
|
||||
@ -363,7 +371,20 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
/* reset curfile when we're finished */
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
/* el-torito? */
|
||||
if (t->eltorito) {
|
||||
|
||||
/* add catalog block */
|
||||
t->catalog->file->block = t->curblock;
|
||||
t->curblock += div_up(2048, t->block_size);
|
||||
el_torito_get_image_files(t);
|
||||
}
|
||||
|
||||
calc_file_pos(t, t->root);
|
||||
|
||||
if (t->eltorito)
|
||||
el_torito_patch_image_files(t);
|
||||
|
||||
if (t->rockridge) {
|
||||
susp_finalize(t, t->root);
|
||||
@ -389,11 +410,19 @@ is_joliet_state(enum ecma119_write_state state)
|
||||
|| state == ECMA119_WRITE_DIR_RECORDS_JOLIET;
|
||||
}
|
||||
|
||||
static int
|
||||
is_eltorito_state(enum ecma119_write_state state)
|
||||
{
|
||||
return state == ECMA119_WRITE_ELTORITO_BOOT_VOL_DESC
|
||||
|| state == ECMA119_WRITE_ELTORITO_CATALOG;
|
||||
}
|
||||
|
||||
static void
|
||||
next_state(struct ecma119_write_target *t)
|
||||
{
|
||||
t->state++;
|
||||
while (!t->joliet && is_joliet_state(t->state))
|
||||
while ( (!t->joliet && is_joliet_state(t->state))
|
||||
||(!t->eltorito && is_eltorito_state(t->state)) )
|
||||
t->state++;
|
||||
|
||||
printf ("now in state %d, curblock=%d\n", (int)t->state, (int)t->curblock);
|
||||
|
@ -29,6 +29,7 @@ enum ecma119_write_state
|
||||
|
||||
ECMA119_WRITE_SYSTEM_AREA,
|
||||
ECMA119_WRITE_PRI_VOL_DESC,
|
||||
ECMA119_WRITE_ELTORITO_BOOT_VOL_DESC,
|
||||
ECMA119_WRITE_SUP_VOL_DESC_JOLIET,
|
||||
ECMA119_WRITE_VOL_DESC_TERMINATOR,
|
||||
ECMA119_WRITE_L_PATH_TABLE,
|
||||
@ -37,6 +38,7 @@ enum ecma119_write_state
|
||||
ECMA119_WRITE_M_PATH_TABLE_JOLIET,
|
||||
ECMA119_WRITE_DIR_RECORDS,
|
||||
ECMA119_WRITE_DIR_RECORDS_JOLIET,
|
||||
ECMA119_WRITE_ELTORITO_CATALOG,
|
||||
ECMA119_WRITE_FILES,
|
||||
|
||||
ECMA119_WRITE_DONE
|
||||
@ -61,6 +63,9 @@ struct ecma119_write_target
|
||||
unsigned int rockridge:1;
|
||||
unsigned int joliet:1;
|
||||
unsigned int iso_level:2;
|
||||
unsigned int eltorito:1;
|
||||
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
int replace_mode; /**< Replace ownership and modes of files
|
||||
*
|
||||
@ -252,6 +257,17 @@ struct ecma119_sup_vol_desc
|
||||
uint8_t reserved2 BP(1396, 2048);
|
||||
};
|
||||
|
||||
struct ecma119_boot_rec_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 boot_sys_id BP(8, 39);
|
||||
uint8_t boot_id BP(40, 71);
|
||||
uint8_t boot_catalog BP(72, 75);
|
||||
uint8_t unused BP(76, 2048);
|
||||
};
|
||||
|
||||
struct ecma119_vol_desc_terminator
|
||||
{
|
||||
uint8_t vol_desc_type BP(1, 1);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "ecma119_tree.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
static size_t calc_dirent_len(struct ecma119_tree_node *n)
|
||||
{
|
||||
@ -200,6 +201,33 @@ create_symlink(struct ecma119_write_target *t,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_boot_catalog(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_boot_catalog *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
struct iso_file *file;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
/*
|
||||
* This will simply create a ECMA119 file, with the only difference
|
||||
* that the iso_file is not taken from table, but from boot catalog
|
||||
*/
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->type = ECMA119_FILE;
|
||||
|
||||
file = iso->catalog->file;
|
||||
file->ino = ++t->ino;
|
||||
|
||||
ret->attrib.st_nlink = file->nlink;
|
||||
ret->attrib.st_ino = file->ino;
|
||||
ret->info.file = file;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ecma119_tree_node*
|
||||
create_tree(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
@ -212,18 +240,18 @@ create_tree(struct ecma119_write_target *t,
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_RR )
|
||||
return NULL;
|
||||
|
||||
switch (iso->attrib.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
switch ( iso->type ) {
|
||||
case LIBISO_NODE_FILE:
|
||||
ret = create_file(t, parent, (struct iso_tree_node_file*)iso);
|
||||
break;
|
||||
case S_IFLNK:
|
||||
case LIBISO_NODE_SYMLINK:
|
||||
if ( !t->rockridge )
|
||||
printf("Can't add symlinks to a non ISO tree. Skipping %s \n",
|
||||
iso->name);
|
||||
else
|
||||
ret = create_symlink(t, parent, (struct iso_tree_node_symlink*)iso);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
case LIBISO_NODE_DIR:
|
||||
{
|
||||
size_t i;
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir*)iso;
|
||||
@ -236,6 +264,10 @@ create_tree(struct ecma119_write_target *t,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
ret = create_boot_catalog(t, parent,
|
||||
(struct iso_tree_node_boot_catalog*)iso);
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
assert( 0 );
|
||||
|
@ -17,7 +17,7 @@
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
|
||||
enum {
|
||||
enum ecma119_node_type {
|
||||
ECMA119_FILE,
|
||||
ECMA119_SYMLINK,
|
||||
ECMA119_DIR,
|
||||
@ -58,14 +58,13 @@ struct ecma119_tree_node
|
||||
* not including SU. */
|
||||
|
||||
struct ecma119_tree_node *parent;
|
||||
/*struct iso_tree_node *iso_self;*/
|
||||
struct ecma119_write_target *target;
|
||||
|
||||
struct stat attrib;
|
||||
|
||||
struct susp_info susp;
|
||||
|
||||
int type; /**< file, symlink, directory or placeholder */
|
||||
enum ecma119_node_type type; /**< file, symlink, directory or placeholder */
|
||||
union {
|
||||
struct iso_file *file;
|
||||
char *dest;
|
||||
|
454
libisofs/trunk/libisofs/eltorito.c
Normal file
454
libisofs/trunk/libisofs/eltorito.c
Normal file
@ -0,0 +1,454 @@
|
||||
#include "libisofs.h"
|
||||
|
||||
#include "eltorito.h"
|
||||
#include "volume.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
struct el_torito_validation_entry {
|
||||
uint8_t header_id BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t reserved BP(3, 4);
|
||||
uint8_t id_string BP(5, 28);
|
||||
uint8_t checksum BP(29, 30);
|
||||
uint8_t key_byte1 BP(31, 31);
|
||||
uint8_t key_byte2 BP(32, 32);
|
||||
};
|
||||
|
||||
struct el_torito_default_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t unused2 BP(13, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_header_entry {
|
||||
uint8_t header_indicator BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t number BP(3, 4);
|
||||
uint8_t character BP(5, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t selec_criteria BP(13, 13);
|
||||
uint8_t vendor_sc BP(14, 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* This table should be written with accuracy values at offset
|
||||
* 8 of boot image, when used ISOLINUX boot loader
|
||||
*/
|
||||
struct boot_info_table {
|
||||
uint8_t bi_pvd BP(1, 4); /* LBA of primary volume descriptor */
|
||||
uint8_t bi_file BP(5, 8); /* LBA of boot file */
|
||||
uint8_t bi_length BP(9, 12); /* Length of boot file */
|
||||
uint8_t bi_csum BP(13, 16); /* Checksum of boot file */
|
||||
uint8_t bi_reserved BP(17, 56); /* Reserved */
|
||||
};
|
||||
|
||||
struct partition_desc {
|
||||
uint8_t boot_ind;
|
||||
uint8_t begin_chs[3];
|
||||
uint8_t type;
|
||||
uint8_t end_chs[3];
|
||||
uint8_t start[4];
|
||||
uint8_t size[4];
|
||||
};
|
||||
|
||||
struct hard_disc_mbr {
|
||||
uint8_t code_area[440];
|
||||
uint8_t opt_disk_sg[4];
|
||||
uint8_t pad[2];
|
||||
struct partition_desc partition[4];
|
||||
uint8_t sign1;
|
||||
uint8_t sign2;
|
||||
};
|
||||
|
||||
static struct el_torito_boot_image *
|
||||
create_image(struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type)
|
||||
{
|
||||
struct el_torito_boot_image *boot;
|
||||
int boot_media_type = 0;
|
||||
int load_sectors = 0; /* number of sector to load */
|
||||
unsigned char partition_type = 0;
|
||||
|
||||
switch (type) {
|
||||
case ELTORITO_FLOPPY_EMUL:
|
||||
switch (image->attrib.st_size) {
|
||||
case 1200 * 1024:
|
||||
boot_media_type = 1; /* 1.2 meg diskette */
|
||||
break;
|
||||
case 1440 * 1024:
|
||||
boot_media_type = 2; /* 1.44 meg diskette */
|
||||
break;
|
||||
case 2880 * 1024:
|
||||
boot_media_type = 3; /* 2.88 meg diskette */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid image size %d Kb. Must be one of 1.2, 1.44"
|
||||
"or 2.88 Mb", (int) image->attrib.st_size / 1024);
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE_SIZE;
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
/* it seems that for floppy emulation we need to load
|
||||
* a single sector (512b) */
|
||||
load_sectors = 1;
|
||||
break;
|
||||
case ELTORITO_HARD_DISC_EMUL:
|
||||
{
|
||||
size_t i;
|
||||
int fd;
|
||||
struct hard_disc_mbr mbr;
|
||||
int used_partition;
|
||||
|
||||
/* read the MBR on disc and get the type of the partition */
|
||||
fd = open(((struct iso_tree_node_file*)image)->path, O_RDONLY);
|
||||
if ( fd == -1 ) {
|
||||
fprintf(stderr, "Can't open image file\n");
|
||||
return NULL;
|
||||
}
|
||||
if ( read(fd, &mbr, sizeof(mbr)) ) {
|
||||
fprintf(stderr, "Can't read MBR from image file\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* check valid MBR signature */
|
||||
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
||||
fprintf(stderr, "Invalid MBR. Wrong signature.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ensure single partition */
|
||||
used_partition = -1;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (mbr.partition[i].type != 0) {
|
||||
/* it's an used partition */
|
||||
if (used_partition != -1) {
|
||||
fprintf(stderr, "Invalid MBR. At least 2 paritions: %d and "
|
||||
"%d, are being used\n", used_partition, i);
|
||||
return NULL;
|
||||
} else
|
||||
used_partition = i;
|
||||
}
|
||||
}
|
||||
partition_type = mbr.partition[used_partition].type;
|
||||
}
|
||||
boot_media_type = 4;
|
||||
|
||||
/* only load the MBR */
|
||||
load_sectors = 1;
|
||||
break;
|
||||
case ELTORITO_NO_EMUL:
|
||||
boot_media_type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
boot = calloc(1, sizeof(struct el_torito_boot_image));
|
||||
boot->bootable = 1;
|
||||
boot->image = (struct iso_tree_node_file *) image;
|
||||
boot->type = boot_media_type;
|
||||
boot->load_size = load_sectors;
|
||||
boot->partition_type = partition_type;
|
||||
return boot;
|
||||
}
|
||||
|
||||
static struct iso_tree_node_boot_catalog*
|
||||
create_boot_catalog_node(struct iso_tree_node_dir *parent,
|
||||
const char *name)
|
||||
{
|
||||
struct iso_tree_node_boot_catalog *boot;
|
||||
|
||||
assert( parent && name );
|
||||
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot_catalog));
|
||||
boot->node.attrib.st_mode = S_IFREG | 0444;
|
||||
boot->node.attrib.st_atime =
|
||||
boot->node.attrib.st_mtime =
|
||||
boot->node.attrib.st_ctime = time(NULL);
|
||||
boot->node.type = LIBISO_NODE_BOOTCATALOG;
|
||||
boot->node.name = strdup(name);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) boot);
|
||||
return boot;
|
||||
}
|
||||
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name)
|
||||
{
|
||||
struct el_torito_boot_image *boot_image;
|
||||
struct iso_tree_node_boot_catalog *boot_node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
assert( volume && !volume->bootcat);
|
||||
assert( image && ISO_ISREG(image) && dir && name);
|
||||
|
||||
boot_image = create_image(image, type);
|
||||
if ( !boot_image )
|
||||
return NULL;
|
||||
|
||||
/* creates the catalog with the given default image */
|
||||
catalog = malloc(sizeof(struct el_torito_boot_catalog));
|
||||
catalog->nentries = 1;
|
||||
catalog->entries = malloc(sizeof(struct el_torito_boot_image *));
|
||||
catalog->entries[0] = boot_image;
|
||||
catalog->file = malloc(sizeof(struct iso_file));
|
||||
catalog->file->size = 2048;
|
||||
|
||||
/* add catalog file */
|
||||
boot_node = create_boot_catalog_node(dir, name);
|
||||
boot_node->catalog = catalog;
|
||||
|
||||
volume->bootcat = catalog;
|
||||
|
||||
return boot_image;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_load_seg(struct el_torito_boot_image *bootimg, int segment)
|
||||
{
|
||||
if (bootimg->type != ELTORITO_NO_EMUL)
|
||||
return;
|
||||
bootimg->load_seg = segment;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_load_size(struct el_torito_boot_image *bootimg, int sectors)
|
||||
{
|
||||
if (bootimg->type != ELTORITO_NO_EMUL)
|
||||
return;
|
||||
bootimg->load_size = sectors;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_no_bootable(struct el_torito_boot_image *bootimg)
|
||||
{
|
||||
bootimg->bootable = 0;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg)
|
||||
{
|
||||
bootimg->patch_isolinux = 1;
|
||||
}
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
free(cat->entries[i]);
|
||||
}
|
||||
free(cat->entries);
|
||||
free(cat->file);
|
||||
free(cat);
|
||||
}
|
||||
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
|
||||
struct iso_tree_node_file *image = cat->entries[i]->image;
|
||||
struct iso_file *file = iso_file_table_lookup(t->file_table, image);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(image);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
cat->entries[i]->file = file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
static void
|
||||
write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
struct ecma119_boot_rec_vol_desc *vol =
|
||||
(struct ecma119_boot_rec_vol_desc*)buf;
|
||||
|
||||
assert(cat);
|
||||
|
||||
vol->vol_desc_type[0] = 0;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
memcpy(vol->boot_sys_id, "EL TORITO SPECIFICATION", 23);
|
||||
iso_lsb(vol->boot_catalog, cat->file->block, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
write_validation_entry(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
size_t i;
|
||||
int checksum;
|
||||
|
||||
struct el_torito_validation_entry *ve =
|
||||
(struct el_torito_validation_entry*)buf;
|
||||
ve->header_id[0] = 1;
|
||||
ve->platform_id[0] = 0; /* 0: 80x86, 1: PowerPC, 2: Mac */
|
||||
ve->key_byte1[0] = 0x55;
|
||||
ve->key_byte2[0] = 0xAA;
|
||||
|
||||
/* calculate the checksum, to ensure sum of all words is 0 */
|
||||
checksum = 0;
|
||||
for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) {
|
||||
checksum -= buf[i];
|
||||
checksum -= (buf[i] << 8);
|
||||
}
|
||||
iso_lsb(ve->checksum, checksum, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
patch_boot_file(struct el_torito_boot_image *img)
|
||||
{
|
||||
struct boot_info_table info;
|
||||
int fd;
|
||||
uint32_t checksum;
|
||||
ssize_t len;
|
||||
uint8_t buf[4];
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
/* open image */
|
||||
fd = open(img->image->path, O_RDWR);
|
||||
if ( fd == -1 ) {
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute checksum, as the the sum of all 32 bit words in boot image
|
||||
* from offset 64 */
|
||||
checksum = 0;
|
||||
lseek(fd, (off_t) 64, SEEK_SET);
|
||||
|
||||
//TODO this can (must) be optimizied by reading to a longer buffer
|
||||
while ( (len = read(fd, buf, 4) ) == 4 ) {
|
||||
checksum += iso_read_lsb(buf, 4);
|
||||
}
|
||||
if ( len != 0 ) {
|
||||
/* error reading file, or file length not multiple of 4 */
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill boot info table */
|
||||
iso_lsb(info.bi_pvd, 16, 4); //FIXME this should be changed when we implement ms
|
||||
iso_lsb(info.bi_file, img->file->block, 4);
|
||||
iso_lsb(info.bi_length, img->image->node.attrib.st_size, 4);
|
||||
iso_lsb(info.bi_csum, checksum, 4);
|
||||
|
||||
/* patch file */
|
||||
lseek(fd, (off_t) 8, SEEK_SET);
|
||||
write(fd, &info, sizeof(info));
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_patch_image_files(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
|
||||
for (i = 0; i < cat->nentries; ++i) {
|
||||
struct el_torito_boot_image *img = cat->entries[i];
|
||||
if ( img->patch_isolinux )
|
||||
patch_boot_file(img);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one section entry.
|
||||
* Currently this is used for both default and other entries since we
|
||||
* put selection criteria no 0 (no sel. criteria)
|
||||
*/
|
||||
static void
|
||||
write_section_entry(uint8_t *buf, struct el_torito_boot_image *img)
|
||||
{
|
||||
struct el_torito_section_entry *se =
|
||||
(struct el_torito_section_entry*)buf;
|
||||
|
||||
se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
|
||||
se->boot_media_type[0] = img->type;
|
||||
iso_lsb(se->load_seg, img->load_seg, 2);
|
||||
se->system_type[0] = 0; //TODO need to get the partition type
|
||||
iso_lsb(se->sec_count, img->load_size, 2);
|
||||
iso_lsb(se->block, img->file->block, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write El-Torito Boot Catalog
|
||||
*/
|
||||
static void
|
||||
write_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
assert(cat->nentries >= 1 && cat->nentries < 63);
|
||||
|
||||
write_validation_entry(t, buf);
|
||||
|
||||
/* write default entry */
|
||||
write_section_entry(buf + 32, cat->entries[0]);
|
||||
|
||||
//TODO write all images
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
assert(t->catalog);
|
||||
ecma119_start_chunking(t,
|
||||
write_boot_vol_desc,
|
||||
2048,
|
||||
buf);
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
assert(t->catalog);
|
||||
ecma119_start_chunking(t,
|
||||
write_catalog,
|
||||
2048,
|
||||
buf);
|
||||
}
|
60
libisofs/trunk/libisofs/eltorito.h
Normal file
60
libisofs/trunk/libisofs/eltorito.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef ELTORITO_H_
|
||||
#define ELTORITO_H_
|
||||
|
||||
#include "tree.h"
|
||||
#include "file.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
/**
|
||||
* Location of the boot catalog
|
||||
*/
|
||||
struct iso_tree_node_boot_catalog
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
};
|
||||
|
||||
struct el_torito_boot_catalog {
|
||||
int nentries;
|
||||
struct el_torito_boot_image **entries;
|
||||
struct iso_file *file; /**< The catalog file */
|
||||
};
|
||||
|
||||
struct el_torito_boot_image {
|
||||
unsigned char bootable; /**< If the entry is bootable. */
|
||||
unsigned char patch_isolinux; /**< If the image will be patched */
|
||||
unsigned char type; /**< The type of image */
|
||||
unsigned char partition_type; /**< type of partition for HD-emul images */
|
||||
short load_seg; /**< Load segment for the initial boot image. */
|
||||
short load_size; /**< Number of sector to load. */
|
||||
struct iso_tree_node_file *image;
|
||||
struct iso_file *file;
|
||||
};
|
||||
|
||||
/*struct el_torito_boot_entry *
|
||||
el_torito_add_boot_entry(struct el_torito_boot_catalog *cat,
|
||||
struct iso_tree_node_file *image);
|
||||
*/
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat);
|
||||
|
||||
/**
|
||||
* For each boot image file, this gets the related iso_file object.
|
||||
* In most cases, the file is already in the hash table. However, if the
|
||||
* boot record is hidden in both ISO/RR and joliet trees, this ensures
|
||||
* that boot images will be written to image.
|
||||
*/
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t);
|
||||
|
||||
/**
|
||||
* Patch image files if selected. This is needed for isolinux boot images
|
||||
*/
|
||||
void el_torito_patch_image_files(struct ecma119_write_target *t);
|
||||
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
#endif /*ELTORITO_H_*/
|
@ -7,6 +7,7 @@
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -28,7 +29,7 @@ create_node(struct ecma119_write_target *t,
|
||||
struct iso_tree_node_dir *dir = (struct iso_tree_node_dir *) iso;
|
||||
ret->info.dir.children = calloc(sizeof(void*), dir->nchildren);
|
||||
ret->type = JOLIET_DIR;
|
||||
} else {
|
||||
} else if (ISO_ISREG(iso)) {
|
||||
/* it's a file */
|
||||
struct iso_tree_node_file *iso_f = (struct iso_tree_node_file *) iso;
|
||||
struct iso_file *file;
|
||||
@ -39,6 +40,14 @@ create_node(struct ecma119_write_target *t,
|
||||
}
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
} else {
|
||||
/* it's boot catalog info */
|
||||
struct iso_tree_node_boot_catalog *iso_b =
|
||||
(struct iso_tree_node_boot_catalog *) iso;
|
||||
struct iso_file *file;
|
||||
file = iso_b->catalog->file;
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -55,11 +64,12 @@ create_tree(struct ecma119_write_target *t,
|
||||
if ( iso->hide_flags & LIBISO_HIDE_ON_JOLIET )
|
||||
return NULL;
|
||||
|
||||
switch (iso->attrib.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
switch (iso->type) {
|
||||
case LIBISO_NODE_FILE:
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
root = create_node(t, parent, iso);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
case LIBISO_NODE_DIR:
|
||||
{
|
||||
size_t i;
|
||||
struct joliet_tree_node *node;
|
||||
@ -320,7 +330,6 @@ write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
vol->vol_desc_type[0] = 2;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
memcpy(vol->system_id, "SYSID", 5);
|
||||
if (vol_id)
|
||||
memcpy(vol->volume_id, vol_id, vol_id_len);
|
||||
memcpy(vol->esc_sequences, "%/E", 3);
|
||||
|
@ -17,7 +17,7 @@
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
|
||||
enum {
|
||||
enum joliet_node_type {
|
||||
JOLIET_FILE,
|
||||
JOLIET_DIR
|
||||
};
|
||||
@ -37,7 +37,7 @@ struct joliet_tree_node
|
||||
struct joliet_tree_node *parent;
|
||||
struct ecma119_write_target *target;
|
||||
|
||||
int type;
|
||||
enum joliet_node_type type;
|
||||
union {
|
||||
struct iso_file *file;
|
||||
struct joliet_dir_info dir;
|
||||
|
@ -35,6 +35,12 @@ struct iso_volset;
|
||||
*/
|
||||
struct iso_tree_node;
|
||||
|
||||
/**
|
||||
* El-Torito boot image
|
||||
* \see eltorito.h
|
||||
*/
|
||||
struct el_torito_boot_image;
|
||||
|
||||
/**
|
||||
* A directory in the filesystem tree.
|
||||
* The first member of this is an iso_tree_node.
|
||||
@ -52,6 +58,12 @@ enum hide_node_flag {
|
||||
LIBISO_HIDE_ON_JOLIET = 1 << 1
|
||||
};
|
||||
|
||||
enum eltorito_boot_media_type {
|
||||
ELTORITO_FLOPPY_EMUL,
|
||||
ELTORITO_HARD_DISC_EMUL,
|
||||
ELTORITO_NO_EMUL
|
||||
};
|
||||
|
||||
/**
|
||||
* This will hold the error code for some functions, if them fail.
|
||||
*/
|
||||
@ -65,6 +77,8 @@ int libisofs_errno;
|
||||
#define NO_READ_ACCESS 2
|
||||
/* unexpected file type, eg., passing a dir instead of a regular file */
|
||||
#define UNEXPECTED_FILE_TYPE 3
|
||||
/* invalid boot image size */
|
||||
#define ELTORITO_WRONG_IMAGE_SIZE 4
|
||||
|
||||
/**
|
||||
* Controls the bahavior of iso_tree_radd_dir function
|
||||
@ -157,6 +171,71 @@ void iso_volume_set_abstract_file_id(struct iso_volume *volume,
|
||||
void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
||||
const char *biblio_file_id);
|
||||
|
||||
/**
|
||||
* Create a bootable volume by adding a El-Torito boot image.
|
||||
*
|
||||
* \param volume The volume to make bootable.
|
||||
* \param image The tree node with the file to use as default boot image.
|
||||
* \param type The boot media type. This can be one of 3 types:
|
||||
* - Floppy emulation: Boot image files must be exactly
|
||||
* 1200 kB, 1440 kB or 2880 kB.
|
||||
* - Hard disc emulation: The image must begin with a master
|
||||
* boot record with a single image.
|
||||
* - No emulation. You should specify load segment and load size
|
||||
* of image.
|
||||
* \param dir The directory node where the boot catalog will be located
|
||||
* in image. Usually both boot catalog and boot image will be
|
||||
* located in the same dir, maybe /boot.
|
||||
* \param name The name of the boot catalog.
|
||||
*
|
||||
* \return The default El-Torito bootable image. If specified image file
|
||||
* seems to be not correct, this returns NULL and libisofs_errno
|
||||
* is set propertly.
|
||||
*
|
||||
* \pre \p volume is a volume without any boot catalog yet
|
||||
* \pre \p image is a file tree node already inserted in the volume tree.
|
||||
* \pre \p dir is a directory node already inserted in the volume tree.
|
||||
* \pre \p name There isn't any dir child with the same name.
|
||||
*
|
||||
*/
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name);
|
||||
|
||||
/**
|
||||
* Sets the load segment for the initial boot image. This is only for
|
||||
* no emulation boot images, and is a NOP for other image types.
|
||||
*/
|
||||
void
|
||||
el_torito_set_load_seg(struct el_torito_boot_image *bootimg, int segment);
|
||||
|
||||
/**
|
||||
* Sets the number of sectors (512b) to be load at load segment during
|
||||
* the initial boot procedure. This is only for
|
||||
* no emulation boot images, and is a NOP for other image types.
|
||||
*/
|
||||
void
|
||||
el_torito_set_load_size(struct el_torito_boot_image *bootimg, int sectors);
|
||||
|
||||
/**
|
||||
* Marks the specified boot image as not bootable
|
||||
*/
|
||||
void
|
||||
el_torito_set_no_bootable(struct el_torito_boot_image *bootimg);
|
||||
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* Be aware that libisofs will modify original boot image file, so do a backup
|
||||
* if needed.
|
||||
* This is needed for isolinux boot images.
|
||||
*/
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg);
|
||||
|
||||
/**
|
||||
* Locate a node by its path on disc.
|
||||
*
|
||||
@ -165,8 +244,10 @@ void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
||||
*
|
||||
* \return The node found or NULL.
|
||||
*
|
||||
* TODO we need a way to allow developers know which kind of node is.
|
||||
* Think about this when designing the read api
|
||||
*/
|
||||
//struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path);
|
||||
struct iso_tree_node *iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path);
|
||||
|
||||
/**
|
||||
* Add a file or a directory (recursively) to a volume by specifying its path on the volume.
|
||||
@ -284,10 +365,9 @@ struct iso_tree_node *iso_tree_add_node(struct iso_tree_node_dir *parent,
|
||||
* \pre \p parent is non-NULL.
|
||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||
* filesystem.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_node_dir *iso_tree_radd_dir(struct iso_tree_node_dir *parent,
|
||||
const char *path, struct iso_tree_radd_dir_behavior *behavior);
|
||||
void iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior);
|
||||
|
||||
/**
|
||||
* Set the name of a tree node (using the current locale).
|
||||
@ -353,6 +433,16 @@ void iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w);
|
||||
*/
|
||||
void iso_tree_print(const struct iso_tree_node *root, int spaces);
|
||||
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
//struct ecma119_source_opts {
|
||||
// int volnum; /**< The volume in the set which you want to write (usually 0) */
|
||||
// int level; /**< ISO level to write at. */
|
||||
// int flags; /**< Which extensions to support. */
|
||||
//};
|
||||
|
||||
/** Create a burn_source which can be used as a data source for a track
|
||||
*
|
||||
* The volume set used to create the libburn_source can _not_ be modified
|
||||
|
@ -32,9 +32,9 @@ set_default_stat(struct stat *s)
|
||||
s->st_atime = s->st_mtime = s->st_ctime = now;
|
||||
}
|
||||
|
||||
static void
|
||||
append_node(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child)
|
||||
void
|
||||
iso_tree_add_child(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child)
|
||||
{
|
||||
assert( parent && child);
|
||||
|
||||
@ -54,6 +54,7 @@ iso_tree_new_root()
|
||||
|
||||
set_default_stat(&root->node.attrib);
|
||||
root->node.attrib.st_mode = S_IFDIR | 0777;
|
||||
root->node.type = LIBISO_NODE_DIR;
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -86,13 +87,14 @@ iso_tree_add_file(struct iso_tree_node_dir *parent, const char *path)
|
||||
/* fill fields */
|
||||
f->node.attrib = st;
|
||||
f->path = strdup(path);
|
||||
f->node.type = LIBISO_NODE_FILE;
|
||||
|
||||
p = strdup(path); /* because basename() might modify its arg */
|
||||
f->node.name = strdup( basename(p) );
|
||||
free(p);
|
||||
|
||||
/* add to parent (this also sets f->node->parent) */
|
||||
append_node(parent, (struct iso_tree_node*) f);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) f);
|
||||
|
||||
return (struct iso_tree_node*) f;
|
||||
}
|
||||
@ -109,12 +111,13 @@ iso_tree_add_symlink(struct iso_tree_node_dir *parent,
|
||||
|
||||
/* fill fields */
|
||||
set_default_stat(&link->node.attrib);
|
||||
link->node.attrib.st_mode |= S_IFLNK;
|
||||
link->node.attrib.st_mode |= S_IFLNK;//TODO Not needed
|
||||
link->node.name = strdup(name);
|
||||
link->node.type = LIBISO_NODE_SYMLINK;
|
||||
link->dest = strdup(dest);
|
||||
|
||||
/* add to parent (this also sets link->node->parent) */
|
||||
append_node(parent, (struct iso_tree_node*) link);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) link);
|
||||
|
||||
return (struct iso_tree_node*) link;
|
||||
}
|
||||
@ -130,9 +133,10 @@ iso_tree_add_dir(struct iso_tree_node_dir *parent,
|
||||
dir = calloc(1, sizeof(struct iso_tree_node_dir));
|
||||
|
||||
dir->node.attrib = parent->node.attrib;
|
||||
dir->node.type = LIBISO_NODE_DIR;
|
||||
dir->node.name = strdup(name);
|
||||
|
||||
append_node(parent, (struct iso_tree_node*) dir);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
@ -276,7 +280,7 @@ iso_tree_free(struct iso_tree_node *root)
|
||||
free(root);
|
||||
}
|
||||
|
||||
static struct iso_tree_node*
|
||||
static void
|
||||
iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior,
|
||||
struct iso_hash_table *excludes)
|
||||
@ -285,20 +289,18 @@ iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path,
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
new = iso_tree_add_node(parent, path);
|
||||
if (!new || !ISO_ISDIR(new)) {
|
||||
return new;
|
||||
}
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir) {
|
||||
warn("couldn't open directory %s: %s\n", path, strerror(errno));
|
||||
return new;
|
||||
return;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir))) {
|
||||
char child[strlen(ent->d_name) + strlen(path) + 2];
|
||||
|
||||
if (behavior->stop_on_error & behavior->error)
|
||||
break;
|
||||
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
@ -310,20 +312,23 @@ iso_tree_radd_dir_aux(struct iso_tree_node_dir *parent, const char *path,
|
||||
if (iso_exclude_lookup(excludes, child))
|
||||
continue;
|
||||
|
||||
if ( !iso_tree_radd_dir_aux( (struct iso_tree_node_dir *) new, child,
|
||||
behavior, excludes) ) {
|
||||
/* error */
|
||||
behavior->error = 1;
|
||||
if (behavior->stop_on_error)
|
||||
break;
|
||||
new = iso_tree_add_node(parent, child);
|
||||
if (!new || !ISO_ISDIR(new)) {
|
||||
if (!new)
|
||||
behavior->error = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
iso_tree_radd_dir_aux( (struct iso_tree_node_dir *) new, child,
|
||||
behavior, excludes);
|
||||
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
return new;
|
||||
return;
|
||||
}
|
||||
|
||||
struct iso_tree_node_dir*
|
||||
void
|
||||
iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||
struct iso_tree_radd_dir_behavior *behavior)
|
||||
{
|
||||
@ -344,8 +349,7 @@ iso_tree_radd_dir(struct iso_tree_node_dir *parent, const char *path,
|
||||
}
|
||||
|
||||
/* recurse into dir */
|
||||
dir = (struct iso_tree_node_dir*) iso_tree_radd_dir_aux(
|
||||
parent, path, behavior, &table);
|
||||
iso_tree_radd_dir_aux(parent, path, behavior, &table);
|
||||
|
||||
/* clear hashtable */
|
||||
iso_exclude_empty(&table);
|
||||
@ -382,7 +386,7 @@ iso_tree_print_verbose(const struct iso_tree_node *root,
|
||||
int spaces)
|
||||
{
|
||||
|
||||
(S_ISDIR(root->attrib.st_mode) ? dir : file)
|
||||
(ISO_ISDIR(root) ? dir : file)
|
||||
(root, callback_data, spaces);
|
||||
|
||||
if ( ISO_ISDIR(root) ) {
|
||||
|
@ -44,6 +44,13 @@
|
||||
// /* };*/
|
||||
//};
|
||||
|
||||
enum iso_tree_node_type {
|
||||
LIBISO_NODE_DIR,
|
||||
LIBISO_NODE_FILE,
|
||||
LIBISO_NODE_SYMLINK,
|
||||
LIBISO_NODE_BOOTCATALOG
|
||||
};
|
||||
|
||||
/**
|
||||
* A node in the filesystem tree.
|
||||
*/
|
||||
@ -56,6 +63,7 @@ struct iso_tree_node
|
||||
|
||||
int hide_flags; /**< If the node is to be hidden in RR/ISO or
|
||||
* Joilet tree */
|
||||
enum iso_tree_node_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -112,6 +120,12 @@ struct iso_tree_node_dir
|
||||
*/
|
||||
void iso_tree_free(struct iso_tree_node *root);
|
||||
|
||||
/**
|
||||
* Adds a child to a directory
|
||||
*/
|
||||
void iso_tree_add_child(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child);
|
||||
|
||||
/**
|
||||
* A function that prints verbose information about a directory.
|
||||
*
|
||||
@ -156,8 +170,8 @@ void iso_tree_print_verbose(const struct iso_tree_node *root,
|
||||
void *callback_data,
|
||||
int spaces);
|
||||
|
||||
#define ISO_ISDIR(n) S_ISDIR(n->attrib.st_mode)
|
||||
#define ISO_ISREG(n) S_ISREG(n->attrib.st_mode)
|
||||
#define ISO_ISLNK(n) S_ISLNK(n->attrib.st_mode)
|
||||
#define ISO_ISDIR(n) (n->type == LIBISO_NODE_DIR)
|
||||
#define ISO_ISREG(n) (n->type == LIBISO_NODE_FILE)
|
||||
#define ISO_ISLNK(n) (n->type == LIBISO_NODE_SYMLINK)
|
||||
|
||||
#endif /* LIBISO_TREE_H */
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
struct iso_volset*
|
||||
iso_volset_new(struct iso_volume *vol, const char *id)
|
||||
@ -80,7 +81,13 @@ iso_volume_free(struct iso_volume *volume)
|
||||
free(volume->volume_id);
|
||||
free(volume->publisher_id);
|
||||
free(volume->data_preparer_id);
|
||||
|
||||
free(volume->system_id);
|
||||
free(volume->application_id);
|
||||
free(volume->copyright_file_id);
|
||||
free(volume->abstract_file_id);
|
||||
free(volume->biblio_file_id);
|
||||
if (volume->bootcat)
|
||||
el_torito_boot_catalog_free(volume->bootcat);
|
||||
free(volume);
|
||||
}
|
||||
}
|
||||
@ -139,52 +146,59 @@ void iso_volume_set_biblio_file_id(struct iso_volume *volume,
|
||||
volume->biblio_file_id = strdup(biblio_file_id);
|
||||
}
|
||||
|
||||
//struct iso_tree_node *
|
||||
//iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||
//{
|
||||
// struct iso_tree_node *node;
|
||||
// char *ptr, *brk_info, *component;
|
||||
//
|
||||
// /* get the first child at the root of the volume
|
||||
// * that is "/" */
|
||||
// node=iso_volume_get_root(volume);
|
||||
// if (!strcmp (path, "/"))
|
||||
// return node;
|
||||
//
|
||||
// if (!node->nchildren)
|
||||
// return NULL;
|
||||
//
|
||||
// /* the name of the nodes is in wide characters so first convert path
|
||||
// * into wide characters. */
|
||||
// ptr = strdup(path);
|
||||
//
|
||||
// /* get the first component of the path */
|
||||
// component=strtok_r(ptr, "/", &brk_info);
|
||||
// while (component) {
|
||||
// size_t max;
|
||||
// size_t i;
|
||||
//
|
||||
// /* search among all the children of this directory if this path component exists */
|
||||
// max=node->nchildren;
|
||||
// for (i=0; i < max; i++) {
|
||||
// if (!strcmp(component, node->children[i]->name)) {
|
||||
// node=node->children[i];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /* see if a node could be found */
|
||||
// if (i==max) {
|
||||
// node=NULL;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// component=strtok_r(NULL, "/", &brk_info);
|
||||
// }
|
||||
//
|
||||
// free(ptr);
|
||||
// return node;
|
||||
//}
|
||||
struct iso_tree_node *
|
||||
iso_tree_volume_path_to_node(struct iso_volume *volume, const char *path)
|
||||
{
|
||||
struct iso_tree_node *node;
|
||||
struct iso_tree_node_dir *dir;
|
||||
char *ptr, *brk_info, *component;
|
||||
|
||||
/* get the first child at the root of the volume
|
||||
* that is "/" */
|
||||
dir = iso_volume_get_root(volume);
|
||||
node = (struct iso_tree_node *)dir;
|
||||
if (!strcmp(path, "/"))
|
||||
return node;
|
||||
|
||||
if (!dir->nchildren)
|
||||
return NULL;
|
||||
|
||||
ptr = strdup(path);
|
||||
|
||||
/* get the first component of the path */
|
||||
component=strtok_r(ptr, "/", &brk_info);
|
||||
while (component) {
|
||||
size_t max;
|
||||
size_t i;
|
||||
|
||||
if ( !ISO_ISDIR(node) ) {
|
||||
node=NULL;
|
||||
break;
|
||||
}
|
||||
dir = (struct iso_tree_node_dir *)node;
|
||||
|
||||
/* search among all the children of this directory if this path component exists */
|
||||
max=dir->nchildren;
|
||||
for (i=0; i < max; i++) {
|
||||
if (!strcmp(component, dir->children[i]->name)) {
|
||||
node=dir->children[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if a node could be found */
|
||||
if (i==max) {
|
||||
node=NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
component=strtok_r(NULL, "/", &brk_info);
|
||||
}
|
||||
|
||||
free(ptr);
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
//struct iso_tree_node *
|
||||
//iso_tree_volume_add_path(struct iso_volume *volume,
|
||||
|
@ -30,6 +30,8 @@ struct iso_volume
|
||||
char *copyright_file_id;
|
||||
char *abstract_file_id;
|
||||
char *biblio_file_id;
|
||||
|
||||
struct el_torito_boot_catalog *bootcat; /**< El-Torito boot catalog */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#define SECSIZE 2048
|
||||
|
||||
const char * const optstring = "JRL:h";
|
||||
const char * const optstring = "JRL:b:h";
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
@ -36,6 +36,7 @@ void help()
|
||||
" -J Add Joliet support\n"
|
||||
" -R Add Rock Ridge support\n"
|
||||
" -L <num> Set the ISO level (1 or 2)\n"
|
||||
" -b file Specifies a boot image to add to image\n"
|
||||
" -h Print this message\n"
|
||||
);
|
||||
}
|
||||
@ -51,6 +52,7 @@ int main(int argc, char **argv)
|
||||
int c;
|
||||
struct iso_tree_radd_dir_behavior behav = {0,0,0};
|
||||
int level=1, flags=0;
|
||||
char *boot_img = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, optstring)) != -1) {
|
||||
switch(c) {
|
||||
@ -68,6 +70,9 @@ int main(int argc, char **argv)
|
||||
case 'L':
|
||||
level = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
boot_img = optarg;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(1);
|
||||
@ -96,9 +101,25 @@ int main(int argc, char **argv)
|
||||
err(1, "error opening input directory");
|
||||
}
|
||||
volume = iso_volume_new_with_root( "VOLID", "PUBID", "PREPID", root );
|
||||
|
||||
if ( boot_img ) {
|
||||
/* adds El-Torito boot info. Tunned for isolinux */
|
||||
struct iso_tree_node_dir *boot = (struct iso_tree_node_dir *)
|
||||
iso_tree_volume_path_to_node(volume, "isolinux");
|
||||
struct iso_tree_node *img = iso_tree_volume_path_to_node(volume, boot_img);
|
||||
if (!img) {
|
||||
err(1, "boot image patch is not valid");
|
||||
}
|
||||
struct el_torito_boot_image *bootimg =
|
||||
iso_volume_create_boot_catalog(volume, img, ELTORITO_NO_EMUL,
|
||||
boot, "boot.cat");
|
||||
el_torito_set_load_size(bootimg, 4);
|
||||
el_torito_set_write_boot_info(bootimg);
|
||||
}
|
||||
|
||||
volset = iso_volset_new( volume, "VOLSETID" );
|
||||
|
||||
//some tests
|
||||
/* some tests */
|
||||
iso_volume_set_application_id(volume, "Libburnia");
|
||||
iso_volume_set_copyright_file_id(volume, "LICENSE");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user