15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
22*11963SAfshin.Ardakani@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
235331Samw * Use is subject to license terms.
245331Samw */
255331Samw
265331Samw #ifdef _KERNEL
275331Samw #include <sys/types.h>
285331Samw #include <sys/sunddi.h>
295331Samw #else
3010966SJordan.Brown@Sun.COM #include <stdio.h>
315331Samw #include <stdlib.h>
325331Samw #include <string.h>
335331Samw #include <strings.h>
345331Samw #endif
3510966SJordan.Brown@Sun.COM #include <sys/u8_textprep.h>
3610966SJordan.Brown@Sun.COM #include <smbsrv/alloc.h>
37*11963SAfshin.Ardakani@Sun.COM #include <sys/errno.h>
385331Samw #include <smbsrv/string.h>
3910966SJordan.Brown@Sun.COM #include <smbsrv/cp_usascii.h>
4010966SJordan.Brown@Sun.COM #include <smbsrv/cp_unicode.h>
4110966SJordan.Brown@Sun.COM
4210966SJordan.Brown@Sun.COM #define UNICODE_N_ENTRIES (sizeof (a_unicode) / sizeof (a_unicode[0]))
435331Samw
4410966SJordan.Brown@Sun.COM /*
4510966SJordan.Brown@Sun.COM * Global pointer to the current codepage: defaults to ASCII,
4610966SJordan.Brown@Sun.COM * and a flag indicating whether the codepage is Unicode or ASCII.
4710966SJordan.Brown@Sun.COM */
4810966SJordan.Brown@Sun.COM static smb_codepage_t *current_codepage = usascii_codepage;
4910966SJordan.Brown@Sun.COM static boolean_t is_unicode = B_FALSE;
5010966SJordan.Brown@Sun.COM
5110966SJordan.Brown@Sun.COM static smb_codepage_t *smb_unicode_init(void);
525331Samw
535331Samw /*
545331Samw * strsubst
555331Samw *
565331Samw * Scan a string replacing all occurrences of orgchar with newchar.
575331Samw * Returns a pointer to s, or null of s is null.
585331Samw */
595331Samw char *
strsubst(char * s,char orgchar,char newchar)605331Samw strsubst(char *s, char orgchar, char newchar)
615331Samw {
625331Samw char *p = s;
635331Samw
645331Samw if (p == 0)
655331Samw return (0);
665331Samw
675331Samw while (*p) {
685331Samw if (*p == orgchar)
695331Samw *p = newchar;
705331Samw ++p;
715331Samw }
725331Samw
735331Samw return (s);
745331Samw }
755331Samw
765331Samw /*
775331Samw * strcanon
785331Samw *
795331Samw * Normalize a string by reducing all the repeated characters in
805331Samw * buf as defined by class. For example;
815331Samw *
825331Samw * char *buf = strdup("/d1//d2//d3\\\\d4\\\\f1.txt");
835331Samw * strcanon(buf, "/\\");
845331Samw *
855331Samw * Would result in buf containing the following string:
865331Samw *
875331Samw * /d1/d2/d3\d4\f1.txt
885331Samw *
895331Samw * This function modifies the contents of buf in place and returns
905331Samw * a pointer to buf.
915331Samw */
925331Samw char *
strcanon(char * buf,const char * class)935331Samw strcanon(char *buf, const char *class)
945331Samw {
955331Samw char *p = buf;
965331Samw char *q = buf;
975331Samw char *r;
985331Samw
995331Samw while (*p) {
1005331Samw *q++ = *p;
1015331Samw
1025331Samw if ((r = strchr(class, *p)) != 0) {
1035331Samw while (*p == *r)
1045331Samw ++p;
1055331Samw } else
1065331Samw ++p;
1075331Samw }
1085331Samw
1095331Samw *q = '\0';
1105331Samw return (buf);
1115331Samw }
11210966SJordan.Brown@Sun.COM
11310966SJordan.Brown@Sun.COM void
smb_codepage_init(void)11410966SJordan.Brown@Sun.COM smb_codepage_init(void)
11510966SJordan.Brown@Sun.COM {
11610966SJordan.Brown@Sun.COM smb_codepage_t *cp;
11710966SJordan.Brown@Sun.COM
11810966SJordan.Brown@Sun.COM if (is_unicode)
11910966SJordan.Brown@Sun.COM return;
12010966SJordan.Brown@Sun.COM
12110966SJordan.Brown@Sun.COM if ((cp = smb_unicode_init()) != NULL) {
12210966SJordan.Brown@Sun.COM current_codepage = cp;
12310966SJordan.Brown@Sun.COM is_unicode = B_TRUE;
12410966SJordan.Brown@Sun.COM } else {
12510966SJordan.Brown@Sun.COM current_codepage = usascii_codepage;
12610966SJordan.Brown@Sun.COM is_unicode = B_FALSE;
12710966SJordan.Brown@Sun.COM }
12810966SJordan.Brown@Sun.COM }
12910966SJordan.Brown@Sun.COM
13010966SJordan.Brown@Sun.COM /*
13110966SJordan.Brown@Sun.COM * Determine whether or not a character is an uppercase character.
13210966SJordan.Brown@Sun.COM * This function operates on the current codepage table. Returns
13310966SJordan.Brown@Sun.COM * non-zero if the character is uppercase. Otherwise returns zero.
13410966SJordan.Brown@Sun.COM */
13510966SJordan.Brown@Sun.COM int
smb_isupper(int c)13610966SJordan.Brown@Sun.COM smb_isupper(int c)
13710966SJordan.Brown@Sun.COM {
13810966SJordan.Brown@Sun.COM uint16_t mask = is_unicode ? 0xffff : 0xff;
13910966SJordan.Brown@Sun.COM
14010966SJordan.Brown@Sun.COM return (current_codepage[c & mask].ctype & CODEPAGE_ISUPPER);
14110966SJordan.Brown@Sun.COM }
14210966SJordan.Brown@Sun.COM
14310966SJordan.Brown@Sun.COM /*
14410966SJordan.Brown@Sun.COM * Determine whether or not a character is an lowercase character.
14510966SJordan.Brown@Sun.COM * This function operates on the current codepage table. Returns
14610966SJordan.Brown@Sun.COM * non-zero if the character is lowercase. Otherwise returns zero.
14710966SJordan.Brown@Sun.COM */
14810966SJordan.Brown@Sun.COM int
smb_islower(int c)14910966SJordan.Brown@Sun.COM smb_islower(int c)
15010966SJordan.Brown@Sun.COM {
15110966SJordan.Brown@Sun.COM uint16_t mask = is_unicode ? 0xffff : 0xff;
15210966SJordan.Brown@Sun.COM
15310966SJordan.Brown@Sun.COM return (current_codepage[c & mask].ctype & CODEPAGE_ISLOWER);
15410966SJordan.Brown@Sun.COM }
15510966SJordan.Brown@Sun.COM
15610966SJordan.Brown@Sun.COM /*
15710966SJordan.Brown@Sun.COM * Convert individual characters to their uppercase equivalent value.
15810966SJordan.Brown@Sun.COM * If the specified character is lowercase, the uppercase value will
15910966SJordan.Brown@Sun.COM * be returned. Otherwise the original value will be returned.
16010966SJordan.Brown@Sun.COM */
16110966SJordan.Brown@Sun.COM int
smb_toupper(int c)16210966SJordan.Brown@Sun.COM smb_toupper(int c)
16310966SJordan.Brown@Sun.COM {
16410966SJordan.Brown@Sun.COM uint16_t mask = is_unicode ? 0xffff : 0xff;
16510966SJordan.Brown@Sun.COM
16610966SJordan.Brown@Sun.COM return (current_codepage[c & mask].upper);
16710966SJordan.Brown@Sun.COM }
16810966SJordan.Brown@Sun.COM
16910966SJordan.Brown@Sun.COM /*
17010966SJordan.Brown@Sun.COM * Convert individual characters to their lowercase equivalent value.
17110966SJordan.Brown@Sun.COM * If the specified character is uppercase, the lowercase value will
17210966SJordan.Brown@Sun.COM * be returned. Otherwise the original value will be returned.
17310966SJordan.Brown@Sun.COM */
17410966SJordan.Brown@Sun.COM int
smb_tolower(int c)17510966SJordan.Brown@Sun.COM smb_tolower(int c)
17610966SJordan.Brown@Sun.COM {
17710966SJordan.Brown@Sun.COM uint16_t mask = is_unicode ? 0xffff : 0xff;
17810966SJordan.Brown@Sun.COM
17910966SJordan.Brown@Sun.COM return (current_codepage[c & mask].lower);
18010966SJordan.Brown@Sun.COM }
18110966SJordan.Brown@Sun.COM
18210966SJordan.Brown@Sun.COM /*
18310966SJordan.Brown@Sun.COM * Convert a string to uppercase using the appropriate codepage. The
18410966SJordan.Brown@Sun.COM * string is converted in place. A pointer to the string is returned.
18510966SJordan.Brown@Sun.COM * There is an assumption here that uppercase and lowercase values
18610966SJordan.Brown@Sun.COM * always result encode to the same length.
18710966SJordan.Brown@Sun.COM */
18810966SJordan.Brown@Sun.COM char *
smb_strupr(char * s)18910966SJordan.Brown@Sun.COM smb_strupr(char *s)
19010966SJordan.Brown@Sun.COM {
19110966SJordan.Brown@Sun.COM smb_wchar_t c;
19210966SJordan.Brown@Sun.COM char *p = s;
19310966SJordan.Brown@Sun.COM
19410966SJordan.Brown@Sun.COM while (*p) {
19510966SJordan.Brown@Sun.COM if (smb_isascii(*p)) {
19610966SJordan.Brown@Sun.COM *p = smb_toupper(*p);
19710966SJordan.Brown@Sun.COM p++;
19810966SJordan.Brown@Sun.COM } else {
19910966SJordan.Brown@Sun.COM if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
20010966SJordan.Brown@Sun.COM return (0);
20110966SJordan.Brown@Sun.COM
20210966SJordan.Brown@Sun.COM if (c == 0)
20310966SJordan.Brown@Sun.COM break;
20410966SJordan.Brown@Sun.COM
20510966SJordan.Brown@Sun.COM c = smb_toupper(c);
20610966SJordan.Brown@Sun.COM p += smb_wctomb(p, c);
20710966SJordan.Brown@Sun.COM }
20810966SJordan.Brown@Sun.COM }
20910966SJordan.Brown@Sun.COM
21010966SJordan.Brown@Sun.COM return (s);
21110966SJordan.Brown@Sun.COM }
21210966SJordan.Brown@Sun.COM
21310966SJordan.Brown@Sun.COM /*
21410966SJordan.Brown@Sun.COM * Convert a string to lowercase using the appropriate codepage. The
21510966SJordan.Brown@Sun.COM * string is converted in place. A pointer to the string is returned.
21610966SJordan.Brown@Sun.COM * There is an assumption here that uppercase and lowercase values
21710966SJordan.Brown@Sun.COM * always result encode to the same length.
21810966SJordan.Brown@Sun.COM */
21910966SJordan.Brown@Sun.COM char *
smb_strlwr(char * s)22010966SJordan.Brown@Sun.COM smb_strlwr(char *s)
22110966SJordan.Brown@Sun.COM {
22210966SJordan.Brown@Sun.COM smb_wchar_t c;
22310966SJordan.Brown@Sun.COM char *p = s;
22410966SJordan.Brown@Sun.COM
22510966SJordan.Brown@Sun.COM while (*p) {
22610966SJordan.Brown@Sun.COM if (smb_isascii(*p)) {
22710966SJordan.Brown@Sun.COM *p = smb_tolower(*p);
22810966SJordan.Brown@Sun.COM p++;
22910966SJordan.Brown@Sun.COM } else {
23010966SJordan.Brown@Sun.COM if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
23110966SJordan.Brown@Sun.COM return (0);
23210966SJordan.Brown@Sun.COM
23310966SJordan.Brown@Sun.COM if (c == 0)
23410966SJordan.Brown@Sun.COM break;
23510966SJordan.Brown@Sun.COM
23610966SJordan.Brown@Sun.COM c = smb_tolower(c);
23710966SJordan.Brown@Sun.COM p += smb_wctomb(p, c);
23810966SJordan.Brown@Sun.COM }
23910966SJordan.Brown@Sun.COM }
24010966SJordan.Brown@Sun.COM
24110966SJordan.Brown@Sun.COM return (s);
24210966SJordan.Brown@Sun.COM }
24310966SJordan.Brown@Sun.COM
24410966SJordan.Brown@Sun.COM /*
24510966SJordan.Brown@Sun.COM * Returns 1 if string contains NO uppercase chars 0 otherwise. However,
24610966SJordan.Brown@Sun.COM * -1 is returned if "s" is not a valid multi-byte string.
24710966SJordan.Brown@Sun.COM */
24810966SJordan.Brown@Sun.COM int
smb_isstrlwr(const char * s)24910966SJordan.Brown@Sun.COM smb_isstrlwr(const char *s)
25010966SJordan.Brown@Sun.COM {
25110966SJordan.Brown@Sun.COM smb_wchar_t c;
25210966SJordan.Brown@Sun.COM int n;
25310966SJordan.Brown@Sun.COM const char *p = s;
25410966SJordan.Brown@Sun.COM
25510966SJordan.Brown@Sun.COM while (*p) {
25610966SJordan.Brown@Sun.COM if (smb_isascii(*p) && smb_isupper(*p))
25710966SJordan.Brown@Sun.COM return (0);
25810966SJordan.Brown@Sun.COM else {
25910966SJordan.Brown@Sun.COM if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
26010966SJordan.Brown@Sun.COM return (-1);
26110966SJordan.Brown@Sun.COM
26210966SJordan.Brown@Sun.COM if (c == 0)
26310966SJordan.Brown@Sun.COM break;
26410966SJordan.Brown@Sun.COM
26510966SJordan.Brown@Sun.COM if (smb_isupper(c))
26610966SJordan.Brown@Sun.COM return (0);
26710966SJordan.Brown@Sun.COM
26810966SJordan.Brown@Sun.COM p += n;
26910966SJordan.Brown@Sun.COM }
27010966SJordan.Brown@Sun.COM }
27110966SJordan.Brown@Sun.COM
27210966SJordan.Brown@Sun.COM return (1);
27310966SJordan.Brown@Sun.COM }
27410966SJordan.Brown@Sun.COM
27510966SJordan.Brown@Sun.COM /*
27610966SJordan.Brown@Sun.COM * Returns 1 if string contains NO lowercase chars 0 otherwise. However,
27710966SJordan.Brown@Sun.COM * -1 is returned if "s" is not a valid multi-byte string.
27810966SJordan.Brown@Sun.COM */
27910966SJordan.Brown@Sun.COM int
smb_isstrupr(const char * s)28010966SJordan.Brown@Sun.COM smb_isstrupr(const char *s)
28110966SJordan.Brown@Sun.COM {
28210966SJordan.Brown@Sun.COM smb_wchar_t c;
28310966SJordan.Brown@Sun.COM int n;
28410966SJordan.Brown@Sun.COM const char *p = s;
28510966SJordan.Brown@Sun.COM
28610966SJordan.Brown@Sun.COM while (*p) {
28710966SJordan.Brown@Sun.COM if (smb_isascii(*p) && smb_islower(*p))
28810966SJordan.Brown@Sun.COM return (0);
28910966SJordan.Brown@Sun.COM else {
29010966SJordan.Brown@Sun.COM if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
29110966SJordan.Brown@Sun.COM return (-1);
29210966SJordan.Brown@Sun.COM
29310966SJordan.Brown@Sun.COM if (c == 0)
29410966SJordan.Brown@Sun.COM break;
29510966SJordan.Brown@Sun.COM
29610966SJordan.Brown@Sun.COM if (smb_islower(c))
29710966SJordan.Brown@Sun.COM return (0);
29810966SJordan.Brown@Sun.COM
29910966SJordan.Brown@Sun.COM p += n;
30010966SJordan.Brown@Sun.COM }
30110966SJordan.Brown@Sun.COM }
30210966SJordan.Brown@Sun.COM
30310966SJordan.Brown@Sun.COM return (1);
30410966SJordan.Brown@Sun.COM }
30510966SJordan.Brown@Sun.COM
30610966SJordan.Brown@Sun.COM /*
30710966SJordan.Brown@Sun.COM * Compare the null-terminated strings s1 and s2 and return an integer
30810966SJordan.Brown@Sun.COM * greater than, equal to or less than 0 dependent on whether s1 is
30910966SJordan.Brown@Sun.COM * lexicographically greater than, equal to or less than s2 after
31010966SJordan.Brown@Sun.COM * translation of each character to lowercase. The original strings
31110966SJordan.Brown@Sun.COM * are not modified.
31210966SJordan.Brown@Sun.COM *
31310966SJordan.Brown@Sun.COM * If n is non-zero, at most n bytes are compared. Otherwise, the strings
31410966SJordan.Brown@Sun.COM * are compared until a null terminator is encountered.
31510966SJordan.Brown@Sun.COM *
31610966SJordan.Brown@Sun.COM * Out: 0 if strings are equal
31710966SJordan.Brown@Sun.COM * < 0 if first string < second string
31810966SJordan.Brown@Sun.COM * > 0 if first string > second string
31910966SJordan.Brown@Sun.COM */
32010966SJordan.Brown@Sun.COM int
smb_strcasecmp(const char * s1,const char * s2,size_t n)32110966SJordan.Brown@Sun.COM smb_strcasecmp(const char *s1, const char *s2, size_t n)
32210966SJordan.Brown@Sun.COM {
32310966SJordan.Brown@Sun.COM int err = 0;
32410966SJordan.Brown@Sun.COM int rc;
32510966SJordan.Brown@Sun.COM
32610966SJordan.Brown@Sun.COM rc = u8_strcmp(s1, s2, n, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err);
32710966SJordan.Brown@Sun.COM if (err != 0)
32810966SJordan.Brown@Sun.COM return (-1);
32910966SJordan.Brown@Sun.COM return (rc);
33010966SJordan.Brown@Sun.COM }
33110966SJordan.Brown@Sun.COM
33210966SJordan.Brown@Sun.COM /*
33310966SJordan.Brown@Sun.COM * First build a codepage based on cp_unicode.h. Then build the unicode
33410966SJordan.Brown@Sun.COM * codepage from this interim codepage by copying the entries over while
33510966SJordan.Brown@Sun.COM * fixing them and filling in the gaps.
33610966SJordan.Brown@Sun.COM */
33710966SJordan.Brown@Sun.COM static smb_codepage_t *
smb_unicode_init(void)33810966SJordan.Brown@Sun.COM smb_unicode_init(void)
33910966SJordan.Brown@Sun.COM {
34010966SJordan.Brown@Sun.COM smb_codepage_t *unicode;
34110966SJordan.Brown@Sun.COM uint32_t a = 0;
34210966SJordan.Brown@Sun.COM uint32_t b = 0;
34310966SJordan.Brown@Sun.COM
34410966SJordan.Brown@Sun.COM unicode = MEM_ZALLOC("unicode", sizeof (smb_codepage_t) << 16);
34510966SJordan.Brown@Sun.COM if (unicode == NULL)
34610966SJordan.Brown@Sun.COM return (NULL);
34710966SJordan.Brown@Sun.COM
34810966SJordan.Brown@Sun.COM while (b != 0xffff) {
34910966SJordan.Brown@Sun.COM /*
35010966SJordan.Brown@Sun.COM * If there is a gap in the standard,
35110966SJordan.Brown@Sun.COM * fill in the gap with no-case entries.
35210966SJordan.Brown@Sun.COM */
35310966SJordan.Brown@Sun.COM if (UNICODE_N_ENTRIES <= a || a_unicode[a].val > b) {
35410966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISNONE;
35510966SJordan.Brown@Sun.COM unicode[b].upper = (smb_wchar_t)b;
35610966SJordan.Brown@Sun.COM unicode[b].lower = (smb_wchar_t)b;
35710966SJordan.Brown@Sun.COM b++;
35810966SJordan.Brown@Sun.COM continue;
35910966SJordan.Brown@Sun.COM }
36010966SJordan.Brown@Sun.COM
36110966SJordan.Brown@Sun.COM /*
36210966SJordan.Brown@Sun.COM * Copy the entry and fixup as required.
36310966SJordan.Brown@Sun.COM */
36410966SJordan.Brown@Sun.COM switch (a_unicode[a].ctype) {
36510966SJordan.Brown@Sun.COM case CODEPAGE_ISNONE:
36610966SJordan.Brown@Sun.COM /*
36710966SJordan.Brown@Sun.COM * Replace 0xffff in upper/lower fields with its val.
36810966SJordan.Brown@Sun.COM */
36910966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISNONE;
37010966SJordan.Brown@Sun.COM unicode[b].upper = (smb_wchar_t)b;
37110966SJordan.Brown@Sun.COM unicode[b].lower = (smb_wchar_t)b;
37210966SJordan.Brown@Sun.COM break;
37310966SJordan.Brown@Sun.COM case CODEPAGE_ISUPPER:
37410966SJordan.Brown@Sun.COM /*
37510966SJordan.Brown@Sun.COM * Some characters may have case yet not have
37610966SJordan.Brown@Sun.COM * case conversion. Treat them as no-case.
37710966SJordan.Brown@Sun.COM */
37810966SJordan.Brown@Sun.COM if (a_unicode[a].lower == 0xffff) {
37910966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISNONE;
38010966SJordan.Brown@Sun.COM unicode[b].upper = (smb_wchar_t)b;
38110966SJordan.Brown@Sun.COM unicode[b].lower = (smb_wchar_t)b;
38210966SJordan.Brown@Sun.COM } else {
38310966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISUPPER;
38410966SJordan.Brown@Sun.COM unicode[b].upper = (smb_wchar_t)b;
38510966SJordan.Brown@Sun.COM unicode[b].lower = a_unicode[a].lower;
38610966SJordan.Brown@Sun.COM }
38710966SJordan.Brown@Sun.COM break;
38810966SJordan.Brown@Sun.COM case CODEPAGE_ISLOWER:
38910966SJordan.Brown@Sun.COM /*
39010966SJordan.Brown@Sun.COM * Some characters may have case yet not have
39110966SJordan.Brown@Sun.COM * case conversion. Treat them as no-case.
39210966SJordan.Brown@Sun.COM */
39310966SJordan.Brown@Sun.COM if (a_unicode[a].upper == 0xffff) {
39410966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISNONE;
39510966SJordan.Brown@Sun.COM unicode[b].upper = (smb_wchar_t)b;
39610966SJordan.Brown@Sun.COM unicode[b].lower = (smb_wchar_t)b;
39710966SJordan.Brown@Sun.COM } else {
39810966SJordan.Brown@Sun.COM unicode[b].ctype = CODEPAGE_ISLOWER;
39910966SJordan.Brown@Sun.COM unicode[b].upper = a_unicode[a].upper;
40010966SJordan.Brown@Sun.COM unicode[b].lower = (smb_wchar_t)b;
40110966SJordan.Brown@Sun.COM }
40210966SJordan.Brown@Sun.COM break;
40310966SJordan.Brown@Sun.COM default:
40410966SJordan.Brown@Sun.COM MEM_FREE("unicode", unicode);
40510966SJordan.Brown@Sun.COM return (NULL);
40610966SJordan.Brown@Sun.COM }
40710966SJordan.Brown@Sun.COM
40810966SJordan.Brown@Sun.COM a++;
40910966SJordan.Brown@Sun.COM b++;
41010966SJordan.Brown@Sun.COM };
41110966SJordan.Brown@Sun.COM
41210966SJordan.Brown@Sun.COM return (unicode);
41310966SJordan.Brown@Sun.COM }
414*11963SAfshin.Ardakani@Sun.COM
415*11963SAfshin.Ardakani@Sun.COM /*
416*11963SAfshin.Ardakani@Sun.COM * Parse a UNC path (\\server\share\path) into its components.
417*11963SAfshin.Ardakani@Sun.COM * Although a standard UNC path starts with two '\', in DFS
418*11963SAfshin.Ardakani@Sun.COM * all UNC paths start with one '\'. So, this function only
419*11963SAfshin.Ardakani@Sun.COM * checks for one.
420*11963SAfshin.Ardakani@Sun.COM *
421*11963SAfshin.Ardakani@Sun.COM * A valid UNC must at least contain two components i.e. server
422*11963SAfshin.Ardakani@Sun.COM * and share. The path is parsed to:
423*11963SAfshin.Ardakani@Sun.COM *
424*11963SAfshin.Ardakani@Sun.COM * unc_server server or domain name with no leading/trailing '\'
425*11963SAfshin.Ardakani@Sun.COM * unc_share share name with no leading/trailing '\'
426*11963SAfshin.Ardakani@Sun.COM * unc_path relative path to the share with no leading/trailing '\'
427*11963SAfshin.Ardakani@Sun.COM * it is valid for unc_path to be NULL.
428*11963SAfshin.Ardakani@Sun.COM *
429*11963SAfshin.Ardakani@Sun.COM * Upon successful return of this function, smb_unc_free()
430*11963SAfshin.Ardakani@Sun.COM * MUST be called when returned 'unc' is no longer needed.
431*11963SAfshin.Ardakani@Sun.COM *
432*11963SAfshin.Ardakani@Sun.COM * Returns 0 on success, otherwise returns an errno code.
433*11963SAfshin.Ardakani@Sun.COM */
434*11963SAfshin.Ardakani@Sun.COM int
smb_unc_init(const char * path,smb_unc_t * unc)435*11963SAfshin.Ardakani@Sun.COM smb_unc_init(const char *path, smb_unc_t *unc)
436*11963SAfshin.Ardakani@Sun.COM {
437*11963SAfshin.Ardakani@Sun.COM char *p;
438*11963SAfshin.Ardakani@Sun.COM
439*11963SAfshin.Ardakani@Sun.COM if (path == NULL || unc == NULL || (*path != '\\' && *path != '/'))
440*11963SAfshin.Ardakani@Sun.COM return (EINVAL);
441*11963SAfshin.Ardakani@Sun.COM
442*11963SAfshin.Ardakani@Sun.COM bzero(unc, sizeof (smb_unc_t));
443*11963SAfshin.Ardakani@Sun.COM
444*11963SAfshin.Ardakani@Sun.COM #ifdef _KERNEL
445*11963SAfshin.Ardakani@Sun.COM unc->unc_buf = smb_mem_strdup(path);
446*11963SAfshin.Ardakani@Sun.COM #else
447*11963SAfshin.Ardakani@Sun.COM if ((unc->unc_buf = strdup(path)) == NULL)
448*11963SAfshin.Ardakani@Sun.COM return (ENOMEM);
449*11963SAfshin.Ardakani@Sun.COM #endif
450*11963SAfshin.Ardakani@Sun.COM
451*11963SAfshin.Ardakani@Sun.COM (void) strsubst(unc->unc_buf, '\\', '/');
452*11963SAfshin.Ardakani@Sun.COM (void) strcanon(unc->unc_buf, "/");
453*11963SAfshin.Ardakani@Sun.COM
454*11963SAfshin.Ardakani@Sun.COM unc->unc_server = unc->unc_buf + 1;
455*11963SAfshin.Ardakani@Sun.COM if (*unc->unc_server == '\0') {
456*11963SAfshin.Ardakani@Sun.COM smb_unc_free(unc);
457*11963SAfshin.Ardakani@Sun.COM return (EINVAL);
458*11963SAfshin.Ardakani@Sun.COM }
459*11963SAfshin.Ardakani@Sun.COM
460*11963SAfshin.Ardakani@Sun.COM if ((p = strchr(unc->unc_server, '/')) == NULL) {
461*11963SAfshin.Ardakani@Sun.COM smb_unc_free(unc);
462*11963SAfshin.Ardakani@Sun.COM return (EINVAL);
463*11963SAfshin.Ardakani@Sun.COM }
464*11963SAfshin.Ardakani@Sun.COM
465*11963SAfshin.Ardakani@Sun.COM *p++ = '\0';
466*11963SAfshin.Ardakani@Sun.COM unc->unc_share = p;
467*11963SAfshin.Ardakani@Sun.COM
468*11963SAfshin.Ardakani@Sun.COM if (*unc->unc_share == '\0') {
469*11963SAfshin.Ardakani@Sun.COM smb_unc_free(unc);
470*11963SAfshin.Ardakani@Sun.COM return (EINVAL);
471*11963SAfshin.Ardakani@Sun.COM }
472*11963SAfshin.Ardakani@Sun.COM
473*11963SAfshin.Ardakani@Sun.COM unc->unc_path = strchr(unc->unc_share, '/');
474*11963SAfshin.Ardakani@Sun.COM if ((p = unc->unc_path) == NULL)
475*11963SAfshin.Ardakani@Sun.COM return (0);
476*11963SAfshin.Ardakani@Sun.COM
477*11963SAfshin.Ardakani@Sun.COM unc->unc_path++;
478*11963SAfshin.Ardakani@Sun.COM *p = '\0';
479*11963SAfshin.Ardakani@Sun.COM
480*11963SAfshin.Ardakani@Sun.COM /* remove the last '/' if any */
481*11963SAfshin.Ardakani@Sun.COM if ((p = strchr(unc->unc_path, '\0')) != NULL) {
482*11963SAfshin.Ardakani@Sun.COM if (*(--p) == '/')
483*11963SAfshin.Ardakani@Sun.COM *p = '\0';
484*11963SAfshin.Ardakani@Sun.COM }
485*11963SAfshin.Ardakani@Sun.COM
486*11963SAfshin.Ardakani@Sun.COM return (0);
487*11963SAfshin.Ardakani@Sun.COM }
488*11963SAfshin.Ardakani@Sun.COM
489*11963SAfshin.Ardakani@Sun.COM void
smb_unc_free(smb_unc_t * unc)490*11963SAfshin.Ardakani@Sun.COM smb_unc_free(smb_unc_t *unc)
491*11963SAfshin.Ardakani@Sun.COM {
492*11963SAfshin.Ardakani@Sun.COM if (unc == NULL)
493*11963SAfshin.Ardakani@Sun.COM return;
494*11963SAfshin.Ardakani@Sun.COM
495*11963SAfshin.Ardakani@Sun.COM #ifdef _KERNEL
496*11963SAfshin.Ardakani@Sun.COM smb_mem_free(unc->unc_buf);
497*11963SAfshin.Ardakani@Sun.COM #else
498*11963SAfshin.Ardakani@Sun.COM free(unc->unc_buf);
499*11963SAfshin.Ardakani@Sun.COM #endif
500*11963SAfshin.Ardakani@Sun.COM unc->unc_buf = NULL;
501*11963SAfshin.Ardakani@Sun.COM }
502