LCOV - code coverage report
Current view: top level - fs/ext4 - hash.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 40 86 46.5 %
Date: 2014-02-18 Functions: 2 4 50.0 %
Branches: 21 52 40.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  linux/fs/ext4/hash.c
       3                 :            :  *
       4                 :            :  * Copyright (C) 2002 by Theodore Ts'o
       5                 :            :  *
       6                 :            :  * This file is released under the GPL v2.
       7                 :            :  *
       8                 :            :  * This file may be redistributed under the terms of the GNU Public
       9                 :            :  * License.
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/fs.h>
      13                 :            : #include <linux/jbd2.h>
      14                 :            : #include <linux/cryptohash.h>
      15                 :            : #include "ext4.h"
      16                 :            : 
      17                 :            : #define DELTA 0x9E3779B9
      18                 :            : 
      19                 :          0 : static void TEA_transform(__u32 buf[4], __u32 const in[])
      20                 :            : {
      21                 :            :         __u32   sum = 0;
      22                 :          0 :         __u32   b0 = buf[0], b1 = buf[1];
      23                 :          0 :         __u32   a = in[0], b = in[1], c = in[2], d = in[3];
      24                 :            :         int     n = 16;
      25                 :            : 
      26                 :            :         do {
      27                 :          0 :                 sum += DELTA;
      28                 :          0 :                 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
      29                 :          0 :                 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
      30         [ #  # ]:          0 :         } while (--n);
      31                 :            : 
      32                 :          0 :         buf[0] += b0;
      33                 :          0 :         buf[1] += b1;
      34                 :          0 : }
      35                 :            : 
      36                 :            : 
      37                 :            : /* The old legacy hash */
      38                 :            : static __u32 dx_hack_hash_unsigned(const char *name, int len)
      39                 :            : {
      40                 :            :         __u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
      41                 :            :         const unsigned char *ucp = (const unsigned char *) name;
      42                 :            : 
      43         [ -  + ]:          2 :         while (len--) {
      44                 :          0 :                 hash = hash1 + (hash0 ^ (((int) *ucp++) * 7152373));
      45                 :            : 
      46         [ #  # ]:          0 :                 if (hash & 0x80000000)
      47                 :          0 :                         hash -= 0x7fffffff;
      48                 :            :                 hash1 = hash0;
      49                 :            :                 hash0 = hash;
      50                 :            :         }
      51                 :          2 :         return hash0 << 1;
      52                 :            : }
      53                 :            : 
      54                 :            : static __u32 dx_hack_hash_signed(const char *name, int len)
      55                 :            : {
      56                 :            :         __u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
      57                 :            :         const signed char *scp = (const signed char *) name;
      58                 :            : 
      59         [ #  # ]:          0 :         while (len--) {
      60                 :          0 :                 hash = hash1 + (hash0 ^ (((int) *scp++) * 7152373));
      61                 :            : 
      62         [ #  # ]:          0 :                 if (hash & 0x80000000)
      63                 :          0 :                         hash -= 0x7fffffff;
      64                 :            :                 hash1 = hash0;
      65                 :            :                 hash0 = hash;
      66                 :            :         }
      67                 :          0 :         return hash0 << 1;
      68                 :            : }
      69                 :            : 
      70                 :          0 : static void str2hashbuf_signed(const char *msg, int len, __u32 *buf, int num)
      71                 :            : {
      72                 :            :         __u32   pad, val;
      73                 :            :         int     i;
      74                 :            :         const signed char *scp = (const signed char *) msg;
      75                 :            : 
      76                 :     378070 :         pad = (__u32)len | ((__u32)len << 8);
      77                 :     378070 :         pad |= pad << 16;
      78                 :            : 
      79                 :            :         val = pad;
      80         [ +  + ]:     378070 :         if (len > num*4)
      81                 :            :                 len = num * 4;
      82         [ +  + ]:    4467468 :         for (i = 0; i < len; i++) {
      83         [ +  + ]:    4089398 :                 if ((i % 4) == 0)
      84                 :            :                         val = pad;
      85                 :    4089398 :                 val = ((int) scp[i]) + (val << 8);
      86         [ +  + ]:    4089398 :                 if ((i % 4) == 3) {
      87                 :     893356 :                         *buf++ = val;
      88                 :            :                         val = pad;
      89                 :     893356 :                         num--;
      90                 :            :                 }
      91                 :            :         }
      92         [ +  + ]:     378070 :         if (--num >= 0)
      93                 :     378070 :                 *buf++ = val;
      94         [ +  + ]:    2144585 :         while (--num >= 0)
      95                 :    1766515 :                 *buf++ = pad;
      96                 :     378070 : }
      97                 :            : 
      98                 :          0 : static void str2hashbuf_unsigned(const char *msg, int len, __u32 *buf, int num)
      99                 :            : {
     100                 :            :         __u32   pad, val;
     101                 :            :         int     i;
     102                 :            :         const unsigned char *ucp = (const unsigned char *) msg;
     103                 :            : 
     104                 :          0 :         pad = (__u32)len | ((__u32)len << 8);
     105                 :          0 :         pad |= pad << 16;
     106                 :            : 
     107                 :            :         val = pad;
     108         [ #  # ]:          0 :         if (len > num*4)
     109                 :            :                 len = num * 4;
     110         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     111         [ #  # ]:          0 :                 if ((i % 4) == 0)
     112                 :            :                         val = pad;
     113                 :          0 :                 val = ((int) ucp[i]) + (val << 8);
     114         [ #  # ]:          0 :                 if ((i % 4) == 3) {
     115                 :          0 :                         *buf++ = val;
     116                 :            :                         val = pad;
     117                 :          0 :                         num--;
     118                 :            :                 }
     119                 :            :         }
     120         [ #  # ]:          0 :         if (--num >= 0)
     121                 :          0 :                 *buf++ = val;
     122         [ #  # ]:          0 :         while (--num >= 0)
     123                 :          0 :                 *buf++ = pad;
     124                 :          0 : }
     125                 :            : 
     126                 :            : /*
     127                 :            :  * Returns the hash of a filename.  If len is 0 and name is NULL, then
     128                 :            :  * this function can be used to test whether or not a hash version is
     129                 :            :  * supported.
     130                 :            :  *
     131                 :            :  * The seed is an 4 longword (32 bits) "secret" which can be used to
     132                 :            :  * uniquify a hash.  If the seed is all zero's, then some default seed
     133                 :            :  * may be used.
     134                 :            :  *
     135                 :            :  * A particular hash version specifies whether or not the seed is
     136                 :            :  * represented, and whether or not the returned hash is 32 bits or 64
     137                 :            :  * bits.  32 bit hashes will return 0 for the minor hash.
     138                 :            :  */
     139                 :          0 : int ext4fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
     140                 :            : {
     141                 :            :         __u32   hash;
     142                 :            :         __u32   minor_hash = 0;
     143                 :            :         const char      *p;
     144                 :            :         int             i;
     145                 :            :         __u32           in[8], buf[4];
     146                 :            :         void            (*str2hashbuf)(const char *, int, __u32 *, int) =
     147                 :            :                                 str2hashbuf_signed;
     148                 :            : 
     149                 :            :         /* Initialize the default seed for the hash checksum functions */
     150                 :     365475 :         buf[0] = 0x67452301;
     151                 :     365475 :         buf[1] = 0xefcdab89;
     152                 :     365475 :         buf[2] = 0x98badcfe;
     153                 :     365475 :         buf[3] = 0x10325476;
     154                 :            : 
     155                 :            :         /* Check to see if the seed is all zero's */
     156            [ + ]:     365475 :         if (hinfo->seed) {
     157         [ +  - ]:     365481 :                 for (i = 0; i < 4; i++) {
     158         [ +  - ]:     365481 :                         if (hinfo->seed[i]) {
     159                 :     365481 :                                 memcpy(buf, hinfo->seed, sizeof(buf));
     160                 :     365481 :                                 break;
     161                 :            :                         }
     162                 :            :                 }
     163                 :            :         }
     164                 :            : 
     165   [ +  -  -  +  :     365475 :         switch (hinfo->hash_version) {
                -  -  - ]
     166                 :            :         case DX_HASH_LEGACY_UNSIGNED:
     167                 :            :                 hash = dx_hack_hash_unsigned(name, len);
     168                 :          2 :                 break;
     169                 :            :         case DX_HASH_LEGACY:
     170                 :            :                 hash = dx_hack_hash_signed(name, len);
     171                 :          0 :                 break;
     172                 :            :         case DX_HASH_HALF_MD4_UNSIGNED:
     173                 :            :                 str2hashbuf = str2hashbuf_unsigned;
     174                 :            :         case DX_HASH_HALF_MD4:
     175                 :            :                 p = name;
     176         [ +  + ]:     743540 :                 while (len > 0) {
     177                 :     378064 :                         (*str2hashbuf)(p, len, in, 8);
     178                 :     378066 :                         half_md4_transform(buf, in);
     179                 :     378067 :                         len -= 32;
     180                 :     378067 :                         p += 32;
     181                 :            :                 }
     182                 :     365476 :                 minor_hash = buf[2];
     183                 :     365476 :                 hash = buf[1];
     184                 :     365476 :                 break;
     185                 :            :         case DX_HASH_TEA_UNSIGNED:
     186                 :            :                 str2hashbuf = str2hashbuf_unsigned;
     187                 :            :         case DX_HASH_TEA:
     188                 :            :                 p = name;
     189         [ #  # ]:          0 :                 while (len > 0) {
     190                 :          0 :                         (*str2hashbuf)(p, len, in, 4);
     191                 :          0 :                         TEA_transform(buf, in);
     192                 :          0 :                         len -= 16;
     193                 :          0 :                         p += 16;
     194                 :            :                 }
     195                 :          0 :                 hash = buf[0];
     196                 :          0 :                 minor_hash = buf[1];
     197                 :          0 :                 break;
     198                 :            :         default:
     199                 :          0 :                 hinfo->hash = 0;
     200                 :          0 :                 return -1;
     201                 :            :         }
     202                 :     365478 :         hash = hash & ~1;
     203         [ -  + ]:     365478 :         if (hash == (EXT4_HTREE_EOF_32BIT << 1))
     204                 :            :                 hash = (EXT4_HTREE_EOF_32BIT - 1) << 1;
     205                 :     365478 :         hinfo->hash = hash;
     206                 :     365478 :         hinfo->minor_hash = minor_hash;
     207                 :     365478 :         return 0;
     208                 :            : }

Generated by: LCOV version 1.9