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 /*
229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23da6c28aaSamw * Use is subject to license terms.
24*7206bf49SGordon Ross *
25*7206bf49SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26da6c28aaSamw */
27da6c28aaSamw
28*7206bf49SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
29da6c28aaSamw #include <sys/types.h>
30da6c28aaSamw #include <sys/sunddi.h>
31da6c28aaSamw #else
32bbf6f00cSJordan Brown #include <stdio.h>
33da6c28aaSamw #include <stdlib.h>
34da6c28aaSamw #include <string.h>
35da6c28aaSamw #include <strings.h>
36da6c28aaSamw #endif
37bbf6f00cSJordan Brown #include <sys/u8_textprep.h>
38bbf6f00cSJordan Brown #include <smbsrv/alloc.h>
399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <sys/errno.h>
40da6c28aaSamw #include <smbsrv/string.h>
41bbf6f00cSJordan Brown #include <smbsrv/cp_usascii.h>
42bbf6f00cSJordan Brown #include <smbsrv/cp_unicode.h>
43da6c28aaSamw
44bbf6f00cSJordan Brown #define UNICODE_N_ENTRIES (sizeof (a_unicode) / sizeof (a_unicode[0]))
45bbf6f00cSJordan Brown
46bbf6f00cSJordan Brown /*
47bbf6f00cSJordan Brown * Global pointer to the current codepage: defaults to ASCII,
48bbf6f00cSJordan Brown * and a flag indicating whether the codepage is Unicode or ASCII.
49bbf6f00cSJordan Brown */
50ae240eb8SGordon Ross static const smb_codepage_t *current_codepage = usascii_codepage;
51bbf6f00cSJordan Brown static boolean_t is_unicode = B_FALSE;
52bbf6f00cSJordan Brown
53bbf6f00cSJordan Brown static smb_codepage_t *smb_unicode_init(void);
54da6c28aaSamw
55da6c28aaSamw /*
56da6c28aaSamw * strsubst
57da6c28aaSamw *
58da6c28aaSamw * Scan a string replacing all occurrences of orgchar with newchar.
59da6c28aaSamw * Returns a pointer to s, or null of s is null.
60da6c28aaSamw */
61da6c28aaSamw char *
strsubst(char * s,char orgchar,char newchar)62da6c28aaSamw strsubst(char *s, char orgchar, char newchar)
63da6c28aaSamw {
64da6c28aaSamw char *p = s;
65da6c28aaSamw
66da6c28aaSamw if (p == 0)
67da6c28aaSamw return (0);
68da6c28aaSamw
69da6c28aaSamw while (*p) {
70da6c28aaSamw if (*p == orgchar)
71da6c28aaSamw *p = newchar;
72da6c28aaSamw ++p;
73da6c28aaSamw }
74da6c28aaSamw
75da6c28aaSamw return (s);
76da6c28aaSamw }
77da6c28aaSamw
78da6c28aaSamw /*
79da6c28aaSamw * strcanon
80da6c28aaSamw *
81da6c28aaSamw * Normalize a string by reducing all the repeated characters in
82da6c28aaSamw * buf as defined by class. For example;
83da6c28aaSamw *
84da6c28aaSamw * char *buf = strdup("/d1//d2//d3\\\\d4\\\\f1.txt");
85da6c28aaSamw * strcanon(buf, "/\\");
86da6c28aaSamw *
87da6c28aaSamw * Would result in buf containing the following string:
88da6c28aaSamw *
89da6c28aaSamw * /d1/d2/d3\d4\f1.txt
90da6c28aaSamw *
91da6c28aaSamw * This function modifies the contents of buf in place and returns
92da6c28aaSamw * a pointer to buf.
93da6c28aaSamw */
94da6c28aaSamw char *
strcanon(char * buf,const char * class)95da6c28aaSamw strcanon(char *buf, const char *class)
96da6c28aaSamw {
97da6c28aaSamw char *p = buf;
98da6c28aaSamw char *q = buf;
99da6c28aaSamw char *r;
100da6c28aaSamw
101da6c28aaSamw while (*p) {
102da6c28aaSamw *q++ = *p;
103da6c28aaSamw
104da6c28aaSamw if ((r = strchr(class, *p)) != 0) {
105da6c28aaSamw while (*p == *r)
106da6c28aaSamw ++p;
107da6c28aaSamw } else
108da6c28aaSamw ++p;
109da6c28aaSamw }
110da6c28aaSamw
111da6c28aaSamw *q = '\0';
112da6c28aaSamw return (buf);
113da6c28aaSamw }
114bbf6f00cSJordan Brown
115bbf6f00cSJordan Brown void
smb_codepage_init(void)116bbf6f00cSJordan Brown smb_codepage_init(void)
117bbf6f00cSJordan Brown {
118ae240eb8SGordon Ross const smb_codepage_t *cp;
119bbf6f00cSJordan Brown
120bbf6f00cSJordan Brown if (is_unicode)
121bbf6f00cSJordan Brown return;
122bbf6f00cSJordan Brown
123bbf6f00cSJordan Brown if ((cp = smb_unicode_init()) != NULL) {
124bbf6f00cSJordan Brown current_codepage = cp;
125bbf6f00cSJordan Brown is_unicode = B_TRUE;
126bbf6f00cSJordan Brown } else {
127bbf6f00cSJordan Brown current_codepage = usascii_codepage;
128bbf6f00cSJordan Brown is_unicode = B_FALSE;
129bbf6f00cSJordan Brown }
130bbf6f00cSJordan Brown }
131bbf6f00cSJordan Brown
132bbf6f00cSJordan Brown /*
133bbf6f00cSJordan Brown * Determine whether or not a character is an uppercase character.
134bbf6f00cSJordan Brown * This function operates on the current codepage table. Returns
135bbf6f00cSJordan Brown * non-zero if the character is uppercase. Otherwise returns zero.
136bbf6f00cSJordan Brown */
137bbf6f00cSJordan Brown int
smb_isupper(int c)138bbf6f00cSJordan Brown smb_isupper(int c)
139bbf6f00cSJordan Brown {
140bbf6f00cSJordan Brown uint16_t mask = is_unicode ? 0xffff : 0xff;
141bbf6f00cSJordan Brown
142bbf6f00cSJordan Brown return (current_codepage[c & mask].ctype & CODEPAGE_ISUPPER);
143bbf6f00cSJordan Brown }
144bbf6f00cSJordan Brown
145bbf6f00cSJordan Brown /*
146bbf6f00cSJordan Brown * Determine whether or not a character is an lowercase character.
147bbf6f00cSJordan Brown * This function operates on the current codepage table. Returns
148bbf6f00cSJordan Brown * non-zero if the character is lowercase. Otherwise returns zero.
149bbf6f00cSJordan Brown */
150bbf6f00cSJordan Brown int
smb_islower(int c)151bbf6f00cSJordan Brown smb_islower(int c)
152bbf6f00cSJordan Brown {
153bbf6f00cSJordan Brown uint16_t mask = is_unicode ? 0xffff : 0xff;
154bbf6f00cSJordan Brown
155bbf6f00cSJordan Brown return (current_codepage[c & mask].ctype & CODEPAGE_ISLOWER);
156bbf6f00cSJordan Brown }
157bbf6f00cSJordan Brown
158bbf6f00cSJordan Brown /*
159bbf6f00cSJordan Brown * Convert individual characters to their uppercase equivalent value.
160bbf6f00cSJordan Brown * If the specified character is lowercase, the uppercase value will
161bbf6f00cSJordan Brown * be returned. Otherwise the original value will be returned.
162bbf6f00cSJordan Brown */
163bbf6f00cSJordan Brown int
smb_toupper(int c)164bbf6f00cSJordan Brown smb_toupper(int c)
165bbf6f00cSJordan Brown {
166bbf6f00cSJordan Brown uint16_t mask = is_unicode ? 0xffff : 0xff;
167bbf6f00cSJordan Brown
168bbf6f00cSJordan Brown return (current_codepage[c & mask].upper);
169bbf6f00cSJordan Brown }
170bbf6f00cSJordan Brown
171bbf6f00cSJordan Brown /*
172bbf6f00cSJordan Brown * Convert individual characters to their lowercase equivalent value.
173bbf6f00cSJordan Brown * If the specified character is uppercase, the lowercase value will
174bbf6f00cSJordan Brown * be returned. Otherwise the original value will be returned.
175bbf6f00cSJordan Brown */
176bbf6f00cSJordan Brown int
smb_tolower(int c)177bbf6f00cSJordan Brown smb_tolower(int c)
178bbf6f00cSJordan Brown {
179bbf6f00cSJordan Brown uint16_t mask = is_unicode ? 0xffff : 0xff;
180bbf6f00cSJordan Brown
181bbf6f00cSJordan Brown return (current_codepage[c & mask].lower);
182bbf6f00cSJordan Brown }
183bbf6f00cSJordan Brown
184bbf6f00cSJordan Brown /*
185bbf6f00cSJordan Brown * Convert a string to uppercase using the appropriate codepage. The
186bbf6f00cSJordan Brown * string is converted in place. A pointer to the string is returned.
187bbf6f00cSJordan Brown * There is an assumption here that uppercase and lowercase values
188bbf6f00cSJordan Brown * always result encode to the same length.
189bbf6f00cSJordan Brown */
190bbf6f00cSJordan Brown char *
smb_strupr(char * s)191bbf6f00cSJordan Brown smb_strupr(char *s)
192bbf6f00cSJordan Brown {
193bbf6f00cSJordan Brown smb_wchar_t c;
194bbf6f00cSJordan Brown char *p = s;
195bbf6f00cSJordan Brown
196bbf6f00cSJordan Brown while (*p) {
197bbf6f00cSJordan Brown if (smb_isascii(*p)) {
198bbf6f00cSJordan Brown *p = smb_toupper(*p);
199bbf6f00cSJordan Brown p++;
200bbf6f00cSJordan Brown } else {
201bbf6f00cSJordan Brown if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
202bbf6f00cSJordan Brown return (0);
203bbf6f00cSJordan Brown
204bbf6f00cSJordan Brown if (c == 0)
205bbf6f00cSJordan Brown break;
206bbf6f00cSJordan Brown
207bbf6f00cSJordan Brown c = smb_toupper(c);
208bbf6f00cSJordan Brown p += smb_wctomb(p, c);
209bbf6f00cSJordan Brown }
210bbf6f00cSJordan Brown }
211bbf6f00cSJordan Brown
212bbf6f00cSJordan Brown return (s);
213bbf6f00cSJordan Brown }
214bbf6f00cSJordan Brown
215bbf6f00cSJordan Brown /*
216bbf6f00cSJordan Brown * Convert a string to lowercase using the appropriate codepage. The
217bbf6f00cSJordan Brown * string is converted in place. A pointer to the string is returned.
218bbf6f00cSJordan Brown * There is an assumption here that uppercase and lowercase values
219bbf6f00cSJordan Brown * always result encode to the same length.
220bbf6f00cSJordan Brown */
221bbf6f00cSJordan Brown char *
smb_strlwr(char * s)222bbf6f00cSJordan Brown smb_strlwr(char *s)
223bbf6f00cSJordan Brown {
224bbf6f00cSJordan Brown smb_wchar_t c;
225bbf6f00cSJordan Brown char *p = s;
226bbf6f00cSJordan Brown
227bbf6f00cSJordan Brown while (*p) {
228bbf6f00cSJordan Brown if (smb_isascii(*p)) {
229bbf6f00cSJordan Brown *p = smb_tolower(*p);
230bbf6f00cSJordan Brown p++;
231bbf6f00cSJordan Brown } else {
232bbf6f00cSJordan Brown if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
233bbf6f00cSJordan Brown return (0);
234bbf6f00cSJordan Brown
235bbf6f00cSJordan Brown if (c == 0)
236bbf6f00cSJordan Brown break;
237bbf6f00cSJordan Brown
238bbf6f00cSJordan Brown c = smb_tolower(c);
239bbf6f00cSJordan Brown p += smb_wctomb(p, c);
240bbf6f00cSJordan Brown }
241bbf6f00cSJordan Brown }
242bbf6f00cSJordan Brown
243bbf6f00cSJordan Brown return (s);
244bbf6f00cSJordan Brown }
245bbf6f00cSJordan Brown
246bbf6f00cSJordan Brown /*
247bbf6f00cSJordan Brown * Returns 1 if string contains NO uppercase chars 0 otherwise. However,
248bbf6f00cSJordan Brown * -1 is returned if "s" is not a valid multi-byte string.
249bbf6f00cSJordan Brown */
250bbf6f00cSJordan Brown int
smb_isstrlwr(const char * s)251bbf6f00cSJordan Brown smb_isstrlwr(const char *s)
252bbf6f00cSJordan Brown {
253bbf6f00cSJordan Brown smb_wchar_t c;
254bbf6f00cSJordan Brown int n;
255bbf6f00cSJordan Brown const char *p = s;
256bbf6f00cSJordan Brown
257bbf6f00cSJordan Brown while (*p) {
258bbf6f00cSJordan Brown if (smb_isascii(*p) && smb_isupper(*p))
259bbf6f00cSJordan Brown return (0);
260bbf6f00cSJordan Brown else {
261bbf6f00cSJordan Brown if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
262bbf6f00cSJordan Brown return (-1);
263bbf6f00cSJordan Brown
264bbf6f00cSJordan Brown if (c == 0)
265bbf6f00cSJordan Brown break;
266bbf6f00cSJordan Brown
267bbf6f00cSJordan Brown if (smb_isupper(c))
268bbf6f00cSJordan Brown return (0);
269bbf6f00cSJordan Brown
270bbf6f00cSJordan Brown p += n;
271bbf6f00cSJordan Brown }
272bbf6f00cSJordan Brown }
273bbf6f00cSJordan Brown
274bbf6f00cSJordan Brown return (1);
275bbf6f00cSJordan Brown }
276bbf6f00cSJordan Brown
277bbf6f00cSJordan Brown /*
278bbf6f00cSJordan Brown * Returns 1 if string contains NO lowercase chars 0 otherwise. However,
279bbf6f00cSJordan Brown * -1 is returned if "s" is not a valid multi-byte string.
280bbf6f00cSJordan Brown */
281bbf6f00cSJordan Brown int
smb_isstrupr(const char * s)282bbf6f00cSJordan Brown smb_isstrupr(const char *s)
283bbf6f00cSJordan Brown {
284bbf6f00cSJordan Brown smb_wchar_t c;
285bbf6f00cSJordan Brown int n;
286bbf6f00cSJordan Brown const char *p = s;
287bbf6f00cSJordan Brown
288bbf6f00cSJordan Brown while (*p) {
289bbf6f00cSJordan Brown if (smb_isascii(*p) && smb_islower(*p))
290bbf6f00cSJordan Brown return (0);
291bbf6f00cSJordan Brown else {
292bbf6f00cSJordan Brown if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
293bbf6f00cSJordan Brown return (-1);
294bbf6f00cSJordan Brown
295bbf6f00cSJordan Brown if (c == 0)
296bbf6f00cSJordan Brown break;
297bbf6f00cSJordan Brown
298bbf6f00cSJordan Brown if (smb_islower(c))
299bbf6f00cSJordan Brown return (0);
300bbf6f00cSJordan Brown
301bbf6f00cSJordan Brown p += n;
302bbf6f00cSJordan Brown }
303bbf6f00cSJordan Brown }
304bbf6f00cSJordan Brown
305bbf6f00cSJordan Brown return (1);
306bbf6f00cSJordan Brown }
307bbf6f00cSJordan Brown
308bbf6f00cSJordan Brown /*
309bbf6f00cSJordan Brown * Compare the null-terminated strings s1 and s2 and return an integer
310bbf6f00cSJordan Brown * greater than, equal to or less than 0 dependent on whether s1 is
311bbf6f00cSJordan Brown * lexicographically greater than, equal to or less than s2 after
312bbf6f00cSJordan Brown * translation of each character to lowercase. The original strings
313bbf6f00cSJordan Brown * are not modified.
314bbf6f00cSJordan Brown *
315bbf6f00cSJordan Brown * If n is non-zero, at most n bytes are compared. Otherwise, the strings
316bbf6f00cSJordan Brown * are compared until a null terminator is encountered.
317bbf6f00cSJordan Brown *
318bbf6f00cSJordan Brown * Out: 0 if strings are equal
319bbf6f00cSJordan Brown * < 0 if first string < second string
320bbf6f00cSJordan Brown * > 0 if first string > second string
321bbf6f00cSJordan Brown */
322bbf6f00cSJordan Brown int
smb_strcasecmp(const char * s1,const char * s2,size_t n)323bbf6f00cSJordan Brown smb_strcasecmp(const char *s1, const char *s2, size_t n)
324bbf6f00cSJordan Brown {
325bbf6f00cSJordan Brown int err = 0;
326bbf6f00cSJordan Brown int rc;
327bbf6f00cSJordan Brown
328bbf6f00cSJordan Brown rc = u8_strcmp(s1, s2, n, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err);
329bbf6f00cSJordan Brown if (err != 0)
330bbf6f00cSJordan Brown return (-1);
331bbf6f00cSJordan Brown return (rc);
332bbf6f00cSJordan Brown }
333bbf6f00cSJordan Brown
334bbf6f00cSJordan Brown /*
335bbf6f00cSJordan Brown * First build a codepage based on cp_unicode.h. Then build the unicode
336bbf6f00cSJordan Brown * codepage from this interim codepage by copying the entries over while
337bbf6f00cSJordan Brown * fixing them and filling in the gaps.
338bbf6f00cSJordan Brown */
339bbf6f00cSJordan Brown static smb_codepage_t *
smb_unicode_init(void)340bbf6f00cSJordan Brown smb_unicode_init(void)
341bbf6f00cSJordan Brown {
342bbf6f00cSJordan Brown smb_codepage_t *unicode;
343bbf6f00cSJordan Brown uint32_t a = 0;
344bbf6f00cSJordan Brown uint32_t b = 0;
345bbf6f00cSJordan Brown
346bbf6f00cSJordan Brown unicode = MEM_ZALLOC("unicode", sizeof (smb_codepage_t) << 16);
347bbf6f00cSJordan Brown if (unicode == NULL)
348bbf6f00cSJordan Brown return (NULL);
349bbf6f00cSJordan Brown
350bbf6f00cSJordan Brown while (b != 0xffff) {
351bbf6f00cSJordan Brown /*
352bbf6f00cSJordan Brown * If there is a gap in the standard,
353bbf6f00cSJordan Brown * fill in the gap with no-case entries.
354bbf6f00cSJordan Brown */
355bbf6f00cSJordan Brown if (UNICODE_N_ENTRIES <= a || a_unicode[a].val > b) {
356bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISNONE;
357bbf6f00cSJordan Brown unicode[b].upper = (smb_wchar_t)b;
358bbf6f00cSJordan Brown unicode[b].lower = (smb_wchar_t)b;
359bbf6f00cSJordan Brown b++;
360bbf6f00cSJordan Brown continue;
361bbf6f00cSJordan Brown }
362bbf6f00cSJordan Brown
363bbf6f00cSJordan Brown /*
364bbf6f00cSJordan Brown * Copy the entry and fixup as required.
365bbf6f00cSJordan Brown */
366bbf6f00cSJordan Brown switch (a_unicode[a].ctype) {
367bbf6f00cSJordan Brown case CODEPAGE_ISNONE:
368bbf6f00cSJordan Brown /*
369bbf6f00cSJordan Brown * Replace 0xffff in upper/lower fields with its val.
370bbf6f00cSJordan Brown */
371bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISNONE;
372bbf6f00cSJordan Brown unicode[b].upper = (smb_wchar_t)b;
373bbf6f00cSJordan Brown unicode[b].lower = (smb_wchar_t)b;
374bbf6f00cSJordan Brown break;
375bbf6f00cSJordan Brown case CODEPAGE_ISUPPER:
376bbf6f00cSJordan Brown /*
377bbf6f00cSJordan Brown * Some characters may have case yet not have
378bbf6f00cSJordan Brown * case conversion. Treat them as no-case.
379bbf6f00cSJordan Brown */
380bbf6f00cSJordan Brown if (a_unicode[a].lower == 0xffff) {
381bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISNONE;
382bbf6f00cSJordan Brown unicode[b].upper = (smb_wchar_t)b;
383bbf6f00cSJordan Brown unicode[b].lower = (smb_wchar_t)b;
384bbf6f00cSJordan Brown } else {
385bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISUPPER;
386bbf6f00cSJordan Brown unicode[b].upper = (smb_wchar_t)b;
387bbf6f00cSJordan Brown unicode[b].lower = a_unicode[a].lower;
388bbf6f00cSJordan Brown }
389bbf6f00cSJordan Brown break;
390bbf6f00cSJordan Brown case CODEPAGE_ISLOWER:
391bbf6f00cSJordan Brown /*
392bbf6f00cSJordan Brown * Some characters may have case yet not have
393bbf6f00cSJordan Brown * case conversion. Treat them as no-case.
394bbf6f00cSJordan Brown */
395bbf6f00cSJordan Brown if (a_unicode[a].upper == 0xffff) {
396bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISNONE;
397bbf6f00cSJordan Brown unicode[b].upper = (smb_wchar_t)b;
398bbf6f00cSJordan Brown unicode[b].lower = (smb_wchar_t)b;
399bbf6f00cSJordan Brown } else {
400bbf6f00cSJordan Brown unicode[b].ctype = CODEPAGE_ISLOWER;
401bbf6f00cSJordan Brown unicode[b].upper = a_unicode[a].upper;
402bbf6f00cSJordan Brown unicode[b].lower = (smb_wchar_t)b;
403bbf6f00cSJordan Brown }
404bbf6f00cSJordan Brown break;
405bbf6f00cSJordan Brown default:
406bbf6f00cSJordan Brown MEM_FREE("unicode", unicode);
407bbf6f00cSJordan Brown return (NULL);
408bbf6f00cSJordan Brown }
409bbf6f00cSJordan Brown
410bbf6f00cSJordan Brown a++;
411bbf6f00cSJordan Brown b++;
412bbf6f00cSJordan Brown };
413bbf6f00cSJordan Brown
414bbf6f00cSJordan Brown return (unicode);
415bbf6f00cSJordan Brown }
4169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
4189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Parse a UNC path (\\server\share\path) into its components.
4199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Although a standard UNC path starts with two '\', in DFS
4209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * all UNC paths start with one '\'. So, this function only
4219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * checks for one.
4229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
4239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * A valid UNC must at least contain two components i.e. server
4249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * and share. The path is parsed to:
4259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
4269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * unc_server server or domain name with no leading/trailing '\'
4279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * unc_share share name with no leading/trailing '\'
4289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * unc_path relative path to the share with no leading/trailing '\'
4299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * it is valid for unc_path to be NULL.
4309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
4319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Upon successful return of this function, smb_unc_free()
4329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * MUST be called when returned 'unc' is no longer needed.
4339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
4349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Returns 0 on success, otherwise returns an errno code.
4359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
4369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_unc_init(const char * path,smb_unc_t * unc)4379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_init(const char *path, smb_unc_t *unc)
4389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *p;
4409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (path == NULL || unc == NULL || (*path != '\\' && *path != '/'))
4429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EINVAL);
4439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States bzero(unc, sizeof (smb_unc_t));
4459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
446*7206bf49SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
4479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_buf = smb_mem_strdup(path);
4489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #else
4499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((unc->unc_buf = strdup(path)) == NULL)
4509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (ENOMEM);
4519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #endif
4529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) strsubst(unc->unc_buf, '\\', '/');
4549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) strcanon(unc->unc_buf, "/");
4559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_server = unc->unc_buf + 1;
4579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (*unc->unc_server == '\0') {
4589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(unc);
4599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EINVAL);
4609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((p = strchr(unc->unc_server, '/')) == NULL) {
4639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(unc);
4649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EINVAL);
4659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *p++ = '\0';
4689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_share = p;
4699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (*unc->unc_share == '\0') {
4719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(unc);
4729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EINVAL);
4739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_path = strchr(unc->unc_share, '/');
4769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((p = unc->unc_path) == NULL)
4779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (0);
4789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_path++;
4809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *p = '\0';
4819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* remove the last '/' if any */
4839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((p = strchr(unc->unc_path, '\0')) != NULL) {
4849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (*(--p) == '/')
4859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *p = '\0';
4869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (0);
4899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
4909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
4919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_unc_free(smb_unc_t * unc)4929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(smb_unc_t *unc)
4939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
4949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (unc == NULL)
4959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
4969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
497*7206bf49SGordon Ross #if defined(_KERNEL) || defined(_FAKE_KERNEL)
4989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(unc->unc_buf);
4999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #else
5009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States free(unc->unc_buf);
5019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #endif
5029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States unc->unc_buf = NULL;
5039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
504