Backported fix for charset warning and memory leaks
This commit is contained in:
parent
a52eb43dc6
commit
e2fa483126
@ -429,10 +429,10 @@ write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct ecma119_pri_vol_desc *vol = (struct ecma119_pri_vol_desc*)buf;
|
||||
struct iso_volume *volume = t->volset->volume[t->volnum];
|
||||
char *vol_id = wcstoascii(volume->volume_id);
|
||||
char *pub_id = wcstoascii(volume->publisher_id);
|
||||
char *data_id = wcstoascii(volume->data_preparer_id);
|
||||
char *volset_id = wcstoascii(t->volset->volset_id);
|
||||
char *vol_id = str2ascii(volume->volume_id);
|
||||
char *pub_id = str2ascii(volume->publisher_id);
|
||||
char *data_id = str2ascii(volume->data_preparer_id);
|
||||
char *volset_id = str2ascii(t->volset->volset_id);
|
||||
|
||||
vol->vol_desc_type[0] = 1;
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
|
@ -129,6 +129,7 @@ joliet_calc_dir_pos(struct ecma119_write_target *t,
|
||||
|
||||
root->block = t->curblock;
|
||||
t->curblock += div_up(root->len, t->block_size);
|
||||
|
||||
t->dirlist_joliet[t->curfile++] = root;
|
||||
for (i = 0; i < root->nchildren; i++) {
|
||||
ch = root->children[i];
|
||||
@ -231,10 +232,10 @@ 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];
|
||||
uint16_t *vol_id = wcstoucs(volume->volume_id);
|
||||
uint16_t *pub_id = wcstoucs(volume->publisher_id);
|
||||
uint16_t *data_id = wcstoucs(volume->data_preparer_id);
|
||||
uint16_t *volset_id = wcstoucs(t->volset->volset_id);
|
||||
uint16_t *vol_id = str2ucs(volume->volume_id);
|
||||
uint16_t *pub_id = str2ucs(volume->publisher_id);
|
||||
uint16_t *data_id = str2ucs(volume->data_preparer_id);
|
||||
uint16_t *volset_id = str2ucs(t->volset->volset_id);
|
||||
int vol_id_len = MIN(32, ucslen(vol_id) * 2);
|
||||
int pub_id_len = MIN(128, ucslen(pub_id) * 2);
|
||||
int data_id_len = MIN(128, ucslen(data_id) * 2);
|
||||
|
@ -86,7 +86,7 @@ iso_tree_add_new_file(struct iso_tree_node *parent, const char *name)
|
||||
|
||||
f->volume = parent ? parent->volume : NULL;
|
||||
f->parent = parent;
|
||||
f->name = parent ? towcs(name) : NULL;
|
||||
f->name = parent ? strdup(name) : NULL;
|
||||
f->attrib = get_attrib(parent);
|
||||
f->attrib.st_mode = 0777 | S_IFREG;
|
||||
f->loc.type = LIBISO_NONE;
|
||||
@ -192,7 +192,7 @@ iso_tree_print(const struct iso_tree_node *root, int spaces)
|
||||
memset(sp, ' ', spaces);
|
||||
sp[spaces] = '\0';
|
||||
|
||||
printf("%s%ls\n", sp, root->name);
|
||||
printf("%s%sn", sp, root->name);
|
||||
for (i=0; i < root->nchildren; i++) {
|
||||
iso_tree_print(root->children[i], spaces+2);
|
||||
}
|
||||
@ -219,5 +219,5 @@ void
|
||||
iso_tree_node_set_name(struct iso_tree_node *file, const char *name)
|
||||
{
|
||||
free(file->name);
|
||||
file->name = towcs(name);
|
||||
file->name = strdup(name);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ struct iso_tree_node
|
||||
{
|
||||
struct iso_volume *volume;
|
||||
struct iso_tree_node *parent;
|
||||
wchar_t *name;
|
||||
char *name;
|
||||
struct stat attrib; /**< The POSIX attributes of this node as
|
||||
* documented in "man 2 stat". */
|
||||
struct iso_file_location loc;
|
||||
|
215
libisofs/util.c
215
libisofs/util.c
@ -13,9 +13,15 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* avoids warning and names in iso, joliet and rockridge can't be > 255 bytes
|
||||
* anyway. There are at most 31 characters in iso level 1, 255 for rockridge,
|
||||
* 64 characters (* 2 since UCS) for joliet. */
|
||||
#define NAME_BUFFER_SIZE 255
|
||||
|
||||
int div_up(int n, int div)
|
||||
{
|
||||
return (n + div - 1) / div;
|
||||
@ -26,85 +32,162 @@ int round_up(int n, int mul)
|
||||
return div_up(n, mul) * mul;
|
||||
}
|
||||
|
||||
wchar_t *towcs(const char *str)
|
||||
/* this function must always return a name
|
||||
* since the caller never checks if a NULL
|
||||
* is returned. It also avoids some warnings. */
|
||||
char *str2ascii(const char *src_arg)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
wchar_t *ret = malloc(sizeof(wchar_t) * (len + 1));
|
||||
mbstate_t ps;
|
||||
wchar_t wsrc_[NAME_BUFFER_SIZE];
|
||||
char *src = (char*)wsrc_;
|
||||
char *ret_;
|
||||
char *ret;
|
||||
mbstate_t state;
|
||||
iconv_t conv;
|
||||
size_t numchars;
|
||||
size_t outbytes;
|
||||
size_t inbytes;
|
||||
size_t n;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
n = mbsrtowcs(ret, &str, len, &ps);
|
||||
ret[len] = '\0';
|
||||
|
||||
if (n != len) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *wcstoascii(const wchar_t *wsrc)
|
||||
{
|
||||
if (!wsrc)
|
||||
if (!src_arg)
|
||||
return NULL;
|
||||
|
||||
iconv_t conv = iconv_open("ASCII", "WCHAR_T");
|
||||
size_t outbytes = wcslen(wsrc);
|
||||
size_t inbytes = outbytes * sizeof(wchar_t);
|
||||
char src_[inbytes + sizeof(wchar_t)];
|
||||
char *src = src_;
|
||||
char *ret_, *ret;
|
||||
size_t n;
|
||||
/* convert the string to a wide character string. Note: outbytes
|
||||
* is in fact the number of characters in the string and doesn't
|
||||
* include the last NULL character. */
|
||||
memset(&state, 0, sizeof(state));
|
||||
numchars = mbsrtowcs(wsrc_, &src_arg, NAME_BUFFER_SIZE-1, &state);
|
||||
if (numchars < 0)
|
||||
return NULL;
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
|
||||
ret_ = malloc(numchars+1);
|
||||
outbytes = numchars;
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
conv = iconv_open("ASCII", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1)
|
||||
return NULL;
|
||||
|
||||
memcpy(src, wsrc, inbytes + sizeof(wchar_t));
|
||||
ret = malloc(outbytes+1);
|
||||
ret[outbytes] = '\0';
|
||||
ret_ = ret;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
free(ret_);
|
||||
return NULL;
|
||||
while(n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if(errno == E2BIG)
|
||||
break;
|
||||
|
||||
/* An incomplete multi bytes sequence was found. We
|
||||
* can't do anything here. That's quite unlikely. */
|
||||
if(errno == EINVAL)
|
||||
break;
|
||||
|
||||
/* The last possible error is an invalid multi bytes
|
||||
* sequence. Just replace the character with a "_".
|
||||
* Probably the character doesn't exist in ascii like
|
||||
* "é, è, à, ç, ..." in French. */
|
||||
*ret++ = '_';
|
||||
outbytes--;
|
||||
|
||||
if(!outbytes)
|
||||
break;
|
||||
|
||||
/* There was an error with one character but some other remain
|
||||
* to be converted. That's probably a multibyte character.
|
||||
* See above comment. */
|
||||
src += sizeof(wchar_t);
|
||||
inbytes -= sizeof(wchar_t);
|
||||
|
||||
if(!inbytes)
|
||||
break;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
}
|
||||
|
||||
iconv_close(conv);
|
||||
|
||||
*ret='\0';
|
||||
return ret_;
|
||||
}
|
||||
|
||||
/* FIXME: C&P */
|
||||
uint16_t *wcstoucs(const wchar_t *wsrc)
|
||||
uint16_t *str2ucs(const char *src_arg)
|
||||
{
|
||||
if (!wsrc)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
iconv_t conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
size_t outbytes = wcslen(wsrc) * 2;
|
||||
size_t inbytes = outbytes * sizeof(wchar_t) / 2;
|
||||
char src_[inbytes + sizeof(wchar_t)];
|
||||
char *src = src_;
|
||||
char *ret_, *ret;
|
||||
wchar_t wsrc_[NAME_BUFFER_SIZE];
|
||||
char *src = (char*)wsrc_;
|
||||
char *ret_;
|
||||
char *ret;
|
||||
mbstate_t state;
|
||||
iconv_t conv;
|
||||
size_t outbytes;
|
||||
size_t numchars;
|
||||
size_t inbytes;
|
||||
size_t n;
|
||||
|
||||
if (conv == (iconv_t)-1)
|
||||
return calloc(2, 1);
|
||||
if (!src_arg)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
memcpy(src, wsrc, inbytes + sizeof(wchar_t));
|
||||
ret = malloc(outbytes + sizeof(wchar_t));
|
||||
ret[outbytes] = 0;
|
||||
ret[outbytes+1] = 0;
|
||||
ret_ = ret;
|
||||
/* convert the string to a wide character string. Note: outbytes
|
||||
* is in fact the number of characters in the string and doesn't
|
||||
* include the last NULL character. */
|
||||
memset(&state, 0, sizeof(state));
|
||||
numchars = mbsrtowcs(wsrc_, &src_arg, NAME_BUFFER_SIZE-1, &state);
|
||||
if (numchars < 0)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
|
||||
outbytes = numchars * sizeof(uint16_t);
|
||||
ret_ = malloc ((numchars+1) * sizeof(uint16_t));
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1)
|
||||
return calloc(2, 1); /* empty UCS string */
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
perror ("error in iconv conversion");
|
||||
free(ret_);
|
||||
return calloc(2, 1);
|
||||
while(n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if(errno == E2BIG)
|
||||
break;
|
||||
|
||||
/* An incomplete multi bytes sequence was found. We
|
||||
* can't do anything here. That's quite unlikely. */
|
||||
if(errno == EINVAL)
|
||||
break;
|
||||
|
||||
/* The last possible error is an invalid multi bytes
|
||||
* sequence. Just replace the character with a "_".
|
||||
* Probably the character doesn't exist in ascii like
|
||||
* "é, è, à, ç, ..." in French. */
|
||||
*((uint16_t*) ret) = '_';
|
||||
ret += sizeof(uint16_t);
|
||||
outbytes -= sizeof(uint16_t);
|
||||
|
||||
if(!outbytes)
|
||||
break;
|
||||
|
||||
/* There was an error with one character but some other remain
|
||||
* to be converted. That's probably a multibyte character.
|
||||
* See above comment. */
|
||||
src += sizeof(wchar_t);
|
||||
inbytes -= sizeof(wchar_t);
|
||||
|
||||
if(!inbytes)
|
||||
break;
|
||||
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
}
|
||||
|
||||
iconv_close(conv);
|
||||
|
||||
/* close the ucs string */
|
||||
*((uint16_t*) ret) = 0;
|
||||
|
||||
return (uint16_t*)ret_;
|
||||
}
|
||||
|
||||
|
||||
static int valid_d_char(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
@ -132,9 +215,9 @@ static int valid_p_char(char c)
|
||||
|| (c == '.') || (c == '_') || (c == '-');
|
||||
}
|
||||
|
||||
static char *iso_dirid(const wchar_t *src, int size)
|
||||
static char *iso_dirid(const char *src, int size)
|
||||
{
|
||||
char *ret = wcstoascii(src);
|
||||
char *ret = str2ascii(src);
|
||||
size_t len, i;
|
||||
|
||||
if (!ret)
|
||||
@ -153,19 +236,19 @@ static char *iso_dirid(const wchar_t *src, int size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_1_dirid(const wchar_t *src)
|
||||
char *iso_1_dirid(const char *src)
|
||||
{
|
||||
return iso_dirid(src, 8);
|
||||
}
|
||||
|
||||
char *iso_2_dirid(const wchar_t *src)
|
||||
char *iso_2_dirid(const char *src)
|
||||
{
|
||||
return iso_dirid(src, 31);
|
||||
}
|
||||
|
||||
char *iso_1_fileid(const wchar_t *wsrc)
|
||||
char *iso_1_fileid(const char *src_arg)
|
||||
{
|
||||
char *src = wcstoascii(wsrc);
|
||||
char *src = str2ascii(src_arg);
|
||||
char *dest;
|
||||
char *dot; /* Position of the last dot in the
|
||||
filename, will be used to calculate
|
||||
@ -214,9 +297,9 @@ char *iso_1_fileid(const wchar_t *wsrc)
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *iso_2_fileid(const wchar_t *wsrc)
|
||||
char *iso_2_fileid(const char *src_arg)
|
||||
{
|
||||
char *src = wcstoascii(wsrc);
|
||||
char *src = str2ascii(src_arg);
|
||||
char *dest;
|
||||
char *dot;
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
@ -274,9 +357,9 @@ char *iso_2_fileid(const wchar_t *wsrc)
|
||||
}
|
||||
|
||||
char *
|
||||
iso_p_fileid(const wchar_t *src)
|
||||
iso_p_fileid(const char *src)
|
||||
{
|
||||
char *ret = wcstoascii(src);
|
||||
char *ret = str2ascii(src);
|
||||
size_t i, len;
|
||||
|
||||
if (!ret)
|
||||
@ -291,9 +374,9 @@ iso_p_fileid(const wchar_t *src)
|
||||
}
|
||||
|
||||
uint16_t *
|
||||
iso_j_id(const wchar_t *src)
|
||||
iso_j_id(const char *src_arg)
|
||||
{
|
||||
uint16_t *j_str = wcstoucs(src);
|
||||
uint16_t *j_str = str2ucs(src_arg);
|
||||
size_t len = ucslen(j_str);
|
||||
size_t n;
|
||||
|
||||
|
@ -31,18 +31,18 @@ extern inline int round_up(int n, int mul)
|
||||
}
|
||||
|
||||
wchar_t *towcs(const char *);
|
||||
char *wcstoascii(const wchar_t *);
|
||||
uint16_t *wcstoucs(const wchar_t*);
|
||||
char *str2ascii(const char*);
|
||||
uint16_t *str2ucs(const char*);
|
||||
|
||||
/**
|
||||
* Create a level 1 directory identifier.
|
||||
*/
|
||||
char *iso_1_dirid(const wchar_t *src);
|
||||
char *iso_1_dirid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 2 directory identifier.
|
||||
*/
|
||||
char *iso_2_dirid(const wchar_t *src);
|
||||
char *iso_2_dirid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 1 file identifier that consists of a name, extension and
|
||||
@ -51,7 +51,7 @@ char *iso_2_dirid(const wchar_t *src);
|
||||
* length 3, followed by a separator (;) and a version number (digit 1).
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_1_fileid(const wchar_t *src);
|
||||
char *iso_1_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a level 2 file identifier that consists of a name, extension and
|
||||
@ -60,7 +60,7 @@ char *iso_1_fileid(const wchar_t *src);
|
||||
* followed by a separator (;) and a version number (digit 1).
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_2_fileid(const wchar_t *src);
|
||||
char *iso_2_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a Joliet file or directory identifier that consists of a name,
|
||||
@ -73,7 +73,7 @@ char *iso_2_fileid(const wchar_t *src);
|
||||
* @param size will be set to the size (in bytes) of the identifier.
|
||||
* @return NULL if the original name and extension both are of length 0 or the conversion from the current codeset to UCS-2BE is not available.
|
||||
*/
|
||||
uint16_t *iso_j_id(const wchar_t *src);
|
||||
uint16_t *iso_j_id(const char *src);
|
||||
|
||||
/**
|
||||
* FIXME: what are the requirements for these next two? Is this for RR?
|
||||
@ -82,14 +82,14 @@ uint16_t *iso_j_id(const wchar_t *src);
|
||||
* The resulting file name will not exceed 250 characters.
|
||||
* @return NULL if the original name and extension both are of length 0.
|
||||
*/
|
||||
char *iso_p_fileid(const wchar_t *src);
|
||||
char *iso_p_fileid(const char *src);
|
||||
|
||||
/**
|
||||
* Create a POSIX portable directory name.
|
||||
* The resulting directory name will not exceed 250 characters.
|
||||
* @return NULL if the original name is of length 0.
|
||||
*/
|
||||
char *iso_p_dirid(const wchar_t *src);
|
||||
char *iso_p_dirid(const char *src);
|
||||
|
||||
void iso_lsb(uint8_t *buf, uint32_t num, int bytes);
|
||||
void iso_msb(uint8_t *buf, uint32_t num, int bytes);
|
||||
|
@ -19,7 +19,7 @@ iso_volset_new(struct iso_volume *vol, const char *id)
|
||||
volset->refcount = 1;
|
||||
volset->volume = malloc(sizeof(void *));
|
||||
volset->volume[0] = vol;
|
||||
volset->volset_id = towcs(id);
|
||||
volset->volset_id = strdup(id);
|
||||
|
||||
vol->refcount++;
|
||||
return volset;
|
||||
@ -63,11 +63,11 @@ iso_volume_new_with_root(const char *volume_id,
|
||||
volume->root = root ? root : iso_tree_new_root(volume);
|
||||
|
||||
if (volume_id != NULL)
|
||||
volume->volume_id = towcs(volume_id);
|
||||
volume->volume_id = strdup(volume_id);
|
||||
if (publisher_id != NULL)
|
||||
volume->publisher_id = towcs(publisher_id);
|
||||
volume->publisher_id = strdup(publisher_id);
|
||||
if (data_preparer_id != NULL)
|
||||
volume->data_preparer_id = towcs(data_preparer_id);
|
||||
volume->data_preparer_id = strdup(data_preparer_id);
|
||||
return volume;
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,9 @@ struct iso_volume
|
||||
struct iso_tree_node *root; /**< Root of the directory tree for the
|
||||
volume. */
|
||||
|
||||
wchar_t *volume_id; /**< Volume identifier. */
|
||||
wchar_t *publisher_id; /**< Volume publisher. */
|
||||
wchar_t *data_preparer_id; /**< Volume data preparer. */
|
||||
char *volume_id; /**< Volume identifier. */
|
||||
char *publisher_id; /**< Volume publisher. */
|
||||
char *data_preparer_id; /**< Volume data preparer. */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -38,7 +38,7 @@ struct iso_volset
|
||||
int volset_size; /**< The number of volumes in this
|
||||
volume set. */
|
||||
|
||||
wchar_t *volset_id; /**< The id of this volume set, encoded
|
||||
char *volset_id; /**< The id of this volume set, encoded
|
||||
in the current locale. */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user