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:
Thomas Schmitt 2009-03-10 14:32:05 +01:00
parent 4f468171ad
commit 4d0063f7e2
4 changed files with 491 additions and 11 deletions

View File

@ -419,7 +419,11 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer)
} }
static 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) int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
#endif
{ {
int ret; int ret;
uint8_t buffer[BLOCK_SIZE]; uint8_t buffer[BLOCK_SIZE];
@ -462,7 +466,11 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
} }
} }
len = 34 + info.suf_len; 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); write_one_dir_record(t, dir, 1, buf, 1, &info, 0);
#endif
buf += len; buf += len;
for (i = 0; i < dir->info.dir->nchildren; i++) { for (i = 0; i < dir->info.dir->nchildren; i++) {
@ -519,13 +527,24 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir)
} }
static 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) int write_dirs(Ecma119Image *t, Ecma119Node *root)
#endif
{ {
int ret; int ret;
size_t i; size_t i;
/* write all directory entries for this dir */ /* 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); ret = write_one_dir(t, root);
#endif
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -534,7 +553,11 @@ int write_dirs(Ecma119Image *t, Ecma119Node *root)
for (i = 0; i < root->info.dir->nchildren; i++) { for (i = 0; i < root->info.dir->nchildren; i++) {
Ecma119Node *child = root->info.dir->children[i]; Ecma119Node *child = root->info.dir->children[i];
if (child->type == ECMA119_DIR) { if (child->type == ECMA119_DIR) {
#ifdef Libisofs_use_parent_for_dot_doT
ret = write_dirs(t, child, root);
#else
ret = write_dirs(t, child); ret = write_dirs(t, child);
#endif
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -653,7 +676,11 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
t = writer->target; t = writer->target;
/* first of all, we write the directory structure */ /* 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); ret = write_dirs(t, t->root);
#endif
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }

View File

@ -4771,23 +4771,60 @@ struct burn_source {
#endif /* LIBISOFS_WITHOUT_LIBBURN */ #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, /* Experiment: Ignore PX inode numbers,
have boot image inode number counted by fs_give_ino_number() have boot image inode number counted by fs_give_ino_number()
*/ */
#define Libisofs_new_fs_image_inO yes #define Libisofs_new_fs_image_inO yes
/* Experiment: Trying to avoid the risk of losing file content by duplicate /* Experiment: Trying to avoid the risk of losing file content by duplicate
inodes. iso_file_src_cmp() shall compare sizes too. inodes. iso_file_src_cmp() shall compare sizes too.
*/ */
#define Libisofs_file_src_cmp_sizE yes #define Libisofs_file_src_cmp_sizE yes
/* Experiment: Revoke Ticket 144, use data file LBAs again. /* Experiment: Revoke Ticket 144, use data file LBAs again.
(will work only if not Libisofs_new_fs_image_inO (will work only if not Libisofs_new_fs_image_inO
and wll only be safe with Libisofs_file_src_cmp_sizE) and wll only be safe with Libisofs_file_src_cmp_sizE)
#define Libisofs_ino_from_lbA yes #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_*/ #endif /*LIBISO_LIBISOFS_H_*/

View File

@ -381,6 +381,38 @@ int rrip_SL_append_comp(size_t *n, uint8_t ***comps, char *s, int size, char fl)
return ISO_SUCCESS; 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 * 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 * 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) if (ret < 0)
return ret; return ret;
} }
aapt = *data; aapt = *data;
if (!(aapt[4] & 1)) { if (!(aapt[4] & 1)) {
/* Single field can be handed over directly */ /* Single field can be handed over directly */
@ -554,6 +585,7 @@ int rrip_add_ER(Ecma119Image *t, struct susp_info *susp)
decrease by 1." decrease by 1."
So "IEEE_P1282" would be the new form, "RRIP_1991A" is the old form. So "IEEE_P1282" would be the new form, "RRIP_1991A" is the old form.
*/ */
ER = malloc(182); ER = malloc(182);
if (ER == NULL) { if (ER == NULL) {
return ISO_OUT_OF_MEM; 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) if (t->aaip && !t->aaip_susp_1_10)
su_size += 5; 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 */ /* PX and TF, we are sure they always fit in SUA */
if (!t->rrip_version_1_10) { if (!t->rrip_version_1_10) {
su_size += 44 + 26; su_size += 44 + 26;
@ -996,7 +1033,9 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
} else { } else {
/* "." or ".." entry */ /* "." or ".." entry */
su_size += 5; /* NM field */ su_size += 5; /* NM field */
if (type == 1 && n->parent == NULL) { if (type == 1 && n->parent == NULL) {
/* /*
* "." for root directory * "." 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 * ER needs a Continuation Area, thus we also need a CE entry
*/ */
su_size += 7 + 28; /* SP + CE */ 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) { if (t->aaip) {
*ce += 160; /* ER of 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 *name = NULL;
char *dest = NULL; char *dest = NULL;
size_t aaip_er_len= 0; 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 */ size_t su_size_pd, ce_len_pd; /* predicted sizes of SUA and CA */
int ce_is_predicted = 0; int ce_is_predicted = 0;
size_t aaip_sua_free= 0, aaip_len= 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; 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 */ /* PX and TF, we are sure they always fit in SUA */
ret = rrip_add_PX(t, node, info); ret = rrip_add_PX(t, node, info);
if (ret < 0) { if (ret < 0) {
@ -1448,6 +1513,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
if (ret < 0) { if (ret < 0) {
goto add_susp_cleanup; goto add_susp_cleanup;
} }
if (type == 1 && n->parent == NULL) { if (type == 1 && n->parent == NULL) {
/* /*
* "." for root directory * "." 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 * 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) { if (t->aaip && !t->aaip_susp_1_10) {
aaip_er_len = 160; aaip_er_len = 160;
} }
@ -1469,6 +1557,9 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/* Allocate the necessary CE space */ /* Allocate the necessary CE space */
ret = susp_add_CE(t, 182 + aaip_er_len + aaip_len, info); ret = susp_add_CE(t, 182 + aaip_er_len + aaip_len, info);
/* 182 is RRIP-ER length */ /* 182 is RRIP-ER length */
#endif /* ! Libisofs_rrip_1_10_er_bugfiX */
if (ret < 0) { if (ret < 0) {
goto add_susp_cleanup; goto add_susp_cleanup;
} }

View File

@ -24,7 +24,7 @@
#include <unistd.h> #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 #ifndef HAVE_EACCESS
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -32,6 +32,118 @@
#endif #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 int_pow(int base, int power)
{ {
int result = 1; int result = 1;
@ -71,7 +183,14 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
size_t inbytes; size_t inbytes;
size_t outbytes; size_t outbytes;
size_t n; size_t n;
#ifdef Libisofs_with_iso_iconV
struct iso_iconv_handle conv;
int conv_ret;
#else
iconv_t conv; iconv_t conv;
#endif
char *out; char *out;
char *src; char *src;
char *ret; char *ret;
@ -83,21 +202,41 @@ int strconv(const char *str, const char *icharset, const char *ocharset,
return ISO_OUT_OF_MEM; 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); conv = iconv_open(ocharset, icharset);
if (conv == (iconv_t)(-1)) { if (conv == (iconv_t)(-1)) {
#endif
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
} }
src = (char *)str; src = (char *)str;
ret = (char *)out; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
if (n == -1) { if (n == -1) {
/* error */ /* error */
iconv_close(conv); iconv_close(conv);
#endif
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
} }
*ret = '\0'; *ret = '\0';
#ifdef Libisofs_with_iso_iconV
iso_iconv_close(&conv, 0);
#else
iconv_close(conv); iconv_close(conv);
#endif
*output = malloc(ret - out + 1); *output = malloc(ret - out + 1);
if (*output == NULL) { if (*output == NULL) {
@ -113,7 +252,14 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
size_t inbytes; size_t inbytes;
size_t outbytes; size_t outbytes;
size_t n; size_t n;
#ifdef Libisofs_with_iso_iconV
struct iso_iconv_handle conv;
int conv_ret;
#else
iconv_t conv; iconv_t conv;
#endif
char *out; char *out;
char *src; char *src;
char *ret; char *ret;
@ -125,21 +271,40 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
return ISO_OUT_OF_MEM; 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); conv = iconv_open(ocharset, icharset);
if (conv == (iconv_t)(-1)) { if (conv == (iconv_t)(-1)) {
#endif
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
} }
src = (char *)str; src = (char *)str;
ret = (char *)out; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
if (n == -1) { if (n == -1) {
/* error */ /* error */
iconv_close(conv); iconv_close(conv);
#endif
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
} }
*ret = '\0'; *ret = '\0';
#ifdef Libisofs_with_iso_iconV
iso_iconv_close(&conv, 0);
#else
iconv_close(conv); iconv_close(conv);
#endif
*output = malloc(ret - out + 1); *output = malloc(ret - out + 1);
if (*output == NULL) { if (*output == NULL) {
@ -159,7 +324,17 @@ int strnconv(const char *str, const char *icharset, const char *ocharset,
static static
int str2wchar(const char *icharset, const char *input, wchar_t **output) 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; 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 inbytes;
size_t outbytes; size_t outbytes;
char *ret; char *ret;
@ -171,12 +346,20 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
return ISO_NULL_POINTER; 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); conv = iconv_open("WCHAR_T", icharset);
if (conv == (iconv_t)-1) { if (conv == (iconv_t)-1) {
#endif
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
} }
inbytes = strlen(input); inbytes = strlen(input);
loop_limit = inbytes + 3;
outbytes = (inbytes + 1) * sizeof(wchar_t); outbytes = (inbytes + 1) * sizeof(wchar_t);
/* we are sure that numchars <= inbytes */ /* we are sure that numchars <= inbytes */
@ -187,14 +370,18 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
ret = (char *)wstr; ret = (char *)wstr;
src = (char *)input; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
while (n == -1) { while (n == -1) {
if (errno == E2BIG) { if (errno == E2BIG) {
/* error, should never occur */ /* error, should never occur */
iconv_close(conv); goto conv_error;
free(wstr);
return ISO_CHARSET_CONV_ERROR;
} else { } else {
wchar_t *wret; wchar_t *wret;
@ -214,14 +401,41 @@ int str2wchar(const char *icharset, const char *input, wchar_t **output)
if (!inbytes) if (!inbytes)
break; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
} }
} }
#ifdef Libisofs_with_iso_iconV
iso_iconv_close(&conv, 0);
#else
iconv_close(conv); iconv_close(conv);
#endif
*( (wchar_t *)ret )='\0'; *( (wchar_t *)ret )='\0';
*output = wstr; *output = wstr;
return ISO_SUCCESS; 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) 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 *ret_; char *ret_;
char *src; char *src;
#ifdef Libisofs_with_iso_iconV
struct iso_iconv_handle conv;
int conv_ret;
#else
iconv_t conv; 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 numchars;
size_t outbytes; size_t outbytes;
size_t inbytes; size_t inbytes;
size_t n; size_t n;
if (icharset == NULL || input == NULL || output == NULL) { if (icharset == NULL || input == NULL || output == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
@ -247,12 +475,13 @@ int str2ascii(const char *icharset, const char *input, char **output)
*/ */
result = str2wchar(icharset, input, &wsrc_); result = str2wchar(icharset, input, &wsrc_);
if (result < 0) { if (result < 0) {
return result; goto fallback;
} }
src = (char *)wsrc_; src = (char *)wsrc_;
numchars = wcslen(wsrc_); numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t); inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3;
ret_ = malloc(numchars + 1); ret_ = malloc(numchars + 1);
if (ret_ == NULL) { if (ret_ == NULL) {
@ -262,14 +491,27 @@ int str2ascii(const char *icharset, const char *input, char **output)
ret = ret_; ret = ret_;
/* initialize iconv */ /* 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"); conv = iconv_open("ASCII", "WCHAR_T");
if (conv == (iconv_t)-1) { if (conv == (iconv_t)-1) {
#endif
free(wsrc_); free(wsrc_);
free(ret_); 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
while (n == -1) { while (n == -1) {
/* The destination buffer is too small. Stops here. */ /* The destination buffer is too small. Stops here. */
if (errno == E2BIG) if (errno == E2BIG)
@ -299,16 +541,41 @@ int str2ascii(const char *icharset, const char *input, char **output)
if (!inbytes) if (!inbytes)
break; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
} }
#ifdef Libisofs_with_iso_iconV
iso_iconv_close(&conv, 0);
#else
iconv_close(conv); iconv_close(conv);
#endif
*ret='\0'; *ret='\0';
free(wsrc_); free(wsrc_);
*output = ret_; *output = ret_;
return ISO_SUCCESS; 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 static
@ -343,7 +610,17 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
char *src; char *src;
char *ret; char *ret;
char *ret_; char *ret_;
#ifdef Libisofs_with_iso_iconV
struct iso_iconv_handle conv;
int conv_ret;
#else
iconv_t conv; 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 numchars;
size_t outbytes; size_t outbytes;
size_t inbytes; size_t inbytes;
@ -365,6 +642,7 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
numchars = wcslen(wsrc_); numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t); inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3;
ret_ = malloc((numchars+1) * sizeof(uint16_t)); ret_ = malloc((numchars+1) * sizeof(uint16_t));
if (ret_ == NULL) { if (ret_ == NULL) {
@ -374,14 +652,27 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
ret = ret_; ret = ret_;
/* initialize iconv */ /* 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"); conv = iconv_open("UCS-2BE", "WCHAR_T");
if (conv == (iconv_t)-1) { if (conv == (iconv_t)-1) {
#endif
free(wsrc_); free(wsrc_);
free(ret_); free(ret_);
return ISO_CHARSET_CONV_ERROR; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
while (n == -1) { while (n == -1) {
/* The destination buffer is too small. Stops here. */ /* The destination buffer is too small. Stops here. */
if (errno == E2BIG) if (errno == E2BIG)
@ -411,10 +702,24 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
if (!inbytes) if (!inbytes)
break; 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); n = iconv(conv, &src, &inbytes, &ret, &outbytes);
#endif
} }
#ifdef Libisofs_with_iso_iconV
iso_iconv_close(&conv, 0);
#else
iconv_close(conv); iconv_close(conv);
#endif
/* close the ucs string */ /* close the ucs string */
set_ucsbe((uint16_t*) ret, '\0'); set_ucsbe((uint16_t*) ret, '\0');
@ -1233,7 +1538,14 @@ char *ucs2str(const char *buf, size_t len)
{ {
size_t outbytes, inbytes; size_t outbytes, inbytes;
char *str, *src, *out; char *str, *src, *out;
#ifdef Libisofs_with_iso_iconV
struct iso_iconv_handle conv;
int conv_ret;
#else
iconv_t conv; iconv_t conv;
#endif
size_t n; size_t n;
inbytes = len; inbytes = len;
@ -1250,20 +1562,32 @@ char *ucs2str(const char *buf, size_t len)
*/ */
setlocale(LC_CTYPE, ""); 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"); conv = iconv_open(iso_get_local_charset(0), "UCS-2BE");
if (conv == (iconv_t)(-1)) { if (conv == (iconv_t)(-1)) {
#endif
return NULL; return NULL;
} }
src = (char *)buf; src = (char *)buf;
str = (char *)out; 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); n = iconv(conv, &src, &inbytes, &str, &outbytes);
iconv_close(conv);
#endif
if (n == -1) { if (n == -1) {
/* error */ /* error */
iconv_close(conv);
return NULL; return NULL;
} }
iconv_close(conv);
*str = '\0'; *str = '\0';
/* remove trailing spaces */ /* remove trailing spaces */
@ -1292,3 +1616,4 @@ int iso_lib_is_compatible(int major, int minor, int micro)
&& (cminor > minor && (cminor > minor
|| (cminor == minor && cmicro >= micro))); || (cminor == minor && cmicro >= micro)));
} }