xref: /titanic_50/usr/src/common/smbsrv/smb_string.c (revision 9fb67ea305c66b6a297583b9b0db6796b0dfe497)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #ifdef _KERNEL
27da6c28aaSamw #include <sys/types.h>
28da6c28aaSamw #include <sys/sunddi.h>
29da6c28aaSamw #else
30bbf6f00cSJordan Brown #include <stdio.h>
31da6c28aaSamw #include <stdlib.h>
32da6c28aaSamw #include <string.h>
33da6c28aaSamw #include <strings.h>
34da6c28aaSamw #endif
35bbf6f00cSJordan Brown #include <sys/u8_textprep.h>
36bbf6f00cSJordan Brown #include <smbsrv/alloc.h>
37*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <sys/errno.h>
38da6c28aaSamw #include <smbsrv/string.h>
39bbf6f00cSJordan Brown #include <smbsrv/cp_usascii.h>
40bbf6f00cSJordan Brown #include <smbsrv/cp_unicode.h>
41da6c28aaSamw 
42bbf6f00cSJordan Brown #define	UNICODE_N_ENTRIES	(sizeof (a_unicode) / sizeof (a_unicode[0]))
43bbf6f00cSJordan Brown 
44bbf6f00cSJordan Brown /*
45bbf6f00cSJordan Brown  * Global pointer to the current codepage: defaults to ASCII,
46bbf6f00cSJordan Brown  * and a flag indicating whether the codepage is Unicode or ASCII.
47bbf6f00cSJordan Brown  */
48bbf6f00cSJordan Brown static smb_codepage_t *current_codepage = usascii_codepage;
49bbf6f00cSJordan Brown static boolean_t is_unicode = B_FALSE;
50bbf6f00cSJordan Brown 
51bbf6f00cSJordan Brown static smb_codepage_t *smb_unicode_init(void);
52da6c28aaSamw 
53da6c28aaSamw /*
54da6c28aaSamw  * strsubst
55da6c28aaSamw  *
56da6c28aaSamw  * Scan a string replacing all occurrences of orgchar with newchar.
57da6c28aaSamw  * Returns a pointer to s, or null of s is null.
58da6c28aaSamw  */
59da6c28aaSamw char *
60da6c28aaSamw strsubst(char *s, char orgchar, char newchar)
61da6c28aaSamw {
62da6c28aaSamw 	char *p = s;
63da6c28aaSamw 
64da6c28aaSamw 	if (p == 0)
65da6c28aaSamw 		return (0);
66da6c28aaSamw 
67da6c28aaSamw 	while (*p) {
68da6c28aaSamw 		if (*p == orgchar)
69da6c28aaSamw 			*p = newchar;
70da6c28aaSamw 		++p;
71da6c28aaSamw 	}
72da6c28aaSamw 
73da6c28aaSamw 	return (s);
74da6c28aaSamw }
75da6c28aaSamw 
76da6c28aaSamw /*
77da6c28aaSamw  * strcanon
78da6c28aaSamw  *
79da6c28aaSamw  * Normalize a string by reducing all the repeated characters in
80da6c28aaSamw  * buf as defined by class. For example;
81da6c28aaSamw  *
82da6c28aaSamw  *		char *buf = strdup("/d1//d2//d3\\\\d4\\\\f1.txt");
83da6c28aaSamw  *		strcanon(buf, "/\\");
84da6c28aaSamw  *
85da6c28aaSamw  * Would result in buf containing the following string:
86da6c28aaSamw  *
87da6c28aaSamw  *		/d1/d2/d3\d4\f1.txt
88da6c28aaSamw  *
89da6c28aaSamw  * This function modifies the contents of buf in place and returns
90da6c28aaSamw  * a pointer to buf.
91da6c28aaSamw  */
92da6c28aaSamw char *
93da6c28aaSamw strcanon(char *buf, const char *class)
94da6c28aaSamw {
95da6c28aaSamw 	char *p = buf;
96da6c28aaSamw 	char *q = buf;
97da6c28aaSamw 	char *r;
98da6c28aaSamw 
99da6c28aaSamw 	while (*p) {
100da6c28aaSamw 		*q++ = *p;
101da6c28aaSamw 
102da6c28aaSamw 		if ((r = strchr(class, *p)) != 0) {
103da6c28aaSamw 			while (*p == *r)
104da6c28aaSamw 				++p;
105da6c28aaSamw 		} else
106da6c28aaSamw 			++p;
107da6c28aaSamw 	}
108da6c28aaSamw 
109da6c28aaSamw 	*q = '\0';
110da6c28aaSamw 	return (buf);
111da6c28aaSamw }
112bbf6f00cSJordan Brown 
113bbf6f00cSJordan Brown void
114bbf6f00cSJordan Brown smb_codepage_init(void)
115bbf6f00cSJordan Brown {
116bbf6f00cSJordan Brown 	smb_codepage_t *cp;
117bbf6f00cSJordan Brown 
118bbf6f00cSJordan Brown 	if (is_unicode)
119bbf6f00cSJordan Brown 		return;
120bbf6f00cSJordan Brown 
121bbf6f00cSJordan Brown 	if ((cp = smb_unicode_init()) != NULL) {
122bbf6f00cSJordan Brown 		current_codepage = cp;
123bbf6f00cSJordan Brown 		is_unicode = B_TRUE;
124bbf6f00cSJordan Brown 	} else {
125bbf6f00cSJordan Brown 		current_codepage = usascii_codepage;
126bbf6f00cSJordan Brown 		is_unicode = B_FALSE;
127bbf6f00cSJordan Brown 	}
128bbf6f00cSJordan Brown }
129bbf6f00cSJordan Brown 
130bbf6f00cSJordan Brown /*
131bbf6f00cSJordan Brown  * Determine whether or not a character is an uppercase character.
132bbf6f00cSJordan Brown  * This function operates on the current codepage table. Returns
133bbf6f00cSJordan Brown  * non-zero if the character is uppercase. Otherwise returns zero.
134bbf6f00cSJordan Brown  */
135bbf6f00cSJordan Brown int
136bbf6f00cSJordan Brown smb_isupper(int c)
137bbf6f00cSJordan Brown {
138bbf6f00cSJordan Brown 	uint16_t mask = is_unicode ? 0xffff : 0xff;
139bbf6f00cSJordan Brown 
140bbf6f00cSJordan Brown 	return (current_codepage[c & mask].ctype & CODEPAGE_ISUPPER);
141bbf6f00cSJordan Brown }
142bbf6f00cSJordan Brown 
143bbf6f00cSJordan Brown /*
144bbf6f00cSJordan Brown  * Determine whether or not a character is an lowercase character.
145bbf6f00cSJordan Brown  * This function operates on the current codepage table. Returns
146bbf6f00cSJordan Brown  * non-zero if the character is lowercase. Otherwise returns zero.
147bbf6f00cSJordan Brown  */
148bbf6f00cSJordan Brown int
149bbf6f00cSJordan Brown smb_islower(int c)
150bbf6f00cSJordan Brown {
151bbf6f00cSJordan Brown 	uint16_t mask = is_unicode ? 0xffff : 0xff;
152bbf6f00cSJordan Brown 
153bbf6f00cSJordan Brown 	return (current_codepage[c & mask].ctype & CODEPAGE_ISLOWER);
154bbf6f00cSJordan Brown }
155bbf6f00cSJordan Brown 
156bbf6f00cSJordan Brown /*
157bbf6f00cSJordan Brown  * Convert individual characters to their uppercase equivalent value.
158bbf6f00cSJordan Brown  * If the specified character is lowercase, the uppercase value will
159bbf6f00cSJordan Brown  * be returned. Otherwise the original value will be returned.
160bbf6f00cSJordan Brown  */
161bbf6f00cSJordan Brown int
162bbf6f00cSJordan Brown smb_toupper(int c)
163bbf6f00cSJordan Brown {
164bbf6f00cSJordan Brown 	uint16_t mask = is_unicode ? 0xffff : 0xff;
165bbf6f00cSJordan Brown 
166bbf6f00cSJordan Brown 	return (current_codepage[c & mask].upper);
167bbf6f00cSJordan Brown }
168bbf6f00cSJordan Brown 
169bbf6f00cSJordan Brown /*
170bbf6f00cSJordan Brown  * Convert individual characters to their lowercase equivalent value.
171bbf6f00cSJordan Brown  * If the specified character is uppercase, the lowercase value will
172bbf6f00cSJordan Brown  * be returned. Otherwise the original value will be returned.
173bbf6f00cSJordan Brown  */
174bbf6f00cSJordan Brown int
175bbf6f00cSJordan Brown smb_tolower(int c)
176bbf6f00cSJordan Brown {
177bbf6f00cSJordan Brown 	uint16_t mask = is_unicode ? 0xffff : 0xff;
178bbf6f00cSJordan Brown 
179bbf6f00cSJordan Brown 	return (current_codepage[c & mask].lower);
180bbf6f00cSJordan Brown }
181bbf6f00cSJordan Brown 
182bbf6f00cSJordan Brown /*
183bbf6f00cSJordan Brown  * Convert a string to uppercase using the appropriate codepage. The
184bbf6f00cSJordan Brown  * string is converted in place. A pointer to the string is returned.
185bbf6f00cSJordan Brown  * There is an assumption here that uppercase and lowercase values
186bbf6f00cSJordan Brown  * always result encode to the same length.
187bbf6f00cSJordan Brown  */
188bbf6f00cSJordan Brown char *
189bbf6f00cSJordan Brown smb_strupr(char *s)
190bbf6f00cSJordan Brown {
191bbf6f00cSJordan Brown 	smb_wchar_t c;
192bbf6f00cSJordan Brown 	char *p = s;
193bbf6f00cSJordan Brown 
194bbf6f00cSJordan Brown 	while (*p) {
195bbf6f00cSJordan Brown 		if (smb_isascii(*p)) {
196bbf6f00cSJordan Brown 			*p = smb_toupper(*p);
197bbf6f00cSJordan Brown 			p++;
198bbf6f00cSJordan Brown 		} else {
199bbf6f00cSJordan Brown 			if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
200bbf6f00cSJordan Brown 				return (0);
201bbf6f00cSJordan Brown 
202bbf6f00cSJordan Brown 			if (c == 0)
203bbf6f00cSJordan Brown 				break;
204bbf6f00cSJordan Brown 
205bbf6f00cSJordan Brown 			c = smb_toupper(c);
206bbf6f00cSJordan Brown 			p += smb_wctomb(p, c);
207bbf6f00cSJordan Brown 		}
208bbf6f00cSJordan Brown 	}
209bbf6f00cSJordan Brown 
210bbf6f00cSJordan Brown 	return (s);
211bbf6f00cSJordan Brown }
212bbf6f00cSJordan Brown 
213bbf6f00cSJordan Brown /*
214bbf6f00cSJordan Brown  * Convert a string to lowercase using the appropriate codepage. The
215bbf6f00cSJordan Brown  * string is converted in place. A pointer to the string is returned.
216bbf6f00cSJordan Brown  * There is an assumption here that uppercase and lowercase values
217bbf6f00cSJordan Brown  * always result encode to the same length.
218bbf6f00cSJordan Brown  */
219bbf6f00cSJordan Brown char *
220bbf6f00cSJordan Brown smb_strlwr(char *s)
221bbf6f00cSJordan Brown {
222bbf6f00cSJordan Brown 	smb_wchar_t c;
223bbf6f00cSJordan Brown 	char *p = s;
224bbf6f00cSJordan Brown 
225bbf6f00cSJordan Brown 	while (*p) {
226bbf6f00cSJordan Brown 		if (smb_isascii(*p)) {
227bbf6f00cSJordan Brown 			*p = smb_tolower(*p);
228bbf6f00cSJordan Brown 			p++;
229bbf6f00cSJordan Brown 		} else {
230bbf6f00cSJordan Brown 			if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
231bbf6f00cSJordan Brown 				return (0);
232bbf6f00cSJordan Brown 
233bbf6f00cSJordan Brown 			if (c == 0)
234bbf6f00cSJordan Brown 				break;
235bbf6f00cSJordan Brown 
236bbf6f00cSJordan Brown 			c = smb_tolower(c);
237bbf6f00cSJordan Brown 			p += smb_wctomb(p, c);
238bbf6f00cSJordan Brown 		}
239bbf6f00cSJordan Brown 	}
240bbf6f00cSJordan Brown 
241bbf6f00cSJordan Brown 	return (s);
242bbf6f00cSJordan Brown }
243bbf6f00cSJordan Brown 
244bbf6f00cSJordan Brown /*
245bbf6f00cSJordan Brown  * Returns 1 if string contains NO uppercase chars 0 otherwise. However,
246bbf6f00cSJordan Brown  * -1 is returned if "s" is not a valid multi-byte string.
247bbf6f00cSJordan Brown  */
248bbf6f00cSJordan Brown int
249bbf6f00cSJordan Brown smb_isstrlwr(const char *s)
250bbf6f00cSJordan Brown {
251bbf6f00cSJordan Brown 	smb_wchar_t c;
252bbf6f00cSJordan Brown 	int n;
253bbf6f00cSJordan Brown 	const char *p = s;
254bbf6f00cSJordan Brown 
255bbf6f00cSJordan Brown 	while (*p) {
256bbf6f00cSJordan Brown 		if (smb_isascii(*p) && smb_isupper(*p))
257bbf6f00cSJordan Brown 			return (0);
258bbf6f00cSJordan Brown 		else {
259bbf6f00cSJordan Brown 			if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
260bbf6f00cSJordan Brown 				return (-1);
261bbf6f00cSJordan Brown 
262bbf6f00cSJordan Brown 			if (c == 0)
263bbf6f00cSJordan Brown 				break;
264bbf6f00cSJordan Brown 
265bbf6f00cSJordan Brown 			if (smb_isupper(c))
266bbf6f00cSJordan Brown 				return (0);
267bbf6f00cSJordan Brown 
268bbf6f00cSJordan Brown 			p += n;
269bbf6f00cSJordan Brown 		}
270bbf6f00cSJordan Brown 	}
271bbf6f00cSJordan Brown 
272bbf6f00cSJordan Brown 	return (1);
273bbf6f00cSJordan Brown }
274bbf6f00cSJordan Brown 
275bbf6f00cSJordan Brown /*
276bbf6f00cSJordan Brown  * Returns 1 if string contains NO lowercase chars 0 otherwise. However,
277bbf6f00cSJordan Brown  * -1 is returned if "s" is not a valid multi-byte string.
278bbf6f00cSJordan Brown  */
279bbf6f00cSJordan Brown int
280bbf6f00cSJordan Brown smb_isstrupr(const char *s)
281bbf6f00cSJordan Brown {
282bbf6f00cSJordan Brown 	smb_wchar_t c;
283bbf6f00cSJordan Brown 	int n;
284bbf6f00cSJordan Brown 	const char *p = s;
285bbf6f00cSJordan Brown 
286bbf6f00cSJordan Brown 	while (*p) {
287bbf6f00cSJordan Brown 		if (smb_isascii(*p) && smb_islower(*p))
288bbf6f00cSJordan Brown 			return (0);
289bbf6f00cSJordan Brown 		else {
290bbf6f00cSJordan Brown 			if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
291bbf6f00cSJordan Brown 				return (-1);
292bbf6f00cSJordan Brown 
293bbf6f00cSJordan Brown 			if (c == 0)
294bbf6f00cSJordan Brown 				break;
295bbf6f00cSJordan Brown 
296bbf6f00cSJordan Brown 			if (smb_islower(c))
297bbf6f00cSJordan Brown 				return (0);
298bbf6f00cSJordan Brown 
299bbf6f00cSJordan Brown 			p += n;
300bbf6f00cSJordan Brown 		}
301bbf6f00cSJordan Brown 	}
302bbf6f00cSJordan Brown 
303bbf6f00cSJordan Brown 	return (1);
304bbf6f00cSJordan Brown }
305bbf6f00cSJordan Brown 
306bbf6f00cSJordan Brown /*
307bbf6f00cSJordan Brown  * Compare the null-terminated strings s1 and s2 and return an integer
308bbf6f00cSJordan Brown  * greater than, equal to or less than 0 dependent on whether s1 is
309bbf6f00cSJordan Brown  * lexicographically greater than, equal to or less than s2 after
310bbf6f00cSJordan Brown  * translation of each character to lowercase.  The original strings
311bbf6f00cSJordan Brown  * are not modified.
312bbf6f00cSJordan Brown  *
313bbf6f00cSJordan Brown  * If n is non-zero, at most n bytes are compared.  Otherwise, the strings
314bbf6f00cSJordan Brown  * are compared until a null terminator is encountered.
315bbf6f00cSJordan Brown  *
316bbf6f00cSJordan Brown  * Out:    0 if strings are equal
317bbf6f00cSJordan Brown  *       < 0 if first string < second string
318bbf6f00cSJordan Brown  *       > 0 if first string > second string
319bbf6f00cSJordan Brown  */
320bbf6f00cSJordan Brown int
321bbf6f00cSJordan Brown smb_strcasecmp(const char *s1, const char *s2, size_t n)
322bbf6f00cSJordan Brown {
323bbf6f00cSJordan Brown 	int	err = 0;
324bbf6f00cSJordan Brown 	int	rc;
325bbf6f00cSJordan Brown 
326bbf6f00cSJordan Brown 	rc = u8_strcmp(s1, s2, n, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err);
327bbf6f00cSJordan Brown 	if (err != 0)
328bbf6f00cSJordan Brown 		return (-1);
329bbf6f00cSJordan Brown 	return (rc);
330bbf6f00cSJordan Brown }
331bbf6f00cSJordan Brown 
332bbf6f00cSJordan Brown /*
333bbf6f00cSJordan Brown  * First build a codepage based on cp_unicode.h.  Then build the unicode
334bbf6f00cSJordan Brown  * codepage from this interim codepage by copying the entries over while
335bbf6f00cSJordan Brown  * fixing them and filling in the gaps.
336bbf6f00cSJordan Brown  */
337bbf6f00cSJordan Brown static smb_codepage_t *
338bbf6f00cSJordan Brown smb_unicode_init(void)
339bbf6f00cSJordan Brown {
340bbf6f00cSJordan Brown 	smb_codepage_t	*unicode;
341bbf6f00cSJordan Brown 	uint32_t	a = 0;
342bbf6f00cSJordan Brown 	uint32_t	b = 0;
343bbf6f00cSJordan Brown 
344bbf6f00cSJordan Brown 	unicode = MEM_ZALLOC("unicode", sizeof (smb_codepage_t) << 16);
345bbf6f00cSJordan Brown 	if (unicode == NULL)
346bbf6f00cSJordan Brown 		return (NULL);
347bbf6f00cSJordan Brown 
348bbf6f00cSJordan Brown 	while (b != 0xffff) {
349bbf6f00cSJordan Brown 		/*
350bbf6f00cSJordan Brown 		 * If there is a gap in the standard,
351bbf6f00cSJordan Brown 		 * fill in the gap with no-case entries.
352bbf6f00cSJordan Brown 		 */
353bbf6f00cSJordan Brown 		if (UNICODE_N_ENTRIES <= a || a_unicode[a].val > b) {
354bbf6f00cSJordan Brown 			unicode[b].ctype = CODEPAGE_ISNONE;
355bbf6f00cSJordan Brown 			unicode[b].upper = (smb_wchar_t)b;
356bbf6f00cSJordan Brown 			unicode[b].lower = (smb_wchar_t)b;
357bbf6f00cSJordan Brown 			b++;
358bbf6f00cSJordan Brown 			continue;
359bbf6f00cSJordan Brown 		}
360bbf6f00cSJordan Brown 
361bbf6f00cSJordan Brown 		/*
362bbf6f00cSJordan Brown 		 * Copy the entry and fixup as required.
363bbf6f00cSJordan Brown 		 */
364bbf6f00cSJordan Brown 		switch (a_unicode[a].ctype) {
365bbf6f00cSJordan Brown 		case CODEPAGE_ISNONE:
366bbf6f00cSJordan Brown 			/*
367bbf6f00cSJordan Brown 			 * Replace 0xffff in upper/lower fields with its val.
368bbf6f00cSJordan Brown 			 */
369bbf6f00cSJordan Brown 			unicode[b].ctype = CODEPAGE_ISNONE;
370bbf6f00cSJordan Brown 			unicode[b].upper = (smb_wchar_t)b;
371bbf6f00cSJordan Brown 			unicode[b].lower = (smb_wchar_t)b;
372bbf6f00cSJordan Brown 			break;
373bbf6f00cSJordan Brown 		case CODEPAGE_ISUPPER:
374bbf6f00cSJordan Brown 			/*
375bbf6f00cSJordan Brown 			 * Some characters may have case yet not have
376bbf6f00cSJordan Brown 			 * case conversion.  Treat them as no-case.
377bbf6f00cSJordan Brown 			 */
378bbf6f00cSJordan Brown 			if (a_unicode[a].lower == 0xffff) {
379bbf6f00cSJordan Brown 				unicode[b].ctype = CODEPAGE_ISNONE;
380bbf6f00cSJordan Brown 				unicode[b].upper = (smb_wchar_t)b;
381bbf6f00cSJordan Brown 				unicode[b].lower = (smb_wchar_t)b;
382bbf6f00cSJordan Brown 			} else {
383bbf6f00cSJordan Brown 				unicode[b].ctype = CODEPAGE_ISUPPER;
384bbf6f00cSJordan Brown 				unicode[b].upper = (smb_wchar_t)b;
385bbf6f00cSJordan Brown 				unicode[b].lower = a_unicode[a].lower;
386bbf6f00cSJordan Brown 			}
387bbf6f00cSJordan Brown 			break;
388bbf6f00cSJordan Brown 		case CODEPAGE_ISLOWER:
389bbf6f00cSJordan Brown 			/*
390bbf6f00cSJordan Brown 			 * Some characters may have case yet not have
391bbf6f00cSJordan Brown 			 * case conversion.  Treat them as no-case.
392bbf6f00cSJordan Brown 			 */
393bbf6f00cSJordan Brown 			if (a_unicode[a].upper == 0xffff) {
394bbf6f00cSJordan Brown 				unicode[b].ctype = CODEPAGE_ISNONE;
395bbf6f00cSJordan Brown 				unicode[b].upper = (smb_wchar_t)b;
396bbf6f00cSJordan Brown 				unicode[b].lower = (smb_wchar_t)b;
397bbf6f00cSJordan Brown 			} else {
398bbf6f00cSJordan Brown 				unicode[b].ctype = CODEPAGE_ISLOWER;
399bbf6f00cSJordan Brown 				unicode[b].upper = a_unicode[a].upper;
400bbf6f00cSJordan Brown 				unicode[b].lower = (smb_wchar_t)b;
401bbf6f00cSJordan Brown 			}
402bbf6f00cSJordan Brown 			break;
403bbf6f00cSJordan Brown 		default:
404bbf6f00cSJordan Brown 			MEM_FREE("unicode", unicode);
405bbf6f00cSJordan Brown 			return (NULL);
406bbf6f00cSJordan Brown 		}
407bbf6f00cSJordan Brown 
408bbf6f00cSJordan Brown 		a++;
409bbf6f00cSJordan Brown 		b++;
410bbf6f00cSJordan Brown 	};
411bbf6f00cSJordan Brown 
412bbf6f00cSJordan Brown 	return (unicode);
413bbf6f00cSJordan Brown }
414*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
415*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
416*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Parse a UNC path (\\server\share\path) into its components.
417*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Although a standard UNC path starts with two '\', in DFS
418*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * all UNC paths start with one '\'. So, this function only
419*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * checks for one.
420*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
421*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * A valid UNC must at least contain two components i.e. server
422*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * and share. The path is parsed to:
423*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
424*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * unc_server	server or domain name with no leading/trailing '\'
425*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * unc_share	share name with no leading/trailing '\'
426*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * unc_path	relative path to the share with no leading/trailing '\'
427*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * 		it is valid for unc_path to be NULL.
428*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
429*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Upon successful return of this function, smb_unc_free()
430*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * MUST be called when returned 'unc' is no longer needed.
431*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
432*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Returns 0 on success, otherwise returns an errno code.
433*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
434*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
435*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_init(const char *path, smb_unc_t *unc)
436*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
437*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *p;
438*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
439*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (path == NULL || unc == NULL || (*path != '\\' && *path != '/'))
440*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
441*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
442*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	bzero(unc, sizeof (smb_unc_t));
443*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
444*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #ifdef _KERNEL
445*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_buf = smb_mem_strdup(path);
446*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #else
447*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((unc->unc_buf = strdup(path)) == NULL)
448*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (ENOMEM);
449*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #endif
450*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
451*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) strsubst(unc->unc_buf, '\\', '/');
452*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) strcanon(unc->unc_buf, "/");
453*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
454*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_server = unc->unc_buf + 1;
455*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (*unc->unc_server == '\0') {
456*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_unc_free(unc);
457*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
458*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
459*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
460*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((p = strchr(unc->unc_server, '/')) == NULL) {
461*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_unc_free(unc);
462*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
463*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
464*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
465*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	*p++ = '\0';
466*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_share = p;
467*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
468*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (*unc->unc_share == '\0') {
469*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_unc_free(unc);
470*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
471*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
472*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
473*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_path = strchr(unc->unc_share, '/');
474*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((p = unc->unc_path) == NULL)
475*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (0);
476*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
477*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_path++;
478*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	*p = '\0';
479*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
480*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	/* remove the last '/' if any */
481*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((p = strchr(unc->unc_path, '\0')) != NULL) {
482*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (*(--p) == '/')
483*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			*p = '\0';
484*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
485*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
486*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
487*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
488*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
489*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
490*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(smb_unc_t *unc)
491*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
492*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (unc == NULL)
493*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
494*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
495*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #ifdef _KERNEL
496*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(unc->unc_buf);
497*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #else
498*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	free(unc->unc_buf);
499*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #endif
500*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	unc->unc_buf = NULL;
501*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
502