@@ -448,7 +448,7 @@ static unsigned convert_to_extended_hash_id(unsigned hash_id)
448
448
* Find rhash_vector_item by the given hash_id in rhash context.
449
449
* The context must include the hash algorithm corresponding to the hash_id.
450
450
*
451
- * @param ectx rhash context
451
+ * @param ectx extended rhash context
452
452
* @param hash_id id of hash algorithm, or zero for the first hash algorithm in the rhash context
453
453
* @return item of the rhash context if the hash algorithm has been found, NULL otherwise
454
454
*/
@@ -516,36 +516,76 @@ RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, un
516
516
return 0 ;
517
517
}
518
518
519
- /* universal file context to read a file into a buffer */
519
+ /**
520
+ * Universal file I/O context for buffered file reading.
521
+ */
520
522
struct file_update_context {
521
523
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) */
524
526
};
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 */
527
529
};
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 )
529
539
{
530
540
size_t read_size ;
531
541
if (feof (fctx -> file_fd ))
532
542
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 );
534
545
return (ferror (fctx -> file_fd ) ? -1 : (ssize_t )read_size );
535
546
}
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 )
537
556
{
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 );
539
559
}
540
- typedef ssize_t (* read_file_func )(struct file_update_context * fctx );
541
560
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
+ */
542
580
static int rhash_file_update_impl (
543
581
struct rhash_context_ext * const ectx ,
544
582
struct file_update_context * const fctx ,
545
- read_file_func read_func )
583
+ read_file_func read_func ,
584
+ unsigned long long data_size )
546
585
{
547
586
const size_t buffer_size = 256 * 1024 ;
548
- ssize_t length ;
587
+ size_t read_size = buffer_size ;
588
+ ssize_t length = 0 ;
549
589
if (ectx == NULL ) {
550
590
errno = EINVAL ;
551
591
return -1 ;
@@ -557,7 +597,13 @@ static int rhash_file_update_impl(
557
597
if (!fctx -> buffer ) {
558
598
return -1 ; /* errno is set to ENOMEM according to UNIX 98 */
559
599
}
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 ;
561
607
rhash_update (& ectx -> rc , fctx -> buffer , (size_t )length );
562
608
if (ectx -> callback ) {
563
609
((rhash_callback_t )ectx -> callback )(ectx -> callback_data , ectx -> rc .msg_size );
@@ -567,20 +613,22 @@ static int rhash_file_update_impl(
567
613
return (length < 0 ? -1 : 0 );
568
614
}
569
615
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 )
571
617
{
572
618
struct file_update_context fctx ;
573
619
memset (& fctx , 0 , sizeof (fctx ));
574
620
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 );
576
623
}
577
624
578
625
RHASH_API int rhash_file_update (rhash ctx , FILE * fd )
579
626
{
580
627
struct file_update_context fctx ;
581
628
memset (& fctx , 0 , sizeof (fctx ));
582
629
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 );
584
632
}
585
633
586
634
#ifdef _WIN32
0 commit comments