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, /* norock */
|
||||
0, /* nojoliet */
|
||||
0, /* noiso1999 */
|
||||
0, /* preferjoliet */
|
||||
0, /* uid; */
|
||||
0, /* gid; */
|
||||
|
@ -116,6 +116,7 @@ int main(int argc, char **argv)
|
||||
0, /* block */
|
||||
0, /* norock */
|
||||
0, /* nojoliet */
|
||||
0, /* noiso1999 */
|
||||
0, /* preferjoliet */
|
||||
0, /* uid; */
|
||||
0, /* gid; */
|
||||
|
103
src/fs_image.c
103
src/fs_image.c
@ -91,19 +91,18 @@ typedef struct
|
||||
*/
|
||||
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
|
||||
* extensions, and the user wants to read them.
|
||||
*/
|
||||
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
|
||||
* the beginning of the SUSP system user entries. See IEEE 1281, SUSP. 5.3.
|
||||
@ -132,6 +131,9 @@ typedef struct
|
||||
/** If Joliet extensions are available on image */
|
||||
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.
|
||||
*/
|
||||
@ -695,6 +697,40 @@ IsoFileSourceIface ifs_class = {
|
||||
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
|
||||
@ -991,7 +1027,8 @@ int iso_file_source_new_ifs(IsoImageFilesystem *fs, IsoFileSource *parent,
|
||||
return ISO_WRONG_ECMA119;
|
||||
}
|
||||
} 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) {
|
||||
iso_msg_sorry(fsdata->messenger, LIBISO_WRONG_IMG,
|
||||
"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;
|
||||
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->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) ) {
|
||||
|
||||
/* it's a Joliet Sup. Vol. Desc. */
|
||||
iso_msg_debug(data->messenger, "Found Joliet extensions");
|
||||
data->joliet = 1;
|
||||
root = (struct ecma119_dir_record*)sup->root_dir_record;
|
||||
data->svd_root_block = iso_read_bb(root->block, 4, NULL);
|
||||
|
||||
//TODO maybe we can set the IsoImage attribs from this
|
||||
//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 {
|
||||
iso_msg_hint(data->messenger, LIBISO_UNSUPPORTED_VD,
|
||||
"Unsupported (not Joliet) Sup. Vol. Desc found.");
|
||||
"Unsupported Sup. Vol. Desc found.");
|
||||
}
|
||||
}
|
||||
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 user prefers joliet, that is used */
|
||||
iso_msg_debug(data->messenger, "Reading Joliet extensions.");
|
||||
data->get_name = ucs2str;
|
||||
data->input_charset = strdup("UCS-2BE");
|
||||
data->rr = RR_EXT_NO;
|
||||
data->iso_root_block = data->svd_root_block;
|
||||
} else {
|
||||
/* RR will be used */
|
||||
iso_msg_debug(data->messenger, "Reading Rock Ridge extensions.");
|
||||
data->iso_root_block = data->pvd_root_block;
|
||||
data->get_name = strcopy;
|
||||
}
|
||||
} else {
|
||||
/* RR extensions are not available */
|
||||
if (!opts->nojoliet && data->joliet) {
|
||||
/* joliet will be used */
|
||||
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;
|
||||
} 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 {
|
||||
/* default to plain iso */
|
||||
iso_msg_debug(data->messenger, "Reading plain ISO-9660 tree.");
|
||||
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 */
|
||||
|
||||
*fs = ifs;
|
||||
@ -2203,6 +2261,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
|
||||
if (features != NULL) {
|
||||
features->hasJoliet = data->joliet;
|
||||
features->hasRR = data->rr_version != 0;
|
||||
features->hasIso1999 = data->iso1999;
|
||||
features->hasElTorito = data->eltorito;
|
||||
features->size = data->nblocks;
|
||||
}
|
||||
|
@ -350,6 +350,7 @@ struct iso_read_opts
|
||||
|
||||
unsigned int norock : 1; /*< Do not read Rock Ridge 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.
|
||||
@ -382,6 +383,12 @@ struct iso_read_image_features
|
||||
/** It will be set to 1 if Joliet extensions are present, to 0 if not. */
|
||||
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.*/
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
* 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,
|
||||
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
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user