Skip to content

Commit 0187df9

Browse files
committed
Librhash: Add data_size parameter to rhash_update_fd()
1 parent 22f215f commit 0187df9

File tree

5 files changed

+251
-40
lines changed

5 files changed

+251
-40
lines changed

librhash/byte_order.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ int has_cpu_feature(unsigned feature_bit);
224224
# define HAS_MSVC_INTEL_CPUID
225225
int has_cpu_feature(unsigned feature_bit);
226226
#else
227+
# define NO_HAS_CPU_FEATURE
227228
# define has_cpu_feature(x) (0)
228229
#endif
229230

librhash/rhash.c

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ static unsigned convert_to_extended_hash_id(unsigned hash_id)
448448
* Find rhash_vector_item by the given hash_id in rhash context.
449449
* The context must include the hash algorithm corresponding to the hash_id.
450450
*
451-
* @param ectx rhash context
451+
* @param ectx extended rhash context
452452
* @param hash_id id of hash algorithm, or zero for the first hash algorithm in the rhash context
453453
* @return item of the rhash context if the hash algorithm has been found, NULL otherwise
454454
*/
@@ -516,36 +516,76 @@ RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, un
516516
return 0;
517517
}
518518

519-
/* universal file context to read a file into a buffer */
519+
/**
520+
* Universal file I/O context for buffered file reading.
521+
*/
520522
struct file_update_context {
521523
union {
522-
FILE* file_fd;
523-
int int_fd;
524+
FILE* file_fd; /* Standard C file stream pointer (for fopen/fread) */
525+
int int_fd; /* POSIX file descriptor (for open/read) */
524526
};
525-
unsigned char* buffer;
526-
size_t buffer_size;
527+
unsigned char* buffer; /* Data buffer for read operations */
528+
size_t buffer_size; /* Size of the data buffer */
527529
};
528-
static ssize_t read_file_fd_impl(struct file_update_context *fctx)
530+
531+
/**
532+
* Read data from a C file stream into the context buffer using fread().
533+
*
534+
* @param fctx file context containing a file descriptor and buffer
535+
* @param data_size number of bytes to read
536+
* @return number of bytes read on success, -1 on fail with error code stored in errno
537+
*/
538+
static ssize_t read_file_fd_impl(struct file_update_context *fctx, size_t data_size)
529539
{
530540
size_t read_size;
531541
if (feof(fctx->file_fd))
532542
return 0;
533-
read_size = fread(fctx->buffer, 1, fctx->buffer_size, fctx->file_fd);
543+
assert(data_size <= fctx->buffer_size);
544+
read_size = fread(fctx->buffer, 1, data_size, fctx->file_fd);
534545
return (ferror(fctx->file_fd) ? -1 : (ssize_t)read_size);
535546
}
536-
static ssize_t read_int_fd_impl(struct file_update_context *fctx)
547+
548+
/**
549+
* Read data from a POSIX file descriptor into the context buffer using read().
550+
*
551+
* @param fctx file context containing a file descriptor and buffer
552+
* @param data_size number of bytes to read
553+
* @return number of bytes read on success, -1 on fail with error code stored in errno
554+
*/
555+
static ssize_t read_int_fd_impl(struct file_update_context *fctx, size_t data_size)
537556
{
538-
return read(fctx->int_fd, fctx->buffer, fctx->buffer_size);
557+
assert(data_size <= fctx->buffer_size);
558+
return read(fctx->int_fd, fctx->buffer, data_size);
539559
}
540-
typedef ssize_t (*read_file_func)(struct file_update_context *fctx);
541560

