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