hash.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Original copy from:
  3. * linux/fs/ext3/hash.c
  4. *
  5. * Copyright (C) 2002 by Theodore Ts'o
  6. *
  7. * This file is released under the GPL v2.
  8. *
  9. * This file may be redistributed under the terms of the GNU Public
  10. * License.
  11. */
  12. #include "kerncompat.h"
  13. #define DELTA 0x9E3779B9
  14. static void TEA_transform(__u32 buf[2], __u32 const in[])
  15. {
  16. __u32 sum = 0;
  17. __u32 b0 = buf[0], b1 = buf[1];
  18. __u32 a = in[0], b = in[1], c = in[2], d = in[3];
  19. int n = 16;
  20. do {
  21. sum += DELTA;
  22. b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
  23. b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
  24. } while(--n);
  25. buf[0] += b0;
  26. buf[1] += b1;
  27. }
  28. static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
  29. {
  30. __u32 pad, val;
  31. int i;
  32. pad = (__u32)len | ((__u32)len << 8);
  33. pad |= pad << 16;
  34. val = pad;
  35. if (len > num*4)
  36. len = num * 4;
  37. for (i=0; i < len; i++) {
  38. if ((i % 4) == 0)
  39. val = pad;
  40. val = msg[i] + (val << 8);
  41. if ((i % 4) == 3) {
  42. *buf++ = val;
  43. val = pad;
  44. num--;
  45. }
  46. }
  47. if (--num >= 0)
  48. *buf++ = val;
  49. while (--num >= 0)
  50. *buf++ = pad;
  51. }
  52. int btrfs_name_hash(const char *name, int len, u64 *hash_result)
  53. {
  54. __u32 hash;
  55. __u32 minor_hash = 0;
  56. const char *p;
  57. __u32 in[8], buf[2];
  58. /* Initialize the default seed for the hash checksum functions */
  59. buf[0] = 0x67452301;
  60. buf[1] = 0xefcdab89;
  61. buf[2] = 0x98badcfe;
  62. buf[3] = 0x10325476;
  63. p = name;
  64. while (len > 0) {
  65. str2hashbuf(p, len, in, 4);
  66. TEA_transform(buf, in);
  67. len -= 16;
  68. p += 16;
  69. }
  70. hash = buf[0];
  71. minor_hash = buf[1];
  72. *hash_result = buf[0];
  73. *hash_result <<= 32;
  74. *hash_result |= buf[1];
  75. return 0;
  76. }