Skip to content

Commit

Permalink
Librhash: Add rhash_update_fd() function
Browse files Browse the repository at this point in the history
  • Loading branch information
rhash committed Oct 24, 2024
1 parent 27197f6 commit cf2adf2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 29 deletions.
86 changes: 58 additions & 28 deletions librhash/rhash.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,41 +493,71 @@ RHASH_API int rhash_msg(unsigned hash_id, const void* message, size_t length, un
return 0;
}

RHASH_API int rhash_file_update(rhash ctx, FILE* fd)
{
rhash_context_ext* const ectx = (rhash_context_ext*)ctx;
const size_t block_size = 8192;
/* universal file context to read a file into a buffer */
struct file_update_context {
union {
FILE* file_fd;
int int_fd;
};
unsigned char* buffer;
size_t length = 0;
int res = 0;
if (ectx->state != STATE_ACTIVE)
return 0; /* do nothing if canceled */
if (ctx == NULL) {
size_t buffer_size;
};
static ssize_t read_file_fd_impl(struct file_update_context *fctx)
{
size_t read_size;
if (feof(fctx->file_fd))
return 0;
read_size = fread(fctx->buffer, 1, fctx->buffer_size, fctx->file_fd);
return (ferror(fctx->file_fd) ? -1 : (ssize_t)read_size);
}
static ssize_t read_int_fd_impl(struct file_update_context *fctx)
{
return read(fctx->int_fd, fctx->buffer, fctx->buffer_size);
}
typedef ssize_t (*read_file_func)(struct file_update_context *fctx);

static int rhash_file_update_impl(
struct rhash_context_ext* const ectx,
struct file_update_context* const fctx,
read_file_func read_func)
{
const size_t buffer_size = 256 * 1024;
ssize_t length;
if (ectx == NULL) {
errno = EINVAL;
return -1;
}
buffer = (unsigned char*)rhash_aligned_alloc(DEFAULT_ALIGNMENT, block_size);
if (!buffer)
if (ectx->state != STATE_ACTIVE)
return 0; /* do nothing if canceled */
fctx->buffer_size = buffer_size;
fctx->buffer = (unsigned char*)rhash_aligned_alloc(DEFAULT_ALIGNMENT, buffer_size);
if (!fctx->buffer) {
return -1; /* errno is set to ENOMEM according to UNIX 98 */

while (!feof(fd)) {
if (ectx->state != STATE_ACTIVE)
break; /* stop if canceled */
length = fread(buffer, 1, block_size, fd);

if (ferror(fd)) {
res = -1; /* note: errno contains error code */
break;
} else if (length) {
rhash_update(ctx, buffer, length);

if (ectx->callback) {
((rhash_callback_t)ectx->callback)(ectx->callback_data, ectx->rc.msg_size);
}
}
while ((length = read_func(fctx)) > 0 && ectx->state == STATE_ACTIVE) {
rhash_update(&ectx->rc, fctx->buffer, (size_t)length);
if (ectx->callback) {
((rhash_callback_t)ectx->callback)(ectx->callback_data, ectx->rc.msg_size);
}
}
rhash_aligned_free(buffer);
return res;
rhash_aligned_free(fctx->buffer);
return (length < 0 ? -1 : 0);
}

RHASH_API int rhash_update_fd(rhash ctx, int fd)
{
struct file_update_context fctx;
memset(&fctx, 0, sizeof(fctx));
fctx.int_fd = fd;
return rhash_file_update_impl((rhash_context_ext*)ctx, &fctx, read_int_fd_impl);
}

RHASH_API int rhash_file_update(rhash ctx, FILE* fd)
{
struct file_update_context fctx;
memset(&fctx, 0, sizeof(fctx));
fctx.file_fd = fd;
return rhash_file_update_impl((rhash_context_ext*)ctx, &fctx, read_file_fd_impl);
}

#ifdef _WIN32
Expand Down
17 changes: 16 additions & 1 deletion librhash/rhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ RHASH_API rhash rhash_init(unsigned hash_id);
*/
RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);

/**
* Calculate message digests of a file or stream.
* Multiple message digests can be computed.
* First, inintialize ctx parameter with rhash_init() before calling
* rhash_update_fd(). Then use rhash_final() and rhash_print()
* to retrive message digests. Finaly call rhash_free() on ctx
* to free allocated memory or call rhash_reset() to reuse ctx.
* The file descriptor must correspond to an opened file or stream.
*
* @param ctx the rhash context
* @param fd descriptor of the file to process
* @return 0 on success, -1 on fail with error code stored in errno
*/
RHASH_API int rhash_update_fd(rhash ctx, int fd);

/**
* Process a file or stream. Multiple message digests can be computed.
* First, inintialize ctx parameter with rhash_init() before calling
Expand All @@ -201,7 +216,7 @@ RHASH_API int rhash_update(rhash ctx, const void* message, size_t length);
* to free allocated memory or call rhash_reset() to reuse ctx.
*
* @param ctx rhash context
* @param fd descriptor of the file to hash
* @param fd descriptor of the file to process
* @return 0 on success, -1 on fail with error code stored in errno
*/
RHASH_API int rhash_file_update(rhash ctx, FILE* fd);
Expand Down

0 comments on commit cf2adf2

Please sign in to comment.