summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2013-03-24 18:05:24 +0100
committerHelmut Grohne <helmut@subdivi.de>2013-03-24 18:05:24 +0100
commit5ba224a5aa2c8adb662136e2b8838d1cb0d32f27 (patch)
treece9d5fa5aeb138cc24736d193005aa26a40fc0aa
parent614d6dd08948f25e86911e08efae53bf530d82d5 (diff)
downloadssdeep-5ba224a5aa2c8adb662136e2b8838d1cb0d32f27.tar.gz
rename functions and export them
Use fuzzy_ as a prefix like all of the previous ones. Export fuzzy_new, fuzzy_update, fuzzy_digest and fuzzy_free. These functions are sufficient to put the caller in control and build an API similar to Python's hashlib.
-rw-r--r--fuzzy.c49
-rw-r--r--fuzzy.h40
2 files changed, 64 insertions, 25 deletions
diff --git a/fuzzy.c b/fuzzy.c
index 2530872..19ba00b 100644
--- a/fuzzy.c
+++ b/fuzzy.c
@@ -100,7 +100,7 @@ struct blockhash_context {
unsigned int dlen;
};
-struct ssdeep_context {
+struct fuzzy_state {
unsigned int bhstart, bhend;
struct blockhash_context bh[NUM_BLOCKHASHES];
size_t total_size;
@@ -109,9 +109,9 @@ struct ssdeep_context {
#define SSDEEP_BS(index) (((uint32_t)MIN_BLOCKSIZE) << (index))
-static /*@only@*/ /*@null@*/ struct ssdeep_context *ssdeep_new(void) {
- struct ssdeep_context *self;
- if(NULL == (self = malloc(sizeof(struct ssdeep_context))))
+/*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_new(void) {
+ struct fuzzy_state *self;
+ if(NULL == (self = malloc(sizeof(struct fuzzy_state))))
return NULL;
self->bhstart = 0;
self->bhend = 1;
@@ -123,7 +123,7 @@ static /*@only@*/ /*@null@*/ struct ssdeep_context *ssdeep_new(void) {
return self;
}
-static void ssdeep_try_fork_blockhash(struct ssdeep_context *self) {
+static void fuzzy_try_fork_blockhash(struct fuzzy_state *self) {
struct blockhash_context *obh, *nbh;
if(self->bhend >= NUM_BLOCKHASHES)
return;
@@ -136,7 +136,7 @@ static void ssdeep_try_fork_blockhash(struct ssdeep_context *self) {
++self->bhend;
}
-static void ssdeep_try_reduce_blockhash(struct ssdeep_context *self) {
+static void fuzzy_try_reduce_blockhash(struct fuzzy_state *self) {
assert(self->bhstart < self->bhend);
if(self->bhend - self->bhstart < 2)
/* Need at least two working hashes. */
@@ -157,7 +157,7 @@ static void ssdeep_try_reduce_blockhash(struct ssdeep_context *self) {
static const char *b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static void ssdeep_engine_step(struct ssdeep_context *self, unsigned char c) {
+static void fuzzy_engine_step(struct fuzzy_state *self, unsigned char c) {
size_t h;
unsigned int i;
/* At each character we update the rolling hash and the normal hashes.
@@ -184,7 +184,7 @@ static void ssdeep_engine_step(struct ssdeep_context *self, unsigned char c) {
if(unlikely(0 == self->bh[i].dlen)) {
/* Can only happen 30 times. */
/* First step for this blocksize. Clone next. */
- ssdeep_try_fork_blockhash(self);
+ fuzzy_try_fork_blockhash(self);
}
if(self->bh[i].dlen < SPAMSUM_LENGTH - 1) {
/* We can have a problem with the tail overflowing. The
@@ -199,20 +199,19 @@ static void ssdeep_engine_step(struct ssdeep_context *self, unsigned char c) {
if(self->bh[i].dlen < SPAMSUM_LENGTH / 2)
self->bh[i].halfh = HASH_INIT;
} else
- ssdeep_try_reduce_blockhash(self);
+ fuzzy_try_reduce_blockhash(self);
}
}
-static int ssdeep_engine(struct ssdeep_context *self,
- const unsigned char *buffer, size_t buffer_size) {
+int fuzzy_update(struct fuzzy_state *self, const unsigned char *buffer,
+ size_t buffer_size) {
self->total_size += buffer_size;
for( ;buffer_size > 0; ++buffer, --buffer_size)
- ssdeep_engine_step(self, *buffer);
+ fuzzy_engine_step(self, *buffer);
return 0;
}
-static int ssdeep_digest(const struct ssdeep_context *self,
- /*@out@*/ char *result) {
+int fuzzy_digest(const struct fuzzy_state *self, /*@out@*/ char *result) {
unsigned int bi = self->bhstart;
uint32_t h = roll_sum(&self->roll);
int i, remain = FUZZY_MAX_RESULT - 1;
@@ -275,47 +274,47 @@ static int ssdeep_digest(const struct ssdeep_context *self,
return 0;
}
-static void ssdeep_free(/*@only@*/ struct ssdeep_context *self) {
+void fuzzy_free(/*@only@*/ struct fuzzy_state *self) {
free(self);
}
int fuzzy_hash_buf(const unsigned char *buf, uint32_t buf_len,
/*@out@*/ char *result) {
- struct ssdeep_context *ctx;
+ struct fuzzy_state *ctx;
int ret = -1;
- if(NULL == (ctx = ssdeep_new()))
+ if(NULL == (ctx = fuzzy_new()))
return -1;
- if(ssdeep_engine(ctx, buf, buf_len) < 0)
+ if(fuzzy_update(ctx, buf, buf_len) < 0)
goto out;
- if(ssdeep_digest(ctx, result) < 0)
+ if(fuzzy_digest(ctx, result) < 0)
goto out;
ret = 0;
out:
- ssdeep_free(ctx);
+ fuzzy_free(ctx);
return ret;
}
int fuzzy_hash_stream(FILE *handle, /*@out@*/ char *result) {
- struct ssdeep_context *ctx;
+ struct fuzzy_state *ctx;
unsigned char buffer[4096];
size_t n;
int ret = -1;
- if(NULL == (ctx = ssdeep_new()))
+ if(NULL == (ctx = fuzzy_new()))
return -1;
for(;;) {
n = fread(buffer, 1, 4096, handle);
if(0 == n)
break;
- if(ssdeep_engine(ctx, buffer, n) < 0)
+ if(fuzzy_update(ctx, buffer, n) < 0)
goto out;
}
if(ferror(handle) != 0)
goto out;
- if(ssdeep_digest(ctx, result) < 0)
+ if(fuzzy_digest(ctx, result) < 0)
goto out;
ret = 0;
out:
- ssdeep_free(ctx);
+ fuzzy_free(ctx);
return ret;
}
diff --git a/fuzzy.h b/fuzzy.h
index 32602e6..e08d9f1 100644
--- a/fuzzy.h
+++ b/fuzzy.h
@@ -30,6 +30,46 @@ extern "C" {
#ifndef FUZZY_H
#define FUZZY_H
+struct fuzzy_state;
+
+/**
+ * @brief Construct a fuzzy_state object and return it.
+ *
+ * To use it call fuzzy_update and fuzzy_digest on it. It must be disposed
+ * with fuzzy_free.
+ * @return the constructed fuzzy_state or NULL on failure
+ */
+extern /*@only@*/ /*@null@*/ struct fuzzy_state *fuzzy_new(void);
+
+/**
+ * @brief Feed the data contained in the given buffer to the state.
+ *
+ * When an error occurs, the state is undefined. In that case it must not be
+ * passed to any function besides fuzzy_free.
+ * @param buffer The data to be hashes
+ * @param buffer_size The length of the given buffer
+ * @return zero on success, non-zero on error
+ */
+extern int fuzzy_update(struct fuzzy_state *state, const unsigned char *buffer,
+ size_t buffer_size);
+
+/**
+ * @brief Obtain the fuzzy hash from the state.
+ *
+ * This operation does not change the state at all. It reports the hash for the
+ * concatenation of the data previously fed using fuzzy_update.
+ * @param result Where the fuzzy hash is stored. This variable
+ * must be allocated to hold at least FUZZY_MAX_RESULT bytes.
+ * @return zero on success, non-zero on error
+ */
+extern int fuzzy_digest(const struct fuzzy_state *state,
+ /*@out@*/ char *result);
+
+/**
+ * @brief Dispose a fuzzy state.
+ */
+extern void fuzzy_free(/*@only@*/ struct fuzzy_state *state);
+
/**
* @brief Compute the fuzzy hash of a buffer
*