iconv install memo
ceanではなぜかiconv-1.0/priv以下がインストールされないのでjungerlから手動でインストールした時のメモ。
参考 [ubuntu-jp] stack_chk_fail_local
普通にインストールした場合、"undefined symbol: __stack_chk_fail_local"というエラーで動かないので、jungerl/support/include.mkのLD_SHAREDの値を"ld -shared"から"gcc -shared"に変更する必要がある。
cvs -z3 -d:pserver:anonymous@jungerl.cvs.sourceforge.net:/cvsroot/jungerl co -P jungerl cd jungerl make conf vi jungerl/support # ここでLD_SHAREDの値を変更 cd lib/iconv make release cd .. cp iconv/release/iconv-1.0.tar.gz . tar zxvf iconv-1.0.tar.gz cd iconv-1.0 make cd .. mv iconv-1.0 erlangのebinのディレクトリ
動作確認。
% erl > lists:filter(fun(Elem) -> 0 /= string:str(Elem,"iconv") end,code:get_path()). ["/home/troter/opt/erlang/r11b-4/lib/erlang/lib/iconv-1.0/ebin"] > iconv:start(). {ok,<0.33.0>} > {ok, Cb} = iconv:open("UTF8", "Shift_JIS"). {ok,<<136,5,29,8>>} > {ok, {_,_,Body}} = http:request("http://www.google.com"). =INFO REPORT==== 13-May-2007::19:00:12 === The inets application was not started. Has now been started as a temporary application. {ok,{{"HTTP/1.1",200,"OK"}, [{"cache-control","private"}, {"date","Sun, 13 May 2007 10:00:12 GMT"}, {"server","GWS/2.1"}, {"content-length","2844"}, {"content-type","text/html; charset=Shift_JIS"}, {"set-cookie", "PREF=ID=a40fc2c4b72033e1:TM=1179050412:LM=1179050412:S=OEy5K_fGRGI3ZHc4; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.co.jp"}], [60, 104, 116, 109, 108, 62, 60, 104, 101, 97, 100, 62, 60, 109, 101, 116, 97, 32, 104, 116, 116, 112, 45, 101|...]}} > iconv:conv(Cb, Body). {error,e2big}
なんか動かなかった。バッファが足りないって。
- iconv_drv.c 抜粋
22 /* convert buffers */ 23 #define INBUF_SZ 512 24 #define OUTBUF_SZ INBUF_SZ*4 25 static char inbuf[INBUF_SZ]; 26 static char outbuf[OUTBUF_SZ]; 198 static void iv_conv(t_iconvdrv *iv, iconv_t cd, char *ip, int ileft) 199 { 200 int oleft=OUTBUF_SZ; 201 char *op; 202 int len; 203 ErlDrvBinary *bin; 204 205 op = &outbuf[0]; 206 207 /* Reset cd to initial state */ 208 iconv(cd, NULL, NULL, NULL, NULL); 209 210 if (iconv(cd, &ip, &ileft, &op, &oleft) == (size_t) -1) { 211 if (errno == EILSEQ) 212 driver_send_error(iv, &am_eilseq); 213 else if (errno == EINVAL) 214 driver_send_error(iv, &am_einval); 215 else if (errno == E2BIG) 216 driver_send_error(iv, &am_e2big); 217 else 218 driver_send_error(iv, &am_unknown); 219 }
2KB以上のファイルを入れたら動作しないらしいorz。
で、結局
letter: はてなから移行を元にして動くようにした。iconvの引数の意味がわからなくて、かなり戸惑った。
static void iv_conv(t_iconvdrv *iv, iconv_t cd, char *ip, int ileft) { char *op; int oleft; ErlDrvBinary *bin; int out_size = 0; if (!(bin = driver_alloc_binary(OUTBUF_SZ))) { iconv_close(cd); driver_send_error(iv, &am_enomem); } op = bin->orig_bytes; oleft=OUTBUF_SZ; /* Reset cd to initial state */ iconv(cd, NULL, NULL, NULL, NULL); while(1) { if (iconv(cd, &ip, &ileft, &op, &oleft) == (size_t) -1) { if (errno == E2BIG) { out_size += OUTBUF_SZ - oleft; if (!(bin = driver_realloc_binary(bin, out_size + OUTBUF_SZ))) { iconv_close(cd); driver_send_error(iv, &am_enomem); } op = bin->orig_bytes + out_size; oleft = OUTBUF_SZ; continue; } else if (errno == EINVAL) driver_send_error(iv, &am_einval); else if (errno == EILSEQ) driver_send_error(iv, &am_eilseq); else driver_send_error(iv, &am_unknown); } out_size += OUTBUF_SZ - oleft; break; } driver_send_bin(iv, bin, out_size); driver_free_binary(bin); return; }