fs/exfat/nls.c

Source file repositories/reference/linux-study-clean/fs/exfat/nls.c

File Facts

System
Linux kernel
Corpus path
fs/exfat/nls.c
Extension
.c
Size
34193 bytes
Lines
810
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((*uniname & SURROGATE_MASK) != SURROGATE_PAIR) {
			len = exfat_convert_ucs2_to_char(nls, *uniname, buf,
				NULL);
		} else {
			/* Process UTF-16 surrogate pair as one character */
			if (!(*uniname & SURROGATE_LOW) &&
			    i+1 < MAX_NAME_LENGTH &&
			    (*(uniname+1) & SURROGATE_MASK) == SURROGATE_PAIR &&
			    (*(uniname+1) & SURROGATE_LOW)) {
				uniname++;
				i++;
			}

			/*
			 * UTF-16 surrogate pair encodes code points above
			 * U+FFFF. Code points above U+FFFF are not supported
			 * by kernel NLS framework therefore use replacement
			 * character
			 */
			len = 1;
			buf[0] = '_';
		}

		if (out_len + len >= buflen)
			len = buflen - 1 - out_len;
		out_len += len;

		if (len > 1) {
			for (j = 0; j < len; j++)
				*p_cstring++ = buf[j];
		} else { /* len == 1 */
			*p_cstring++ = *buf;
		}

		uniname++;
		i++;
	}

	*p_cstring = '\0';
	return out_len;
}

static int exfat_nls_to_ucs2(struct super_block *sb,
		const unsigned char *p_cstring, const int len,
		struct exfat_uni_name *p_uniname, int *p_lossy)
{
	int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY;
	__le16 upname[MAX_NAME_LENGTH + 1];
	unsigned short *uniname = p_uniname->name;
	struct nls_table *nls = EXFAT_SB(sb)->nls_io;

	WARN_ON(!len);

	while (unilen < MAX_NAME_LENGTH && i < len) {
		i += exfat_convert_char_to_ucs2(nls, p_cstring + i, len - i,
				uniname, &lossy);

		if (*uniname < 0x0020 ||
		    exfat_wstrchr(bad_uni_chars, *uniname))
			lossy |= NLS_NAME_LOSSY;

		upname[unilen] = cpu_to_le16(exfat_toupper(sb, *uniname));
		uniname++;
		unilen++;
	}

	*uniname = '\0';
	p_uniname->name_len = unilen;
	p_uniname->name_hash = exfat_calc_chksum16(upname, unilen << 1, 0,
			CS_DEFAULT);

	if (p_lossy)
		*p_lossy = lossy;
	return unilen;
}

int exfat_utf16_to_nls(struct super_block *sb, struct exfat_uni_name *uniname,
		unsigned char *p_cstring, int buflen)
{
	if (EXFAT_SB(sb)->options.utf8)
		return exfat_utf16_to_utf8(sb, uniname, p_cstring,
				buflen);
	return __exfat_utf16_to_nls(sb, uniname, p_cstring, buflen);
}

int exfat_nls_to_utf16(struct super_block *sb, const unsigned char *p_cstring,
		const int len, struct exfat_uni_name *uniname, int *p_lossy)
{
	if (EXFAT_SB(sb)->options.utf8)
		return exfat_utf8_to_utf16(sb, p_cstring, len,

Annotation

Implementation Notes