aboutsummaryrefslogtreecommitdiff
path: root/iconv
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-11-24 02:08:40 +0000
committerUlrich Drepper <drepper@redhat.com>1997-11-24 02:08:40 +0000
commite34b0f2902588bbbfaf55829692e32c3c7134b74 (patch)
tree3d74df649b5b0bf80b4f6070e360f405516caec5 /iconv
parentf43ce637b5f35b350b4dff6810dd6a7421fbb952 (diff)
downloadglibc-e34b0f2902588bbbfaf55829692e32c3c7134b74.tar
glibc-e34b0f2902588bbbfaf55829692e32c3c7134b74.tar.gz
glibc-e34b0f2902588bbbfaf55829692e32c3c7134b74.tar.bz2
glibc-e34b0f2902588bbbfaf55829692e32c3c7134b74.zip
1997-11-24 03:01 Ulrich Drepper <drepper@cygnus.com> * elf/dl-support.c: Call __libc_init_secure to make sure __libc_enable_secure is defined early. * sysdeps/generic/enbl-secure.c: Change function name to __libc_init_secure and make it global instead of a constructor. * iconv/gconv.c: Fix lots of bugs. * iconv/gconv.h: Likewise. * iconv/gconv_builtin.h: Likewise. * iconv/gconv_close.c: Likewise. * iconv/gconv_conf.c: Likewise. * iconv/gconv_db.c: Likewise. * iconv/gconv_dl.c: Likewise. * iconv/gconv_open.c: Likewise. * iconv/gconv_simple.c: Likewise. * iconv/iconv.c: Likewise. * iconv/iconv_close.c: Likewise. * iconv/iconv_open.c: Likewise. * wcsmbs/Makefile (routines): Add wmemrtowcs and wmemrtombs. * wcsmbs/wchar.h: Add prototypes for wmemrtowcs and wmemrtombs. * wcsmbs/wmemrtombs.c: New file. * wcsmbs/wmemrtowcs.c: New file.
Diffstat (limited to 'iconv')
-rw-r--r--iconv/gconv.c3
-rw-r--r--iconv/gconv.h1
-rw-r--r--iconv/gconv_builtin.h6
-rw-r--r--iconv/gconv_close.c3
-rw-r--r--iconv/gconv_conf.c158
-rw-r--r--iconv/gconv_db.c72
-rw-r--r--iconv/gconv_dl.c5
-rw-r--r--iconv/gconv_open.c26
-rw-r--r--iconv/gconv_simple.c4
-rw-r--r--iconv/iconv.c38
-rw-r--r--iconv/iconv_close.c7
-rw-r--r--iconv/iconv_open.c13
12 files changed, 211 insertions, 125 deletions
diff --git a/iconv/gconv.c b/iconv/gconv.c
index 0cbb052a6d..5df16354b6 100644
--- a/iconv/gconv.c
+++ b/iconv/gconv.c
@@ -30,6 +30,9 @@ __gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
size_t oldinbytes = *inbytesleft;
int result;
+ if (cd == (gconv_t) -1L)
+ return GCONV_ILLEGAL_DESCRIPTOR;
+
cd->data[last_step].outbuf = *outbuf;
cd->data[last_step].outbufavail = 0;
cd->data[last_step].outbufsize = *outbytesleft;
diff --git a/iconv/gconv.h b/iconv/gconv.h
index 2c42f99ace..879db49e1c 100644
--- a/iconv/gconv.h
+++ b/iconv/gconv.h
@@ -37,6 +37,7 @@ enum
GCONV_EMPTY_INPUT,
GCONV_FULL_OUTPUT,
GCONV_ILLEGAL_INPUT,
+ GCONV_INCOMPLETE_INPUT,
GCONV_ILLEGAL_DESCRIPTOR,
GCONV_INTERNAL_ERROR
diff --git a/iconv/gconv_builtin.h b/iconv/gconv_builtin.h
index a3070a532f..8dcc3aaaa2 100644
--- a/iconv/gconv_builtin.h
+++ b/iconv/gconv_builtin.h
@@ -18,17 +18,17 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UCS4/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UCS4/([^/]*)", NULL, 0,
"\\1/UTF8/\\2", 1, "=ucs4->utf8",
__gconv_transform_ucs4_utf8,
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UTF8/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UTF8/([^/]*)", NULL, 0,
"\\1/UCS4/\\2", 1, "=utf8->ucs4",
__gconv_transform_utf8_ucs4,
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
-BUILTIN_TRANSFORMATION ("\\(.*\\)", NULL, 0, "\\1", 1, "=dummy",
+BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy",
__gconv_transform_dummy, NULL, NULL)
diff --git a/iconv/gconv_close.c b/iconv/gconv_close.c
index d3d023f488..791c0259a3 100644
--- a/iconv/gconv_close.c
+++ b/iconv/gconv_close.c
@@ -48,9 +48,8 @@ __gconv_close (gconv_t cd)
/* Next step. */
++srunp;
- ++drunp;
}
- while (!drunp->is_last);
+ while (!(drunp++)->is_last);
/* Save the pointer, we need it below. */
srunp = cd->steps;
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
index d3c13d75c9..8a72c7aac9 100644
--- a/iconv/gconv_conf.c
+++ b/iconv/gconv_conf.c
@@ -19,6 +19,7 @@
Boston, MA 02111-1307, USA. */
#include <ctype.h>
+#include <errno.h>
#include <gconv.h>
#include <search.h>
#include <stdio.h>
@@ -35,6 +36,12 @@ static const char default_gconv_path[] = GCONV_PATH;
along the path. */
static const char gconv_conf_filename[] = "gconv-modules";
+/* Filename extension for the modules. */
+#ifndef MODULE_EXT
+# define MODULE_EXT ".so"
+#endif
+static const char gconv_module_ext[] = MODULE_EXT;
+
/* We have a few builtin transformations. */
static struct gconv_module builtin_modules[] =
{
@@ -111,15 +118,18 @@ add_alias (char *rp)
new_alias = (struct gconv_alias *)
malloc (sizeof (struct gconv_alias) + (wp - from));
- new_alias->fromname = memcpy ((char *) new_alias
- + sizeof (struct gconv_alias),
- from, to - from);
- new_alias->toname = memcpy ((char *) new_alias + sizeof (struct gconv_alias)
- + (to - from), to, wp - to);
-
- if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare) == NULL)
- /* Something went wrong, free this entry. */
- free (new_alias);
+ if (new_alias != NULL)
+ {
+ new_alias->fromname = memcpy ((char *) new_alias
+ + sizeof (struct gconv_alias),
+ from, wp - from);
+ new_alias->toname = new_alias->fromname + (to - from);
+
+ if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare)
+ == NULL)
+ /* Something went wrong, free this entry. */
+ free (new_alias);
+ }
}
@@ -138,6 +148,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
char *from, *to, *module, *wp;
size_t const_len;
int from_is_regex;
+ int need_ext;
int cost;
while (isspace (*rp))
@@ -195,65 +206,68 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
/* Increment by one for the slash. */
++dir_len;
+ /* See whether we must add the ending. */
+ need_ext = 0;
+ if (wp - module < sizeof (gconv_module_ext)
+ || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
+ sizeof (gconv_module_ext)) != 0)
+ /* We must add the module extension. */
+ need_ext = sizeof (gconv_module_ext) - 1;
+
/* We've collected all the information, now create an entry. */
- const_len = 0;
if (from_is_regex)
- do
- ++const_len;
- while (isalnum (from[const_len]) || from[const_len] == '-'
- || from[const_len] == '/' || from[const_len] == '.'
- || from[const_len] == '_');
+ {
+ const_len = 0;
+ while (isalnum (from[const_len]) || from[const_len] == '-'
+ || from[const_len] == '/' || from[const_len] == '.'
+ || from[const_len] == '_')
+ ++const_len;
+ }
+ else
+ const_len = to - from - 1;
new_module = (struct gconv_module *) malloc (sizeof (struct gconv_module)
- + (wp - from) + const_len
- + dir_len);
+ + (wp - from)
+ + dir_len + need_ext);
if (new_module != NULL)
{
+ char *tmp;
+
+ new_module->from_constpfx = memcpy ((char *) new_module
+ + sizeof (struct gconv_module),
+ from, to - from);
if (from_is_regex)
- {
- new_module->from_pattern = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx = memcpy ((char *) new_module->from_pattern
- + (to - from),
- from, const_len);
- ((char *) new_module->from_constpfx)[const_len] = '\0';
- new_module->from_constpfx_len = const_len;
- ++const_len;
- }
+ new_module->from_pattern = new_module->from_constpfx;
else
- {
- new_module->from_pattern = NULL;
- new_module->from_constpfx = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx_len = to - from - 1;
- const_len = to - from;
- }
+ new_module->from_pattern = NULL;
+
+ new_module->from_constpfx_len = const_len;
+
new_module->from_regex = NULL;
new_module->to_string = memcpy ((char *) new_module->from_constpfx
- + const_len + 1, to, module - to);
+ + (to - from), to, module - to);
new_module->cost = cost;
+ new_module->module_name = (char *) new_module->to_string + (module - to);
+
if (dir_len == 0)
- new_module->module_name = memcpy ((char *) new_module->to_string
- + (module - to),
- module, wp - module);
+ tmp = (char *) new_module->module_name;
else
{
- char *tmp;
- new_module->module_name = ((char *) new_module->to_string
- + (module - to));
tmp = __mempcpy ((char *) new_module->module_name,
directory, dir_len - 1);
*tmp++ = '/';
- memcpy (tmp, module, wp - module);
}
- if (__tfind (new_module, *modules, module_compare) != NULL)
+ tmp = __mempcpy (tmp, module, wp - module);
+
+ if (need_ext)
+ memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
+
+ if (__tfind (new_module, modules, module_compare) == NULL)
if (__tsearch (new_module, modules, module_compare) == NULL)
/* Something went wrong while inserting the new module. */
free (new_module);
@@ -267,7 +281,7 @@ static void
insert_module (const void *nodep, VISIT value, int level)
{
if (value == preorder || value == leaf)
- __gconv_modules_db[__gconv_nmodules++] = (struct gconv_module *) nodep;
+ __gconv_modules_db[__gconv_nmodules++] = *(struct gconv_module **) nodep;
}
static void
@@ -302,8 +316,6 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
break;
rp = line;
- while (isspace (*rp))
- ++rp;
/* Terminate the line (excluding comments or newline) by an NUL byte
to simplify the following code. */
endp = strchr (rp, '#');
@@ -316,6 +328,9 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
*endp = '\0';
}
+ while (isspace (*rp))
+ ++rp;
+
/* If this is an empty line go on with the next one. */
if (rp == endp)
continue;
@@ -325,10 +340,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
++rp;
if (rp - word == sizeof ("alias") - 1
- && memcpy (word, "alias", sizeof ("alias") - 1) == 0)
+ && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
add_alias (rp);
else if (rp - word == sizeof ("module") - 1
- && memcpy (word, "module", sizeof ("module") - 1) == 0)
+ && memcmp (word, "module", sizeof ("module") - 1) == 0)
add_module (rp, directory, dir_len, modules, nmodules);
/* else */
/* Otherwise ignore the line. */
@@ -349,6 +364,7 @@ __gconv_read_conf (void)
char *gconv_path, *elem;
void *modules = NULL;
size_t nmodules = 0;
+ int save_errno = errno;
if (user_path == NULL)
/* No user-defined path. Make a modifiable copy of the default path. */
@@ -390,31 +406,31 @@ __gconv_read_conf (void)
/* If the configuration files do not contain any valid module specification
remember this by setting the pointer to the module array to NULL. */
- nmodules = sizeof (builtin_modules) / sizeof (struct gconv_module);
+ nmodules += sizeof (builtin_modules) / sizeof (builtin_modules[0]);
if (nmodules == 0)
+ __gconv_modules_db = NULL;
+ else
{
- __gconv_modules_db = NULL;
- return;
- }
+ __gconv_modules_db =
+ (struct gconv_module **) malloc (nmodules
+ * sizeof (struct gconv_module));
+ if (__gconv_modules_db != NULL)
+ {
+ size_t cnt;
- __gconv_modules_db =
- (struct gconv_module **) malloc (nmodules * sizeof (struct gconv_module));
- if (__gconv_modules_db == NULL)
- /* We cannot do anything. */
- return;
+ /* Insert all module entries into the array. */
+ __twalk (modules, insert_module);
- /* First insert the builtin transformations. */
- while (__gconv_nmodules < (sizeof (builtin_modules)
- / sizeof (struct gconv_module)))
- {
- __gconv_modules_db[__gconv_nmodules] =
- &builtin_modules[__gconv_nmodules];
- ++__gconv_nmodules;
- }
+ /* No remove the tree data structure. */
+ __tdestroy (modules, nothing);
- /* Insert all module entries into the array. */
- __twalk (modules, insert_module);
+ /* Finally insert the builtin transformations. */
+ for (cnt = 0; cnt < (sizeof (builtin_modules)
+ / sizeof (struct gconv_module)); ++cnt)
+ __gconv_modules_db[__gconv_nmodules++] = &builtin_modules[cnt];
+ }
+ }
- /* No remove the tree data structure. */
- __tdestroy (modules, nothing);
+ /* Restore the error number. */
+ __set_errno (save_errno);
}
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index ceb94be2b1..b1320ac7e8 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -99,7 +99,7 @@ derivation_lookup (const char *fromset, const char *toset,
struct known_derivation key = { fromset, toset, NULL, 0 };
struct known_derivation *result;
- result = __tfind (&key, known_derivations, derivation_compare);
+ result = __tfind (&key, &known_derivations, derivation_compare);
if (result == NULL)
return GCONV_NOCONV;
@@ -169,11 +169,18 @@ gen_steps (struct derivation_step *best, const char *toset,
* step_cnt);
if (result != NULL)
{
+ int failed = 0;
+
+ *nsteps = step_cnt;
current = best;
while (step_cnt-- > 0)
{
- result[step_cnt].from_name = current->last->result_set;
- result[step_cnt].to_name = current->result_set;
+ result[step_cnt].from_name = (step_cnt == 0
+ ? __strdup (fromset)
+ : current->last->result_set);
+ result[step_cnt].to_name = (step_cnt + 1 == *nsteps
+ ? __strdup (current->result_set)
+ : result[step_cnt + 1].from_name);
if (current->code->module_name[0] == '/')
{
@@ -182,7 +189,10 @@ gen_steps (struct derivation_step *best, const char *toset,
__gconv_find_shlib (current->code->module_name);
if (shlib_handle == NULL)
- break;
+ {
+ failed = 1;
+ break;
+ }
result[step_cnt].shlib_handle = shlib_handle;
@@ -192,6 +202,7 @@ gen_steps (struct derivation_step *best, const char *toset,
/* Argh, no conversion function. There is something
wrong here. */
__gconv_release_shlib (result[step_cnt].shlib_handle);
+ failed = 1;
break;
}
@@ -208,18 +219,18 @@ gen_steps (struct derivation_step *best, const char *toset,
current = current->last;
}
- if (step_cnt != 0)
+ if (failed != 0)
{
/* Something went wrong while initializing the modules. */
- while (step_cnt-- > 0)
+ while (++step_cnt < *nsteps)
__gconv_release_shlib (result[step_cnt].shlib_handle);
free (result);
+ *nsteps = 0;
status = GCONV_NOCONV;
}
else
{
*handle = result;
- *nsteps = step_cnt;
status = GCONV_OK;
}
}
@@ -231,12 +242,13 @@ gen_steps (struct derivation_step *best, const char *toset,
/* The main function: find a possible derivation from the `fromset' (either
the given name or the alias) to the `toset' (again with alias). */
static int
+internal_function
find_derivation (const char *toset, const char *toset_expand,
const char *fromset, const char *fromset_expand,
struct gconv_step **handle, size_t *nsteps)
{
__libc_lock_define_initialized (static, lock)
- struct derivation_step *current, **lastp, *best = NULL;
+ struct derivation_step *first, *current, **lastp, *best = NULL;
int best_cost = 0;
int result;
@@ -260,16 +272,17 @@ find_derivation (const char *toset, const char *toset_expand,
The task is to match the `toset' with any of the available. */
if (fromset_expand != NULL)
{
- current = NEW_STEP (fromset_expand, NULL, NULL);
- current->next = NEW_STEP (fromset, NULL, NULL);
- lastp = &current->next->next;
+ first = NEW_STEP (fromset_expand, NULL, NULL);
+ first->next = NEW_STEP (fromset, NULL, NULL);
+ lastp = &first->next->next;
}
else
{
- current = NEW_STEP (fromset, NULL, NULL);
- lastp = &current->next;
+ first = NEW_STEP (fromset, NULL, NULL);
+ lastp = &first->next;
}
+ current = first;
while (current != NULL)
{
/* Now match all the available module specifications against the
@@ -419,13 +432,28 @@ find_derivation (const char *toset, const char *toset_expand,
}
else
{
- /* Append at the end. */
- *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
- current);
- lastp = &(*lastp)->next;
+ /* Append at the end if there is no entry with this name. */
+ struct derivation_step *runp = first;
+
+ while (runp != NULL)
+ {
+ if (__strcasecmp (result_set, runp->result_set) == 0)
+ break;
+ runp = runp->next;
+ }
+
+ if (runp == NULL)
+ {
+ *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
+ current);
+ lastp = &(*lastp)->next;
+ }
}
}
}
+
+ /* Go on with the next entry. */
+ current = current->next;
}
if (best != NULL)
@@ -470,15 +498,15 @@ __gconv_find_transform (const char *toset, const char *fromset,
if (__gconv_alias_db != NULL)
{
struct gconv_alias key;
- struct gconv_alias *found;
+ struct gconv_alias **found;
key.fromname = fromset;
- found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
- fromset_expand = found != NULL ? found->toname : NULL;
+ found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+ fromset_expand = found != NULL ? (*found)->toname : NULL;
key.fromname = toset;
- found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
- toset_expand = found != NULL ? found->toname : NULL;
+ found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+ toset_expand = found != NULL ? (*found)->toname : NULL;
}
result = find_derivation (toset, toset_expand, fromset, fromset_expand,
diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
index a0003a82db..a80e5ef4ef 100644
--- a/iconv/gconv_dl.c
+++ b/iconv/gconv_dl.c
@@ -84,6 +84,7 @@ do_open (void *a)
static int
+internal_function
dlerror_run (void (*operate) (void *), void *args)
{
char *last_errstring = NULL;
@@ -156,7 +157,7 @@ __gconv_find_shlib (const char *name)
enough to a pointer to our structure to use as a lookup key that
will be passed to `known_compare' (above). */
- found = __tfind (&name, loaded, known_compare);
+ found = __tfind (&name, &loaded, known_compare);
if (found == NULL)
{
/* This name was not known before. */
@@ -208,7 +209,7 @@ static void *release_handle;
static void
do_release_shlib (const void *nodep, VISIT value, int level)
{
- struct loaded_object *obj = (struct loaded_object *) nodep;
+ struct loaded_object *obj = *(struct loaded_object **) nodep;
if (value != preorder && value != leaf)
return;
diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c
index 0e789df896..343cb70773 100644
--- a/iconv/gconv_open.c
+++ b/iconv/gconv_open.c
@@ -69,19 +69,19 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
if (res != GCONV_OK)
break;
}
- else
- if (!data[cnt].is_last)
- {
- data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
- data[cnt].outbuf =
- (char *) malloc (data[cnt].outbufsize);
- if (data[cnt].outbuf == NULL)
- {
- res = GCONV_NOMEM;
- break;
- }
- data[cnt].outbufavail = 0;
- }
+
+ if (!data[cnt].is_last && data[cnt].outbuf == NULL)
+ {
+ data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
+ data[cnt].outbuf =
+ (char *) malloc (data[cnt].outbufsize);
+ if (data[cnt].outbuf == NULL)
+ {
+ res = GCONV_NOMEM;
+ break;
+ }
+ data[cnt].outbufavail = 0;
+ }
}
}
}
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index 582c6f5a27..f769795273 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -117,7 +117,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step,
do
{
const char *newinbuf = inbuf;
- size_t actually = __wcsnrtombs (&data->outbuf[data->outbufavail],
+ size_t actually = __wmemrtombs (&data->outbuf[data->outbufavail],
(const wchar_t **) &newinbuf,
*inlen / sizeof (wchar_t),
data->outbufsize - data->outbufavail,
@@ -206,7 +206,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
do
{
const char *newinbuf = inbuf;
- size_t actually = __mbsnrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
+ size_t actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
&newinbuf, *inlen,
((data->outbufsize
- data->outbufavail)
diff --git a/iconv/iconv.c b/iconv/iconv.c
index e5b0eb7c0d..8804e851b6 100644
--- a/iconv/iconv.c
+++ b/iconv/iconv.c
@@ -19,9 +19,12 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <errno.h>
#include <iconv.h>
#include <gconv.h>
+#include <assert.h>
+
size_t
iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
@@ -29,10 +32,39 @@ iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
{
gconv_t gcd = (gconv_t) cd;
size_t converted;
+ int result;
+
+ result = __gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted);
+ switch (result)
+ {
+ case GCONV_ILLEGAL_DESCRIPTOR:
+ __set_errno (EBADF);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_ILLEGAL_INPUT:
+ __set_errno (EILSEQ);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_FULL_OUTPUT:
+ __set_errno (E2BIG);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_INCOMPLETE_INPUT:
+ __set_errno (EINVAL);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_EMPTY_INPUT:
+ case GCONV_OK:
+ /* Nothing. */
+ break;
- if (__gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted)
- != GCONV_OK)
- return (size_t) -1;
+ default:
+ assert (!"Nothing like this should happen");
+ }
return converted;
}
diff --git a/iconv/iconv_close.c b/iconv/iconv_close.c
index d3123e21d8..ccd9d5f3ad 100644
--- a/iconv/iconv_close.c
+++ b/iconv/iconv_close.c
@@ -18,6 +18,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <errno.h>
#include <iconv.h>
#include <gconv.h>
@@ -26,5 +27,11 @@
int
iconv_close (iconv_t cd)
{
+ if (cd == (iconv_t *) -1L)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
return __gconv_close ((gconv_t) cd) ? -1 : 0;
}
diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c
index 82802b7451..bfff00d917 100644
--- a/iconv/iconv_open.c
+++ b/iconv/iconv_open.c
@@ -27,11 +27,9 @@
static inline void
-strip (char *s)
+strip (char *wp, const char *s)
{
int slash_count = 0;
- char *wp;
- wp = s;
while (*s != '\0')
{
@@ -39,7 +37,7 @@ strip (char *s)
*wp++ = *s;
else if (*s == '/')
{
- if (++slash_count == 2)
+ if (++slash_count == 3)
break;
*wp++ = '/';
}
@@ -67,14 +65,15 @@ iconv_open (const char *tocode, const char *fromcode)
'_', '-', '/', and '.'. */
tocode_len = strlen (tocode);
tocode_conv = alloca (tocode_len + 3);
- strip (memcpy (tocode_conv, tocode, tocode_len + 1));
+ strip (tocode_conv, tocode);
fromcode_len = strlen (fromcode);
fromcode_conv = alloca (fromcode_len + 3);
- strip (memcpy (fromcode_conv, fromcode, fromcode_len + 1));
+ strip (fromcode_conv, fromcode);
res = __gconv_open (tocode_conv[2] == '\0' ? tocode : tocode_conv,
- fromcode_conv[2] == '\0' ? fromcode, fromcode_conv, &cd);
+ fromcode_conv[2] == '\0' ? fromcode : fromcode_conv,
+ &cd);
if (res != GCONV_OK)
{