Done major changes to libisofs, including multisession and reading support
This commit is contained in:
parent
a4e0041128
commit
df04ee014e
13
Makefile.am
13
Makefile.am
@ -38,7 +38,11 @@ libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/ecma119_read.h \
|
||||
libisofs/ecma119_read.c \
|
||||
libisofs/ecma119_read_rr.h \
|
||||
libisofs/ecma119_read_rr.c
|
||||
libisofs/ecma119_read_rr.c \
|
||||
libisofs/libdax_msgs.h \
|
||||
libisofs/libdax_msgs.c \
|
||||
libisofs/messages.h \
|
||||
libisofs/messages.c
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libisofs/libisofs.h
|
||||
@ -50,7 +54,8 @@ noinst_PROGRAMS = \
|
||||
test/iso \
|
||||
test/isoread \
|
||||
test/isoms \
|
||||
test/isoadd
|
||||
test/isoadd \
|
||||
test/isogrow
|
||||
|
||||
test_iso_CPPFLAGS = -Ilibisofs
|
||||
test_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
@ -68,6 +73,10 @@ test_isoadd_CPPFLAGS = -Ilibisofs
|
||||
test_isoadd_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_isoadd_SOURCES = test/iso_add.c
|
||||
|
||||
test_isogrow_CPPFLAGS = -Ilibisofs
|
||||
test_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_isogrow_SOURCES = test/iso_grow.c
|
||||
|
||||
## Build unit test
|
||||
|
||||
check_PROGRAMS = \
|
||||
|
25
TODO
25
TODO
@ -7,10 +7,12 @@ FEATURES
|
||||
CD reading
|
||||
[ok] plain iso
|
||||
[ok] Rock Ridge
|
||||
Joliet
|
||||
[ok] Joliet
|
||||
Merge RR and Joliet trees
|
||||
User options to customize reading
|
||||
Multisession
|
||||
[ok] User options to customize reading
|
||||
Read El-Torito info
|
||||
[ok] Multisession
|
||||
[ok] DVD+RW image growing
|
||||
UDF
|
||||
[ok] ISO relaxed contraints
|
||||
ISO 9660:1998
|
||||
@ -29,11 +31,20 @@ IMPLEMENTATION
|
||||
==============
|
||||
|
||||
a way to return NULL sources meaning a failure!!
|
||||
Error message queue
|
||||
[ok] Error message queue
|
||||
Better charset support
|
||||
default input charset to locale one, no always UTF-8
|
||||
[ok] default input charset to locale one, no always UTF-8
|
||||
add charset management on image reading
|
||||
use iso-8859-1 instead of UTF-8 dor RR?
|
||||
Improve date handling
|
||||
use iso-8859-1 instead of UTF-8 on RR?
|
||||
[ok] Improve date handling
|
||||
for DVD+RW, the VD to be written at the beginning of disc must be
|
||||
returned as 32KB block
|
||||
|
||||
BUGS
|
||||
====
|
||||
|
||||
Joliet names need ";1" at the end
|
||||
RR Continuation Areas can't be in Directory Record block
|
||||
[ok] Fix mangle names when iso relaxed constraints
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <locale.h>
|
||||
#include <langinfo.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ecma119.h"
|
||||
#include "ecma119_tree.h"
|
||||
@ -20,6 +23,7 @@
|
||||
#include "libisofs.h"
|
||||
#include "libburn/libburn.h"
|
||||
#include "eltorito.h"
|
||||
#include "messages.h"
|
||||
|
||||
/* burn-source compatible stuff */
|
||||
static int
|
||||
@ -287,7 +291,7 @@ calc_file_pos(struct ecma119_write_target *t,
|
||||
*/
|
||||
static struct ecma119_write_target*
|
||||
ecma119_target_new(struct iso_volset *volset,
|
||||
const struct ecma119_source_opts *opts)
|
||||
struct ecma119_source_opts *opts)
|
||||
{
|
||||
struct ecma119_write_target *t =
|
||||
calloc(1, sizeof(struct ecma119_write_target));
|
||||
@ -310,8 +314,13 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
t->gid = opts->gid;
|
||||
t->uid = opts->uid;
|
||||
|
||||
//TODO get defailt values for current locale, no UTF-8
|
||||
t->input_charset = opts->input_charset ? opts->input_charset : "UTF-8";
|
||||
if (opts->input_charset) {
|
||||
t->input_charset = opts->input_charset;
|
||||
} else {
|
||||
/* default to locale charset */
|
||||
setlocale(LC_CTYPE, "");
|
||||
t->input_charset = nl_langinfo(CODESET);
|
||||
}
|
||||
t->ouput_charset = opts->ouput_charset ? opts->ouput_charset : "UTF-8";
|
||||
t->sort_files = opts->sort_files;
|
||||
|
||||
@ -419,11 +428,43 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
rrip_finalize(t, t->root);
|
||||
}
|
||||
|
||||
t->total_size = t->curblock * t->block_size;
|
||||
t->total_size = (t->curblock - t->ms_block) * t->block_size;
|
||||
|
||||
if (opts->dvd_plus_rw) {
|
||||
|
||||
/*
|
||||
* Get a copy of the volume descriptors to be written in a DVD+RW
|
||||
* disc
|
||||
*/
|
||||
uint8_t *buf;
|
||||
opts->vol_desc_count = 2 + (t->eltorito ? 1 : 0) +
|
||||
(t->joliet ? 1 : 0);
|
||||
opts->vol_desc = calloc(opts->vol_desc_count, t->block_size);
|
||||
buf = opts->vol_desc;
|
||||
|
||||
/*
|
||||
* In the PVM to be written in the 16th sector of the disc, we
|
||||
* need to specify the full size.
|
||||
*/
|
||||
t->vol_space_size = t->curblock;
|
||||
write_pri_vol_desc(t, buf);
|
||||
buf += t->block_size;
|
||||
if (t->joliet) {
|
||||
joliet_write_sup_vol_desc(t, buf);
|
||||
buf += t->block_size;
|
||||
}
|
||||
if (t->eltorito) {
|
||||
el_torito_write_boot_vol_desc(t, buf);
|
||||
buf += t->block_size;
|
||||
}
|
||||
write_vol_desc_terminator(t, buf);
|
||||
}
|
||||
|
||||
//TODO how needs to be here for ms?
|
||||
// a change here requires changes in bs_read!!
|
||||
t->vol_space_size = t->curblock;
|
||||
/*
|
||||
* The volume space size is just the size of the last session, in
|
||||
* case of ms images.
|
||||
*/
|
||||
t->vol_space_size = t->curblock - t->ms_block;
|
||||
|
||||
/* prepare for writing */
|
||||
t->curblock = 0;
|
||||
@ -456,7 +497,11 @@ next_state(struct ecma119_write_target *t)
|
||||
||(!t->eltorito && is_eltorito_state(t->state)) )
|
||||
t->state++;
|
||||
|
||||
printf ("now in state %d, curblock=%d\n", (int)t->state, (int)t->curblock);
|
||||
{
|
||||
char msg[42];
|
||||
sprintf(msg, "Now in state %d, curblock=%d.", t->state, t->curblock);
|
||||
iso_msg_debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -526,11 +571,16 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
const char *path = f->path;
|
||||
|
||||
if (!f_st->fd) {
|
||||
printf("Writing file %s\n", path);
|
||||
|
||||
char msg[PATH_MAX + 14];
|
||||
sprintf(msg, "Writing file %s", path);
|
||||
iso_msg_debug(msg);
|
||||
|
||||
f_st->data_len = f->size;
|
||||
f_st->fd = fopen(path, "r");
|
||||
if (!f_st->fd)
|
||||
if (!f_st->fd) {
|
||||
err(1, "couldn't open %s for reading", path);
|
||||
}
|
||||
assert(t->curblock + t->ms_block == f->block);
|
||||
}
|
||||
|
||||
@ -824,7 +874,7 @@ bs_read(struct burn_source *bs, unsigned char *buf, int size)
|
||||
warnx("you must read data in block-sized chunks (%d bytes)",
|
||||
(int)t->block_size);
|
||||
return 0;
|
||||
} else if (t->curblock + t->ms_block >= t->vol_space_size) {
|
||||
} else if (t->curblock >= t->vol_space_size + t->ms_block) {
|
||||
return 0;
|
||||
}
|
||||
if (t->state_data_valid)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "tree.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
|
||||
@ -153,20 +154,22 @@ iso_read_single_directory_record(struct iso_read_info *info,
|
||||
*/
|
||||
relocated_dir = iso_read_bb(sue->data.CL.child_loc, 4, NULL);
|
||||
} else if (SUSP_SIG(sue, 'S', 'F')) {
|
||||
printf("[ERROR] Sparse files not supported.\n");
|
||||
iso_msg_sorry(LIBISO_RR_UNSUPPORTED, "Sparse files not supported.");
|
||||
info->error = LIBISOFS_UNSUPPORTED_IMAGE;
|
||||
break;
|
||||
} else if (SUSP_SIG(sue, 'R', 'R')) {
|
||||
/* TODO I've seen this RR on mkisofs images. what's this? */
|
||||
continue;
|
||||
} else {
|
||||
printf("[DEBUG] Unhandled SUSP entry %c%c\n", sue->sig[0], sue->sig[1]);
|
||||
char msg[28];
|
||||
sprintf(msg, "Unhandled SUSP entry %c%c.", sue->sig[0], sue->sig[1]);
|
||||
iso_msg_hint(LIBISO_SUSP_UNHANLED, msg);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !info->error && !relocated_dir && atts.st_mode == (mode_t) 0 ) {
|
||||
printf("[ERROR] Mandatory Rock Ridge PX entry is not present "
|
||||
"or it contains invalid values.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "Mandatory Rock Ridge PX entry is "
|
||||
"not present or it contains invalid values.");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
}
|
||||
|
||||
@ -179,22 +182,30 @@ iso_read_single_directory_record(struct iso_read_info *info,
|
||||
|
||||
} else {
|
||||
/* RR extensions are not read / used */
|
||||
//TODO allow to specify suitable values
|
||||
atts.st_mode = 0555;
|
||||
atts.st_gid = 0;
|
||||
atts.st_uid = 0;
|
||||
atts.st_mode = info->mode;
|
||||
atts.st_gid = info->gid;
|
||||
atts.st_uid = info->uid;
|
||||
if (record->flags[0] & 0x02)
|
||||
atts.st_mode |= S_IFDIR;
|
||||
else
|
||||
atts.st_mode |= S_IFREG;
|
||||
atts.st_ino = ++info->ino;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or no NM entry is present,
|
||||
* we use the plain ISO name
|
||||
* we use the name in directory record
|
||||
*/
|
||||
if (!name)
|
||||
name = strcopy((char*)record->file_id, record->len_fi[0]);
|
||||
if (!name) {
|
||||
size_t len;
|
||||
name = info->get_name((char*)record->file_id, record->len_fi[0]);
|
||||
|
||||
/* remove trailing version number */
|
||||
len = strlen(name);
|
||||
if (len > 2 && name[len-2] == ';' && name[len-1] == '1') {
|
||||
name[len-2] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if we haven't RR extensions, or a needed TF time stamp is not present,
|
||||
@ -255,7 +266,7 @@ iso_read_single_directory_record(struct iso_read_info *info,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("[ERROR] File type not supported.\n");
|
||||
iso_msg_sorry(LIBISO_RR_UNSUPPORTED, "File type not supported.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -354,7 +365,7 @@ iso_read_dir(struct iso_read_info *info, struct iso_tree_node_dir *dir,
|
||||
|
||||
/* check for unsupported multiextend */
|
||||
if (record->flags[0] & 0x80) {
|
||||
printf("[ERROR] Unsupported image.\n"
|
||||
iso_msg_fatal(LIBISO_IMG_UNSUPPORTED, "Unsupported image.\n"
|
||||
"This image makes use of Multi-Extend features, that "
|
||||
"are not supported at this time.\n"
|
||||
"If you need support for that, please request us this feature.\n"
|
||||
@ -364,7 +375,7 @@ iso_read_dir(struct iso_read_info *info, struct iso_tree_node_dir *dir,
|
||||
}
|
||||
/* check for unsupported interleaved mode */
|
||||
if ( record->file_unit_size[0] || record->interleave_gap_size[0] ) {
|
||||
printf("[ERROR] Unsupported image.\n"
|
||||
iso_msg_fatal(LIBISO_IMG_UNSUPPORTED, "Unsupported image.\n"
|
||||
"This image has at least one file recorded in "
|
||||
"interleaved mode.\n"
|
||||
"We don't support this mode, as we think it's not used.\n"
|
||||
@ -410,7 +421,7 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
record = (struct ecma119_dir_record *)buffer;
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
* TODO
|
||||
* SUSP specification claims that for CD-ROM XA the SP entry
|
||||
* is not at position BP 1, but at BP 15. Is that used?
|
||||
* In that case, we need to set info->len_skp to 15!!
|
||||
@ -424,7 +435,7 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
susp_iter_free(iter);
|
||||
return -1;
|
||||
} else if (!sue || !SUSP_SIG(sue, 'S', 'P') ) {
|
||||
printf("[DEBUG] SUSP/RR is not being used.\n");
|
||||
iso_msg_debug("SUSP/RR is not being used.");
|
||||
susp_iter_free(iter);
|
||||
return 0;
|
||||
}
|
||||
@ -433,13 +444,13 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
if ( sue->version[0] != 1 || sue->data.SP.be[0] != 0xBE
|
||||
|| sue->data.SP.ef[0] != 0xEF) {
|
||||
|
||||
printf("[WARN] SUSP SP system use entry seems to be wrong.\n"
|
||||
"Ignoring Rock Ridge Extensions.\n");
|
||||
iso_msg_sorry(LIBISO_SUSP_WRONG, "SUSP SP system use entry seems to "
|
||||
"be wrong. Ignoring Rock Ridge Extensions.");
|
||||
susp_iter_free(iter);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("[DEBUG] SUSP is being used.\n");
|
||||
iso_msg_debug("SUSP/RR is being used.");
|
||||
|
||||
/*
|
||||
* The LEN_SKP field, defined in IEEE 1281, SUSP. 5.3, specifies the
|
||||
@ -469,10 +480,10 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
if (SUSP_SIG(sue, 'E', 'R')) {
|
||||
|
||||
if (info->rr) {
|
||||
printf("[WARN] More than one ER has found. "
|
||||
"This is not supported.\n"
|
||||
"It will be ignored, but can cause problems. "
|
||||
"Please notify us about this.\n");
|
||||
iso_msg_warn(LIBISO_SUSP_MULTIPLE_ER,
|
||||
"More than one ER has found. This is not supported.\n"
|
||||
"It will be ignored, but can cause problems. "
|
||||
"Please notify us about this.\n");
|
||||
}
|
||||
/*
|
||||
* it seems that Rock Ridge can be identified with any
|
||||
@ -481,27 +492,23 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
if ( sue->data.ER.len_id[0] == 10 &&
|
||||
!strncmp((char*)sue->data.ER.ext_id, "RRIP_1991A", 10) ) {
|
||||
|
||||
printf("[DEBUG] suitable Rock Ridge ER found. Version 1.10.\n");
|
||||
iso_msg_debug("Suitable Rock Ridge ER found. Version 1.10.");
|
||||
info->rr = RR_EXT_110;
|
||||
|
||||
} else if ( ( sue->data.ER.len_id[0] == 10 &&
|
||||
!strncmp((char*)sue->data.ER.ext_id, "IEEE_P1282", 10) )
|
||||
|| ( sue->data.ER.len_id[0] == 9 &&
|
||||
!strncmp((char*)sue->data.ER.ext_id, "IEEE_1282", 9) ) ) {
|
||||
|
||||
printf("[DEBUG] suitable Rock Ridge ER found. Version 1.12.\n");
|
||||
|
||||
iso_msg_debug("Suitable Rock Ridge ER found. Version 1.12.");
|
||||
info->rr = RR_EXT_112;
|
||||
//TODO check also version?
|
||||
} else {
|
||||
printf("[WARN] Not Rock Ridge ER (%s) found.\n"
|
||||
"That will be ignored, but can cause problems in "
|
||||
"image reading. Please notify us about this.\n",
|
||||
sue->data.ER.ext_id);
|
||||
}
|
||||
|
||||
} else {
|
||||
//TODO look also for other RR entries???
|
||||
//printf("[DEBUG] Unhandled SUSP entry %c%c\n", sue->sig[0], sue->sig[1]);
|
||||
iso_msg_warn(LIBISO_SUSP_MULTIPLE_ER,
|
||||
"Not Rock Ridge ER found.\n"
|
||||
"That will be ignored, but can cause problems in "
|
||||
"image reading. Please notify us about this");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,8 +543,8 @@ read_pvm(struct iso_read_info *info, uint32_t block)
|
||||
|| pvm->vol_desc_version[0] != 1
|
||||
|| pvm->file_structure_version[0] != 1 ) {
|
||||
|
||||
printf("Wrong file.\n"
|
||||
"Maybe this is a damaged image, or it's not an ISO-9660 image.\n");
|
||||
iso_msg_fatal(LIBISO_WRONG_IMG, "Wrong PVM. Maybe this is a damaged "
|
||||
"image, or it's not an ISO-9660 image.\n");
|
||||
info->error = LIBISOFS_WRONG_PVM;
|
||||
return NULL;
|
||||
}
|
||||
@ -556,11 +563,13 @@ read_pvm(struct iso_read_info *info, uint32_t block)
|
||||
|
||||
volset_id = strcopy((char*)pvm->vol_set_id, 128);
|
||||
|
||||
*(info->size) = iso_read_bb(pvm->vol_space_size, 4, NULL);
|
||||
|
||||
volset = iso_volset_new(volume, volset_id);
|
||||
free(volset_id);
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
* TODO
|
||||
* I don't like the way the differences volset - volume are hanled now.
|
||||
* While theorically right (a volset can contain several volumes), in
|
||||
* practice it seems that this never happen. Current implementation, with
|
||||
@ -584,20 +593,10 @@ read_pvm(struct iso_read_info *info, uint32_t block)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* we want to read RR? */
|
||||
/* are RR ext present */
|
||||
info->hasRR = info->rr ? 1 : 0;
|
||||
if (info->norock)
|
||||
info->rr = RR_EXT_NO;
|
||||
|
||||
/* Now, read the tree */
|
||||
if ( iso_read_dir(info, volume->root,
|
||||
iso_read_bb(rootdr->block, 4, NULL)) ) {
|
||||
|
||||
/* error, cleanup and return */
|
||||
iso_volset_free(volset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->iso_root_block = iso_read_bb(rootdr->block, 4, NULL);
|
||||
|
||||
/*
|
||||
* PVM has things that can be interested, but don't have a member in
|
||||
@ -613,6 +612,8 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
{
|
||||
struct iso_read_info info;
|
||||
struct iso_volset *volset;
|
||||
uint32_t block, root_dir_block;
|
||||
unsigned char buffer[BLOCK_SIZE];
|
||||
|
||||
assert(src && opts);
|
||||
|
||||
@ -623,6 +624,11 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
info.len_skp = 0;
|
||||
info.ino = 0;
|
||||
info.norock = opts->norock;
|
||||
info.uid = opts->uid;
|
||||
info.gid = opts->gid;
|
||||
info.mode = opts->mode & ~S_IFMT;
|
||||
info.size = &opts->size;
|
||||
root_dir_block = 0;
|
||||
|
||||
/* read primary volume description */
|
||||
volset = read_pvm(&info, opts->block + 16);
|
||||
@ -632,15 +638,108 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts->hasRR = info.hasRR;
|
||||
block = opts->block + 17;
|
||||
do {
|
||||
if ( info.src->read_block(info.src, block, buffer) < 0 ) {
|
||||
info.error = LIBISOFS_READ_FAILURE;
|
||||
iso_volset_free(volset);
|
||||
return NULL;
|
||||
}
|
||||
switch (buffer[0]) {
|
||||
case 0:
|
||||
/* boot record */
|
||||
//TODO handle el-torito
|
||||
break;
|
||||
case 2:
|
||||
/* suplementary volume descritor */
|
||||
{
|
||||
struct ecma119_sup_vol_desc *sup;
|
||||
struct ecma119_dir_record *root;
|
||||
|
||||
sup = (struct ecma119_sup_vol_desc*)buffer;
|
||||
if (sup->esc_sequences[0] == 0x25 &&
|
||||
sup->esc_sequences[1] == 0x2F &&
|
||||
(sup->esc_sequences[2] == 0x40 ||
|
||||
sup->esc_sequences[2] == 0x43 ||
|
||||
sup->esc_sequences[2] == 0x45) ) {
|
||||
|
||||
/* it's a Joliet Sup. Vol. Desc. */
|
||||
info.hasJoliet = 1;
|
||||
root = (struct ecma119_dir_record*)sup->root_dir_record;
|
||||
root_dir_block = iso_read_bb(root->block, 4, NULL);
|
||||
//TODO maybe we can set the volume attribs from this
|
||||
//descriptor
|
||||
} else {
|
||||
iso_msg_hint(LIBISO_UNSUPPORTED_VD,
|
||||
"Not supported Sup. Vol. Desc found.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 255:
|
||||
/*
|
||||
* volume set terminator
|
||||
* ignore, as it's checked in loop end condition
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char msg[32];
|
||||
sprintf(msg, "Ignoring Volume descriptor %d.", buffer[0]);
|
||||
iso_msg_hint(LIBISO_UNSUPPORTED_VD, msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
block++;
|
||||
} while (buffer[0] != 255);
|
||||
|
||||
// TODO read other volume descriptors
|
||||
// - supplementary: for joliet
|
||||
// - boot: el-torito
|
||||
// Read all volume descriptor till Volume Descriptor Set Terminator
|
||||
|
||||
opts->hasRR = info.hasRR;
|
||||
opts->hasJoliet = info.hasJoliet;
|
||||
|
||||
/* user doesn't want to read RR extensions */
|
||||
if (info.norock)
|
||||
info.rr = RR_EXT_NO;
|
||||
|
||||
/* select what tree to read */
|
||||
if (info.rr) {
|
||||
/* RR extensions are available */
|
||||
if (opts->preferjoliet && info.hasJoliet) {
|
||||
/* if user prefers joliet, that is used */
|
||||
iso_msg_debug("Reading Joliet extensions.");
|
||||
info.get_name = ucs2str;
|
||||
info.rr = RR_EXT_NO;
|
||||
/* root_dir_block already contains root for joliet */
|
||||
} else {
|
||||
/* RR will be used */
|
||||
iso_msg_debug("Reading Rock Ridge extensions.");
|
||||
root_dir_block = info.iso_root_block;
|
||||
info.get_name = strcopy;
|
||||
}
|
||||
} else {
|
||||
/* RR extensions are not available */
|
||||
if (info.hasJoliet && !opts->nojoliet) {
|
||||
/* joliet will be used */
|
||||
iso_msg_debug("Reading Joliet extensions.");
|
||||
info.get_name = ucs2str;
|
||||
/* root_dir_block already contains root for joliet */
|
||||
} else {
|
||||
/* default to plain iso */
|
||||
iso_msg_debug("Reading plain ISO-9660 tree.");
|
||||
root_dir_block = info.iso_root_block;
|
||||
info.get_name = strcopy;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the ISO/RR or Joliet tree */
|
||||
if ( iso_read_dir(&info, volset->volume[0]->root, root_dir_block) ) {
|
||||
|
||||
/* error, cleanup and return */
|
||||
iso_volset_free(volset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO merge tree info
|
||||
|
||||
// TODO free here? data_source_free(src);
|
||||
return volset;
|
||||
}
|
||||
|
@ -35,10 +35,27 @@ struct iso_read_info {
|
||||
struct data_source *src;
|
||||
enum read_error error;
|
||||
|
||||
uid_t uid; /**< Default uid when no RR */
|
||||
gid_t gid; /**< Default uid when no RR */
|
||||
mode_t mode; /**< Default mode when no RR (only permissions) */
|
||||
|
||||
uint32_t iso_root_block; /**< Will be filled with the block lba of the
|
||||
* extend for the root directory, as read from
|
||||
* the PVM
|
||||
*/
|
||||
|
||||
enum read_rr_ext rr; /*< If we need to read RR extensions. i.e., if the image
|
||||
* contains RR extensions, and the user wants to read them. */
|
||||
ino_t ino; /*< RR version 1.10 does not have file serial numbers, we
|
||||
* need to generate it */
|
||||
|
||||
char *(*get_name)(const char *, size_t);
|
||||
/**<
|
||||
* The function used to read the name from a directoy record. For
|
||||
* ISO, the name is in US-ASCII. For Joliet, in UCS-2BE. Thus, we
|
||||
* need different functions for both.
|
||||
*/
|
||||
|
||||
ino_t ino; /*< Joliet and RR version 1.10 does not have file serial numbers,
|
||||
* we need to generate it. */
|
||||
uint8_t len_skp; /*< bytes skipped within the System Use field of a
|
||||
directory record, before the beginning of the SUSP
|
||||
system user entries. See IEEE 1281, SUSP. 5.3. */
|
||||
@ -46,6 +63,9 @@ struct iso_read_info {
|
||||
unsigned int norock:1; /*< Do not read Rock Ridge extensions */
|
||||
unsigned int hasRR:1; /*< It will be set to 1 if RR extensions are present,
|
||||
to 0 if not. */
|
||||
unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet ext are present,
|
||||
to 0 if not. */
|
||||
uint32_t *size;
|
||||
};
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "ecma119_read.h"
|
||||
#include "ecma119_read_rr.h"
|
||||
#include "util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
|
||||
@ -30,11 +31,11 @@ read_rr_PX(struct iso_read_info *info, struct susp_sys_user_entry *px,
|
||||
assert( px->sig[0] == 'P' && px->sig[1] == 'X');
|
||||
|
||||
if ( info->rr == RR_EXT_112 && px->len_sue[0] != 44 ) {
|
||||
printf("[ERROR] Invalid PX entry for RR version 1.12\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "Invalid PX entry for RR version 1.12");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
return -1;
|
||||
} else if ( info->rr == RR_EXT_110 && px->len_sue[0] != 36 ) {
|
||||
printf("[ERROR] Invalid PX entry for RR version 1.10\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "Invalid PX entry for RR version 1.10");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
return -1;
|
||||
}
|
||||
@ -85,7 +86,7 @@ read_rr_TF(struct iso_read_info *info, struct susp_sys_user_entry *tf,
|
||||
/* 2. modify time */
|
||||
if (tf->data.TF.flags[0] & (1 << 1)) {
|
||||
if (tf->len_sue[0] < 5 + (nts+1) * s) {
|
||||
printf("[ERROR] RR TF entry too short.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "RR TF entry too short.");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
return -1;
|
||||
}
|
||||
@ -101,7 +102,7 @@ read_rr_TF(struct iso_read_info *info, struct susp_sys_user_entry *tf,
|
||||
/* 3. access time */
|
||||
if (tf->data.TF.flags[0] & (1 << 2)) {
|
||||
if (tf->len_sue[0] < 5 + (nts+1) * s) {
|
||||
printf("[ERROR] RR TF entry too short.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "RR TF entry too short.");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
return -1;
|
||||
}
|
||||
@ -117,7 +118,7 @@ read_rr_TF(struct iso_read_info *info, struct susp_sys_user_entry *tf,
|
||||
/* 4. attributes time */
|
||||
if (tf->data.TF.flags[0] & (1 << 3)) {
|
||||
if (tf->len_sue[0] < 5 + (nts+1) * s) {
|
||||
printf("[ERROR] RR TF entry too short.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "RR TF entry too short.");
|
||||
info->error = LIBISOFS_WRONG_RR;
|
||||
return -1;
|
||||
}
|
||||
@ -178,7 +179,9 @@ read_rr_SL(struct susp_sys_user_entry *sl, char *dest)
|
||||
len = 1;
|
||||
comp = "/";
|
||||
} else if (flags & ~0x01) {
|
||||
printf("[ERROR] SL component flag %x not supported.\n", flags);
|
||||
char msg[38];
|
||||
sprintf(msg, "SL component flag %x not supported.", flags);
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, msg);
|
||||
return NULL;
|
||||
} else {
|
||||
len = sl->data.SL.comps[pos + 1];
|
||||
@ -275,7 +278,7 @@ susp_iter_next(struct susp_iterator* iter)
|
||||
|
||||
if (entry->len_sue[0] == 0) {
|
||||
/* a wrong image with this lead us to a infinity loop */
|
||||
printf("[ERROR] Damaged RR/SUSP information.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "Damaged RR/SUSP information.");
|
||||
iter->info->error = LIBISOFS_WRONG_RR;
|
||||
return NULL;
|
||||
}
|
||||
@ -285,10 +288,10 @@ susp_iter_next(struct susp_iterator* iter)
|
||||
if ( SUSP_SIG(entry, 'C', 'E') ) {
|
||||
/* Continuation entry */
|
||||
if (iter->ce_len) {
|
||||
printf("[WARN] More than one CE System user entry has found "
|
||||
"in a single System Use field or continuation area.\n"
|
||||
"This breaks SUSP standard and it's not supported.\n"
|
||||
"Ignoring last CE. Maybe the image is damaged.\n");
|
||||
iso_msg_sorry(LIBISO_RR_ERROR, "More than one CE System user entry "
|
||||
"has found in a single System Use field or continuation area. "
|
||||
"This breaks SUSP standard and it's not supported.\n"
|
||||
"Ignoring last CE. Maybe the image is damaged.\n");
|
||||
} else {
|
||||
iter->ce_block = iso_read_bb(entry->data.CE.block, 4, NULL);
|
||||
iter->ce_off = iso_read_bb(entry->data.CE.offset, 4, NULL);
|
||||
|
@ -53,7 +53,7 @@ struct ecma119_tree_node
|
||||
{
|
||||
char *iso_name; /**< in ASCII, conforming to the
|
||||
* current ISO level. */
|
||||
char *full_name; /**< full name, in current locale (TODO put this in UTF-8?) */
|
||||
char *full_name; /**< full name, in current locale */
|
||||
size_t dirent_len; /**< Length of the directory record,
|
||||
* not including SU. */
|
||||
|
||||
|
@ -149,7 +149,7 @@ create_image(struct iso_tree_node *image,
|
||||
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 "
|
||||
fprintf(stderr, "Invalid MBR. At least 2 partitions: %d and "
|
||||
"%d, are being used\n", used_partition, i);
|
||||
return NULL;
|
||||
} else
|
||||
@ -294,8 +294,8 @@ void el_torito_get_image_files(struct ecma119_write_target *t)
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
static void
|
||||
write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
void
|
||||
el_torito_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 =
|
||||
@ -438,7 +438,7 @@ 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,
|
||||
el_torito_write_boot_vol_desc,
|
||||
2048,
|
||||
buf);
|
||||
}
|
||||
|
@ -51,6 +51,12 @@ void el_torito_get_image_files(struct ecma119_write_target *t);
|
||||
*/
|
||||
void el_torito_patch_image_files(struct ecma119_write_target *t);
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
void
|
||||
el_torito_write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
|
@ -302,8 +302,8 @@ write_m_path_table(struct ecma119_write_target *t, uint8_t *buf)
|
||||
write_path_table (t, 0, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
void
|
||||
joliet_write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_sup_vol_desc *vol = (struct ecma119_sup_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
@ -414,7 +414,7 @@ write_dirs(struct ecma119_write_target *t, uint8_t *buf)
|
||||
size_t i;
|
||||
struct joliet_tree_node *dir;
|
||||
|
||||
assert (t->curblock == t->dirlist_joliet[0]->info.dir.block);
|
||||
assert (t->curblock + t->ms_block == t->dirlist_joliet[0]->info.dir.block);
|
||||
for (i = 0; i < t->dirlist_len_joliet; i++) {
|
||||
dir = t->dirlist_joliet[i];
|
||||
write_one_dir(t, dir, buf);
|
||||
@ -427,7 +427,7 @@ joliet_wr_sup_vol_desc(struct ecma119_write_target *t,
|
||||
uint8_t *buf)
|
||||
{
|
||||
ecma119_start_chunking(t,
|
||||
write_sup_vol_desc,
|
||||
joliet_write_sup_vol_desc,
|
||||
2048,
|
||||
buf);
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ joliet_prepare_path_tables(struct ecma119_write_target *t);
|
||||
void
|
||||
joliet_tree_free(struct joliet_tree_node *root);
|
||||
|
||||
void
|
||||
joliet_write_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
void
|
||||
joliet_wr_sup_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
|
@ -51,7 +51,8 @@ struct iso_tree_node;
|
||||
* iso_tree_node_get_type to get the current type of the node, and then
|
||||
* cast to the appropriate subtype. For example:
|
||||
*
|
||||
* struct iso_tree_node *node = iso... TODO
|
||||
* ...
|
||||
* struct iso_tree_node *node = iso_tree_iter_next(iter);
|
||||
* if ( iso_tree_node_get_type(node) == LIBISO_NODE_DIR ) {
|
||||
* struct iso_tree_node_dir *dir = (struct iso_tree_node_dir *)node;
|
||||
* ...
|
||||
@ -161,12 +162,47 @@ enum eltorito_boot_media_type {
|
||||
ELTORITO_NO_EMUL
|
||||
};
|
||||
|
||||
/**
|
||||
* ISO-9660 (ECMA-119) has important restrictions in both file/dir names
|
||||
* and deep of the directory hierarchy. These are intented for compatibility
|
||||
* with old systems, and most modern operative system can safety deal with
|
||||
* ISO filesystems with relaxed constraints.
|
||||
* You can use some of these flags to generate that kind of filesystems with
|
||||
* libisofs. Of course, all these options will lead to an image not conforming
|
||||
* with ISO-9660 specification, so use them with caution.
|
||||
* Moreover, note that there are much better options to have an ISO-9660 image
|
||||
* compliant with modern systems, such as the Rock Ridge and Joliet extensions,
|
||||
* that add support for longer filenames, deeper directory hierarchy and even
|
||||
* file permissions (in case of RR), while keeping a standard ISO structure
|
||||
* suitable for old systems.
|
||||
* Thus, in most cases you don't want to use the relaxed constraints.
|
||||
*/
|
||||
enum ecma119_relaxed_constraints_flag {
|
||||
ECMA119_OMIT_VERSION_NUMBERS = (1<<0),
|
||||
/* 37 char filenames involves no version number */
|
||||
/**<
|
||||
* ISO-9660 requires a version number at the end of each file name.
|
||||
* That number is just ignored on most systems, so you can omit them
|
||||
* if you want.
|
||||
*/
|
||||
ECMA119_37_CHAR_FILENAMES = (1<<1) | (1<<0),
|
||||
/**<
|
||||
* Allow ISO-9660 filenames to be up to 37 characters long. The extra
|
||||
* space is taken from the version number, so this option involves
|
||||
* no version number
|
||||
*/
|
||||
ECMA119_NO_DIR_REALOCATION = (1<<2),
|
||||
/**<
|
||||
* In ISO-9660 images the depth of the directory hierarchy can't be
|
||||
* greater than 8 levels. In addition, a path to a file on disc can't
|
||||
* be more than 255 characteres. Use the ECMA119_NO_DIR_REALOCATION
|
||||
* to disable this restriction.
|
||||
*/
|
||||
ECMA119_RELAXED_FILENAMES = (1<<3)
|
||||
/**<
|
||||
* Allow filenames with any character. Note that with this flag, the
|
||||
* filename provide by the user will be used without any modification
|
||||
* other that a truncate to max. length.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
@ -241,27 +277,77 @@ struct ecma119_source_opts {
|
||||
* image, used to read file contents.
|
||||
* Otherwise it can be NULL.
|
||||
*/
|
||||
unsigned int dvd_plus_rw:1;
|
||||
/**<
|
||||
* When 1, vol_desc and vol_desc_count will be filled propertly
|
||||
* with information useful for "growing" a DVD+RW.
|
||||
*/
|
||||
uint8_t *vol_desc;
|
||||
/**<
|
||||
* If dvd_plus_rw is set to one, this will be filled with a
|
||||
* pointer to a memory region containing a copy of the
|
||||
* volume descriptors of the image, including the volume
|
||||
* descriptor set terminator.
|
||||
* A suitable program can write the contents of this memory
|
||||
* region from sector 16 of a DVD+RW to "grow" its image.
|
||||
* The size of this region will be vol_desc_count * 2048 and
|
||||
* should be freed by user when no more needed.
|
||||
*/
|
||||
int vol_desc_count;
|
||||
/**<
|
||||
* If dvd_plus_rw is set to one, this will be filled with the
|
||||
* number of volume descriptors written to vol_desc.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME documentar isto!!!
|
||||
* Options for image reading.
|
||||
* There are four kind of options:
|
||||
* - Related to multisession support.
|
||||
* In most cases, an image begins at LBA 0 of the data source. However,
|
||||
* in multisession discs, the later image begins in the last session on
|
||||
* disc. The block option can be used to specify the start of that last
|
||||
* session.
|
||||
* - Related to the tree that will be read.
|
||||
* As default, when Rock Ridge extensions are present in the image, that
|
||||
* will be used to get the tree. If RR extensions are not present, libisofs
|
||||
* will use the Joliet extensions if available. Finally, the plain ISO-9660
|
||||
* tree is used if neither RR nor Joliet extensions are available. With
|
||||
* norock, nojoliet, and preferjoliet options, you can change this
|
||||
* default behavior.
|
||||
* - Related to default POSIX attributes.
|
||||
* When Rock Ridege extensions are not used, libisofs can't figure out what
|
||||
* are the the permissions, uid or gid for the files. You should supply
|
||||
* default values for that.
|
||||
* - Return information for image.
|
||||
* Both size, hasRR and hasJoliet will be filled by libisofs with suitable values.
|
||||
* Also, error is set to non-0 if some error happens (error codes are
|
||||
* private now)
|
||||
*/
|
||||
struct ecma119_read_opts {
|
||||
int tree_to_read;
|
||||
int block; /** Block where the image begins, usually 0, can be
|
||||
* different on a multisession disc.
|
||||
*/
|
||||
//TODO....
|
||||
uint32_t block; /** Block where the image begins, usually 0, can be
|
||||
* different on a multisession disc.
|
||||
*/
|
||||
|
||||
unsigned int norock:1; /*< Do not read Rock Ridge extensions */
|
||||
//nojoliet
|
||||
//check -> convert names to lower case
|
||||
//uid, gid (when no RR)
|
||||
//file and dir mode (when no RR)
|
||||
unsigned int nojoliet:1; /*< Do not read Joliet extensions */
|
||||
unsigned int preferjoliet:1;
|
||||
/*< When both Joliet and RR extensions are present, the RR
|
||||
* tree is used. If you prefer using Joliet, set this to 1. */
|
||||
|
||||
uid_t uid; /**< Default uid when no RR */
|
||||
gid_t gid; /**< Default uid when no RR */
|
||||
mode_t mode; /**< Default mode when no RR (only permissions) */
|
||||
//TODO differ file and dir mode
|
||||
//option to convert names to lower case?
|
||||
|
||||
/* modified by the function */
|
||||
unsigned int hasRR:1; /*< It will be set to 1 if RR extensions are present,
|
||||
to 0 if not. */
|
||||
//hasJoliet
|
||||
unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet extensions are
|
||||
present, to 0 if not. */
|
||||
uint32_t size; /**< Will be filled with the size (in 2048 byte block) of
|
||||
* the image, as reported in the PVM. */
|
||||
int error;
|
||||
};
|
||||
|
||||
@ -327,6 +413,17 @@ struct iso_tree_radd_dir_behavior {
|
||||
//char** errors;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize libisofs. You must call this before any usage of the library.
|
||||
* @return 1 on success, 0 on error
|
||||
*/
|
||||
int iso_init();
|
||||
|
||||
/**
|
||||
* Finalize libisofs.
|
||||
*/
|
||||
void iso_finish();
|
||||
|
||||
/**
|
||||
* Create a new volume.
|
||||
* The parameters can be set to NULL if you wish to set them later.
|
||||
@ -804,6 +901,14 @@ struct iso_tree_iter *iso_tree_node_children(struct iso_tree_node_dir *dir);
|
||||
*/
|
||||
struct iso_tree_node *iso_tree_iter_next(struct iso_tree_iter *iter);
|
||||
|
||||
/**
|
||||
* Check if there're more children.
|
||||
* @return
|
||||
* 1 if next call to iso_tree_iter_next() will return != NULL,
|
||||
* 0 otherwise
|
||||
*/
|
||||
int iso_tree_iter_has_next(struct iso_tree_iter *iter);
|
||||
|
||||
/** Free an iteration */
|
||||
void iso_tree_iter_free(struct iso_tree_iter *iter);
|
||||
|
||||
@ -933,4 +1038,42 @@ void data_source_free(struct data_source*);
|
||||
struct iso_volset *iso_volset_read(struct data_source *src,
|
||||
struct ecma119_read_opts *opts);
|
||||
|
||||
/**
|
||||
* Control queueing and stderr printing of messages from libisofs.
|
||||
* Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
|
||||
* "NOTE", "UPDATE", "DEBUG", "ALL".
|
||||
*
|
||||
* @param queue_severity Gives the minimum limit for messages to be queued.
|
||||
* Default: "NEVER". If you queue messages then you
|
||||
* must consume them by iso_msgs_obtain().
|
||||
* @param print_severity Does the same for messages to be printed directly
|
||||
* to stderr.
|
||||
* @param print_id A text prefix to be printed before the message.
|
||||
* @return >0 for success, <=0 for error
|
||||
*/
|
||||
int iso_msgs_set_severities(char *queue_severity,
|
||||
char *print_severity, char *print_id);
|
||||
|
||||
#define ISO_MSGS_MESSAGE_LEN 4096
|
||||
|
||||
/**
|
||||
* Obtain the oldest pending libisofs message from the queue which has at
|
||||
* least the given minimum_severity. This message and any older message of
|
||||
* lower severity will get discarded from the queue and is then lost forever.
|
||||
*
|
||||
* Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
|
||||
* "NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
|
||||
* will discard the whole queue.
|
||||
*
|
||||
* @param error_code Will become a unique error code as listed in messages.h
|
||||
* @param msg_text Must provide at least ISO_MSGS_MESSAGE_LEN bytes.
|
||||
* @param os_errno Will become the eventual errno related to the message
|
||||
* @param severity Will become the severity related to the message and
|
||||
* should provide at least 80 bytes.
|
||||
* @return 1 if a matching item was found, 0 if not, <0 for severe errors
|
||||
*/
|
||||
int iso_msgs_obtain(char *minimum_severity,
|
||||
int *error_code, char msg_text[], int *os_errno,
|
||||
char severity[]);
|
||||
|
||||
#endif /* LIBISO_LIBISOFS_H */
|
||||
|
@ -36,7 +36,8 @@ void
|
||||
iso_tree_add_child(struct iso_tree_node_dir *parent,
|
||||
struct iso_tree_node *child)
|
||||
{
|
||||
assert( parent && child);
|
||||
assert(parent && child);
|
||||
assert(!child->parent);
|
||||
|
||||
parent->nchildren++;
|
||||
parent->children =
|
||||
@ -338,6 +339,13 @@ iso_tree_iter_next(struct iso_tree_iter *iter)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
iso_tree_iter_has_next(struct iso_tree_iter *iter)
|
||||
{
|
||||
assert(iter);
|
||||
return iter->index + 1 < iter->dir->nchildren;
|
||||
}
|
||||
|
||||
void
|
||||
iso_tree_iter_free(struct iso_tree_iter *iter)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <limits.h>
|
||||
|
||||
@ -571,7 +572,7 @@ iso_r_fileid(const char *src_arg, const char *icharset, int flag)
|
||||
/* no relaxed filenames */
|
||||
dot = strrchr(src, '.');
|
||||
|
||||
max = size == 37 ? 36 : 30;
|
||||
max = (size == 37 ? 36 : 30);
|
||||
/* Since the maximum length can be divided freely over the name and
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
@ -851,5 +852,55 @@ char *strcopy(const char *buf, size_t len)
|
||||
str = malloc( (len+1) * sizeof(char) );
|
||||
strncpy(str, buf, len);
|
||||
str[len] = '\0';
|
||||
|
||||
/* remove trailing spaces */
|
||||
for (len = len-1; str[len] == ' ' && len > 0; --len)
|
||||
str[len] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char *ucs2str(const char *buf, size_t len)
|
||||
{
|
||||
size_t outbytes, inbytes;
|
||||
char *str;
|
||||
|
||||
inbytes = len;
|
||||
|
||||
outbytes = (inbytes+1) * MB_LEN_MAX;
|
||||
{
|
||||
/* ensure enought space */
|
||||
char out[outbytes];
|
||||
char *src;
|
||||
iconv_t conv;
|
||||
size_t n;
|
||||
|
||||
/* convert to local charset */
|
||||
setlocale(LC_CTYPE, "");
|
||||
conv = iconv_open(nl_langinfo(CODESET), "UCS-2BE");
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
printf("Can't convert from %s to %s\n", "UCS-2BE", nl_langinfo(CODESET));
|
||||
return NULL;
|
||||
}
|
||||
src = (char *)buf;
|
||||
str = (char *)out;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &str, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error just return input stream */
|
||||
perror("Convert error.");
|
||||
printf("Maybe string is not encoded in UCS-2BE.\n");
|
||||
|
||||
iconv_close(conv);
|
||||
return NULL;
|
||||
}
|
||||
iconv_close(conv);
|
||||
*str = '\0';
|
||||
|
||||
/* remove trailing spaces */
|
||||
for (len = strlen(out) - 1; out[len] == ' ' && len > 0; --len)
|
||||
out[len] = '\0';
|
||||
str = strdup(out);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
@ -141,9 +141,13 @@ int ucscmp(const uint16_t *s1, const uint16_t *s2);
|
||||
/**
|
||||
* Copy up to \p len chars from \p buf and return this newly allocated
|
||||
* string. The new string is null-terminated.
|
||||
* TODO it would be great to return NULL is the original string was all
|
||||
* white spaces.
|
||||
*/
|
||||
char *strcopy(const char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Convert a Joliet string with a length of \p len bytes to a new string
|
||||
* in local charset.
|
||||
*/
|
||||
char *ucs2str(const char *buf, size_t len);
|
||||
|
||||
#endif /* LIBISO_UTIL_H */
|
||||
|
@ -92,6 +92,12 @@ int main(int argc, char **argv)
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!iso_init()) {
|
||||
err(1, "Can't init libisofs");
|
||||
}
|
||||
iso_msgs_set_severities("NEVER", "ALL", "");
|
||||
|
||||
fd = fopen(argv[optind+1], "w");
|
||||
if (!fd) {
|
||||
err(1, "error opening output file");
|
||||
@ -133,7 +139,7 @@ int main(int argc, char **argv)
|
||||
opts.level = level;
|
||||
opts.flags = flags;
|
||||
opts.relaxed_constraints = 0;//constraints;
|
||||
opts.input_charset = "UTF-8";
|
||||
opts.input_charset = NULL;//"UTF-8";
|
||||
opts.ouput_charset = "UTF-8";
|
||||
|
||||
src = iso_source_new_ecma119(volset, &opts);
|
||||
@ -143,5 +149,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
iso_finish();
|
||||
return 0;
|
||||
}
|
||||
|
@ -98,6 +98,11 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!iso_init()) {
|
||||
err(1, "Can't init libisofs");
|
||||
}
|
||||
iso_msgs_set_severities("NEVER", "ALL", "");
|
||||
|
||||
rsrc = data_source_from_file(argv[optind]);
|
||||
if (rsrc == NULL) {
|
||||
printf ("Can't open device\n");
|
||||
@ -111,6 +116,11 @@ int main(int argc, char **argv)
|
||||
|
||||
ropts.block = 0;
|
||||
ropts.norock = 0;
|
||||
ropts.nojoliet = 0;
|
||||
ropts.preferjoliet = 0;
|
||||
ropts.mode = 0555;
|
||||
ropts.uid = 0;
|
||||
ropts.gid = 0;
|
||||
volset = iso_volset_read(rsrc, &ropts);
|
||||
|
||||
if (volset == NULL) {
|
||||
@ -141,5 +151,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
iso_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -101,6 +101,11 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!iso_init()) {
|
||||
err(1, "Can't init libisofs");
|
||||
}
|
||||
iso_msgs_set_severities("NEVER", "ALL", "");
|
||||
|
||||
rsrc = data_source_from_file(argv[optind+2]);
|
||||
if (rsrc == NULL) {
|
||||
printf ("Can't open device\n");
|
||||
@ -114,6 +119,11 @@ int main(int argc, char **argv)
|
||||
|
||||
ropts.block = atoi(argv[optind]);
|
||||
ropts.norock = 0;
|
||||
ropts.nojoliet = 0;
|
||||
ropts.preferjoliet = 0;
|
||||
ropts.mode = 0555;
|
||||
ropts.uid = 0;
|
||||
ropts.gid = 0;
|
||||
volset = iso_volset_read(rsrc, &ropts);
|
||||
|
||||
if (volset == NULL) {
|
||||
@ -143,5 +153,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
iso_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,6 +81,11 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!iso_init()) {
|
||||
err(1, "Can't init libisofs");
|
||||
}
|
||||
iso_msgs_set_severities("NEVER", "ALL", "");
|
||||
|
||||
src = data_source_from_file(argv[1]);
|
||||
if (src == NULL) {
|
||||
printf ("Can't open image\n");
|
||||
@ -89,6 +94,12 @@ int main(int argc, char **argv)
|
||||
|
||||
opts.block = 0;
|
||||
opts.norock = 0;
|
||||
opts.nojoliet = 0;
|
||||
opts.preferjoliet = 1;
|
||||
opts.mode = 0555;
|
||||
opts.uid = 0;
|
||||
opts.gid = 0;
|
||||
|
||||
volset = iso_volset_read(src, &opts);
|
||||
|
||||
if (volset == NULL) {
|
||||
@ -110,6 +121,11 @@ int main(int argc, char **argv)
|
||||
printf("Abstract: %s\n", iso_volume_get_abstract_file_id(volume));
|
||||
printf("Biblio: %s\n", iso_volume_get_biblio_file_id(volume));
|
||||
|
||||
if (opts.hasRR)
|
||||
printf("Rock Ridge Extensions are available.\n");
|
||||
if (opts.hasJoliet)
|
||||
printf("Joliet Extensions are available.\n");
|
||||
|
||||
printf("\nDIRECTORY TREE\n");
|
||||
printf("==============\n");
|
||||
|
||||
@ -120,5 +136,7 @@ int main(int argc, char **argv)
|
||||
data_source_free(src);
|
||||
iso_volset_free(volset);
|
||||
|
||||
iso_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user