2007-06-12 09:07:21 -04:00
/*
* Copyright ( C ) 2007 Oracle . All rights reserved .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public
* License along with this program ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 021110 - 1307 , USA .
*/
2007-03-15 12:56:47 -04:00
/*
* Original copy from :
* linux / fs / ext3 / hash . c
*
* Copyright ( C ) 2002 by Theodore Ts ' o
*
* This file is released under the GPL v2 .
*
* This file may be redistributed under the terms of the GNU Public
* License .
*/
2007-03-22 12:13:20 -04:00
# include <linux/types.h>
2007-05-02 15:53:43 -04:00
# include "hash.h"
2007-03-15 12:56:47 -04:00
# define DELTA 0x9E3779B9
static void TEA_transform ( __u32 buf [ 2 ] , __u32 const in [ ] )
{
__u32 sum = 0 ;
__u32 b0 = buf [ 0 ] , b1 = buf [ 1 ] ;
__u32 a = in [ 0 ] , b = in [ 1 ] , c = in [ 2 ] , d = in [ 3 ] ;
int n = 16 ;
do {
sum + = DELTA ;
b0 + = ( ( b1 < < 4 ) + a ) ^ ( b1 + sum ) ^ ( ( b1 > > 5 ) + b ) ;
b1 + = ( ( b0 < < 4 ) + c ) ^ ( b0 + sum ) ^ ( ( b0 > > 5 ) + d ) ;
} while ( - - n ) ;
buf [ 0 ] + = b0 ;
buf [ 1 ] + = b1 ;
}
static void str2hashbuf ( const char * msg , int len , __u32 * buf , int num )
{
__u32 pad , val ;
int i ;
pad = ( __u32 ) len | ( ( __u32 ) len < < 8 ) ;
pad | = pad < < 16 ;
val = pad ;
if ( len > num * 4 )
len = num * 4 ;
for ( i = 0 ; i < len ; i + + ) {
if ( ( i % 4 ) = = 0 )
val = pad ;
val = msg [ i ] + ( val < < 8 ) ;
if ( ( i % 4 ) = = 3 ) {
* buf + + = val ;
val = pad ;
num - - ;
}
}
if ( - - num > = 0 )
* buf + + = val ;
while ( - - num > = 0 )
* buf + + = pad ;
}
2008-02-15 10:40:52 -05:00
u64 btrfs_name_hash ( const char * name , int len )
2007-03-15 12:56:47 -04:00
{
__u32 hash ;
__u32 minor_hash = 0 ;
const char * p ;
2008-04-01 11:21:40 -04:00
__u32 in [ 8 ] , buf [ 4 ] ;
2008-02-15 10:40:52 -05:00
u64 hash_result ;
2007-03-15 12:56:47 -04:00
2007-03-22 12:13:20 -04:00
if ( len = = 1 & & * name = = ' . ' ) {
2008-02-15 10:40:52 -05:00
return 1 ;
2007-03-22 12:13:20 -04:00
} else if ( len = = 2 & & name [ 0 ] = = ' . ' & & name [ 1 ] = = ' . ' ) {
2008-02-15 10:40:52 -05:00
return 2 ;
2007-03-22 12:13:20 -04:00
}
2007-03-15 12:56:47 -04:00
/* Initialize the default seed for the hash checksum functions */
buf [ 0 ] = 0x67452301 ;
buf [ 1 ] = 0xefcdab89 ;
buf [ 2 ] = 0x98badcfe ;
buf [ 3 ] = 0x10325476 ;
p = name ;
while ( len > 0 ) {
str2hashbuf ( p , len , in , 4 ) ;
TEA_transform ( buf , in ) ;
len - = 16 ;
p + = 16 ;
}
hash = buf [ 0 ] ;
minor_hash = buf [ 1 ] ;
2008-02-15 10:40:52 -05:00
hash_result = buf [ 0 ] ;
hash_result < < = 32 ;
hash_result | = buf [ 1 ] ;
return hash_result ;
2007-03-15 12:56:47 -04:00
}