^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * cifs_unicode: Unicode kernel case support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Function:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Convert a unicode character to upper or lower case using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * compressed tables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) International Business Machines Corp., 2000,2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * These APIs are based on the C library functions. The semantics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * should match the C functions but with expanded size operands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * The upper/lower functions are based on a table created by mkupr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This is a compressed table of upper and lower case conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifndef _CIFS_UNICODE_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define _CIFS_UNICODE_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/nls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define UNIUPR_NOLOWER /* Example to not expand lower case tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Windows maps these to the user defined 16 bit Unicode range since they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * reserved symbols (along with \ and /), otherwise illegal to store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * in filenames in NTFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define UNI_ASTERISK (__u16) ('*' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define UNI_QUESTION (__u16) ('?' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define UNI_COLON (__u16) (':' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define UNI_LESSTHAN (__u16) ('<' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define UNI_PIPE (__u16) ('|' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define UNI_SLASH (__u16) ('\\' + 0xF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Macs use an older "SFM" mapping of the symbols above. Fortunately it does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * not conflict (although almost does) with the mapping above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SFM_DOUBLEQUOTE ((__u16) 0xF020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SFM_ASTERISK ((__u16) 0xF021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SFM_QUESTION ((__u16) 0xF025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SFM_COLON ((__u16) 0xF022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SFM_GRTRTHAN ((__u16) 0xF024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SFM_LESSTHAN ((__u16) 0xF023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SFM_PIPE ((__u16) 0xF027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SFM_SLASH ((__u16) 0xF026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SFM_SPACE ((__u16) 0xF028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SFM_PERIOD ((__u16) 0xF029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Mapping mechanism to use when one of the seven reserved characters is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * encountered. We can only map using one of the mechanisms at a time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * since otherwise readdir could return directory entries which we would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * not be able to open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * NO_MAP_UNI_RSVD = do not perform any remapping of the character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define NO_MAP_UNI_RSVD 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define SFM_MAP_UNI_RSVD 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SFU_MAP_UNI_RSVD 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Just define what we want from uniupr.h. We don't want to define the tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * in each source file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #ifndef UNICASERANGE_DEFINED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct UniCaseRange {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) wchar_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) wchar_t end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) signed char *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #endif /* UNICASERANGE_DEFINED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #ifndef UNIUPR_NOUPPER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) extern signed char CifsUniUpperTable[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) extern const struct UniCaseRange CifsUniUpperRange[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #endif /* UNIUPR_NOUPPER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #ifndef UNIUPR_NOLOWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) extern signed char CifsUniLowerTable[512];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) extern const struct UniCaseRange CifsUniLowerRange[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #endif /* UNIUPR_NOLOWER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #ifdef __KERNEL__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const struct nls_table *cp, int map_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int cifs_utf16_bytes(const __le16 *from, int maxbytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const struct nls_table *codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) char *cifs_strndup_from_utf16(const char *src, const int maxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) const bool is_unicode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) const struct nls_table *codepage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) const struct nls_table *cp, int mapChars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) extern int cifs_remap(struct cifs_sb_info *cifs_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int *utf16_len, const struct nls_table *cp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int remap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) wchar_t cifs_toupper(wchar_t in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * UniStrcat: Concatenate the second string to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Address of the first string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline __le16 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) UniStrcat(__le16 *ucs1, const __le16 *ucs2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) while (*ucs1++) ; /* To end of first string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ucs1--; /* Return to the null */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return anchor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * UniStrchr: Find a character in a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Address of first occurrence of character in string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * or NULL if the character is not in the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) UniStrchr(const wchar_t *ucs, wchar_t uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) while ((*ucs != uc) && *ucs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ucs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (*ucs == uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return (wchar_t *) ucs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * UniStrcmp: Compare two strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * < 0: First string is less than second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * = 0: Strings are equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * > 0: First string is greater than second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) while ((*ucs1 == *ucs2) && *ucs1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ucs1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return (int) *ucs1 - (int) *ucs2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * UniStrcpy: Copy a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) wchar_t *anchor = ucs1; /* save the start of result string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) while ((*ucs1++ = *ucs2++)) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return anchor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static inline size_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) UniStrlen(const wchar_t *ucs1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) while (*ucs1++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * string (length limited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static inline size_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) UniStrnlen(const wchar_t *ucs1, int maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) while (*ucs1++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (i >= maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * UniStrncat: Concatenate length limited string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) wchar_t *anchor = ucs1; /* save pointer to string 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) while (*ucs1++) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ucs1--; /* point to null terminator of s1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ucs1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *ucs1 = 0; /* Null terminate the result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return (anchor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * UniStrncmp: Compare length limited string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0; /* Null strings are equal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) while ((*ucs1 == *ucs2) && *ucs1 && --n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ucs1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return (int) *ucs1 - (int) *ucs2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * UniStrncmp_le: Compare length limited string - native to little-endian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0; /* Null strings are equal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ucs1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * UniStrncpy: Copy length limited string with pad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) wchar_t *anchor = ucs1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) while (n-- && *ucs2) /* Copy the strings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *ucs1++ = *ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) while (n--) /* Pad with nulls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *ucs1++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return anchor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * UniStrncpy_le: Copy length limited string with pad to little-endian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) wchar_t *anchor = ucs1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) while (n-- && *ucs2) /* Copy the strings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *ucs1++ = __le16_to_cpu(*ucs2++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) while (n--) /* Pad with nulls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *ucs1++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return anchor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * UniStrstr: Find a string in a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * Address of first match found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * NULL if no matching string is found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) const wchar_t *anchor1 = ucs1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) const wchar_t *anchor2 = ucs2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) while (*ucs1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (*ucs1 == *ucs2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* Partial match found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ucs1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ucs2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!*ucs2) /* Match found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return (wchar_t *) anchor1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ucs1 = ++anchor1; /* No match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ucs2 = anchor2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (!*ucs2) /* Both end together */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return (wchar_t *) anchor1; /* Match found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return NULL; /* No match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) #ifndef UNIUPR_NOUPPER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * UniToupper: Convert a unicode character to upper case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static inline wchar_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) UniToupper(register wchar_t uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) register const struct UniCaseRange *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (uc < sizeof(CifsUniUpperTable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Latin characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return uc + CifsUniUpperTable[uc]; /* Use base tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) rp = CifsUniUpperRange; /* Use range tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) while (rp->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (uc < rp->start) /* Before start of range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return uc; /* Uppercase = input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (uc <= rp->end) /* In range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return uc + rp->table[uc - rp->start];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) rp++; /* Try next range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return uc; /* Past last range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * UniStrupr: Upper case a unicode string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static inline __le16 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) UniStrupr(register __le16 *upin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) register __le16 *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) up = upin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) while (*up) { /* For all characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) up++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return upin; /* Return input pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #endif /* UNIUPR_NOUPPER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) #ifndef UNIUPR_NOLOWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * UniTolower: Convert a unicode character to lower case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static inline wchar_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) UniTolower(register wchar_t uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) register const struct UniCaseRange *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (uc < sizeof(CifsUniLowerTable)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Latin characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return uc + CifsUniLowerTable[uc]; /* Use base tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) rp = CifsUniLowerRange; /* Use range tables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) while (rp->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (uc < rp->start) /* Before start of range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return uc; /* Uppercase = input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (uc <= rp->end) /* In range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return uc + rp->table[uc - rp->start];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) rp++; /* Try next range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return uc; /* Past last range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * UniStrlwr: Lower case a unicode string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static inline wchar_t *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) UniStrlwr(register wchar_t *upin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) register wchar_t *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) up = upin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) while (*up) { /* For all characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) *up = UniTolower(*up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) up++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return upin; /* Return input pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) #endif /* _CIFS_UNICODE_H */