[PATCH] Fix linking with iconv under FreeBSD

Konstantin Belyavskiy k.belyavskiy at tarantool.org
Wed Feb 21 19:52:13 MSK 2018


On FreeBSD we have either system iconv (part of libc) or the one
in /usr/local. The first one is not fully compatible with Linux/
OSX iconv and both adds specific prefixes to function names.
So to use them via Lua FFI mechanism, specific names are required.
Proposal fix:
Under FreeBSD link with /usr/local/lib/libiconv.so and add prefix.
---
branch: gh-3073-iconv-freebsd-fix

 src/CMakeLists.txt |  6 ++++++
 src/lua/iconv.lua  | 33 ++++++++++++++++++++++++++++-----
 2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 01f73a0aa..8ab09e968 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -234,6 +234,12 @@ if (TARGET_OS_FREEBSD AND NOT TARGET_OS_DEBIAN_FREEBSD)
     else()
         set (common_libraries ${common_libraries} ${INTL})
     endif()
+    find_library (ICONV iconv)
+    if (NOT ICONV)
+        message(FATAL_ERROR "iconv library not found")
+    else()
+        set (common_libraries ${common_libraries} ${ICONV})
+    endif()
 endif()
 
 set (common_libraries ${common_libraries} ${LIBUUID_LIBRARIES})
diff --git a/src/lua/iconv.lua b/src/lua/iconv.lua
index 304768d8f..6a6bfeb76 100644
--- a/src/lua/iconv.lua
+++ b/src/lua/iconv.lua
@@ -8,6 +8,13 @@ iconv_t iconv_open(const char *tocode, const char *fromcode);
 void    iconv_close(iconv_t cd);
 size_t  iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
               char **outbuf, size_t *outbytesleft);
+/*
+ * add prefix 'lib' under FreeBSD
+ */
+iconv_t libiconv_open(const char *tocode, const char *fromcode);
+void    libiconv_close(iconv_t cd);
+size_t  libiconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
+                 char **outbuf, size_t *outbytesleft);
 ]]
 
 local iconv_t         = ffi.typeof('struct iconv')
@@ -16,6 +23,22 @@ local cchar_ptr_arr_t = ffi.typeof('const char *[1]')
 local cchar_ptr_t     = ffi.typeof('const char *')
 local size_t_arr_t    = ffi.typeof('size_t [1]')
 
+local _iconv_open
+local _iconv_close
+local _iconv
+
+-- To fix #3073, BSD iconv implementation is not fully
+-- compatible with iconv, so use external iconv.so lib
+if jit.os == 'BSD' then
+    _iconv_open = ffi.C.libiconv_open
+    _iconv_close = ffi.C.libiconv_close
+    _iconv = ffi.C.libiconv
+else
+    _iconv_open = ffi.C.iconv_open
+    _iconv_close = ffi.C.iconv_close
+    _iconv = ffi.C.iconv
+end
+
 local E2BIG    = errno['E2BIG']
 local EINVAL   = errno['EINVAL']
 local EILSEQ   = errno['EILSEQ']
@@ -41,10 +64,10 @@ local function iconv_convert(iconv, data)
     while data_left[0] > 0 do
         buf_ptr[0]  = buf:reserve(output_len)
         buf_left[0] = buf:unused()
-        local res = ffi.C.iconv(iconv, data_ptr, data_left,
+        local res = _iconv(iconv, data_ptr, data_left,
                                 buf_ptr, buf_left)
         if res == ffi.cast('size_t', -1) and errno() ~= E2BIG then
-            ffi.C.iconv(iconv, nil, nil, nil, nil)
+            _iconv(iconv, nil, nil, nil, nil)
             if errno() == EINVAL then
                 error('Invalid multibyte sequence')
             end
@@ -57,7 +80,7 @@ local function iconv_convert(iconv, data)
     end
 
     -- iconv function sets cd's conversion state to the initial state
-    ffi.C.iconv(iconv, nil, nil, nil, nil)
+    _iconv(iconv, nil, nil, nil, nil)
     local result = ffi.string(buf.rpos, buf:size())
     buf:reset()
     return result
@@ -65,7 +88,7 @@ end
 
 local iconv_mt = {
     __call = iconv_convert,
-    __gc = ffi.C.iconv_close,
+    __gc = _iconv_close,
     __tostring = function(iconv) return string.format("iconv: %p", iconv) end
 }
 
@@ -75,7 +98,7 @@ local function iconv_new(to, from)
     if type(to) ~= 'string' or type(from) ~= 'string' then
         error('Usage: iconv.new("CP1251", "KOI8-R")')
     end
-    local iconv = ffi.C.iconv_open(to, from)
+    local iconv = _iconv_open(to, from)
     if iconv == conv_rv_error then
         error('iconv: '..errno.strerror())
     end
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list