aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHiroki Sato <hrs@FreeBSD.org>2013-11-25 01:26:06 +0000
committerHiroki Sato <hrs@FreeBSD.org>2013-11-25 01:26:06 +0000
commit7c5b23111c5fd1992047922d4247c4a1ce1bb6c3 (patch)
tree7c53259610137077d7bca0370a6246a61e862300 /lib
parent1b57cec7d999c971d6c4bcb3df6f6397670e1326 (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/iconv/citrus_iconv_local.h1
-rw-r--r--lib/libc/iconv/iconv.c6
-rw-r--r--lib/libc/iconv/iconvctl.327
-rw-r--r--lib/libiconv_modules/iconv_std/citrus_iconv_std.c10
4 files changed, 43 insertions, 1 deletions
diff --git a/lib/libc/iconv/citrus_iconv_local.h b/lib/libc/iconv/citrus_iconv_local.h
index e673c9a6afa1..12d2fa33fa73 100644
--- a/lib/libc/iconv/citrus_iconv_local.h
+++ b/lib/libc/iconv/citrus_iconv_local.h
@@ -99,6 +99,7 @@ struct _citrus_iconv_shared {
char *ci_convname;
bool ci_discard_ilseq;
struct iconv_hooks *ci_hooks;
+ bool ci_ilseq_invalid;
};
struct _citrus_iconv {
diff --git a/lib/libc/iconv/iconv.c b/lib/libc/iconv/iconv.c
index 555efd8616e7..40a1a4e88909 100644
--- a/lib/libc/iconv/iconv.c
+++ b/lib/libc/iconv/iconv.c
@@ -298,6 +298,12 @@ __bsd_iconvctl(iconv_t cd, int request, void *argument)
case ICONV_SET_FALLBACKS:
errno = EOPNOTSUPP;
return (-1);
+ case ICONV_GET_ILSEQ_INVALID:
+ *i = cv->cv_shared->ci_ilseq_invalid ? 1 : 0;
+ return (0);
+ case ICONV_SET_ILSEQ_INVALID:
+ cv->cv_shared->ci_ilseq_invalid = *i;
+ return (0);
default:
errno = EINVAL;
return (-1);
diff --git a/lib/libc/iconv/iconvctl.3 b/lib/libc/iconv/iconvctl.3
index f0121573af99..5bd06ea122c2 100644
--- a/lib/libc/iconv/iconvctl.3
+++ b/lib/libc/iconv/iconvctl.3
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 7, 2009
+.Dd November 25, 2009
.Dt ICONVCTL 3
.Os
.Sh NAME
@@ -110,6 +110,31 @@ variable, which is passed to
via
.Fa argument
by its address.
+.It ICONV_GET_ILSEQ_INVALID
+Determines if a character in the input buffer that is valid,
+but for which an identical character does not exist in the target
+codeset returns
+.Er EILSEQ
+or not.
+The answer is stored in
+.Fa argument ,
+which is of
+.Ft int * .
+It will be set to 1 if this feature is enabled or set to 0 otherwise.
+.It ICONV_SET_ILSEQ_INVALID
+Sets whether a character in the input buffer that is valid,
+but for which an identical character does not exist in the target
+codeset returns
+.Er EILSEQ
+or not.
+If
+.Fa argument ,
+which is of
+.Ft int *
+is set to 1 it will be enabled,
+and if
+.Fa argument
+is set to 0 it will be disabled.
.El
.\" XXX: fallbacks are unimplemented and trying to set them will always
.\" return EOPNOTSUPP but definitions are provided for source-level
diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
index b30f09928ae8..54a00d0d56ae 100644
--- a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
+++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
@@ -543,6 +543,16 @@ _citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv,
ret = do_conv(is, &csid, &idx);
if (ret) {
if (ret == E_NO_CORRESPONDING_CHAR) {
+ /*
+ * GNU iconv returns EILSEQ when no
+ * corresponding character in the output.
+ * Some software depends on this behavior
+ * though this is against POSIX specification.
+ */
+ if (cv->cv_shared->ci_ilseq_invalid != 0) {
+ ret = EILSEQ;
+ goto err;
+ }
inval++;
szrout = 0;
if ((((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0) &&