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

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)