- Make the spec as follows ... Summary: default summary Summary(ja_JP.eucJP): [some strings encoded in euc-jp] Name:hogefuga ... - Show summary in each locale. $ LANG=ja_JP.utf8 rpm -qp --qf "%{SUMMARY}\n" hogefuga.rpm [some strings encoded in euc-jp] do not display in UTF-8. This patch improve the parser of spec-file which are written in multi-languages. In case the language code is ja_JP , as you know ja_JP use some different encodings such as ja_JP.eucJP,ja_JP.sjis,ja_JP.utf8... When the spec-file are written in eucJP but the local LANG environment is UTF-8, rpm will display encoded characters not same as LANG environment(a.k.a Mojibake). So this patch will convert the data to a specific encoding which used in the selected locale. --- rpm-4.4.2.3-rc1/rpmdb/header.c.toshi 2008-02-14 11:04:11.000000000 +0000 +++ rpm-4.4.2.3-rc1/rpmdb/header.c 2008-02-14 11:05:47.000000000 +0000 @@ -9,6 +9,8 @@ /* network byte order and is converted on the fly to host order. */ #include "system.h" +#include <iconv.h> +#include <langinfo.h> #define __HEADER_PROTOTYPES__ @@ -1595,6 +1597,54 @@ static int headerMatchLocale(const char return 0; } +/** \ingroup header + * convert data to specific encoding used in the selected locale. + * @param td header i18n table data, NUL terminated + * @param indata original data + * @return converted data(or original data if failed) + */ +static const char *headerIconv(const char *td,const char *indata) +{ + char *tcode=NULL; + char *fcode=NULL; + + if( strstr(td,".") != NULL ){ + fcode=strchr(td,'.')+1; + tcode=nl_langinfo(CODESET); + if( tcode!=NULL && *tcode != '\0' && strcasecmp(fcode,tcode) != 0 ){ +// fprintf(stderr,"%s:fcode=%s,tcode=%s\n",__func__,fcode,tcode); + iconv_t conv = iconv_open(tcode,fcode); + if (conv != (iconv_t)-1) { + char *inp = indata; + char *outp,*outdata; + size_t inleft = strlen(indata); + size_t outleft; + size_t outdata_size = (inleft+1)*2; + outp = outdata = calloc(1,outdata_size); + outleft = outdata_size - 1; + int status = E2BIG; + + while (inleft > 0 && status == E2BIG) { + iconv(conv, &inp, &inleft, &outp, &outleft); + status = errno; + size_t used = outp-outdata; + char *newdest; + outdata_size *=2; + newdest = realloc(outdata,outdata_size); + if(newdest==NULL) break; + outdata = newdest; + outp = outdata+used; + outleft = outdata_size - used - 1; + *outp = '\0'; + } + iconv_close(conv); + return outdata; + } + } + } + return strdup(indata); +} + /** * Return i18n string from header that matches locale. * @param h header @@ -1639,11 +1689,11 @@ headerFindI18NString(Header h, indexEntr langNum++, td += strlen(td) + 1, ed += strlen(ed) + 1) { int match = headerMatchLocale(td, l, le); - if (match == 1) return ed; + if (match == 1) return headerIconv(td,ed); else if (match == 2) ed_weak = ed; } - if (ed_weak) return ed_weak; + if (ed_weak) return headerIconv(td,ed_weak); } /*@=boundsread@*/