AlmaLinuxにプリインストールされているiconvをShift JISに対応させる

`glibc-gconv-extra` パッケージをインストールすればOK。

```bash
dnf install -y glibc-gconv-extra
```

## 解説

AlmaLinux 9のDocker Imageから起動したコンテナでiconvを試すと以下のエラーが発生する場合があります。

```bash
$ echo 'あ' | iconv -f UTF8 -t SHIFT_JIS
iconv: failed to start conversion processing: No such file or directory
```

このエラーはプリインストールされているiconvに対応していないキャラクターセットを指定した場合に発生します。
今回の場合は `SHIFT_JIS` に対応していなかったのでエラーが発生しました。

```bash
# 対応しているキャラクターセット一覧の表示
$ iconv -l
The following list contains all the coded character sets known.  This does
not necessarily mean that all combinations of these names can be used for
the FROM and TO command line parameters.  One coded character set can be
listed with several different names (aliases).

  8859_1, 10646-1:1993, 10646-1:1993/UCS4, ANSI_X3.4-1968, ANSI_X3.4-1986,
  ANSI_X3.4, ANSI_X3.110-1983, ANSI_X3.110, ASCII, CP367, CP819, CP1252,
  CSASCII, CSA_T500-1983, CSA_T500, CSISO99NAPLPS, CSISOLATIN1, CSUCS4,
  CSUNICODE, IBM367, IBM819, ISO-8859-1, ISO-8859-15, ISO-10646,
  ISO-10646/UCS2, ISO-10646/UCS4, ISO-10646/UTF-8, ISO-10646/UTF8, ISO-IR-6,
  ISO-IR-99, ISO-IR-100, ISO-IR-193, ISO-IR-203, ISO646-US, ISO8859-1,
  ISO8859-15, ISO88591, ISO885915, ISO_646.IRV:1991, ISO_8859-1,
  ISO_8859-1:1987, ISO_8859-15, ISO_8859-15:1998, L1, LATIN-9, LATIN1, LATIN9,
  MS-ANSI, NAPLPS, OSF00010001, OSF00010020, OSF00010100, OSF00010101,
  OSF00010102, OSF00010104, OSF00010105, OSF00010106, OSF05010001, UCS-2,
  UCS-2BE, UCS-2LE, UCS-4, UCS-4BE, UCS-4LE, UCS2, UCS4, UNICODE, UNICODEBIG,
  UNICODELITTLE, US-ASCII, US, UTF-7, UTF-8, UTF-16, UTF-16BE, UTF-16LE,
  UTF-32, UTF-32BE, UTF-32LE, UTF7, UTF8, UTF16, UTF16BE, UTF16LE, UTF32,
  UTF32BE, UTF32LE, WCHAR_T, WINDOWS-1252
```

この場合は `glibc-gconv-extra` をインストールするとiconvが拡張され変換処理が成功するようになります。

```bash
# glibc-gconv-extra のインストール
$ dnf install -y glibc-gconv-extra

# SHIFT_JISが追加されていることを確認
$ iconv -l | grep SHIFT_JIS
SHIFT_JIS//
SHIFT_JISX0213//

# 変換処理の確認
$ echo 'あ' | iconv -f UTF8 -t SHIFT_JIS | iconv -f SHIFT_JIS -t UTF8
あ
```


## おまけ

パッケージ名及びその説明にも記載されている通り、正確にはglibcとセットで扱うiconvコンバータモジュールがインストールされます。
従って、glibcに組み込まれているiconv関連の機能を使う場合も、前述のパッケージをインストールしないと対応していないキャラクターセットの変換処理ができないので要注意です。

```bash
# RPMパッケージの情報を表示
$ rpm -qi glibc-gconv-extra
Name        : glibc-gconv-extra
Version     : 2.34
Release     : 28.el9_0
Architecture: x86_64
Install Date: Tue Jun  7 14:30:17 2022
Group       : Unspecified
Size        : 8253076
License     : LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL
Signature   : RSA/SHA256, Wed Apr 13 03:25:20 2022, Key ID d36cb86cb86b3716
Source RPM  : glibc-2.34-28.el9_0.src.rpm
Build Date  : Mon Apr 11 20:59:48 2022
Build Host  : x64-builder01.almalinux.org
Packager    : AlmaLinux Packaging Team <packager@almalinux.org>
Vendor      : AlmaLinux
URL         : http://www.gnu.org/software/glibc/
Summary     : All iconv converter modules for glibc.
Description :
This package contains all iconv converter modules built in glibc.
```

試しにiconvコマンドの中で最初に呼ばれる `iconv_open` なる関数を利用してみましょう。

```
$ dnf install -y man man-pages
$ man iconv | grep -A 5 'ENVIRONMENT'
ENVIRONMENT
       Internally,  the iconv program uses the iconv(3) function which in turn uses gconv modules (dy‐
       namically loaded shared libraries) to convert to and from  a  character  set.   Before  calling
       iconv(3),  the  iconv  program must first allocate a conversion descriptor using iconv_open(3).
       The operation of the latter function is influenced by the setting of the GCONV_PATH environment
       variable:
```

この関数はキャラクターセット変換のためのディスクリプターを割り当てる機能で、対応するキャラクターセットが見つからない場合などはエラーとして `-1` を返します。
例えば、 `SHIFT_JIS` に対応してないのに指定をした場合は `-1` が返ります。

```
$  man iconv_open | grep -A 1 'NAME'
NAME
       iconv_open - allocate descriptor for character set conversion

$ man iconv_open | grep -A 3 'RETURN VALUE'
RETURN VALUE
       The iconv_open() function returns a freshly allocated conversion descriptor.  In case of error,
       it sets errno and returns (iconv_t) -1.
```

早速C言語を利用して呼び出してみましょう。

```main.c
#include <iconv.h>

int main() {
    return iconv_open("UTF8", "SHIFT_JIS") == (iconv_t)-1 ? 1 : 0;
}
```

```bash
$ gcc ./main.c -o ./c
$ ./c && echo $?
1

$ dnf install -y glibc-gconv-extra
$ ./c && echo $?
0
```

`glibc-gconv-extra` パッケージのインストール前後で返却される値に差があることが確認できました。
というわけで、iconv関連の機能がうまく動かない場合も対応しているキャラクターセットが存在するかどうかをまずは確認するといいかもしれません。