Bug fix: ECMA-119 ".." pointed always to the same block as ".".
Bug fix: iso_write_opts_set_rrip_version_1_10() caused wrong size of root record CE, Stability enhancement: util.c:str2ascii() got a fallback for the case that charset "WCHAR_T" is not available, Debugging wrapper around iconv*() calls, Experiments about inode numbers in fs_image, Experiment to insert obsolete RR entries. (Sorry for the obfuscation. Most is due to a hard ride on Solaris. See macros at the end of libisofs/libisofs.h)
This commit is contained in:
parent
4f468171ad
commit
4d0063f7e2
@ -419,7 +419,11 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
}
|
||||
|
||||
static
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
#else
|
||||
int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
uint8_t buffer[BLOCK_SIZE];
|
||||
@ -462,7 +466,11 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
||||
}
|
||||
}
|
||||
len = 34 + info.suf_len;
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
write_one_dir_record(t, parent, 1, buf, 1, &info, 0);
|
||||
#else
|
||||
write_one_dir_record(t, dir, 1, buf, 1, &info, 0);
|
||||
#endif
|
||||
buf += len;
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
@ -519,13 +527,24 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
|
||||
}
|
||||
|
||||
static
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
|
||||
/* ts A90309 : todo ? : rename parameter "root" to "dir" */
|
||||
|
||||
int write_dirs(Ecma119Image *t, Ecma119Node *root, Ecma119Node *parent)
|
||||
#else
|
||||
int write_dirs(Ecma119Image *t, Ecma119Node *root)
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
|
||||
/* write all directory entries for this dir */
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
ret = write_one_dir(t, root, parent);
|
||||
#else
|
||||
ret = write_one_dir(t, root);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -534,7 +553,11 @@ int write_dirs(Ecma119Image *t, Ecma119Node *root)
|
||||
for (i = 0; i < root->info.dir->nchildren; i++) {
|
||||
Ecma119Node *child = root->info.dir->children[i];
|
||||
if (child->type == ECMA119_DIR) {
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
ret = write_dirs(t, child, root);
|
||||
#else
|
||||
ret = write_dirs(t, child);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -653,7 +676,11 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
|
||||
t = writer->target;
|
||||
|
||||
/* first of all, we write the directory structure */
|
||||
#ifdef Libisofs_use_parent_for_dot_doT
|
||||
ret = write_dirs(t, t->root, t->root);
|
||||
#else
|
||||
ret = write_dirs(t, t->root);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -4771,23 +4771,60 @@ struct burn_source {
|
||||
|
||||
#endif /* LIBISOFS_WITHOUT_LIBBURN */
|
||||
|
||||
/* ----------------------------- Bug Fixes ----------------------------- */
|
||||
|
||||
|
||||
/* Bug Fix : Augment ecma119.c:write_dirs() by parameter parent
|
||||
and use that one for the second directory entry 001 = "..".
|
||||
|
||||
Everything else seems wrong.
|
||||
*/
|
||||
#define Libisofs_use_parent_for_dot_doT yes
|
||||
|
||||
|
||||
/* Bug fix : Use correct size of 237 if the ER of RRIP-1.10 shal be written
|
||||
(rather than size 182 of RRIP-1.12)
|
||||
|
||||
*/
|
||||
#define Libisofs_rrip_1_10_er_bugfiX yes
|
||||
|
||||
|
||||
/* ---------------------------- Experiments ---------------------------- */
|
||||
|
||||
/* Attempt to fix several issues about inode numbers from ISO images */
|
||||
|
||||
/* Experiment: Ignore PX inode numbers,
|
||||
have boot image inode number counted by fs_give_ino_number()
|
||||
*/
|
||||
#define Libisofs_new_fs_image_inO yes
|
||||
|
||||
|
||||
/* Experiment: Trying to avoid the risk of losing file content by duplicate
|
||||
inodes. iso_file_src_cmp() shall compare sizes too.
|
||||
*/
|
||||
#define Libisofs_file_src_cmp_sizE yes
|
||||
|
||||
|
||||
/* Experiment: Revoke Ticket 144, use data file LBAs again.
|
||||
(will work only if not Libisofs_new_fs_image_inO
|
||||
and wll only be safe with Libisofs_file_src_cmp_sizE)
|
||||
#define Libisofs_ino_from_lbA yes
|
||||
*/
|
||||
|
||||
|
||||
/* Experiment: Write obsolete RR entries with Rock Ridge.
|
||||
I suspect Solaris wants to see them.
|
||||
DID NOT HELP: Solaris knows only RRIP_1991A.
|
||||
|
||||
#define Libisofs_with_rrip_rR yes
|
||||
*/
|
||||
|
||||
|
||||
/* Experiment: Use iso_iconv*() wrappers.
|
||||
They can print errno messages and they
|
||||
can avoid iconv() if the identical mapping is desired.
|
||||
One could install own simple conversion capabilities.
|
||||
*/
|
||||
#define Libisofs_with_iso_iconV yes
|
||||
|
||||
|
||||
#endif /*LIBISO_LIBISOFS_H_*/
|
||||
|
@ -381,6 +381,38 @@ int rrip_SL_append_comp(size_t *n, uint8_t ***comps, char *s, int size, char fl)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_rrip_rR
|
||||
|
||||
/* ts A90307 */
|
||||
/**
|
||||
* Add to the given tree node a RR System Use Entry. This is an obsolete
|
||||
* entry from before RRIP-1.10. Nevertheless mkisofs produces it and there
|
||||
* is the suspicion that Solaris takes it as indication for Rock Ridge.
|
||||
*
|
||||
* I once saw a copy of a RRIP spec which mentioned RR. Here i just use
|
||||
* the same constant 5 bytes as produced by mkisofs.
|
||||
*/
|
||||
static
|
||||
int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
|
||||
{
|
||||
uint8_t *RR;
|
||||
RR = malloc(5);
|
||||
if (RR == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
RR[0] = 'R';
|
||||
RR[1] = 'R';
|
||||
RR[2] = 5;
|
||||
RR[3] = 1;
|
||||
RR[4] = 0201;
|
||||
return susp_append(t, susp, RR);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_rrip_rR */
|
||||
|
||||
|
||||
/**
|
||||
* Add a SL System Use Entry to the given tree node. This is used to store
|
||||
* the content of a symbolic link, and is mandatory if the tree node
|
||||
@ -496,7 +528,6 @@ int aaip_add_AA(Ecma119Image *t, struct susp_info *susp,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
aapt = *data;
|
||||
if (!(aapt[4] & 1)) {
|
||||
/* Single field can be handed over directly */
|
||||
@ -554,6 +585,7 @@ int rrip_add_ER(Ecma119Image *t, struct susp_info *susp)
|
||||
decrease by 1."
|
||||
So "IEEE_P1282" would be the new form, "RRIP_1991A" is the old form.
|
||||
*/
|
||||
|
||||
ER = malloc(182);
|
||||
if (ER == NULL) {
|
||||
return ISO_OUT_OF_MEM;
|
||||
@ -958,6 +990,11 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
if (t->aaip && !t->aaip_susp_1_10)
|
||||
su_size += 5;
|
||||
|
||||
#ifdef Libisofs_with_rrip_rR
|
||||
/* obsolete RR field (once in AAIP-1.09) */
|
||||
su_size += 5;
|
||||
#endif
|
||||
|
||||
/* PX and TF, we are sure they always fit in SUA */
|
||||
if (!t->rrip_version_1_10) {
|
||||
su_size += 44 + 26;
|
||||
@ -996,7 +1033,9 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
} else {
|
||||
|
||||
/* "." or ".." entry */
|
||||
|
||||
su_size += 5; /* NM field */
|
||||
|
||||
if (type == 1 && n->parent == NULL) {
|
||||
/*
|
||||
* "." for root directory
|
||||
@ -1004,7 +1043,20 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
|
||||
* ER needs a Continuation Area, thus we also need a CE entry
|
||||
*/
|
||||
su_size += 7 + 28; /* SP + CE */
|
||||
*ce = 182; /* ER of RRIP */
|
||||
|
||||
#ifdef Libisofs_rrip_1_10_er_bugfiX
|
||||
|
||||
/* ER of RRIP */
|
||||
if (t->rrip_version_1_10) {
|
||||
*ce = 237;
|
||||
} else {
|
||||
*ce = 182;
|
||||
}
|
||||
|
||||
#else
|
||||
*ce = 182;
|
||||
#endif
|
||||
|
||||
if (t->aaip) {
|
||||
*ce += 160; /* ER of AAIP */
|
||||
}
|
||||
@ -1095,6 +1147,11 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
char *name = NULL;
|
||||
char *dest = NULL;
|
||||
size_t aaip_er_len= 0;
|
||||
|
||||
#ifdef Libisofs_rrip_1_10_er_bugfiX
|
||||
size_t rrip_er_len= 182;
|
||||
#endif
|
||||
|
||||
size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */
|
||||
int ce_is_predicted = 0;
|
||||
size_t aaip_sua_free= 0, aaip_len= 0;
|
||||
@ -1138,6 +1195,14 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
goto add_susp_cleanup;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_rrip_rR
|
||||
/* ts A90307 */
|
||||
ret = rrip_add_RR(t, node, info);
|
||||
if (ret < 0) {
|
||||
goto add_susp_cleanup;
|
||||
}
|
||||
#endif /* Libisofs_with_rrip_rR */
|
||||
|
||||
/* PX and TF, we are sure they always fit in SUA */
|
||||
ret = rrip_add_PX(t, node, info);
|
||||
if (ret < 0) {
|
||||
@ -1448,6 +1513,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
if (ret < 0) {
|
||||
goto add_susp_cleanup;
|
||||
}
|
||||
|
||||
if (type == 1 && n->parent == NULL) {
|
||||
/*
|
||||
* "." for root directory
|
||||
@ -1456,6 +1522,28 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
* Note that SP entry was already added above
|
||||
*/
|
||||
|
||||
#ifdef Libisofs_rrip_1_10_er_bugfiX
|
||||
|
||||
if (t->rrip_version_1_10) {
|
||||
rrip_er_len = 237;
|
||||
} else {
|
||||
rrip_er_len = 182;
|
||||
}
|
||||
if (t->aaip && !t->aaip_susp_1_10) {
|
||||
aaip_er_len = 160;
|
||||
}
|
||||
|
||||
/* Compute length of AAIP string of root node */
|
||||
aaip_sua_free= 0;
|
||||
ret = add_aa_string(t, n, info, &aaip_sua_free, &aaip_len, 1);
|
||||
if (ret < 0)
|
||||
goto add_susp_cleanup;
|
||||
|
||||
/* Allocate the necessary CE space */
|
||||
ret = susp_add_CE(t, rrip_er_len + aaip_er_len + aaip_len, info);
|
||||
|
||||
#else /* Libisofs_rrip_1_10_er_bugfiX */
|
||||
|
||||
if (t->aaip && !t->aaip_susp_1_10) {
|
||||
aaip_er_len = 160;
|
||||
}
|
||||
@ -1469,6 +1557,9 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
/* Allocate the necessary CE space */
|
||||
ret = susp_add_CE(t, 182 + aaip_er_len + aaip_len, info);
|
||||
/* 182 is RRIP-ER length */
|
||||
|
||||
#endif /* ! Libisofs_rrip_1_10_er_bugfiX */
|
||||
|
||||
if (ret < 0) {
|
||||
goto add_susp_cleanup;
|
||||
}
|
||||
|
341
libisofs/util.c
341
libisofs/util.c
@ -24,7 +24,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/* if we don't have eaccess, we check file access by openning it */
|
||||
/* if we don't have eaccess, we check file access by opening it */
|
||||
#ifndef HAVE_EACCESS
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -32,6 +32,118 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
|
||||
|
||||
/* Produce possibly inflationary error messages directly to stderr */
|
||||
static int iso_iconv_debug = 0;
|
||||
|
||||
|
||||
struct iso_iconv_handle {
|
||||
int status; /* bit0= open , bit1= identical mapping */
|
||||
iconv_t descr;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
@param flag bit0= shortcut by identical mapping is not allowed
|
||||
*/
|
||||
static
|
||||
int iso_iconv_open(struct iso_iconv_handle *handle,
|
||||
char *tocode, char *fromcode, int flag)
|
||||
{
|
||||
handle->status = 0;
|
||||
handle->descr = (iconv_t) -1;
|
||||
|
||||
if (strcmp(tocode, fromcode) == 0 && !(flag & 1)) {
|
||||
handle->status = 1 | 2;
|
||||
return 1;
|
||||
}
|
||||
handle->descr = iconv_open(tocode, fromcode);
|
||||
if (handle->descr == (iconv_t) -1) {
|
||||
if (strlen(tocode) + strlen(fromcode) <= 160 && iso_iconv_debug)
|
||||
fprintf(stderr,
|
||||
"libisofs_DEBUG: iconv_open(\"%s\", \"%s\") failed: errno= %d %s\n",
|
||||
tocode, fromcode, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
handle->status = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
size_t iso_iconv(struct iso_iconv_handle *handle,
|
||||
char **inbuf, size_t *inbytesleft,
|
||||
char **outbuf, size_t *outbytesleft, int flag)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
if (!(handle->status & 1)) {
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr,
|
||||
"libisofs_DEBUG: iso_iconv(): iso_iconv_handle not in open state\n");
|
||||
return (size_t) -1;
|
||||
}
|
||||
if (handle->status & 2) {
|
||||
if (inbuf == NULL || outbuf == NULL) {
|
||||
null_buf:;
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr,
|
||||
"libisofs_DEBUG: iso_iconv(): NULL buffers not allowed in shortcut mapping\n");
|
||||
return (size_t) -1;
|
||||
}
|
||||
if (*inbuf == NULL || *outbuf == NULL)
|
||||
goto null_buf;
|
||||
while (*inbytesleft > 0 && *outbytesleft > 0) {
|
||||
*((*outbuf)++) = *((*inbuf)++);
|
||||
(*inbytesleft)--;
|
||||
(*outbytesleft)--;
|
||||
}
|
||||
if (*inbytesleft > 0 && *outbytesleft <= 0)
|
||||
return (size_t) -1;
|
||||
return (size_t) 0;
|
||||
}
|
||||
ret = iconv(handle->descr, inbuf, inbytesleft, outbuf, outbytesleft);
|
||||
if (ret == (size_t) -1) {
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr, "libisofs_DEBUG: iconv() failed: errno= %d %s\n",
|
||||
errno, strerror(errno));
|
||||
return (size_t) -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int iso_iconv_close(struct iso_iconv_handle *handle, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!(handle->status & 1)) {
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr,
|
||||
"libisofs_DEBUG: iso_iconv_close(): iso_iconv_handle not in open state\n");
|
||||
return -1;
|
||||
}
|
||||
handle->status &= ~1;
|
||||
if (handle->status & 2)
|
||||
return 0;
|
||||
|
||||
ret = iconv_close(handle->descr);
|
||||
if (ret == -1) {
|
||||
if (iso_iconv_debug)
|
||||
fprintf(stderr,
|
||||
"libisofs_DEBUG: iconv_close() failed: errno= %d %s\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_with_iso_iconV */
|
||||
|
||||
|
||||
int int_pow(int base, int power)
|
||||
{
|
||||
int result = 1;
|
||||
@ -71,7 +183,14 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out;
|
||||
char *src;
|
||||
char *ret;
|
||||
@ -83,21 +202,41 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -113,7 +252,14 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t n;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
char *out;
|
||||
char *src;
|
||||
char *ret;
|
||||
@ -125,21 +271,40 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
return ISO_OUT_OF_MEM;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, (char *) ocharset, (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(ocharset, icharset);
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
src = (char *)str;
|
||||
ret = (char *)out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
*ret = '\0';
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*output = malloc(ret - out + 1);
|
||||
if (*output == NULL) {
|
||||
@ -159,7 +324,17 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
|
||||
static
|
||||
int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
{
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* ts A90308 : that while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
char *ret;
|
||||
@ -171,12 +346,20 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "WCHAR_T", (char *) icharset, 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("WCHAR_T", icharset);
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
inbytes = strlen(input);
|
||||
loop_limit = inbytes + 3;
|
||||
outbytes = (inbytes + 1) * sizeof(wchar_t);
|
||||
|
||||
/* we are sure that numchars <= inbytes */
|
||||
@ -187,14 +370,18 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
ret = (char *)wstr;
|
||||
src = (char *)input;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
|
||||
if (errno == E2BIG) {
|
||||
/* error, should never occur */
|
||||
iconv_close(conv);
|
||||
free(wstr);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
goto conv_error;
|
||||
} else {
|
||||
wchar_t *wret;
|
||||
|
||||
@ -214,14 +401,41 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
|
||||
|
||||
if (!inbytes)
|
||||
break;
|
||||
|
||||
/* Just to appease my remorse about unclear loop ends */
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
goto conv_error;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*( (wchar_t *)ret )='\0';
|
||||
*output = wstr;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
conv_error:;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
free(wstr);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
int str2ascii(const char *icharset, const char *input, char **output)
|
||||
@ -231,12 +445,26 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
char *ret;
|
||||
char *ret_;
|
||||
char *src;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* ts A90308 : that while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
|
||||
/* ts A90308 : fallback in case that iconv() is too demanding for system */
|
||||
unsigned char *cpt;
|
||||
|
||||
size_t numchars;
|
||||
size_t outbytes;
|
||||
size_t inbytes;
|
||||
size_t n;
|
||||
|
||||
|
||||
if (icharset == NULL || input == NULL || output == NULL) {
|
||||
return ISO_NULL_POINTER;
|
||||
}
|
||||
@ -247,12 +475,13 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
*/
|
||||
result = str2wchar(icharset, input, &wsrc_);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
goto fallback;
|
||||
}
|
||||
src = (char *)wsrc_;
|
||||
numchars = wcslen(wsrc_);
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
loop_limit = inbytes + 3;
|
||||
|
||||
ret_ = malloc(numchars + 1);
|
||||
if (ret_ == NULL) {
|
||||
@ -262,14 +491,27 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("ASCII", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -299,16 +541,41 @@ int str2ascii(const char *icharset, const char *input, char **output)
|
||||
if (!inbytes)
|
||||
break;
|
||||
|
||||
/* Just to appease my remorse about unclear loop ends */
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
*ret='\0';
|
||||
free(wsrc_);
|
||||
|
||||
*output = ret_;
|
||||
return ISO_SUCCESS;
|
||||
|
||||
fallback:;
|
||||
/* Assume to have a single byte charset with ASCII as core.
|
||||
Anything suspicious will be mapped to '_'.
|
||||
*/
|
||||
*output = strdup(input);
|
||||
for (cpt = (unsigned char *) *output; *cpt; cpt++) {
|
||||
if (*cpt < 32 || *cpt > 126)
|
||||
*cpt = '_';
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
@ -343,7 +610,17 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
char *src;
|
||||
char *ret;
|
||||
char *ret_;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
/* ts A90308 : that while loop smells like a potential show stopper */
|
||||
size_t loop_counter = 0, loop_limit = 3;
|
||||
|
||||
size_t numchars;
|
||||
size_t outbytes;
|
||||
size_t inbytes;
|
||||
@ -365,6 +642,7 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
numchars = wcslen(wsrc_);
|
||||
|
||||
inbytes = numchars * sizeof(wchar_t);
|
||||
loop_limit = inbytes + 3;
|
||||
|
||||
ret_ = malloc((numchars+1) * sizeof(uint16_t));
|
||||
if (ret_ == NULL) {
|
||||
@ -374,14 +652,27 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
ret = ret_;
|
||||
|
||||
/* initialize iconv */
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open("UCS-2BE", "WCHAR_T");
|
||||
if (conv == (iconv_t)-1) {
|
||||
#endif
|
||||
|
||||
free(wsrc_);
|
||||
free(ret_);
|
||||
return ISO_CHARSET_CONV_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
while (n == -1) {
|
||||
/* The destination buffer is too small. Stops here. */
|
||||
if (errno == E2BIG)
|
||||
@ -411,10 +702,24 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
|
||||
if (!inbytes)
|
||||
break;
|
||||
|
||||
/* Just to appease my remorse about unclear loop ends */
|
||||
loop_counter++;
|
||||
if (loop_counter > loop_limit)
|
||||
break;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &ret, &outbytes);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
/* close the ucs string */
|
||||
set_ucsbe((uint16_t*) ret, '\0');
|
||||
@ -1233,7 +1538,14 @@ char *ucs2str(const char *buf, size_t len)
|
||||
{
|
||||
size_t outbytes, inbytes;
|
||||
char *str, *src, *out;
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
struct iso_iconv_handle conv;
|
||||
int conv_ret;
|
||||
#else
|
||||
iconv_t conv;
|
||||
#endif
|
||||
|
||||
size_t n;
|
||||
|
||||
inbytes = len;
|
||||
@ -1250,20 +1562,32 @@ char *ucs2str(const char *buf, size_t len)
|
||||
*/
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
conv_ret = iso_iconv_open(&conv, iso_get_local_charset(0), "UCS-2BE", 0);
|
||||
if (conv_ret <= 0) {
|
||||
#else
|
||||
conv = iconv_open(iso_get_local_charset(0), "UCS-2BE");
|
||||
if (conv == (iconv_t)(-1)) {
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
src = (char *)buf;
|
||||
str = (char *)out;
|
||||
|
||||
|
||||
#ifdef Libisofs_with_iso_iconV
|
||||
n = iso_iconv(&conv, &src, &inbytes, &str, &outbytes, 0);
|
||||
iso_iconv_close(&conv, 0);
|
||||
#else
|
||||
n = iconv(conv, &src, &inbytes, &str, &outbytes);
|
||||
iconv_close(conv);
|
||||
#endif
|
||||
|
||||
if (n == -1) {
|
||||
/* error */
|
||||
iconv_close(conv);
|
||||
return NULL;
|
||||
}
|
||||
iconv_close(conv);
|
||||
*str = '\0';
|
||||
|
||||
/* remove trailing spaces */
|
||||
@ -1292,3 +1616,4 @@ int iso_lib_is_compatible(int major, int minor, int micro)
|
||||
&& (cminor > minor
|
||||
|| (cminor == minor && cmicro >= micro)));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user