Fixes so "make allnoconfig" works again.
[oweals/busybox.git] / libbb / hash_fd.c
index b95c1369b3c808d3d9ac93ad9534e3095b3b2d32..5f12259b3d6482161b6049fb86eebeaa6c57beb3 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2003 Glenn L. McGrath
  *  Copyright (C) 2003 Erik Andersen
- * 
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
 
  LICENSE TERMS
 
- The free distribution and use of this software in both source and binary 
+ The free distribution and use of this software in both source and binary
  form is allowed (with or without changes) provided that:
 
-   1. distributions of this source code include the above copyright 
+   1. distributions of this source code include the above copyright
       notice, this list of conditions and the following disclaimer;
 
    2. distributions in binary form include the above copyright
       notice, this list of conditions and the following disclaimer
       in the documentation and/or other associated materials;
 
-   3. the copyright holder's name is not used to endorse products 
-      built using this software without specific written permission. 
+   3. the copyright holder's name is not used to endorse products
+      built using this software without specific written permission.
 
  ALTERNATIVELY, provided that this notice is retained in full, this product
  may be distributed under the terms of the GNU General Public License (GPL),
  in which case the provisions of the GPL apply INSTEAD OF those given above.
+
  DISCLAIMER
 
  This software is provided 'as is' with no explicit or implied warranties
- in respect of its properties, including, but not limited to, correctness 
+ in respect of its properties, including, but not limited to, correctness
  and/or fitness for purpose.
  ---------------------------------------------------------------------------
  Issue Date: 10/11/2002
@@ -95,9 +95,9 @@
 # define SHA1_MASK   (SHA1_BLOCK_SIZE - 1)
 
 /* reverse byte order in 32-bit words   */
-# define ch(x,y,z)       (((x) & (y)) ^ (~(x) & (z)))
-# define parity(x,y,z)   ((x) ^ (y) ^ (z))
-# define maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#define ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))
+#define parity(x,y,z)   ((x) ^ (y) ^ (z))
+#define maj(x,y,z)      (((x) & (y)) | ((z) & ((x) | (y))))
 
 /* A normal version as set out in the FIPS. This version uses   */
 /* partial loop unrolling and is optimised for the Pentium 4    */
     e = d; d = c; c = rotl32(b, 30); b = t
 
 /* type to hold the SHA1 context  */
-typedef struct {
+struct sha1_ctx_t {
        uint32_t count[2];
        uint32_t hash[5];
        uint32_t wbuf[16];
-} sha1_ctx;
+};
 
-static void sha1_compile(sha1_ctx ctx[1])
+static void sha1_compile(struct sha1_ctx_t *ctx)
 {
        uint32_t w[80], i, a, b, c, d, e, t;
 
@@ -154,7 +154,7 @@ static void sha1_compile(sha1_ctx ctx[1])
        ctx->hash[4] += e;
 }
 
