[patches] [PATCH] Fix linking with iconv under FreeBSD

Georgy Kirichenko georgy at tarantool.org
Thu Feb 22 09:11:08 MSK 2018


Seems to be Ok to push

On Wednesday, February 21, 2018 7:52:13 PM MSK Konstantin Belyavskiy wrote:
> 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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20180222/3a62c429/attachment.sig>


More information about the Tarantool-patches mailing list