patch-2.4.9 linux/fs/ntfs/util.c
Next file: linux/fs/ntfs/util.h
Previous file: linux/fs/ntfs/unistr.c
Back to the patch index
Back to the overall index
- Lines: 275
- Date:
Mon Aug 13 16:40:19 2001
- Orig file:
v2.4.8/linux/fs/ntfs/util.c
- Orig date:
Wed Jul 25 17:10:24 2001
diff -u --recursive --new-file v2.4.8/linux/fs/ntfs/util.c linux/fs/ntfs/util.c
@@ -13,12 +13,15 @@
#include "util.h"
#include <linux/string.h>
#include <linux/errno.h>
+#include <asm/div64.h> /* For do_div(). */
#include "support.h"
-/* Converts a single wide character to a sequence of utf8 bytes.
+/*
+ * 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)
+ * 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. */
@@ -34,22 +37,21 @@
}
return 2;
}
- if (c < 0x10000) {
- if (buf) {
- buf[0] = 0xe0 | (c >> 12);
- buf[1] = 0x80 | ((c >> 6) & 0x3f);
- buf[2] = 0x80 | (c & 0x3f);
- }
- return 3;
+ /* c < 0x10000 */
+ if (buf) {
+ buf[0] = 0xe0 | (c >> 12);
+ buf[1] = 0x80 | ((c >> 6) & 0x3f);
+ buf[2] = 0x80 | (c & 0x3f);
}
- /* We don't support characters above 0xFFFF in NTFS. */
- return 0;
+ return 3;
}
-/* Decodes a sequence of utf8 bytes into a single wide character.
+/*
+ * 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)
+ * 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;
@@ -80,11 +82,12 @@
return l;
}
-/* Converts wide string to UTF-8. Expects two in- and two out-parameters.
+/*
+ * 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.
- * There is no support for UTF-16, yet. */
-static int ntfs_dupuni2utf8(ntfs_u16* in, int in_len, char **out, int *out_len)
+ */
+static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len)
{
int i, tmp;
int len8;
@@ -92,15 +95,14 @@
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++){
+ for (i = len8 = 0; i < in_len; i++) {
tmp = to_utf8(NTFS_GETU16(in + i), 0);
if (!tmp)
- /* invalid character */
+ /* Invalid character. */
return -EILSEQ;
len8 += tmp;
}
*out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */
-
if (!result)
return -ENOMEM;
result[len8] = '\0';
@@ -111,10 +113,12 @@
return 0;
}
-/* Converts an UTF-8 sequence to a wide string. Same conventions as the
- * previous function. */
+/*
+ * 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 *out_len)
{
int i, tmp;
int len16;
@@ -131,76 +135,30 @@
return -ENOMEM;
result[len16] = 0;
*out_len = len16;
- for (i = len16 = 0; i < in_len; i += tmp, len16++)
- {
+ for (i = len16 = 0; i < in_len; i += tmp, len16++) {
tmp = from_utf8(in + i, &wtmp);
NTFS_PUTU16(result + len16, wtmp);
}
return 0;
}
-/* See above. Produces ISO-8859-1 from wide strings. */
-static int ntfs_dupuni288591(ntfs_u16* in, int in_len, char** out, int *out_len)
-{
- int i;
- char *result;
-
- /* Check for characters out of range. */
- for (i = 0; i < in_len; i++)
- if (NTFS_GETU16(in + i) >= 256)
- return -EILSEQ;
- *out = result = ntfs_malloc(in_len + 1);
- if (!result)
- return -ENOMEM;
- result[in_len] = '\0';
- *out_len = in_len;
- for (i = 0; i < in_len; i++)
- result[i] = (unsigned char)NTFS_GETU16(in + i);
- return 0;
-}
-
-/* See above. */
-static int ntfs_dup885912uni(unsigned char* in, int in_len, ntfs_u16 **out,
- int *out_len)
-{
- int i;
-
- ntfs_u16* result;
- *out = result = ntfs_malloc(2 * in_len);
- if (!result)
- return -ENOMEM;
- *out_len = in_len;
- for (i = 0; i < in_len; i++)
- NTFS_PUTU16(result + i, in[i]);
- return 0;
-}
-
-/* Encodings dispatcher */
+/* Encodings dispatchers. */
int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
- int *out_len)
+ int *out_len)
{
- if (vol->nct & nct_utf8)
- return ntfs_dupuni2utf8(in, in_len, out, out_len);
- else if (vol->nct & nct_iso8859_1)
- return ntfs_dupuni288591(in, in_len, out, out_len);
- else if(vol->nct & (nct_map | nct_uni_xlate))
- /* uni_xlate is handled inside map. */
+ if (vol->nls_map)
return ntfs_dupuni2map(vol, in, in_len, out, out_len);
else
- return -EINVAL; /* unknown encoding */
+ 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)
+ int *out_len)
{
- if (vol->nct & nct_utf8)
- return ntfs_duputf82uni(in, in_len, out, out_len);
- else if (vol->nct & nct_iso8859_1)
- return ntfs_dup885912uni(in, in_len, out, out_len);
- else if (vol->nct & (nct_map | nct_uni_xlate))
+ if (vol->nls_map)
return ntfs_dupmap2uni(vol, in, in_len, out, out_len);
else
- return -EINVAL;
+ return ntfs_duputf82uni(in, in_len, out, out_len);
}
/* Same address space copies. */
@@ -224,18 +182,6 @@
return result;
}
-#if 0
-/* Copy len unicode characters from from to to. :) */
-void ntfs_uni2ascii(char *to, short int *from, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- to[i] = NTFS_GETU16(from + i);
- to[i] = '\0';
-}
-#endif
-
/* Copy len ascii characters from from to to. :) */
void ntfs_ascii2uni(short int *to, char *from, int len)
{
@@ -279,57 +225,26 @@
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)
{
-/* This is very gross because:
- * 1: We must do 64-bit division on a 32-bit machine.
- * 2: We can't use libgcc for long long operations in the kernel.
- * 3: Floating point math in the kernel would corrupt user data. */
- const unsigned int D = 10000000;
- unsigned int H = (unsigned int)(ntutc >> 32);
- unsigned int L = (unsigned int)ntutc;
- unsigned int numerator2;
- unsigned int lowseconds;
- unsigned int result;
-
- /* It is best to subtract 0x019db1ded53e8000 first. */
- /* Then the 1601-based date becomes a 1970-based date. */
- if (L < (unsigned)0xd53e8000)
- H--;
- L -= (unsigned)0xd53e8000;
- H -= (unsigned)0x019db1de;
-
- /* Now divide 64-bit numbers on a 32-bit machine. :-)
- * With the subtraction already done, the result fits in 32 bits.
- * The numerator fits in 56 bits and the denominator fits
- * in 24 bits, so we can shift by 8 bits to make this work. */
-
- numerator2 = (H << 8) | (L >> 24);
- result = (numerator2 / D); /* shifted 24 right!! */
- lowseconds = result << 24;
-
- numerator2 = ((numerator2 - result * D) << 8) | ((L >> 16) & 0xff);
- result = (numerator2 / D); /* shifted 16 right!! */
- lowseconds |= result << 16;
-
- numerator2 = ((numerator2 - result * D) << 8) | ((L >> 8) & 0xff);
- result = (numerator2 / D); /* shifted 8 right!! */
- lowseconds |= result << 8;
-
- numerator2 = ((numerator2 - result * D) << 8) | (L & 0xff);
- result = (numerator2 / D); /* not shifted */
- lowseconds |= result;
-
- return lowseconds;
+ /* 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)
{
- return ((t + (ntfs_time64_t)(369 * 365 + 89) * 24 * 3600) * 10000000);
+ /* 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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)