561+
/**
562+
* File read operation callback signature.
563+
*
564+
* @param fctx file context with configured buffer and file handle
565+
* @param data_size requested read size
566+
* @return bytes read (0 = EOF), or -1 on error (must set errno)
567+
*/
568+
typedef ssize_t (*read_file_func)(struct file_update_context *fctx, size_t data_size);
569+
570+
/**
571+
* Internal implementation for hashing file/stream data.
572+
* Used by rhash_update_fd() and rhash_file_update().
573+
*
574+
* @param ectx extended rhash context (must be initialized)
575+
* @param fctx configured file context (buffer must be pre-allocated)
576+
* @param read_func callback for reading data
577+
* @param data_size maximum bytes to hash (RHASH_MAX_FILE_SIZE for entire file)
578+
* @return 0 on success, -1 on fail with error code stored in errno
579+
*/
542580
static int rhash_file_update_impl(
543581
struct rhash_context_ext* const ectx,
544582
struct file_update_context* const fctx,
545-
read_file_func read_func)
583+
read_file_func read_func,
584+
unsigned long long data_size)
546585
{
547586
const size_t buffer_size = 256 * 1024;
548-
ssize_t length;
587+
size_t read_size = buffer_size;
588+
ssize_t length = 0;
549589
if (ectx == NULL) {
550590
errno = EINVAL;
551591
return -1;
@@ -557,7 +597,13 @@ static int rhash_file_update_impl(
557597
if (!fctx->buffer) {
558598
return -1; /* errno is set to ENOMEM according to UNIX 98 */
559599
}
560-
while ((length = read_func(fctx)) > 0 && ectx->state == STATE_ACTIVE) {
600+
while (data_size > (size_t)length) {
601+
data_size -= (size_t)length;
602+
if (data_size < read_size)
603+
read_size = (size_t)data_size;
604+
length = read_func(fctx, read_size);
605+
if (length <= 0 || ectx->state != STATE_ACTIVE)
606+
break;
561607
rhash_update(&ectx->rc, fctx->buffer, (size_t)length);
562608
if (ectx->callback) {
563609
((rhash_callback_t)ectx->callback)(ectx->callback_data, ectx->rc.msg_size);
@@ -567,20 +613,22 @@ static int rhash_file_update_impl(
567613
return (length < 0 ? -1 : 0);
568614
}
569615

570-
RHASH_API int rhash_update_fd(rhash ctx, int fd)
616+
RHASH_API int rhash_update_fd(rhash ctx, int fd, unsigned long long data_size)
571617
{
572618
struct file_update_context fctx;
573619
memset(&fctx, 0, sizeof(fctx));
574620
fctx.int_fd = fd;
575-
return rhash_file_update_impl((rhash_context_ext*)ctx, &fctx, read_int_fd_impl);
621+
return rhash_file_update_impl((rhash_context_ext*)ctx,
622+
&fctx, read_int_fd_impl, data_size);
576623
}
577624

578625
RHASH_API int rhash_file_update(rhash ctx, FILE* fd)
579626
{
580627
struct file_update_context fctx;
581628
memset(&fctx, 0, sizeof(fctx));
582629
fctx.file_fd = fd;
583-
return rhash_file_update_impl((rhash_context_ext*)ctx, &fctx, read_file_fd_impl);
630+
return rhash_file_update_impl((rhash_context_ext*)ctx,
631+
&fctx, read_file_fd_impl, RHASH_MAX_FILE_SIZE);
584632
}
585633

586634
#ifdef _WIN32

librhash/rhash.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,25 +201,31 @@ RHASH_API rhash rhash_init(unsigned hash_id);
201201
RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);
202202

203203
/**
204+
* Special value meaning "read and hash until end of file".
205+
*/
206+
#define RHASH_MAX_FILE_SIZE ((unsigned long long)-1)
207+
208+
/**
204209
* Calculate message digests of a file or stream.
205210
* Multiple message digests can be computed.
206-
* First, inintialize ctx parameter with rhash_init() before calling
211+
* First, initialize ctx parameter with rhash_init() before calling
207212
* rhash_update_fd(). Then use rhash_final() and rhash_print()
208-
* to retrive message digests. Finaly call rhash_free() on ctx
213+
* to retrieve message digests. Finally, call rhash_free() on ctx
209214
* to free allocated memory or call rhash_reset() to reuse ctx.
210215
* The file descriptor must correspond to an opened file or stream.
211216
*
212-
* @param ctx the rhash context
217+
* @param ctx the rhash context (must be initialized)
213218
* @param fd descriptor of the file to process
219+
* @param data_size maximum bytes to process (RHASH_MAX_FILE_SIZE for entire file)
214220
* @return 0 on success, -1 on fail with error code stored in errno
215221
*/
216-
RHASH_API int rhash_update_fd(rhash ctx, int fd);
222+
RHASH_API int rhash_update_fd(rhash ctx, int fd, unsigned long long data_size);
217223

218224
/**
219225
* Process a file or stream. Multiple message digests can be computed.
220226
* First, inintialize ctx parameter with rhash_init() before calling
221227
* rhash_file_update(). Then use rhash_final() and rhash_print()
222-
* to retrive message digests. Finaly call rhash_free() on ctx
228+
* to retrieve message digests. Finally, call rhash_free() on ctx
223229
* to free allocated memory or call rhash_reset() to reuse ctx.
224230
*
225231
* @param ctx rhash context

librhash/sha3.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,11 @@ void rhash_sha3_final(sha3_ctx* ctx, unsigned char* result)
334334

335335
#ifdef USE_KECCAK
336336
/**
337-
* Store calculated hash into the given array.
338-
*
339-
* @param ctx the algorithm context containing current hashing state
340-
* @param result calculated hash in binary form
341-
*/
337+
* Store calculated hash into the given array.
338+
*
339+
* @param ctx the algorithm context containing current hashing state
340+
* @param result calculated hash in binary form
341+
*/
342342
void rhash_keccak_final(sha3_ctx* ctx, unsigned char* result)
343343
{
344344
size_t digest_length = 100 - ctx->block_size / 2;

0 commit comments

Comments
 (0)