smb_string.c revision b819cea2f73f98c5662230cc9affc8cc84f77fcf
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#endif
#include <sys/u8_textprep.h>
#include <smbsrv/cp_usascii.h>
#include <smbsrv/cp_unicode.h>
/*
* Global pointer to the current codepage: defaults to ASCII,
* and a flag indicating whether the codepage is Unicode or ASCII.
*/
static smb_codepage_t *smb_unicode_init(void);
/*
* strsubst
*
* Scan a string replacing all occurrences of orgchar with newchar.
* Returns a pointer to s, or null of s is null.
*/
char *
{
char *p = s;
if (p == 0)
return (0);
while (*p) {
if (*p == orgchar)
*p = newchar;
++p;
}
return (s);
}
/*
* strcanon
*
* Normalize a string by reducing all the repeated characters in
* buf as defined by class. For example;
*
* char *buf = strdup("/d1//d2//d3\\\\d4\\\\f1.txt");
* strcanon(buf, "/\\");
*
* Would result in buf containing the following string:
*
*
* This function modifies the contents of buf in place and returns
* a pointer to buf.
*/
char *
{
char *p = buf;
char *q = buf;
char *r;
while (*p) {
*q++ = *p;
while (*p == *r)
++p;
} else
++p;
}
*q = '\0';
return (buf);
}
void
smb_codepage_init(void)
{
const smb_codepage_t *cp;
if (is_unicode)
return;
is_unicode = B_TRUE;
} else {
}
}
/*
* Determine whether or not a character is an uppercase character.
* This function operates on the current codepage table. Returns
* non-zero if the character is uppercase. Otherwise returns zero.
*/
int
smb_isupper(int c)
{
}
/*
* Determine whether or not a character is an lowercase character.
* This function operates on the current codepage table. Returns
* non-zero if the character is lowercase. Otherwise returns zero.
*/
int
smb_islower(int c)
{
}
/*
* Convert individual characters to their uppercase equivalent value.
* If the specified character is lowercase, the uppercase value will
* be returned. Otherwise the original value will be returned.
*/
int
smb_toupper(int c)
{
}
/*
* Convert individual characters to their lowercase equivalent value.
* If the specified character is uppercase, the lowercase value will
* be returned. Otherwise the original value will be returned.
*/
int
smb_tolower(int c)
{
}
/*
* Convert a string to uppercase using the appropriate codepage. The
* string is converted in place. A pointer to the string is returned.
* There is an assumption here that uppercase and lowercase values
* always result encode to the same length.
*/
char *
smb_strupr(char *s)
{
smb_wchar_t c;
char *p = s;
while (*p) {
if (smb_isascii(*p)) {
*p = smb_toupper(*p);
p++;
} else {
if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
return (0);
if (c == 0)
break;
c = smb_toupper(c);
p += smb_wctomb(p, c);
}
}
return (s);
}
/*
* Convert a string to lowercase using the appropriate codepage. The
* string is converted in place. A pointer to the string is returned.
* There is an assumption here that uppercase and lowercase values
* always result encode to the same length.
*/
char *
smb_strlwr(char *s)
{
smb_wchar_t c;
char *p = s;
while (*p) {
if (smb_isascii(*p)) {
*p = smb_tolower(*p);
p++;
} else {
if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0)
return (0);
if (c == 0)
break;
c = smb_tolower(c);
p += smb_wctomb(p, c);
}
}
return (s);
}
/*
* Returns 1 if string contains NO uppercase chars 0 otherwise. However,
* -1 is returned if "s" is not a valid multi-byte string.
*/
int
smb_isstrlwr(const char *s)
{
smb_wchar_t c;
int n;
const char *p = s;
while (*p) {
if (smb_isascii(*p) && smb_isupper(*p))
return (0);
else {
if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
return (-1);
if (c == 0)
break;
if (smb_isupper(c))
return (0);
p += n;
}
}
return (1);
}
/*
* Returns 1 if string contains NO lowercase chars 0 otherwise. However,
* -1 is returned if "s" is not a valid multi-byte string.
*/
int
smb_isstrupr(const char *s)
{
smb_wchar_t c;
int n;
const char *p = s;
while (*p) {
if (smb_isascii(*p) && smb_islower(*p))
return (0);
else {
if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0)
return (-1);
if (c == 0)
break;
if (smb_islower(c))
return (0);
p += n;
}
}
return (1);
}
/*
* Compare the null-terminated strings s1 and s2 and return an integer
* greater than, equal to or less than 0 dependent on whether s1 is
* lexicographically greater than, equal to or less than s2 after
* translation of each character to lowercase. The original strings
* are not modified.
*
* If n is non-zero, at most n bytes are compared. Otherwise, the strings
* are compared until a null terminator is encountered.
*
* Out: 0 if strings are equal
* < 0 if first string < second string
* > 0 if first string > second string
*/
int
{
int err = 0;
int rc;
if (err != 0)
return (-1);
return (rc);
}
/*
* First build a codepage based on cp_unicode.h. Then build the unicode
* codepage from this interim codepage by copying the entries over while
* fixing them and filling in the gaps.
*/
static smb_codepage_t *
smb_unicode_init(void)
{
uint32_t a = 0;
uint32_t b = 0;
return (NULL);
while (b != 0xffff) {
/*
* If there is a gap in the standard,
* fill in the gap with no-case entries.
*/
b++;
continue;
}
/*
* Copy the entry and fixup as required.
*/
case CODEPAGE_ISNONE:
/*
*/
break;
case CODEPAGE_ISUPPER:
/*
* Some characters may have case yet not have
* case conversion. Treat them as no-case.
*/
} else {
}
break;
case CODEPAGE_ISLOWER:
/*
* Some characters may have case yet not have
* case conversion. Treat them as no-case.
*/
} else {
}
break;
default:
return (NULL);
}
a++;
b++;
};
return (unicode);
}
/*
* Parse a UNC path (\\server\share\path) into its components.
* Although a standard UNC path starts with two '\', in DFS
* all UNC paths start with one '\'. So, this function only
* checks for one.
*
* A valid UNC must at least contain two components i.e. server
* and share. The path is parsed to:
*
* it is valid for unc_path to be NULL.
*
* Upon successful return of this function, smb_unc_free()
* MUST be called when returned 'unc' is no longer needed.
*
* Returns 0 on success, otherwise returns an errno code.
*/
int
{
char *p;
return (EINVAL);
#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#else
return (ENOMEM);
#endif
return (EINVAL);
}
return (EINVAL);
}
*p++ = '\0';
return (EINVAL);
}
return (0);
*p = '\0';
/* remove the last '/' if any */
if (*(--p) == '/')
*p = '\0';
}
return (0);
}
void
{
return;
#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#else
#endif
}