-static void sha1_begin(sha1_ctx ctx[1])
+static void sha1_begin(struct sha1_ctx_t *ctx)
 {
        ctx->count[0] = ctx->count[1] = 0;
        ctx->hash[0] = 0x67452301;
@@ -166,10 +166,11 @@ static void sha1_begin(sha1_ctx ctx[1])
 
 /* SHA1 hash data in an array of bytes into hash buffer and call the        */
 /* hash_compile function as required.                                       */
-static void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1])
+static void sha1_hash(const void *data, size_t len, void *ctx_v)
 {
-       uint32_t pos = (uint32_t) (ctx->count[0] & SHA1_MASK),
-               freeb = SHA1_BLOCK_SIZE - pos;
+       struct sha1_ctx_t *ctx = (struct sha1_ctx_t *) ctx_v;
+       uint32_t pos = (uint32_t) (ctx->count[0] & SHA1_MASK);
+       uint32_t freeb = SHA1_BLOCK_SIZE - pos;
        const unsigned char *sp = data;
 
        if ((ctx->count[0] += len) < len)
@@ -196,7 +197,7 @@ static uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
 static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
 # endif /* __BYTE_ORDER */
 
-void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
+static void sha1_end(unsigned char hval[], struct sha1_ctx_t *ctx)
 {
        uint32_t i, cnt = (uint32_t) (ctx->count[0] & SHA1_MASK);
 
@@ -275,6 +276,8 @@ void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
 /* Handle endian-ness */
 # if __BYTE_ORDER == __LITTLE_ENDIAN
 #  define SWAP(n) (n)
+# elif defined(bswap_32)
+#  define SWAP(n) bswap_32(n)
 # else
 #  define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
 # endif
@@ -285,24 +288,21 @@ void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */  };
 # endif        /* MD5SUM_SIZE_VS_SPEED == 0 */
 
-typedef u_int32_t md5_uint32;
-
 /* Structure to save state of computation between the single steps.  */
-struct md5_ctx {
-       md5_uint32 A;
-       md5_uint32 B;
-       md5_uint32 C;
-       md5_uint32 D;
-
-       md5_uint32 total[2];
-       md5_uint32 buflen;
+struct md5_ctx_t {
+       uint32_t A;
+       uint32_t B;
+       uint32_t C;
+       uint32_t D;
+       uint32_t total[2];
+       uint32_t buflen;
        char buffer[128];
 };
 
 /* Initialize structure containing state of computation.
  * (RFC 1321, 3.3: Step 3)
  */
-static void md5_begin(struct md5_ctx *ctx)
+static void md5_begin(struct md5_ctx_t *ctx)
 {
        ctx->A = 0x67452301;
        ctx->B = 0xefcdab89;
@@ -328,16 +328,15 @@ static void md5_begin(struct md5_ctx *ctx)
  * starting at BUFFER.
  * It is necessary that LEN is a multiple of 64!!!
  */
-static void md5_hash_block(const void *buffer, size_t len,
-                                                  struct md5_ctx *ctx)
+static void md5_hash_block(const void *buffer, size_t len, struct md5_ctx_t *ctx)
 {
-       md5_uint32 correct_words[16];
-       const md5_uint32 *words = buffer;
-       size_t nwords = len / sizeof(md5_uint32);
-       const md5_uint32 *endp = words + nwords;
+       uint32_t correct_words[16];
+       const uint32_t *words = buffer;
+       size_t nwords = len / sizeof(uint32_t);
+       const uint32_t *endp = words + nwords;
 
 # if MD5SUM_SIZE_VS_SPEED > 0
-       static const md5_uint32 C_array[] = {
+       static const uint32_t C_array[] = {
                /* round 1 */
                0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
                0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
@@ -379,10 +378,10 @@ static void md5_hash_block(const void *buffer, size_t len,
 #  endif       /* MD5SUM_SIZE_VS_SPEED > 1 */
 # endif
 
-       md5_uint32 A = ctx->A;
-       md5_uint32 B = ctx->B;
-       md5_uint32 C = ctx->C;
-       md5_uint32 D = ctx->D;
+       uint32_t A = ctx->A;
+       uint32_t B = ctx->B;
+       uint32_t C = ctx->C;
+       uint32_t D = ctx->D;
 
        /* First increment the byte count.  RFC 1321 specifies the possible
           length of the file up to 2^64 bits.  Here we only compute the
@@ -394,20 +393,20 @@ static void md5_hash_block(const void *buffer, size_t len,
        /* Process all bytes in the buffer with 64 bytes in each round of
           the loop.  */
        while (words < endp) {
-               md5_uint32 *cwp = correct_words;
-               md5_uint32 A_save = A;
-               md5_uint32 B_save = B;
-               md5_uint32 C_save = C;
-               md5_uint32 D_save = D;
+               uint32_t *cwp = correct_words;
+               uint32_t A_save = A;
+               uint32_t B_save = B;
+               uint32_t C_save = C;
+               uint32_t D_save = D;
 
 # if MD5SUM_SIZE_VS_SPEED > 1
 #  define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
 
-               const md5_uint32 *pc;
+               const uint32_t *pc;
                const char *pp;
                const char *ps;
                int i;
-               md5_uint32 temp;
+               uint32_t temp;
 
                for (i = 0; i < 16; i++) {
                        cwp[i] = SWAP(words[i]);
@@ -521,7 +520,7 @@ static void md5_hash_block(const void *buffer, size_t len,
                 */
 
 #  if MD5SUM_SIZE_VS_SPEED == 1
-               const md5_uint32 *pc;
+               const uint32_t *pc;
                const char *pp;
                int i;
 #  endif       /* MD5SUM_SIZE_VS_SPEED */
@@ -670,8 +669,7 @@ static void md5_hash_block(const void *buffer, size_t len,
  * It is NOT required that LEN is a multiple of 64.
  */
 
-static void md5_hash_bytes(const void *buffer, size_t len,
-                                                  struct md5_ctx *ctx)
+static void md5_hash_bytes(const void *buffer, size_t len, struct md5_ctx_t *ctx)
 {
        /* When we already have some bits in our internal buffer concatenate
           both inputs first.  */
@@ -708,6 +706,15 @@ static void md5_hash_bytes(const void *buffer, size_t len,
        }
 }
 
+static void md5_hash(const void *buffer, size_t length, void *md5_ctx)
+{
+       if (length % 64 == 0) {
+               md5_hash_block(buffer, length, md5_ctx);
+       } else {
+               md5_hash_bytes(buffer, length, md5_ctx);
+       }
+}
+
 /* Process the remaining bytes in the buffer and put result from CTX
  * in first 16 bytes following RESBUF.  The result is always in little
  * endian byte order, so that a byte-wise output yields to the wanted
@@ -716,10 +723,10 @@ static void md5_hash_bytes(const void *buffer, size_t len,
  * IMPORTANT: On some systems it is required that RESBUF is correctly
  * aligned for a 32 bits value.
  */
-static void *md5_end(void *resbuf, struct md5_ctx *ctx)
+static void *md5_end(void *resbuf, struct md5_ctx_t *ctx)
 {
        /* Take yet unprocessed bytes into account.  */
-       md5_uint32 bytes = ctx->buflen;
+       uint32_t bytes = ctx->buflen;
        size_t pad;
 
        /* Now count remaining bytes.  */
@@ -736,8 +743,8 @@ static void *md5_end(void *resbuf, struct md5_ctx *ctx)
 # endif        /* MD5SUM_SIZE_VS_SPEED > 0 */
 
        /* Put the 64-bit file length in *bits* at the end of the buffer.  */
-       *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
-       *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
+       *(uint32_t *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
+       *(uint32_t *) & ctx->buffer[bytes + pad + 4] =
                SWAP(((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
 
        /* Process last bytes.  */
@@ -750,10 +757,10 @@ static void *md5_end(void *resbuf, struct md5_ctx *ctx)
         * IMPORTANT: On some systems it is required that RESBUF is correctly
         * aligned for a 32 bits value.
         */
-       ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
-       ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
-       ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
-       ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
+       ((uint32_t *) resbuf)[0] = SWAP(ctx->A);
+       ((uint32_t *) resbuf)[1] = SWAP(ctx->B);
+       ((uint32_t *) resbuf)[2] = SWAP(ctx->C);
+       ((uint32_t *) resbuf)[3] = SWAP(ctx->D);
 
        return resbuf;
 }
@@ -762,18 +769,22 @@ static void *md5_end(void *resbuf, struct md5_ctx *ctx)
 
 
 
-extern int hash_fd(int src_fd, const off_t size, const uint8_t hash_algo,
+extern int hash_fd(int src_fd, const size_t size, const uint8_t hash_algo,
                                   uint8_t * hashval)
 {
        int result = EXIT_SUCCESS;
-       off_t hashed_count = 0;
-       unsigned int blocksize = 0;
+//     size_t hashed_count = 0;
+       size_t blocksize = 0;
+       size_t remaining = size;
        unsigned char *buffer = NULL;
+       void (*hash_fn_ptr)(const void *, size_t, void *) = NULL;
+       void *cx = NULL;
+
 #ifdef CONFIG_SHA1SUM
-       sha1_ctx sha1_cx[1];
+       struct sha1_ctx_t sha1_cx;
 #endif
 #ifdef CONFIG_MD5SUM
-       struct md5_ctx md5_cx;
+       struct md5_ctx_t md5_cx;
 #endif
 
 
@@ -781,20 +792,24 @@ extern int hash_fd(int src_fd, const off_t size, const uint8_t hash_algo,
        if (hash_algo == HASH_SHA1) {
                /* Ensure that BLOCKSIZE is a multiple of 64.  */
                blocksize = 65536;
-               buffer = malloc(blocksize);
+               buffer = xmalloc(blocksize);
+               hash_fn_ptr = sha1_hash;
+               cx = &sha1_cx;
        }
 #endif
 #ifdef CONFIG_MD5SUM
        if (hash_algo == HASH_MD5) {
                blocksize = 4096;
-               buffer = malloc(blocksize + 72);
+               buffer = xmalloc(blocksize + 72);
+               hash_fn_ptr = md5_hash;
+               cx = &md5_cx;
        }
 #endif
-       
+
        /* Initialize the computation context.  */
 #ifdef CONFIG_SHA1SUM
        if (hash_algo == HASH_SHA1) {
-               sha1_begin(sha1_cx);
+               sha1_begin(&sha1_cx);
        }
 #endif
 #ifdef CONFIG_MD5SUM
@@ -803,38 +818,34 @@ extern int hash_fd(int src_fd, const off_t size, const uint8_t hash_algo,
        }
 #endif
        /* Iterate over full file contents.  */
-       do {
-               const ssize_t count = bb_full_read(src_fd, buffer, blocksize);
-
-               if (count < 1) {
+       while ((remaining == (size_t) -1) || (remaining > 0)) {
+               size_t read_try;
+               ssize_t read_got;
+
+               if (remaining > blocksize) {
+                       read_try = blocksize;
+               } else {
+                       read_try = remaining;
+               }
+               read_got = bb_full_read(src_fd, buffer, read_try);
+               if (read_got < 1) {
                        /* count == 0 means short read
                         * count == -1 means read error */
-                       result = count - 1;
+                       result = read_got - 1;
                        break;
                }
-               hashed_count += count;
+               if (remaining != (size_t) -1) {
+                       remaining -= read_got;
+               }
 
                /* Process buffer */
-#ifdef CONFIG_SHA1SUM
-               if (hash_algo == HASH_SHA1) {
-                       sha1_hash(buffer, count, sha1_cx);
-               }
-#endif
-#ifdef CONFIG_MD5SUM
-               if (hash_algo == HASH_MD5) {
-                       if (count % 64 == 0) {
-                               md5_hash_block(buffer, count, &md5_cx);
-                       } else {
-                               md5_hash_bytes(buffer, count, &md5_cx);
-                       }
-               }
-#endif
-       } while ((size == (off_t) - 1) || (hashed_count < size));
+               hash_fn_ptr(buffer, read_got, cx);
+       }
 
        /* Finalize and write the hash into our buffer.  */
 #ifdef CONFIG_SHA1SUM
        if (hash_algo == HASH_SHA1) {
-               sha1_end(hashval, sha1_cx);
+               sha1_end(hashval, &sha1_cx);
        }
 #endif
 #ifdef CONFIG_MD5SUM