Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Some of the source code in this file came from fs/cifs/cifs_unicode.c
0004  * cifs_unicode:  Unicode kernel case support
0005  *
0006  * Function:
0007  *     Convert a unicode character to upper or lower case using
0008  *     compressed tables.
0009  *
0010  *   Copyright (c) International Business Machines  Corp., 2000,2009
0011  *
0012  *
0013  * Notes:
0014  *     These APIs are based on the C library functions.  The semantics
0015  *     should match the C functions but with expanded size operands.
0016  *
0017  *     The upper/lower functions are based on a table created by mkupr.
0018  *     This is a compressed table of upper and lower case conversion.
0019  *
0020  */
0021 #ifndef _CIFS_UNICODE_H
0022 #define _CIFS_UNICODE_H
0023 
0024 #include <asm/byteorder.h>
0025 #include <linux/types.h>
0026 #include <linux/nls.h>
0027 
0028 #define  UNIUPR_NOLOWER     /* Example to not expand lower case tables */
0029 
0030 /*
0031  * Windows maps these to the user defined 16 bit Unicode range since they are
0032  * reserved symbols (along with \ and /), otherwise illegal to store
0033  * in filenames in NTFS
0034  */
0035 #define UNI_ASTERISK    ((__u16)('*' + 0xF000))
0036 #define UNI_QUESTION    ((__u16)('?' + 0xF000))
0037 #define UNI_COLON       ((__u16)(':' + 0xF000))
0038 #define UNI_GRTRTHAN    ((__u16)('>' + 0xF000))
0039 #define UNI_LESSTHAN    ((__u16)('<' + 0xF000))
0040 #define UNI_PIPE        ((__u16)('|' + 0xF000))
0041 #define UNI_SLASH       ((__u16)('\\' + 0xF000))
0042 
0043 /* Just define what we want from uniupr.h.  We don't want to define the tables
0044  * in each source file.
0045  */
0046 #ifndef UNICASERANGE_DEFINED
0047 struct UniCaseRange {
0048     wchar_t start;
0049     wchar_t end;
0050     signed char *table;
0051 };
0052 #endif              /* UNICASERANGE_DEFINED */
0053 
0054 #ifndef UNIUPR_NOUPPER
0055 extern signed char SmbUniUpperTable[512];
0056 extern const struct UniCaseRange SmbUniUpperRange[];
0057 #endif              /* UNIUPR_NOUPPER */
0058 
0059 #ifndef UNIUPR_NOLOWER
0060 extern signed char CifsUniLowerTable[512];
0061 extern const struct UniCaseRange CifsUniLowerRange[];
0062 #endif              /* UNIUPR_NOLOWER */
0063 
0064 #ifdef __KERNEL__
0065 int smb_strtoUTF16(__le16 *to, const char *from, int len,
0066            const struct nls_table *codepage);
0067 char *smb_strndup_from_utf16(const char *src, const int maxlen,
0068                  const bool is_unicode,
0069                  const struct nls_table *codepage);
0070 int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
0071               const struct nls_table *cp, int mapchars);
0072 char *ksmbd_extract_sharename(char *treename);
0073 #endif
0074 
0075 /*
0076  * UniStrcat:  Concatenate the second string to the first
0077  *
0078  * Returns:
0079  *     Address of the first string
0080  */
0081 static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2)
0082 {
0083     wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
0084 
0085     while (*ucs1++)
0086     /*NULL*/;   /* To end of first string */
0087     ucs1--;         /* Return to the null */
0088     while ((*ucs1++ = *ucs2++))
0089     /*NULL*/;   /* copy string 2 over */
0090     return anchor;
0091 }
0092 
0093 /*
0094  * UniStrchr:  Find a character in a string
0095  *
0096  * Returns:
0097  *     Address of first occurrence of character in string
0098  *     or NULL if the character is not in the string
0099  */
0100 static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc)
0101 {
0102     while ((*ucs != uc) && *ucs)
0103         ucs++;
0104 
0105     if (*ucs == uc)
0106         return (wchar_t *)ucs;
0107     return NULL;
0108 }
0109 
0110 /*
0111  * UniStrcmp:  Compare two strings
0112  *
0113  * Returns:
0114  *     < 0:  First string is less than second
0115  *     = 0:  Strings are equal
0116  *     > 0:  First string is greater than second
0117  */
0118 static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2)
0119 {
0120     while ((*ucs1 == *ucs2) && *ucs1) {
0121         ucs1++;
0122         ucs2++;
0123     }
0124     return (int)*ucs1 - (int)*ucs2;
0125 }
0126 
0127 /*
0128  * UniStrcpy:  Copy a string
0129  */
0130 static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2)
0131 {
0132     wchar_t *anchor = ucs1; /* save the start of result string */
0133 
0134     while ((*ucs1++ = *ucs2++))
0135     /*NULL*/;
0136     return anchor;
0137 }
0138 
0139 /*
0140  * UniStrlen:  Return the length of a string (in 16 bit Unicode chars not bytes)
0141  */
0142 static inline size_t UniStrlen(const wchar_t *ucs1)
0143 {
0144     int i = 0;
0145 
0146     while (*ucs1++)
0147         i++;
0148     return i;
0149 }
0150 
0151 /*
0152  * UniStrnlen:  Return the length (in 16 bit Unicode chars not bytes) of a
0153  *      string (length limited)
0154  */
0155 static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen)
0156 {
0157     int i = 0;
0158 
0159     while (*ucs1++) {
0160         i++;
0161         if (i >= maxlen)
0162             break;
0163     }
0164     return i;
0165 }
0166 
0167 /*
0168  * UniStrncat:  Concatenate length limited string
0169  */
0170 static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
0171 {
0172     wchar_t *anchor = ucs1; /* save pointer to string 1 */
0173 
0174     while (*ucs1++)
0175     /*NULL*/;
0176     ucs1--;         /* point to null terminator of s1 */
0177     while (n-- && (*ucs1 = *ucs2)) {    /* copy s2 after s1 */
0178         ucs1++;
0179         ucs2++;
0180     }
0181     *ucs1 = 0;      /* Null terminate the result */
0182     return anchor;
0183 }
0184 
0185 /*
0186  * UniStrncmp:  Compare length limited string
0187  */
0188 static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
0189 {
0190     if (!n)
0191         return 0;   /* Null strings are equal */
0192     while ((*ucs1 == *ucs2) && *ucs1 && --n) {
0193         ucs1++;
0194         ucs2++;
0195     }
0196     return (int)*ucs1 - (int)*ucs2;
0197 }
0198 
0199 /*
0200  * UniStrncmp_le:  Compare length limited string - native to little-endian
0201  */
0202 static inline int
0203 UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n)
0204 {
0205     if (!n)
0206         return 0;   /* Null strings are equal */
0207     while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
0208         ucs1++;
0209         ucs2++;
0210     }
0211     return (int)*ucs1 - (int)__le16_to_cpu(*ucs2);
0212 }
0213 
0214 /*
0215  * UniStrncpy:  Copy length limited string with pad
0216  */
0217 static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
0218 {
0219     wchar_t *anchor = ucs1;
0220 
0221     while (n-- && *ucs2)    /* Copy the strings */
0222         *ucs1++ = *ucs2++;
0223 
0224     n++;
0225     while (n--)     /* Pad with nulls */
0226         *ucs1++ = 0;
0227     return anchor;
0228 }
0229 
0230 /*
0231  * UniStrncpy_le:  Copy length limited string with pad to little-endian
0232  */
0233 static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n)
0234 {
0235     wchar_t *anchor = ucs1;
0236 
0237     while (n-- && *ucs2)    /* Copy the strings */
0238         *ucs1++ = __le16_to_cpu(*ucs2++);
0239 
0240     n++;
0241     while (n--)     /* Pad with nulls */
0242         *ucs1++ = 0;
0243     return anchor;
0244 }
0245 
0246 /*
0247  * UniStrstr:  Find a string in a string
0248  *
0249  * Returns:
0250  *     Address of first match found
0251  *     NULL if no matching string is found
0252  */
0253 static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2)
0254 {
0255     const wchar_t *anchor1 = ucs1;
0256     const wchar_t *anchor2 = ucs2;
0257 
0258     while (*ucs1) {
0259         if (*ucs1 == *ucs2) {
0260             /* Partial match found */
0261             ucs1++;
0262             ucs2++;
0263         } else {
0264             if (!*ucs2) /* Match found */
0265                 return (wchar_t *)anchor1;
0266             ucs1 = ++anchor1;   /* No match */
0267             ucs2 = anchor2;
0268         }
0269     }
0270 
0271     if (!*ucs2)     /* Both end together */
0272         return (wchar_t *)anchor1;  /* Match found */
0273     return NULL;        /* No match */
0274 }
0275 
0276 #ifndef UNIUPR_NOUPPER
0277 /*
0278  * UniToupper:  Convert a unicode character to upper case
0279  */
0280 static inline wchar_t UniToupper(register wchar_t uc)
0281 {
0282     register const struct UniCaseRange *rp;
0283 
0284     if (uc < sizeof(SmbUniUpperTable)) {
0285         /* Latin characters */
0286         return uc + SmbUniUpperTable[uc];   /* Use base tables */
0287     }
0288 
0289     rp = SmbUniUpperRange;  /* Use range tables */
0290     while (rp->start) {
0291         if (uc < rp->start) /* Before start of range */
0292             return uc;  /* Uppercase = input */
0293         if (uc <= rp->end)  /* In range */
0294             return uc + rp->table[uc - rp->start];
0295         rp++;   /* Try next range */
0296     }
0297     return uc;      /* Past last range */
0298 }
0299 
0300 /*
0301  * UniStrupr:  Upper case a unicode string
0302  */
0303 static inline __le16 *UniStrupr(register __le16 *upin)
0304 {
0305     register __le16 *up;
0306 
0307     up = upin;
0308     while (*up) {       /* For all characters */
0309         *up = cpu_to_le16(UniToupper(le16_to_cpu(*up)));
0310         up++;
0311     }
0312     return upin;        /* Return input pointer */
0313 }
0314 #endif              /* UNIUPR_NOUPPER */
0315 
0316 #ifndef UNIUPR_NOLOWER
0317 /*
0318  * UniTolower:  Convert a unicode character to lower case
0319  */
0320 static inline wchar_t UniTolower(register wchar_t uc)
0321 {
0322     register const struct UniCaseRange *rp;
0323 
0324     if (uc < sizeof(CifsUniLowerTable)) {
0325         /* Latin characters */
0326         return uc + CifsUniLowerTable[uc];  /* Use base tables */
0327     }
0328 
0329     rp = CifsUniLowerRange; /* Use range tables */
0330     while (rp->start) {
0331         if (uc < rp->start) /* Before start of range */
0332             return uc;  /* Uppercase = input */
0333         if (uc <= rp->end)  /* In range */
0334             return uc + rp->table[uc - rp->start];
0335         rp++;   /* Try next range */
0336     }
0337     return uc;      /* Past last range */
0338 }
0339 
0340 /*
0341  * UniStrlwr:  Lower case a unicode string
0342  */
0343 static inline wchar_t *UniStrlwr(register wchar_t *upin)
0344 {
0345     register wchar_t *up;
0346 
0347     up = upin;
0348     while (*up) {       /* For all characters */
0349         *up = UniTolower(*up);
0350         up++;
0351     }
0352     return upin;        /* Return input pointer */
0353 }
0354 
0355 #endif
0356 
0357 #endif /* _CIFS_UNICODE_H */