Support for reading ISO-9660:1999 images.
This commit is contained in:
parent
c57a5196a3
commit
57025a614d
@ -59,6 +59,7 @@ int main(int argc, char **argv)
|
|||||||
0, /* block */
|
0, /* block */
|
||||||
0, /* norock */
|
0, /* norock */
|
||||||
0, /* nojoliet */
|
0, /* nojoliet */
|
||||||
|
0, /* noiso1999 */
|
||||||
0, /* preferjoliet */
|
0, /* preferjoliet */
|
||||||
0, /* uid; */
|
0, /* uid; */
|
||||||
0, /* gid; */
|
0, /* gid; */
|
||||||
|
@ -116,6 +116,7 @@ int main(int argc, char **argv)
|
|||||||
0, /* block */
|
0, /* block */
|
||||||
0, /* norock */
|
0, /* norock */
|
||||||
0, /* nojoliet */
|
0, /* nojoliet */
|
||||||
|
0, /* noiso1999 */
|
||||||
0, /* preferjoliet */
|
0, /* preferjoliet */
|
||||||
0, /* uid; */
|
0, /* uid; */
|
||||||
0, /* gid; */
|
0, /* gid; */
|
||||||
|
103
src/fs_image.c
103
src/fs_image.c
@ -91,19 +91,18 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
uint32_t svd_root_block;
|
uint32_t svd_root_block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be filled with the block lba of the extend for the root directory,
|
||||||
|
* as read from the enhanced volume descriptor (ISO 9660:1999)
|
||||||
|
*/
|
||||||
|
uint32_t evd_root_block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we need to read RR extensions. i.e., if the image contains RR
|
* If we need to read RR extensions. i.e., if the image contains RR
|
||||||
* extensions, and the user wants to read them.
|
* extensions, and the user wants to read them.
|
||||||
*/
|
*/
|
||||||
enum read_rr_ext rr;
|
enum read_rr_ext rr;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
char *(*get_name)(const char *, size_t);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bytes skipped within the System Use field of a directory record, before
|
* 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.
|
* the beginning of the SUSP system user entries. See IEEE 1281, SUSP. 5.3.
|
||||||
@ -131,6 +130,9 @@ typedef struct
|
|||||||
|
|
||||||
/** If Joliet extensions are available on image */
|
/** If Joliet extensions are available on image */
|
||||||
unsigned int joliet : 1;
|
unsigned int joliet : 1;
|
||||||
|
|
||||||
|
/** If ISO 9660:1999 is available on image */
|
||||||
|
unsigned int iso1999 : 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of blocks of the volume, as reported in the PVM.
|
* Number of blocks of the volume, as reported in the PVM.
|
||||||
@ -695,6 +697,40 @@ IsoFileSourceIface ifs_class = {
|
|||||||
ifs_free
|
ifs_free
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a file name from a directory record, doing the needed charset
|
||||||
|
* conversion
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
char *get_name(_ImageFsData *fsdata, const char *str, size_t len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *name = NULL;
|
||||||
|
if (strcmp(fsdata->local_charset, fsdata->input_charset)) {
|
||||||
|
/* charset conversion needed */
|
||||||
|
ret = strnconv(str, fsdata->input_charset, fsdata->local_charset, len,
|
||||||
|
&name);
|
||||||
|
if (ret == 1) {
|
||||||
|
return name;
|
||||||
|
} else {
|
||||||
|
iso_msg_sorry(fsdata->messenger, LIBISO_CHARSET_ERROR,
|
||||||
|
"Charset conversion error. Can't convert %s from %s to %s",
|
||||||
|
str, fsdata->input_charset, fsdata->local_charset);
|
||||||
|
/* fallback */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we reach here when the charset conversion is not needed or has failed */
|
||||||
|
|
||||||
|
name = malloc(len + 1);
|
||||||
|
if (name == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(name, str, len);
|
||||||
|
name[len] = '\0';
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
@ -991,7 +1027,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
|||||||
return ISO_WRONG_ECMA119;
|
return ISO_WRONG_ECMA119;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
name = fsdata->get_name((char*)record->file_id, record->len_fi[0]);
|
|
||||||
|
name = get_name(fsdata, (char*)record->file_id, record->len_fi[0]);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
iso_msg_sorry(fsdata->messenger, LIBISO_WRONG_IMG,
|
iso_msg_sorry(fsdata->messenger, LIBISO_WRONG_IMG,
|
||||||
"Can't retrieve file name");
|
"Can't retrieve file name");
|
||||||
@ -1625,15 +1662,6 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
|||||||
ret = ISO_MEM_ERROR;
|
ret = ISO_MEM_ERROR;
|
||||||
goto fs_cleanup;
|
goto fs_cleanup;
|
||||||
}
|
}
|
||||||
if (opts->input_charset != NULL) {
|
|
||||||
data->input_charset = strdup(opts->input_charset);
|
|
||||||
} else {
|
|
||||||
data->input_charset = strdup(data->local_charset);
|
|
||||||
}
|
|
||||||
if (data->input_charset == NULL) {
|
|
||||||
ret = ISO_MEM_ERROR;
|
|
||||||
goto fs_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifs->open = ifs_fs_open;
|
ifs->open = ifs_fs_open;
|
||||||
ifs->close = ifs_fs_close;
|
ifs->close = ifs_fs_close;
|
||||||
@ -1701,15 +1729,30 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
|||||||
sup->esc_sequences[2] == 0x45) ) {
|
sup->esc_sequences[2] == 0x45) ) {
|
||||||
|
|
||||||
/* it's a Joliet Sup. Vol. Desc. */
|
/* it's a Joliet Sup. Vol. Desc. */
|
||||||
|
iso_msg_debug(data->messenger, "Found Joliet extensions");
|
||||||
data->joliet = 1;
|
data->joliet = 1;
|
||||||
root = (struct ecma119_dir_record*)sup->root_dir_record;
|
root = (struct ecma119_dir_record*)sup->root_dir_record;
|
||||||
data->svd_root_block = iso_read_bb(root->block, 4, NULL);
|
data->svd_root_block = iso_read_bb(root->block, 4, NULL);
|
||||||
|
|
||||||
//TODO maybe we can set the IsoImage attribs from this
|
//TODO maybe we can set the IsoImage attribs from this
|
||||||
//descriptor
|
//descriptor
|
||||||
|
//TODO a joliet tree can also have RR extensions. What
|
||||||
|
//about this?
|
||||||
|
|
||||||
|
} else if (sup->vol_desc_version[0] == 2) {
|
||||||
|
/*
|
||||||
|
* It is an Enhanced Volume Descriptor, image is an
|
||||||
|
* ISO 9660:1999
|
||||||
|
*/
|
||||||
|
iso_msg_debug(data->messenger, "Found ISO 9660:1999");
|
||||||
|
data->iso1999 = 1;
|
||||||
|
root = (struct ecma119_dir_record*)sup->root_dir_record;
|
||||||
|
data->evd_root_block = iso_read_bb(root->block, 4, NULL);
|
||||||
|
//TODO an ISO 9660:1999 tree can also have RR extensions.
|
||||||
|
// What about this?
|
||||||
} else {
|
} else {
|
||||||
iso_msg_hint(data->messenger, LIBISO_UNSUPPORTED_VD,
|
iso_msg_hint(data->messenger, LIBISO_UNSUPPORTED_VD,
|
||||||
"Unsupported (not Joliet) Sup. Vol. Desc found.");
|
"Unsupported Sup. Vol. Desc found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1746,30 +1789,45 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
|||||||
if (!opts->nojoliet && opts->preferjoliet && data->joliet) {
|
if (!opts->nojoliet && opts->preferjoliet && data->joliet) {
|
||||||
/* if user prefers joliet, that is used */
|
/* if user prefers joliet, that is used */
|
||||||
iso_msg_debug(data->messenger, "Reading Joliet extensions.");
|
iso_msg_debug(data->messenger, "Reading Joliet extensions.");
|
||||||
data->get_name = ucs2str;
|
data->input_charset = strdup("UCS-2BE");
|
||||||
data->rr = RR_EXT_NO;
|
data->rr = RR_EXT_NO;
|
||||||
data->iso_root_block = data->svd_root_block;
|
data->iso_root_block = data->svd_root_block;
|
||||||
} else {
|
} else {
|
||||||
/* RR will be used */
|
/* RR will be used */
|
||||||
iso_msg_debug(data->messenger, "Reading Rock Ridge extensions.");
|
iso_msg_debug(data->messenger, "Reading Rock Ridge extensions.");
|
||||||
data->iso_root_block = data->pvd_root_block;
|
data->iso_root_block = data->pvd_root_block;
|
||||||
data->get_name = strcopy;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* RR extensions are not available */
|
/* RR extensions are not available */
|
||||||
if (!opts->nojoliet && data->joliet) {
|
if (!opts->nojoliet && data->joliet) {
|
||||||
/* joliet will be used */
|
/* joliet will be used */
|
||||||
iso_msg_debug(data->messenger, "Reading Joliet extensions.");
|
iso_msg_debug(data->messenger, "Reading Joliet extensions.");
|
||||||
data->get_name = ucs2str;
|
data->input_charset = strdup("UCS-2BE");
|
||||||
data->iso_root_block = data->svd_root_block;
|
data->iso_root_block = data->svd_root_block;
|
||||||
|
} else if (!opts->noiso1999 && data->iso1999) {
|
||||||
|
/* we will read ISO 9660:1999 */
|
||||||
|
iso_msg_debug(data->messenger, "Reading ISO-9660:1999 tree.");
|
||||||
|
data->iso_root_block = data->evd_root_block;
|
||||||
} else {
|
} else {
|
||||||
/* default to plain iso */
|
/* default to plain iso */
|
||||||
iso_msg_debug(data->messenger, "Reading plain ISO-9660 tree.");
|
iso_msg_debug(data->messenger, "Reading plain ISO-9660 tree.");
|
||||||
data->iso_root_block = data->pvd_root_block;
|
data->iso_root_block = data->pvd_root_block;
|
||||||
data->get_name = strcopy;
|
data->input_charset = strdup("ASCII");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->input_charset == NULL) {
|
||||||
|
if (opts->input_charset != NULL) {
|
||||||
|
data->input_charset = strdup(opts->input_charset);
|
||||||
|
} else {
|
||||||
|
data->input_charset = strdup(data->local_charset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data->input_charset == NULL) {
|
||||||
|
ret = ISO_MEM_ERROR;
|
||||||
|
goto fs_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* and finally return. Note that we keep the DataSource opened */
|
/* and finally return. Note that we keep the DataSource opened */
|
||||||
|
|
||||||
*fs = ifs;
|
*fs = ifs;
|
||||||
@ -2203,6 +2261,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
|||||||
if (features != NULL) {
|
if (features != NULL) {
|
||||||
features->hasJoliet = data->joliet;
|
features->hasJoliet = data->joliet;
|
||||||
features->hasRR = data->rr_version != 0;
|
features->hasRR = data->rr_version != 0;
|
||||||
|
features->hasIso1999 = data->iso1999;
|
||||||
features->hasElTorito = data->eltorito;
|
features->hasElTorito = data->eltorito;
|
||||||
features->size = data->nblocks;
|
features->size = data->nblocks;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +350,7 @@ struct iso_read_opts
|
|||||||
|
|
||||||
unsigned int norock : 1; /*< Do not read Rock Ridge extensions */
|
unsigned int norock : 1; /*< Do not read Rock Ridge extensions */
|
||||||
unsigned int nojoliet : 1; /*< Do not read Joliet extensions */
|
unsigned int nojoliet : 1; /*< Do not read Joliet extensions */
|
||||||
|
unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When both Joliet and RR extensions are present, the RR tree is used.
|
* When both Joliet and RR extensions are present, the RR tree is used.
|
||||||
@ -382,6 +383,12 @@ struct iso_read_image_features
|
|||||||
/** It will be set to 1 if Joliet extensions are present, to 0 if not. */
|
/** It will be set to 1 if Joliet extensions are present, to 0 if not. */
|
||||||
unsigned int hasJoliet :1;
|
unsigned int hasJoliet :1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It will be set to 1 if the image is an ISO 9660:1999, i.e. it ha
|
||||||
|
* a version 2 Enhanced Volume Descriptor.
|
||||||
|
*/
|
||||||
|
unsigned int hasIso1999 :1;
|
||||||
|
|
||||||
/** It will be set to 1 if El-Torito boot record is present, to 0 if not.*/
|
/** It will be set to 1 if El-Torito boot record is present, to 0 if not.*/
|
||||||
unsigned int hasElTorito :1;
|
unsigned int hasElTorito :1;
|
||||||
|
|
||||||
|
42
src/util.c
42
src/util.c
@ -86,6 +86,48 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
|||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||||
|
size_t len, char **output)
|
||||||
|
{
|
||||||
|
size_t inbytes;
|
||||||
|
size_t outbytes;
|
||||||
|
size_t n;
|
||||||
|
iconv_t conv;
|
||||||
|
char *out;
|
||||||
|
char *src;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
inbytes = len;
|
||||||
|
outbytes = (inbytes + 1) * MB_LEN_MAX;
|
||||||
|
out = alloca(outbytes);
|
||||||
|
if (out == NULL) {
|
||||||
|
return ISO_MEM_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
conv = iconv_open(ocharset, icharset);
|
||||||
|
if (conv == (iconv_t)(-1)) {
|
||||||
|
return ISO_CHARSET_CONV_ERROR;
|
||||||
|
}
|
||||||
|
src = (char *)str;
|
||||||
|
ret = (char *)out;
|
||||||
|
|
||||||
|
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||||
|
if (n == -1) {
|
||||||
|
/* error */
|
||||||
|
iconv_close(conv);
|
||||||
|
return ISO_CHARSET_CONV_ERROR;
|
||||||
|
}
|
||||||
|
*ret = '\0';
|
||||||
|
iconv_close(conv);
|
||||||
|
|
||||||
|
*output = malloc(ret - out + 1);
|
||||||
|
if (*output == NULL) {
|
||||||
|
return ISO_MEM_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(*output, out, ret - out + 1);
|
||||||
|
return ISO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a str in a specified codeset to WCHAR_T.
|
* Convert a str in a specified codeset to WCHAR_T.
|
||||||
* The result must be free() when no more needed
|
* The result must be free() when no more needed
|
||||||
|
@ -42,6 +42,9 @@ int int_pow(int base, int power);
|
|||||||
int strconv(const char *input, const char *icharset, const char *ocharset,
|
int strconv(const char *input, const char *icharset, const char *ocharset,
|
||||||
char **output);
|
char **output);
|
||||||
|
|
||||||
|
int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||||
|
size_t len, char **output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a given string from any input charset to ASCII
|
* Convert a given string from any input charset to ASCII
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user