util.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * util.c -  Miscellaneous support
  3.  *
  4.  * Copyright (C) 1997,1999 Martin von L鰓is
  5.  * Copyright (C) 1997 R間is Duchesne
  6.  * Copyright (C) 2001 Anton Altaparmakov (AIA)
  7.  *
  8.  * The utf8 routines are copied from Python wstrop module.
  9.  */
  10. #include "ntfstypes.h"
  11. #include "struct.h"
  12. #include "util.h"
  13. #include <linux/string.h>
  14. #include <linux/errno.h>
  15. #include <asm/div64.h> /* For do_div(). */
  16. #include "support.h"
  17. /*
  18.  * Converts a single wide character to a sequence of utf8 bytes.
  19.  * The character is represented in host byte order.
  20.  * Returns the number of bytes, or 0 on error.
  21.  */
  22. static int to_utf8(ntfs_u16 c, unsigned char *buf)
  23. {
  24. if (c == 0)
  25. return 0; /* No support for embedded 0 runes. */
  26. if (c < 0x80) {
  27. if (buf)
  28. buf[0] = (unsigned char)c;
  29. return 1;
  30. }
  31. if (c < 0x800) {
  32. if (buf) {
  33. buf[0] = 0xc0 | (c >> 6);
  34. buf[1] = 0x80 | (c & 0x3f);
  35. }
  36. return 2;
  37. }
  38. /* c < 0x10000 */
  39. if (buf) {
  40. buf[0] = 0xe0 | (c >> 12);
  41. buf[1] = 0x80 | ((c >> 6) & 0x3f);
  42. buf[2] = 0x80 | (c & 0x3f);
  43. }
  44. return 3;
  45. }
  46. /*
  47.  * Decodes a sequence of utf8 bytes into a single wide character.
  48.  * The character is returned in host byte order.
  49.  * Returns the number of bytes consumed, or 0 on error.
  50.  */
  51. static int from_utf8(const unsigned char *str, ntfs_u16 *c)
  52. {
  53. int l = 0, i;
  54. if (*str < 0x80) {
  55. *c = *str;
  56. return 1;
  57. }
  58. if (*str < 0xc0) /* Lead byte must not be 10xxxxxx. */
  59. return 0; /* Is c0 a possible lead byte? */
  60. if (*str < 0xe0) { /* 110xxxxx */
  61. *c = *str & 0x1f;
  62. l = 2;
  63. } else if (*str < 0xf0) { /* 1110xxxx */
  64. *c = *str & 0xf;
  65. l = 3;
  66. } else if (*str < 0xf8) {    /* 11110xxx */
  67. *c = *str & 7;
  68. l = 4;
  69. } else /* We don't support characters above 0xFFFF in NTFS. */
  70. return 0;
  71. for (i = 1; i < l; i++) {
  72. /* All other bytes must be 10xxxxxx. */
  73. if ((str[i] & 0xc0) != 0x80)
  74. return 0;
  75. *c <<= 6;
  76. *c |= str[i] & 0x3f;
  77. }
  78. return l;
  79. }
  80. /*
  81.  * Converts wide string to UTF-8. Expects two in- and two out-parameters.
  82.  * Returns 0 on success, or error code. 
  83.  * The caller has to free the result string.
  84.  */
  85. static int ntfs_dupuni2utf8(ntfs_u16 *in, int in_len, char **out, int *out_len)
  86. {
  87. int i, tmp;
  88. int len8;
  89. unsigned char *result;
  90. ntfs_debug(DEBUG_NAME1, "converting l = %dn", in_len);
  91. /* Count the length of the resulting UTF-8. */
  92. for (i = len8 = 0; i < in_len; i++) {
  93. tmp = to_utf8(NTFS_GETU16(in + i), 0);
  94. if (!tmp)
  95. /* Invalid character. */
  96. return -EILSEQ;
  97. len8 += tmp;
  98. }
  99. *out = result = ntfs_malloc(len8 + 1); /* allow for zero-termination */
  100. if (!result)
  101. return -ENOMEM;
  102. result[len8] = '';
  103. *out_len = len8;
  104. for (i = len8 = 0; i < in_len; i++)
  105. len8 += to_utf8(NTFS_GETU16(in + i), result + len8);
  106. ntfs_debug(DEBUG_NAME1, "result %p:%sn", result, result);
  107. return 0;
  108. }
  109. /*
  110.  * Converts an UTF-8 sequence to a wide string. Same conventions as the
  111.  * previous function.
  112.  */
  113. static int ntfs_duputf82uni(unsigned char* in, int in_len, ntfs_u16** out,
  114. int *out_len)
  115. {
  116. int i, tmp;
  117. int len16;
  118. ntfs_u16* result;
  119. ntfs_u16 wtmp;
  120. for (i = len16 = 0; i < in_len; i += tmp, len16++) {
  121. tmp = from_utf8(in + i, &wtmp);
  122. if (!tmp)
  123. return -EILSEQ;
  124. }
  125. *out = result = ntfs_malloc(2 * (len16 + 1));
  126. if (!result)
  127. return -ENOMEM;
  128. result[len16] = 0;
  129. *out_len = len16;
  130. for (i = len16 = 0; i < in_len; i += tmp, len16++) {
  131. tmp = from_utf8(in + i, &wtmp);
  132. NTFS_PUTU16(result + len16, wtmp);
  133. }
  134. return 0;
  135. }
  136. /* Encodings dispatchers. */
  137. int ntfs_encodeuni(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
  138. int *out_len)
  139. {
  140. if (vol->nls_map)
  141. return ntfs_dupuni2map(vol, in, in_len, out, out_len);
  142. else
  143. return ntfs_dupuni2utf8(in, in_len, out, out_len);
  144. }
  145. int ntfs_decodeuni(ntfs_volume *vol, char *in, int in_len, ntfs_u16 **out,
  146. int *out_len)
  147. {
  148. if (vol->nls_map)
  149. return ntfs_dupmap2uni(vol, in, in_len, out, out_len);
  150. else
  151. return ntfs_duputf82uni(in, in_len, out, out_len);
  152. }
  153. /* Same address space copies. */
  154. void ntfs_put(ntfs_io *dest, void *src, ntfs_size_t n)
  155. {
  156. ntfs_memcpy(dest->param, src, n);
  157. ((char*)dest->param) += n;
  158. }
  159. void ntfs_get(void* dest, ntfs_io *src, ntfs_size_t n)
  160. {
  161. ntfs_memcpy(dest, src->param, n);
  162. ((char*)src->param) += n;
  163. }
  164. void *ntfs_calloc(int size)
  165. {
  166. void *result = ntfs_malloc(size);
  167. if (result)
  168. ntfs_bzero(result, size);
  169. return result;
  170. }
  171. /* Copy len ascii characters from from to to. :) */
  172. void ntfs_ascii2uni(short int *to, char *from, int len)
  173. {
  174. int i;
  175. for (i = 0; i < len; i++)
  176. NTFS_PUTU16(to + i, from[i]);
  177. to[i] = 0;
  178. }
  179. /* strncmp for Unicode strings. */
  180. int ntfs_uni_strncmp(short int* a, short int *b, int n)
  181. {
  182. int i;
  183. for(i = 0; i < n; i++)
  184. {
  185. if (NTFS_GETU16(a + i) < NTFS_GETU16(b + i))
  186. return -1;
  187. if (NTFS_GETU16(b + i) < NTFS_GETU16(a + i))
  188. return 1;
  189. if (NTFS_GETU16(a + i) == 0)
  190. break;
  191. }
  192. return 0;
  193. }
  194. /* strncmp between Unicode and ASCII strings. */
  195. int ntfs_ua_strncmp(short int* a, char* b, int n)
  196. {
  197. int i;
  198. for (i = 0; i < n; i++) {
  199. if(NTFS_GETU16(a + i) < b[i])
  200. return -1;
  201. if(b[i] < NTFS_GETU16(a + i))
  202. return 1;
  203. if (b[i] == 0)
  204. return 0;
  205. }
  206. return 0;
  207. }
  208. #define NTFS_TIME_OFFSET ((ntfs_time64_t)(369*365 + 89) * 24 * 3600 * 10000000)
  209. /* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units)
  210.  * into Unix UTC (based 1.1.1970, in seconds). */
  211. ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc)
  212. {
  213. /* Subtract the NTFS time offset, then convert to 1s intervals. */
  214. ntfs_time64_t t = ntutc - NTFS_TIME_OFFSET;
  215. do_div(t, 10000000);
  216. return (ntfs_time_t)t;
  217. }
  218. /* Convert the Unix UTC into NT UTC. */
  219. ntfs_time64_t ntfs_unixutc2ntutc(ntfs_time_t t)
  220. {
  221. /* Convert to 100ns intervals and then add the NTFS time offset. */
  222. return (ntfs_time64_t)t * 10000000 + NTFS_TIME_OFFSET;
  223. }
  224. #undef NTFS_TIME_OFFSET
  225. /* Fill index name. */
  226. void ntfs_indexname(char *buf, int type)
  227. {
  228. char hex[] = "0123456789ABCDEF";
  229. int index;
  230. *buf++ = '$';
  231. *buf++ = 'I';
  232. for (index = 24; index > 0; index -= 4)
  233. if ((0xF << index) & type)
  234. break;
  235. while (index >= 0) {
  236. *buf++ = hex[(type >> index) & 0xF];
  237. index -= 4;
  238. }
  239. *buf = '';
  240. }