xref: /kernel/linux/linux-5.10/fs/nls/nls_koi8-ru.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * linux/fs/nls/nls_koi8-ru.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Charset koi8-ru translation based on charset koi8-u.
58c2ecf20Sopenharmony_ci * The Unicode to charset table has only exact mappings.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/string.h>
118c2ecf20Sopenharmony_ci#include <linux/nls.h>
128c2ecf20Sopenharmony_ci#include <linux/errno.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic struct nls_table *p_nls;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic int uni2char(const wchar_t uni,
178c2ecf20Sopenharmony_ci		    unsigned char *out, int boundlen)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	if (boundlen <= 0)
208c2ecf20Sopenharmony_ci		return -ENAMETOOLONG;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	if ((uni & 0xffaf) == 0x040e || (uni & 0xffce) == 0x254c) {
238c2ecf20Sopenharmony_ci		/* koi8-ru and koi8-u differ only on two characters */
248c2ecf20Sopenharmony_ci		if (uni == 0x040e)
258c2ecf20Sopenharmony_ci			out[0] = 0xbe;
268c2ecf20Sopenharmony_ci		else if (uni == 0x045e)
278c2ecf20Sopenharmony_ci			out[0] = 0xae;
288c2ecf20Sopenharmony_ci		else if (uni == 0x255d || uni == 0x256c)
298c2ecf20Sopenharmony_ci			return 0;
308c2ecf20Sopenharmony_ci		else
318c2ecf20Sopenharmony_ci			return p_nls->uni2char(uni, out, boundlen);
328c2ecf20Sopenharmony_ci		return 1;
338c2ecf20Sopenharmony_ci	}
348c2ecf20Sopenharmony_ci	else
358c2ecf20Sopenharmony_ci		/* fast path */
368c2ecf20Sopenharmony_ci		return p_nls->uni2char(uni, out, boundlen);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic int char2uni(const unsigned char *rawstring, int boundlen,
408c2ecf20Sopenharmony_ci		    wchar_t *uni)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	int n;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if ((*rawstring & 0xef) != 0xae) {
458c2ecf20Sopenharmony_ci		/* koi8-ru and koi8-u differ only on two characters */
468c2ecf20Sopenharmony_ci		*uni = (*rawstring & 0x10) ? 0x040e : 0x045e;
478c2ecf20Sopenharmony_ci		return 1;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	n = p_nls->char2uni(rawstring, boundlen, uni);
518c2ecf20Sopenharmony_ci	return n;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic struct nls_table table = {
558c2ecf20Sopenharmony_ci	.charset	= "koi8-ru",
568c2ecf20Sopenharmony_ci	.uni2char	= uni2char,
578c2ecf20Sopenharmony_ci	.char2uni	= char2uni,
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic int __init init_nls_koi8_ru(void)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	p_nls = load_nls("koi8-u");
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	if (p_nls) {
658c2ecf20Sopenharmony_ci		table.charset2upper = p_nls->charset2upper;
668c2ecf20Sopenharmony_ci		table.charset2lower = p_nls->charset2lower;
678c2ecf20Sopenharmony_ci		return register_nls(&table);
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return -EINVAL;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic void __exit exit_nls_koi8_ru(void)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	unregister_nls(&table);
768c2ecf20Sopenharmony_ci	unload_nls(p_nls);
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cimodule_init(init_nls_koi8_ru)
808c2ecf20Sopenharmony_cimodule_exit(exit_nls_koi8_ru)
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
83