summaryrefslogtreecommitdiff
path: root/source3/modules/charset_macosxfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/modules/charset_macosxfs.c')
-rw-r--r--source3/modules/charset_macosxfs.c604
1 files changed, 0 insertions, 604 deletions
diff --git a/source3/modules/charset_macosxfs.c b/source3/modules/charset_macosxfs.c
deleted file mode 100644
index 8c2fdc7776..0000000000
--- a/source3/modules/charset_macosxfs.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Samba charset module for Mac OS X/Darwin
- Copyright (C) Benjamin Riefenstahl 2003
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * modules/charset_macosxfs.c
- *
- * A Samba charset module to use on Mac OS X/Darwin as the filesystem
- * and display encoding.
- *
- * Actually two implementations are provided here. The default
- * implementation is based on the official CFString API. The other is
- * based on internal CFString APIs as defined in the OpenDarwin
- * source.
- */
-
-#include "includes.h"
-
-/*
- * Include OS frameworks. These are only needed in this module.
- */
-#include <CoreFoundation/CFString.h>
-
-/*
- * See if autoconf has found us the internal headers in some form.
- */
-#if HAVE_COREFOUNDATION_CFSTRINGENCODINGCONVERTER_H
-# include <CoreFoundation/CFStringEncodingConverter.h>
-# include <CoreFoundation/CFUnicodePrecomposition.h>
-# define USE_INTERNAL_API 1
-#elif HAVE_CFSTRINGENCODINGCONVERTER_H
-# include <CFStringEncodingConverter.h>
-# include <CFUnicodePrecomposition.h>
-# define USE_INTERNAL_API 1
-#endif
-
-/*
- * Compile time configuration: Do we want debug output?
- */
-/* #define DEBUG_STRINGS 1 */
-
-/*
- * A simple, but efficient memory provider for our buffers.
- */
-static inline void *resize_buffer (void *buffer, size_t *size, size_t newsize)
-{
- if (newsize > *size) {
- *size = newsize + 128;
- buffer = SMB_REALLOC(buffer, *size);
- }
- return buffer;
-}
-
-/*
- * While there is a version of OpenDarwin for intel, the usual case is
- * big-endian PPC. So we need byte swapping to handle the
- * little-endian byte order of the network protocol. We also need an
- * additional dynamic buffer to do this work for incoming data blocks,
- * because we have to consider the original data as constant.
- *
- * We abstract the differences away by providing a simple facade with
- * these functions/macros:
- *
- * le_to_native(dst,src,len)
- * native_to_le(cp,len)
- * set_ucbuffer_with_le(buffer,bufsize,data,size)
- * set_ucbuffer_with_le_copy(buffer,bufsize,data,size,reserve)
- */
-#ifdef WORDS_BIGENDIAN
-
-static inline void swap_bytes (char * dst, const char * src, size_t len)
-{
- const char *srcend = src + len;
- while (src < srcend) {
- dst[0] = src[1];
- dst[1] = src[0];
- dst += 2;
- src += 2;
- }
-}
-static inline void swap_bytes_inplace (char * cp, size_t len)
-{
- char temp;
- char *end = cp + len;
- while (cp < end) {
- temp = cp[1];
- cp[1] = cp[0];
- cp[0] = temp;
- cp += 2;
- }
-}
-
-#define le_to_native(dst,src,len) swap_bytes(dst,src,len)
-#define native_to_le(cp,len) swap_bytes_inplace(cp,len)
-#define set_ucbuffer_with_le(buffer,bufsize,data,size) \
- set_ucbuffer_with_le_copy(buffer,bufsize,data,size,0)
-
-#else /* ! WORDS_BIGENDIAN */
-
-#define le_to_native(dst,src,len) memcpy(dst,src,len)
-#define native_to_le(cp,len) /* nothing */
-#define set_ucbuffer_with_le(buffer,bufsize,data,size) \
- (((void)(bufsize)),(UniChar*)(data))
-
-#endif
-
-static inline UniChar *set_ucbuffer_with_le_copy (
- UniChar *buffer, size_t *bufsize,
- const void *data, size_t size, size_t reserve)
-{
- buffer = resize_buffer(buffer, bufsize, size+reserve);
- le_to_native((char*)buffer,data,size);
- return buffer;
-}
-
-
-/*
- * A simple hexdump function for debugging error conditions.
- */
-#define debug_out(s) DEBUG(0,(s))
-
-#ifdef DEBUG_STRINGS
-
-static void hexdump( const char * label, const char * s, size_t len )
-{
- size_t restlen = len;
- debug_out("<<<<<<<\n");
- debug_out(label);
- debug_out("\n");
- while (restlen > 0) {
- char line[100];
- size_t i, j;
- char * d = line;
-#undef sprintf
- d += sprintf(d, "%04X ", (unsigned)(len-restlen));
- *d++ = ' ';
- for( i = 0; i<restlen && i<8; ++i ) {
- d += sprintf(d, "%02X ", ((unsigned)s[i]) & 0xFF);
- }
- for( j = i; j<8; ++j ) {
- d += sprintf(d, " ");
- }
- *d++ = ' ';
- for( i = 8; i<restlen && i<16; ++i ) {
- d += sprintf(d, "%02X ", ((unsigned)s[i]) & 0xFF);
- }
- for( j = i; j<16; ++j ) {
- d += sprintf(d, " ");
- }
- *d++ = ' ';
- for( i = 0; i<restlen && i<16; ++i ) {
- if(s[i] < ' ' || s[i] >= 0x7F || !isprint(s[i]))
- *d++ = '.';
- else
- *d++ = s[i];
- }
- *d++ = '\n';
- *d = 0;
- restlen -= i;
- s += i;
- debug_out(line);
- }
- debug_out(">>>>>>>\n");
-}
-
-#else /* !DEBUG_STRINGS */
-
-#define hexdump(label,s,len) /* nothing */
-
-#endif
-
-
-#if !USE_INTERNAL_API
-
-/*
- * An implementation based on documented Mac OS X APIs.
- *
- * This does a certain amount of memory management, creating and
- * manipulating CFString objects. We try to minimize the impact by
- * keeping those objects around and re-using them. We also use
- * external backing store for the CFStrings where this is possible and
- * benficial.
- *
- * The Unicode normalizations forms available at this level are
- * generic, not specifically for the file system. So they may not be
- * perfect fits.
- */
-static size_t macosxfs_encoding_pull(
- void *cd, /* Encoder handle */
- char **inbuf, size_t *inbytesleft, /* Script string */
- char **outbuf, size_t *outbytesleft) /* UTF-16-LE string */
-{
- static const int script_code = kCFStringEncodingUTF8;
- static CFMutableStringRef cfstring = NULL;
- size_t outsize;
- CFRange range;
-
- (void) cd; /* UNUSED */
-
- if (0 == *inbytesleft) {
- return 0;
- }
-
- if (NULL == cfstring) {
- /*
- * A version with an external backing store as in the
- * push function should have been more efficient, but
- * testing shows, that it is actually slower (!).
- * Maybe kCFAllocatorDefault gets shortcut evaluation
- * internally, while kCFAllocatorNull doesn't.
- */
- cfstring = CFStringCreateMutable(kCFAllocatorDefault,0);
- }
-
- /*
- * Three methods of appending to a CFString, choose the most
- * efficient.
- */
- if (0 == (*inbuf)[*inbytesleft-1]) {
- CFStringAppendCString(cfstring, *inbuf, script_code);
- } else if (*inbytesleft <= 255) {
- Str255 buffer;
- buffer[0] = *inbytesleft;
- memcpy(buffer+1, *inbuf, buffer[0]);
- CFStringAppendPascalString(cfstring, buffer, script_code);
- } else {
- /*
- * We would like to use a fixed buffer and a loop
- * here, but than we can't garantee that the input is
- * well-formed UTF-8, as we are supposed to do.
- */
- static char *buffer = NULL;
- static size_t buflen = 0;
- buffer = resize_buffer(buffer, &buflen, *inbytesleft+1);
- memcpy(buffer, *inbuf, *inbytesleft);
- buffer[*inbytesleft] = 0;
- CFStringAppendCString(cfstring, *inbuf, script_code);
- }
-
- /*
- * Compose characters, using the non-canonical composition
- * form.
- */
- CFStringNormalize(cfstring, kCFStringNormalizationFormC);
-
- outsize = CFStringGetLength(cfstring);
- range = CFRangeMake(0,outsize);
-
- if (outsize == 0) {
- /*
- * HACK: smbd/mangle_hash2.c:is_legal_name() expects
- * errors here. That function will always pass 2
- * characters. smbd/open.c:check_for_pipe() cuts a
- * patchname to 10 characters blindly. Suppress the
- * debug output in those cases.
- */
- if(2 != *inbytesleft && 10 != *inbytesleft) {
- debug_out("String conversion: "
- "An unknown error occurred\n");
- hexdump("UTF8->UTF16LE (old) input",
- *inbuf, *inbytesleft);
- }
- errno = EILSEQ; /* Not sure, but this is what we have
- * actually seen. */
- return -1;
- }
- if (outsize*2 > *outbytesleft) {
- CFStringDelete(cfstring, range);
- debug_out("String conversion: "
- "Output buffer too small\n");
- hexdump("UTF8->UTF16LE (old) input",
- *inbuf, *inbytesleft);
- errno = E2BIG;
- return -1;
- }
-
- CFStringGetCharacters(cfstring, range, (UniChar*)*outbuf);
- CFStringDelete(cfstring, range);
-
- native_to_le(*outbuf, outsize*2);
-
- /*
- * Add a converted null byte, if the CFString conversions
- * prevented that until now.
- */
- if (0 == (*inbuf)[*inbytesleft-1] &&
- (0 != (*outbuf)[outsize*2-1] || 0 != (*outbuf)[outsize*2-2])) {
-
- if ((outsize*2+2) > *outbytesleft) {
- debug_out("String conversion: "
- "Output buffer too small\n");
- hexdump("UTF8->UTF16LE (old) input",
- *inbuf, *inbytesleft);
- errno = E2BIG;
- return -1;
- }
-
- (*outbuf)[outsize*2] = (*outbuf)[outsize*2+1] = 0;
- outsize += 2;
- }
-
- *inbuf += *inbytesleft;
- *inbytesleft = 0;
- *outbuf += outsize*2;
- *outbytesleft -= outsize*2;
-
- return 0;
-}
-
-static size_t macosxfs_encoding_push(
- void *cd, /* Encoder handle */
- char **inbuf, size_t *inbytesleft, /* UTF-16-LE string */
- char **outbuf, size_t *outbytesleft) /* Script string */
-{
- static const int script_code = kCFStringEncodingUTF8;
- static CFMutableStringRef cfstring = NULL;
- static UniChar *buffer = NULL;
- static size_t buflen = 0;
- CFIndex outsize, cfsize, charsconverted;
-
- (void) cd; /* UNUSED */
-
- if (0 == *inbytesleft) {
- return 0;
- }
-
- /*
- * We need a buffer that can hold 4 times the original data,
- * because that is the theoretical maximum that decomposition
- * can create currently (in Unicode 4.0).
- */
- buffer = set_ucbuffer_with_le_copy(
- buffer, &buflen, *inbuf, *inbytesleft, 3 * *inbytesleft);
-
- if (NULL == cfstring) {
- cfstring = CFStringCreateMutableWithExternalCharactersNoCopy(
- kCFAllocatorDefault,
- buffer, *inbytesleft/2, buflen/2,
- kCFAllocatorNull);
- } else {
- CFStringSetExternalCharactersNoCopy(
- cfstring,
- buffer, *inbytesleft/2, buflen/2);
- }
-
- /*
- * Decompose characters, using the non-canonical decomposition
- * form.
- *
- * NB: This isn't exactly what HFS+ wants (see note on
- * kCFStringEncodingUseHFSPlusCanonical in
- * CFStringEncodingConverter.h), but AFAIK it's the best that
- * the official API can do.
- */
- CFStringNormalize(cfstring, kCFStringNormalizationFormD);
-
- cfsize = CFStringGetLength(cfstring);
- charsconverted = CFStringGetBytes(
- cfstring, CFRangeMake(0,cfsize),
- script_code, 0, False,
- *outbuf, *outbytesleft, &outsize);
-
- if (0 == charsconverted) {
- debug_out("String conversion: "
- "Buffer too small or not convertable\n");
- hexdump("UTF16LE->UTF8 (old) input",
- *inbuf, *inbytesleft);
- errno = EILSEQ; /* Probably more likely. */
- return -1;
- }
-
- /*
- * Add a converted null byte, if the CFString conversions
- * prevented that until now.
- */
- if (0 == (*inbuf)[*inbytesleft-1] && 0 == (*inbuf)[*inbytesleft-2] &&
- (0 != (*outbuf)[outsize-1])) {
-
- if (((size_t)outsize+1) > *outbytesleft) {
- debug_out("String conversion: "
- "Output buffer too small\n");
- hexdump("UTF16LE->UTF8 (old) input",
- *inbuf, *inbytesleft);
- errno = E2BIG;
- return -1;
- }
-
- (*outbuf)[outsize] = 0;
- ++outsize;
- }
-
- *inbuf += *inbytesleft;
- *inbytesleft = 0;
- *outbuf += outsize;
- *outbytesleft -= outsize;
-
- return 0;
-}
-
-#else /* USE_INTERNAL_API */
-
-/*
- * An implementation based on internal code as known from the
- * OpenDarwin CVS.
- *
- * This code doesn't need much memory management because it uses
- * functions that operate on the raw memory directly.
- *
- * The push routine here is faster and more compatible with HFS+ than
- * the other implementation above. The pull routine is only faster
- * for some strings, slightly slower for others. The pull routine
- * looses because it has to iterate over the data twice, once to
- * decode UTF-8 and than to do the character composition required by
- * Windows.
- */
-static size_t macosxfs_encoding_pull(
- void *cd, /* Encoder handle */
- char **inbuf, size_t *inbytesleft, /* Script string */
- char **outbuf, size_t *outbytesleft) /* UTF-16-LE string */
-{
- static const int script_code = kCFStringEncodingUTF8;
- UInt32 srcCharsUsed = 0;
- UInt32 dstCharsUsed = 0;
- UInt32 result;
- uint32_t dstDecomposedUsed = 0;
- uint32_t dstPrecomposedUsed = 0;
-
- (void) cd; /* UNUSED */
-
- if (0 == *inbytesleft) {
- return 0;
- }
-
- result = CFStringEncodingBytesToUnicode(
- script_code, kCFStringEncodingComposeCombinings,
- *inbuf, *inbytesleft, &srcCharsUsed,
- (UniChar*)*outbuf, *outbytesleft, &dstCharsUsed);
-
- switch(result) {
- case kCFStringEncodingConversionSuccess:
- if (*inbytesleft == srcCharsUsed)
- break;
- else
- ; /*fall through*/
- case kCFStringEncodingInsufficientOutputBufferLength:
- debug_out("String conversion: "
- "Output buffer too small\n");
- hexdump("UTF8->UTF16LE (new) input",
- *inbuf, *inbytesleft);
- errno = E2BIG;
- return -1;
- case kCFStringEncodingInvalidInputStream:
- /*
- * HACK: smbd/mangle_hash2.c:is_legal_name() expects
- * errors here. That function will always pass 2
- * characters. smbd/open.c:check_for_pipe() cuts a
- * patchname to 10 characters blindly. Suppress the
- * debug output in those cases.
- */
- if(2 != *inbytesleft && 10 != *inbytesleft) {
- debug_out("String conversion: "
- "Invalid input sequence\n");
- hexdump("UTF8->UTF16LE (new) input",
- *inbuf, *inbytesleft);
- }
- errno = EILSEQ;
- return -1;
- case kCFStringEncodingConverterUnavailable:
- debug_out("String conversion: "
- "Unknown encoding\n");
- hexdump("UTF8->UTF16LE (new) input",
- *inbuf, *inbytesleft);
- errno = EINVAL;
- return -1;
- }
-
- /*
- * It doesn't look like CFStringEncodingBytesToUnicode() can
- * produce precomposed characters (flags=ComposeCombinings
- * doesn't do it), so we need another pass over the data here.
- * We can do this in-place, as the string can only get
- * shorter.
- *
- * (Actually in theory there should be an internal
- * decomposition and reordering before the actual composition
- * step. But we should be able to rely on that we always get
- * fully decomposed strings for input, so this can't create
- * problems in reality.)
- */
- CFUniCharPrecompose(
- (const UTF16Char *)*outbuf, dstCharsUsed, &dstDecomposedUsed,
- (UTF16Char *)*outbuf, dstCharsUsed, &dstPrecomposedUsed);
-
- native_to_le(*outbuf, dstPrecomposedUsed*2);
-
- *inbuf += srcCharsUsed;
- *inbytesleft -= srcCharsUsed;
- *outbuf += dstPrecomposedUsed*2;
- *outbytesleft -= dstPrecomposedUsed*2;
-
- return 0;
-}
-
-static size_t macosxfs_encoding_push(
- void *cd, /* Encoder handle */
- char **inbuf, size_t *inbytesleft, /* UTF-16-LE string */
- char **outbuf, size_t *outbytesleft) /* Script string */
-{
- static const int script_code = kCFStringEncodingUTF8;
- static UniChar *buffer = NULL;
- static size_t buflen = 0;
- UInt32 srcCharsUsed=0, dstCharsUsed=0, result;
-
- (void) cd; /* UNUSED */
-
- if (0 == *inbytesleft) {
- return 0;
- }
-
- buffer = set_ucbuffer_with_le(
- buffer, &buflen, *inbuf, *inbytesleft);
-
- result = CFStringEncodingUnicodeToBytes(
- script_code, kCFStringEncodingUseHFSPlusCanonical,
- buffer, *inbytesleft/2, &srcCharsUsed,
- *outbuf, *outbytesleft, &dstCharsUsed);
-
- switch(result) {
- case kCFStringEncodingConversionSuccess:
- if (*inbytesleft/2 == srcCharsUsed)
- break;
- else
- ; /*fall through*/
- case kCFStringEncodingInsufficientOutputBufferLength:
- debug_out("String conversion: "
- "Output buffer too small\n");
- hexdump("UTF16LE->UTF8 (new) input",
- *inbuf, *inbytesleft);
- errno = E2BIG;
- return -1;
- case kCFStringEncodingInvalidInputStream:
- /*
- * HACK: smbd/open.c:check_for_pipe():is_legal_name()
- * cuts a pathname to 10 characters blindly. Suppress
- * the debug output in those cases.
- */
- if(10 != *inbytesleft) {
- debug_out("String conversion: "
- "Invalid input sequence\n");
- hexdump("UTF16LE->UTF8 (new) input",
- *inbuf, *inbytesleft);
- }
- errno = EILSEQ;
- return -1;
- case kCFStringEncodingConverterUnavailable:
- debug_out("String conversion: "
- "Unknown encoding\n");
- hexdump("UTF16LE->UTF8 (new) input",
- *inbuf, *inbytesleft);
- errno = EINVAL;
- return -1;
- }
-
- *inbuf += srcCharsUsed*2;
- *inbytesleft -= srcCharsUsed*2;
- *outbuf += dstCharsUsed;
- *outbytesleft -= dstCharsUsed;
-
- return 0;
-}
-
-#endif /* USE_INTERNAL_API */
-
-/*
- * For initialization, actually install the encoding as "macosxfs".
- */
-static struct charset_functions macosxfs_encoding_functions = {
- "MACOSXFS", macosxfs_encoding_pull, macosxfs_encoding_push
-};
-
-NTSTATUS charset_macosxfs_init(void)
-{
- if (!smb_register_charset(&macosxfs_encoding_functions)) {
- return NT_STATUS_INTERNAL_ERROR;
- }
- return NT_STATUS_OK;
-}
-
-/* eof */