Subject: lib/30050: iconv returns ENOENT in exception to man page
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <jklowden@schemamania.org>
List: netbsd-bugs
Date: 04/24/2005 17:35:00
>Number:         30050
>Category:       lib
>Synopsis:       iconv returns ENOENT in exception to man page
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 24 17:35:00 +0000 2005
>Originator:     jklowden@schemamania.org
>Release:        NetBSD 2.0
>Organization:

>Environment:
System: NetBSD oak.schemamania.org 2.0 NetBSD 2.0 (GENERIC) #0: Wed Dec 1 10:58:25 UTC 2004 builds@build:/big/builds/ab/netbsd-2-0-RELEASE/i386/200411300000Z-obj/big/builds/ab/netbsd-2-0-RELEASE/src/sys/arch/i386/compile/GENERIC i386
ldd `which iconv`
	/usr/bin/iconv:
         -lc.12 => /usr/lib/libc.so.12	
ident /usr/lib/libc.so.12 |grep iconv
     $NetBSD: iconv.c,v 1.2 2003/07/01 09:42:17 tshiozak Exp $
     $NetBSD: citrus_iconv.c,v 1.3 2003/07/10 09:08:57 tshiozak Exp $
Architecture: i386
Machine: i386
>Description:
/usr/src/lib/libc/iconv/iconv.c::_iconv_open calls _citrus_iconv_open,
which apparently returns ENOENT if the 'in' or 'out' arguments don't
exist.  The function sets errno, which iconv(1) duly reports to the poor
user as "No such file or directory".  That contradicts both the iconv(3)
man page (and, IMHO, good sense).  It should set errno to EINVAL.  

>How-To-Repeat:
$ echo 'hi' | iconv -t asdf -f ucs-2le
	iconv: iconv_open(asdf, ucs-2le): No such file or directory
	
>Fix:
Perhaps something like this:
Index: iconv.c
===================================================================
RCS file: /cvsroot/src/lib/libc/iconv/iconv.c,v
retrieving revision 1.4
diff -u -r1.4 iconv.c
--- iconv.c     2 Aug 2004 13:38:21 -0000       1.4
+++ iconv.c     24 Apr 2005 17:32:52 -0000
@@ -63,7 +63,7 @@
 
        ret = _citrus_iconv_open(&handle, _PATH_ICONV, in, out);
        if (ret) {
-               errno = ret;
+               errno = ret == ENOENT? EINVAL : ret;
                return ((iconv_t)-1);
        }