11da177e4SLinus Torvalds /*
2*f30c2269SUwe Zeisberger * linux/fs/nls/nls_koi8-ru.c
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * Charset koi8-ru translation based on charset koi8-u.
51da177e4SLinus Torvalds * The Unicode to charset table has only exact mappings.
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds #include <linux/module.h>
91da177e4SLinus Torvalds #include <linux/kernel.h>
101da177e4SLinus Torvalds #include <linux/string.h>
111da177e4SLinus Torvalds #include <linux/nls.h>
121da177e4SLinus Torvalds #include <linux/errno.h>
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds static struct nls_table *p_nls;
151da177e4SLinus Torvalds
uni2char(const wchar_t uni,unsigned char * out,int boundlen)161da177e4SLinus Torvalds static int uni2char(const wchar_t uni,
171da177e4SLinus Torvalds unsigned char *out, int boundlen)
181da177e4SLinus Torvalds {
191da177e4SLinus Torvalds if (boundlen <= 0)
201da177e4SLinus Torvalds return -ENAMETOOLONG;
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds if ((uni & 0xffaf) == 0x040e || (uni & 0xffce) == 0x254c) {
231da177e4SLinus Torvalds /* koi8-ru and koi8-u differ only on two characters */
241da177e4SLinus Torvalds if (uni == 0x040e)
251da177e4SLinus Torvalds out[0] = 0xbe;
261da177e4SLinus Torvalds else if (uni == 0x045e)
271da177e4SLinus Torvalds out[0] = 0xae;
281da177e4SLinus Torvalds else if (uni == 0x255d || uni == 0x256c)
291da177e4SLinus Torvalds return 0;
301da177e4SLinus Torvalds else
311da177e4SLinus Torvalds return p_nls->uni2char(uni, out, boundlen);
321da177e4SLinus Torvalds return 1;
331da177e4SLinus Torvalds }
341da177e4SLinus Torvalds else
351da177e4SLinus Torvalds /* fast path */
361da177e4SLinus Torvalds return p_nls->uni2char(uni, out, boundlen);
371da177e4SLinus Torvalds }
381da177e4SLinus Torvalds
char2uni(const unsigned char * rawstring,int boundlen,wchar_t * uni)391da177e4SLinus Torvalds static int char2uni(const unsigned char *rawstring, int boundlen,
401da177e4SLinus Torvalds wchar_t *uni)
411da177e4SLinus Torvalds {
421da177e4SLinus Torvalds int n;
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds if ((*rawstring & 0xef) != 0xae) {
451da177e4SLinus Torvalds /* koi8-ru and koi8-u differ only on two characters */
461da177e4SLinus Torvalds *uni = (*rawstring & 0x10) ? 0x040e : 0x045e;
471da177e4SLinus Torvalds return 1;
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds n = p_nls->char2uni(rawstring, boundlen, uni);
511da177e4SLinus Torvalds return n;
521da177e4SLinus Torvalds }
531da177e4SLinus Torvalds
541da177e4SLinus Torvalds static struct nls_table table = {
551da177e4SLinus Torvalds .charset = "koi8-ru",
561da177e4SLinus Torvalds .uni2char = uni2char,
571da177e4SLinus Torvalds .char2uni = char2uni,
581da177e4SLinus Torvalds };
591da177e4SLinus Torvalds
init_nls_koi8_ru(void)601da177e4SLinus Torvalds static int __init init_nls_koi8_ru(void)
611da177e4SLinus Torvalds {
621da177e4SLinus Torvalds p_nls = load_nls("koi8-u");
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds if (p_nls) {
651da177e4SLinus Torvalds table.charset2upper = p_nls->charset2upper;
661da177e4SLinus Torvalds table.charset2lower = p_nls->charset2lower;
671da177e4SLinus Torvalds return register_nls(&table);
681da177e4SLinus Torvalds }
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds return -EINVAL;
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds
exit_nls_koi8_ru(void)731da177e4SLinus Torvalds static void __exit exit_nls_koi8_ru(void)
741da177e4SLinus Torvalds {
751da177e4SLinus Torvalds unregister_nls(&table);
761da177e4SLinus Torvalds unload_nls(p_nls);
771da177e4SLinus Torvalds }
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds module_init(init_nls_koi8_ru)
801da177e4SLinus Torvalds module_exit(exit_nls_koi8_ru)
811da177e4SLinus Torvalds
821da177e4SLinus Torvalds MODULE_LICENSE("Dual BSD/GPL");
83