--- zzzz-none-000/linux-2.4.17/fs/ntfs/util.c 2001-08-13 23:40:19.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/fs/ntfs/util.c 2004-11-24 13:22:16.000000000 +0000 @@ -1,265 +1,265 @@ -/* - * util.c - Miscellaneous support - * - * Copyright (C) 1997,1999 Martin von Löwis - * Copyright (C) 1997 Régis Duchesne - * Copyright (C) 2001 Anton Altaparmakov (AIA) - * - * The utf8 routines are copied from Python wstrop module. - */ - -#include "ntfstypes.h" -#include "struct.h" -#include "util.h" -#include -#include -#include /* For do_div(). */ -#include "support.h" - -/* - * Converts a single wide character to a sequence of utf8 bytes. - * The character is represented in host byte order. - * Returns the number of bytes, or 0 on error. - */ -static int to_utf8(ntfs_u16 c, unsigned char *buf) -{ - if (c == 0) - return 0; /* No support for embedded 0 runes. */ - if (c < 0x80) { - if (buf) - buf[0] = (unsigned char)c; - return 1; - } - if (c < 0x800) { - if (buf) { - buf[0] = 0xc0 | (c >> 6); - buf[1] = 0x80 | (c & 0x3f); - } - return 2; - } - /* c < 0x10000 */ - if (buf) { - buf[0] = 0xe0 | (c >> 12); - buf[1] = 0x80 | ((c >> 6) & 0x3f); - buf[2] = 0x80 | (c & 0x3f); - } - return 3; -} - -/* - * Decodes a sequence of utf8 bytes into a single wide character. - * The character is returned in host byte order. - * Returns the number of bytes consumed, or 0 on error. - */ -static int from_utf8(const unsigned char *str, ntfs_u16 *c) -{ - int l = 0, i; - - if (*str < 0x80) { - *c = *str; - return 1; - } - if (*str < 0xc0) /* Lead byte must not be 10xxxxxx. */ - return 0; /* Is c0 a possible lead byte? */ - if (*str < 0xe0) { /* 110xxxxx */ - *c = *str & 0x1f; - l = 2; - } else if (*str < 0xf0) { /* 1110xxxx */ - *c = *str & 0xf; - l = 3; - } else if (*str < 0xf8) { /* 11110xxx */ - *c = *str & 7; - l = 4; - } else /* We don't support characters above 0xFFFF in NTFS. */ - return 0; - for (i = 1; i < l; i++) { - /* All other bytes must be 10xxxxxx. */ - if ((str[i] & 0xc0) != 0x80) - return 0; - *c <<= 6; - *c |= str[i] & 0x3f; - } - return l; -} - -/* - * Converts wide string to UTF-8. Expects two in- and two out-parameters. - * Returns 0 on success, or error code. - * The caller has to free the result string. - */ -static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len) -{ - int i, tmp; - int len8; - unsigned char *result; - - ntfs_debug(DEBUG_NAME1, "converting l = %d\n", in_len); - /* Count the length of the resulting UTF-8. */ - for (i = len8 = 0; i < in_len; i++) { - tmp = to_utf8(NTFS_GETU16(in + i), 0); - if (!tmp) - /* Invalid character. */ - return -EILSEQ; - len8 += tmp; - } - *out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */ - if (!result) - return -ENOMEM; - result[len8] = '\0'; - *out_len = len8; - for (i = len8 = 0; i < in_len; i++) - len8 += to_utf8(NTFS_GETU16(in + i), result + len8); - ntfs_debug(DEBUG_NAME1, "result %p:%s\n", result, result); - return 0; -} - -/* - * Converts an UTF-8 sequence to a wide string. Same conventions as the - * previous function. - */ -static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out, - int *out_len) -{ - int i, tmp; - int len16; - ntfs_u16* result; - ntfs_u16 wtmp; - - for (i = len16 = 0; i < in_len; i += tmp, len16++) { - tmp = from_utf8(in + i, &wtmp); - if (!tmp) - return -EILSEQ; - } - *out = result = ntfs_malloc(2 * (len16 + 1)); - if (!result) - return -ENOMEM; - result[len16] = 0; - *out_len = len16; - for (i = len16 = 0; i < in_len; i += tmp, len16++) { - tmp = from_utf8(in + i, &wtmp); - NTFS_PUTU16(result + len16, wtmp); - } - return 0; -} - -/* Encodings dispatchers. */ -int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out, - int *out_len) -{ - if (vol->nls_map) - return ntfs_dupuni2map(vol, in, in_len, out, out_len); - else - return ntfs_dupuni2utf8(in, in_len, out, out_len); -} - -int ntfs_decodeuni(ntfs_volume *vol, char *in, int in_len, ntfs_u16 **out, - int *out_len) -{ - if (vol->nls_map) - return ntfs_dupmap2uni(vol, in, in_len, out, out_len); - else - return ntfs_duputf82uni(in, in_len, out, out_len); -} - -/* Same address space copies. */ -void ntfs_put(ntfs_io *dest, void *src, ntfs_size_t n) -{ - ntfs_memcpy(dest->param, src, n); - ((char*)dest->param) += n; -} - -void ntfs_get(void* dest, ntfs_io *src, ntfs_size_t n) -{ - ntfs_memcpy(dest, src->param, n); - ((char*)src->param) += n; -} - -void *ntfs_calloc(int size) -{ - void *result = ntfs_malloc(size); - if (result) - ntfs_bzero(result, size); - return result; -} - -/* Copy len ascii characters from from to to. :) */ -void ntfs_ascii2uni(short int *to, char *from, int len) -{ - int i; - - for (i = 0; i < len; i++) - NTFS_PUTU16(to + i, from[i]); - to[i] = 0; -} - -/* strncmp for Unicode strings. */ -int ntfs_uni_strncmp(short int* a, short int *b, int n) -{ - int i; - - for(i = 0; i < n; i++) - { - if (NTFS_GETU16(a + i) < NTFS_GETU16(b + i)) - return -1; - if (NTFS_GETU16(b + i) < NTFS_GETU16(a + i)) - return 1; - if (NTFS_GETU16(a + i) == 0) - break; - } - return 0; -} - -/* strncmp between Unicode and ASCII strings. */ -int ntfs_ua_strncmp(short int* a, char* b, int n) -{ - int i; - - for (i = 0; i < n; i++) { - if(NTFS_GETU16(a + i) < b[i]) - return -1; - if(b[i] < NTFS_GETU16(a + i)) - return 1; - if (b[i] == 0) - return 0; - } - return 0; -} - -#define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000) - -/* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units) - * into Unix UTC (based 1.1.1970, in seconds). */ -ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc) -{ - /* Subtract the NTFS time offset, then convert to 1s intervals. */ - ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET; - do_div(t, 10000000); - return (ntfs_time_t)t; -} - -/* Convert the Unix UTC into NT UTC. */ -ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t) -{ - /* Convert to 100ns intervals and then add the NTFS time offset. */ - return (ntfs_time64_t)t * 10000000 + NTFS_TIME_OFFSET; -} - -#undef NTFS_TIME_OFFSET - -/* Fill index name. */ -void ntfs_indexname(char *buf, int type) -{ - char hex[] = "0123456789ABCDEF"; - int index; - *buf++ = '$'; - *buf++ = 'I'; - for (index = 24; index > 0; index -= 4) - if ((0xF << index) & type) - break; - while (index >= 0) { - *buf++ = hex[(type >> index) & 0xF]; - index -= 4; - } - *buf = '\0'; -} - +/* + * util.c - Miscellaneous support + * + * Copyright (C) 1997,1999 Martin von Löwis + * Copyright (C) 1997 Régis Duchesne + * Copyright (C) 2001 Anton Altaparmakov (AIA) + * + * The utf8 routines are copied from Python wstrop module. + */ + +#include "ntfstypes.h" +#include "struct.h" +#include "util.h" +#include +#include +#include /* For do_div(). */ +#include "support.h" + +/* + * Converts a single wide character to a sequence of utf8 bytes. + * The character is represented in host byte order. + * Returns the number of bytes, or 0 on error. + */ +static int to_utf8(ntfs_u16 c, unsigned char *buf) +{ + if (c == 0) + return 0; /* No support for embedded 0 runes. */ + if (c < 0x80) { + if (buf) + buf[0] = (unsigned char)c; + return 1; + } + if (c < 0x800) { + if (buf) { + buf[0] = 0xc0 | (c >> 6); + buf[1] = 0x80 | (c & 0x3f); + } + return 2; + } + /* c < 0x10000 */ + if (buf) { + buf[0] = 0xe0 | (c >> 12); + buf[1] = 0x80 | ((c >> 6) & 0x3f); + buf[2] = 0x80 | (c & 0x3f); + } + return 3; +} + +/* + * Decodes a sequence of utf8 bytes into a single wide character. + * The character is returned in host byte order. + * Returns the number of bytes consumed, or 0 on error. + */ +static int from_utf8(const unsigned char *str, ntfs_u16 *c) +{ + int l = 0, i; + + if (*str < 0x80) { + *c = *str; + return 1; + } + if (*str < 0xc0) /* Lead byte must not be 10xxxxxx. */ + return 0; /* Is c0 a possible lead byte? */ + if (*str < 0xe0) { /* 110xxxxx */ + *c = *str & 0x1f; + l = 2; + } else if (*str < 0xf0) { /* 1110xxxx */ + *c = *str & 0xf; + l = 3; + } else if (*str < 0xf8) { /* 11110xxx */ + *c = *str & 7; + l = 4; + } else /* We don't support characters above 0xFFFF in NTFS. */ + return 0; + for (i = 1; i < l; i++) { + /* All other bytes must be 10xxxxxx. */ + if ((str[i] & 0xc0) != 0x80) + return 0; + *c <<= 6; + *c |= str[i] & 0x3f; + } + return l; +} + +/* + * Converts wide string to UTF-8. Expects two in- and two out-parameters. + * Returns 0 on success, or error code. + * The caller has to free the result string. + */ +static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len) +{ + int i, tmp; + int len8; + unsigned char *result; + + ntfs_debug(DEBUG_NAME1, "converting l = %d\n", in_len); + /* Count the length of the resulting UTF-8. */ + for (i = len8 = 0; i < in_len; i++) { + tmp = to_utf8(NTFS_GETU16(in + i), 0); + if (!tmp) + /* Invalid character. */ + return -EILSEQ; + len8 += tmp; + } + *out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */ + if (!result) + return -ENOMEM; + result[len8] = '\0'; + *out_len = len8; + for (i = len8 = 0; i < in_len; i++) + len8 += to_utf8(NTFS_GETU16(in + i), result + len8); + ntfs_debug(DEBUG_NAME1, "result %p:%s\n", result, result); + return 0; +} + +/* + * Converts an UTF-8 sequence to a wide string. Same conventions as the + * previous function. + */ +static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out, + int *out_len) +{ + int i, tmp; + int len16; + ntfs_u16* result; + ntfs_u16 wtmp; + + for (i = len16 = 0; i < in_len; i += tmp, len16++) { + tmp = from_utf8(in + i, &wtmp); + if (!tmp) + return -EILSEQ; + } + *out = result = ntfs_malloc(2 * (len16 + 1)); + if (!result) + return -ENOMEM; + result[len16] = 0; + *out_len = len16; + for (i = len16 = 0; i < in_len; i += tmp, len16++) { + tmp = from_utf8(in + i, &wtmp); + NTFS_PUTU16(result + len16, wtmp); + } + return 0; +} + +/* Encodings dispatchers. */ +int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out, + int *out_len) +{ + if (vol->nls_map) + return ntfs_dupuni2map(vol, in, in_len, out, out_len); + else + return ntfs_dupuni2utf8(in, in_len, out, out_len); +} + +int ntfs_decodeuni(ntfs_volume *vol, char *in, int in_len, ntfs_u16 **out, + int *out_len) +{ + if (vol->nls_map) + return ntfs_dupmap2uni(vol, in, in_len, out, out_len); + else + return ntfs_duputf82uni(in, in_len, out, out_len); +} + +/* Same address space copies. */ +void ntfs_put(ntfs_io *dest, void *src, ntfs_size_t n) +{ + ntfs_memcpy(dest->param, src, n); + ((char*)dest->param) += n; +} + +void ntfs_get(void* dest, ntfs_io *src, ntfs_size_t n) +{ + ntfs_memcpy(dest, src->param, n); + ((char*)src->param) += n; +} + +void *ntfs_calloc(int size) +{ + void *result = ntfs_malloc(size); + if (result) + ntfs_bzero(result, size); + return result; +} + +/* Copy len ascii characters from from to to. :) */ +void ntfs_ascii2uni(short int *to, char *from, int len) +{ + int i; + + for (i = 0; i < len; i++) + NTFS_PUTU16(to + i, from[i]); + to[i] = 0; +} + +/* strncmp for Unicode strings. */ +int ntfs_uni_strncmp(short int* a, short int *b, int n) +{ + int i; + + for(i = 0; i < n; i++) + { + if (NTFS_GETU16(a + i) < NTFS_GETU16(b + i)) + return -1; + if (NTFS_GETU16(b + i) < NTFS_GETU16(a + i)) + return 1; + if (NTFS_GETU16(a + i) == 0) + break; + } + return 0; +} + +/* strncmp between Unicode and ASCII strings. */ +int ntfs_ua_strncmp(short int* a, char* b, int n) +{ + int i; + + for (i = 0; i < n; i++) { + if(NTFS_GETU16(a + i) < b[i]) + return -1; + if(b[i] < NTFS_GETU16(a + i)) + return 1; + if (b[i] == 0) + return 0; + } + return 0; +} + +#define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000) + +/* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units) + * into Unix UTC (based 1.1.1970, in seconds). */ +ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc) +{ + /* Subtract the NTFS time offset, then convert to 1s intervals. */ + ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET; + do_div(t, 10000000); + return (ntfs_time_t)t; +} + +/* Convert the Unix UTC into NT UTC. */ +ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t) +{ + /* Convert to 100ns intervals and then add the NTFS time offset. */ + return (ntfs_time64_t)t * 10000000 + NTFS_TIME_OFFSET; +} + +#undef NTFS_TIME_OFFSET + +/* Fill index name. */ +void ntfs_indexname(char *buf, int type) +{ + char hex[] = "0123456789ABCDEF"; + int index; + *buf++ = '$'; + *buf++ = 'I'; + for (index = 24; index > 0; index -= 4) + if ((0xF << index) & type) + break; + while (index >= 0) { + *buf++ = hex[(type >> index) & 0xF]; + index -= 4; + } + *buf = '\0'; +} +