2 * util.c - Miscellaneous support
4 * Copyright (C) 1997,1999 Martin von Löwis
5 * Copyright (C) 1997 Régis Duchesne
6 * Copyright (C) 2001 Anton Altaparmakov (AIA)
8 * The utf8 routines are copied from Python wstrop module.
11 #include "ntfstypes.h"
14 #include <linux/string.h>
15 #include <linux/errno.h>
16 #include <asm/div64.h> /* For do_div(). */
20 * Converts a single wide character to a sequence of utf8 bytes.
21 * The character is represented in host byte order.
22 * Returns the number of bytes, or 0 on error.
24 static int to_utf8(ntfs_u16 c
, unsigned char *buf
)
27 return 0; /* No support for embedded 0 runes. */
30 buf
[0] = (unsigned char)c
;
35 buf
[0] = 0xc0 | (c
>> 6);
36 buf
[1] = 0x80 | (c
& 0x3f);
42 buf
[0] = 0xe0 | (c
>> 12);
43 buf
[1] = 0x80 | ((c
>> 6) & 0x3f);
44 buf
[2] = 0x80 | (c
& 0x3f);
50 * Decodes a sequence of utf8 bytes into a single wide character.
51 * The character is returned in host byte order.
52 * Returns the number of bytes consumed, or 0 on error.
54 static int from_utf8(const unsigned char *str
, ntfs_u16
*c
)
62 if (*str
< 0xc0) /* Lead byte must not be 10xxxxxx. */
63 return 0; /* Is c0 a possible lead byte? */
64 if (*str
< 0xe0) { /* 110xxxxx */
67 } else if (*str
< 0xf0) { /* 1110xxxx */
70 } else if (*str
< 0xf8) { /* 11110xxx */
73 } else /* We don't support characters above 0xFFFF in NTFS. */
75 for (i
= 1; i
< l
; i
++) {
76 /* All other bytes must be 10xxxxxx. */
77 if ((str
[i
] & 0xc0) != 0x80)
86 * Converts wide string to UTF-8. Expects two in- and two out-parameters.
87 * Returns 0 on success, or error code.
88 * The caller has to free the result string.
90 static int ntfs_dupuni2utf8(ntfs_u16
*in
, int in_len
, char **out
, int *out_len
)
94 unsigned char *result
;
96 ntfs_debug(DEBUG_NAME1
, "converting l = %d\n", in_len
);
97 /* Count the length of the resulting UTF-8. */
98 for (i
= len8
= 0; i
< in_len
; i
++) {
99 tmp
= to_utf8(NTFS_GETU16(in
+ i
), 0);
101 /* Invalid character. */
105 *out
= result
= ntfs_malloc(len8
+ 1); /* allow for zero-termination */
110 for (i
= len8
= 0; i
< in_len
; i
++)
111 len8
+= to_utf8(NTFS_GETU16(in
+ i
), result
+ len8
);
112 ntfs_debug(DEBUG_NAME1
, "result %p:%s\n", result
, result
);
117 * Converts an UTF-8 sequence to a wide string. Same conventions as the
120 static int ntfs_duputf82uni(unsigned char* in
, int in_len
, ntfs_u16
** out
,
128 for (i
= len16
= 0; i
< in_len
; i
+= tmp
, len16
++) {
129 tmp
= from_utf8(in
+ i
, &wtmp
);
133 *out
= result
= ntfs_malloc(2 * (len16
+ 1));
138 for (i
= len16
= 0; i
< in_len
; i
+= tmp
, len16
++) {
139 tmp
= from_utf8(in
+ i
, &wtmp
);
140 NTFS_PUTU16(result
+ len16
, wtmp
);
145 /* Encodings dispatchers. */
146 int ntfs_encodeuni(ntfs_volume
*vol
, ntfs_u16
*in
, int in_len
, char **out
,
150 return ntfs_dupuni2map(vol
, in
, in_len
, out
, out_len
);
152 return ntfs_dupuni2utf8(in
, in_len
, out
, out_len
);
155 int ntfs_decodeuni(ntfs_volume
*vol
, char *in
, int in_len
, ntfs_u16
**out
,
159 return ntfs_dupmap2uni(vol
, in
, in_len
, out
, out_len
);
161 return ntfs_duputf82uni(in
, in_len
, out
, out_len
);
164 /* Same address space copies. */
165 void ntfs_put(ntfs_io
*dest
, void *src
, ntfs_size_t n
)
167 ntfs_memcpy(dest
->param
, src
, n
);
168 dest
->param
= (char*)dest
->param
+ n
;
171 void ntfs_get(void* dest
, ntfs_io
*src
, ntfs_size_t n
)
173 ntfs_memcpy(dest
, src
->param
, n
);
174 src
->param
= (char*)src
->param
+ n
;
177 void *ntfs_calloc(int size
)
179 void *result
= ntfs_malloc(size
);
181 ntfs_bzero(result
, size
);
185 /* Copy len ascii characters from from to to. :) */
186 void ntfs_ascii2uni(short int *to
, char *from
, int len
)
190 for (i
= 0; i
< len
; i
++)
191 NTFS_PUTU16(to
+ i
, from
[i
]);
195 /* strncmp for Unicode strings. */
196 int ntfs_uni_strncmp(short int* a
, short int *b
, int n
)
200 for(i
= 0; i
< n
; i
++)
202 if (NTFS_GETU16(a
+ i
) < NTFS_GETU16(b
+ i
))
204 if (NTFS_GETU16(b
+ i
) < NTFS_GETU16(a
+ i
))
206 if (NTFS_GETU16(a
+ i
) == 0)
212 /* strncmp between Unicode and ASCII strings. */
213 int ntfs_ua_strncmp(short int* a
, char* b
, int n
)
217 for (i
= 0; i
< n
; i
++) {
218 if(NTFS_GETU16(a
+ i
) < b
[i
])
220 if(b
[i
] < NTFS_GETU16(a
+ i
))
228 #define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000)
230 /* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units)
231 * into Unix UTC (based 1.1.1970, in seconds). */
232 ntfs_time_t
ntfs_ntutc2unixutc(ntfs_time64_t ntutc
)
234 /* Subtract the NTFS time offset, then convert to 1s intervals. */
235 ntfs_time64_t t
= ntutc
- NTFS_TIME_OFFSET
;
237 return (ntfs_time_t
)t
;
240 /* Convert the Unix UTC into NT UTC. */
241 ntfs_time64_t
ntfs_unixutc2ntutc(ntfs_time_t t
)
243 /* Convert to 100ns intervals and then add the NTFS time offset. */
244 return (ntfs_time64_t
)t
* 10000000 + NTFS_TIME_OFFSET
;
247 #undef NTFS_TIME_OFFSET
249 /* Fill index name. */
250 void ntfs_indexname(char *buf
, int type
)
252 char hex
[] = "0123456789ABCDEF";
256 for (index
= 24; index
> 0; index
-= 4)
257 if ((0xF << index
) & type
)
260 *buf
++ = hex
[(type
>> index
) & 0xF];