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