[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#663520: Support for incremental updates, bigarrays and multithreading



Source: ocaml-sha
Version: 1.7-2
Followup-For: Bug #663520

Hi,

I've split up the patch into multiple files. Unfortunately I don't
have a github account, github won't let me file an issue without
one and I don't have time to wait for an account to be created before
leaving for the weekend.

But maybe one of the debian maintainer could submit the patches to

http://github.com/vincenthz/ocaml-sha/

and add the correct forwarded tag and links to the upstream BTS to the
debian bug.

MfG
	Goswin

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.1.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=C, LC_CTYPE=de_DE (charmap=ISO-8859-1)
Shell: /bin/sh linked to /bin/dash
Description: Incremental checksumming
 This patch exposes the context and provides incremental update
 functions for strings.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-16

---

Index: ocaml-sha-1.7/sha1.mli
===================================================================
--- ocaml-sha-1.7.orig/sha1.mli	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha1.mli	2012-03-16 18:30:03.000000000 +0100
@@ -14,12 +14,26 @@
 
 (** SHA1 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha1_init"
+
+(** Sha1.update ctx s ofs len updates the context with the substring
+    of s starting at character number ofs and containing len
+    characters. Unsafe: No range checking! *)
+external update: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha1_finalize"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Index: ocaml-sha-1.7/sha256.mli
===================================================================
--- ocaml-sha-1.7.orig/sha256.mli	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha256.mli	2012-03-16 18:30:45.000000000 +0100
@@ -14,12 +14,26 @@
 
 (** SHA256 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha256_init"
+
+(** Sha256.update ctx s ofs len updates the context with the substring
+    of s starting at character number ofs and containing len
+    characters. Unsafe: No range checking! *)
+external update: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha256_finalize"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Index: ocaml-sha-1.7/sha512.mli
===================================================================
--- ocaml-sha-1.7.orig/sha512.mli	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha512.mli	2012-03-16 18:31:10.000000000 +0100
@@ -14,12 +14,26 @@
 
 (** SHA512 OCaml binding *)
 
+(** context type - opaque *)
+type ctx
+
 (** digest type - opaque *)
 type t
 
 (** The zero digest *)
 val zero : t
 
+(** Create a new context *)
+external init: unit -> ctx = "stub_sha512_init"
+
+(** Sha512.update ctx s ofs len updates the context with the substring
+    of s starting at character number ofs and containing len
+    characters. Unsafe: No range checking! *)
+external update: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+
+(** Finalize the context and return digest *)
+external finalize: ctx -> t = "stub_sha512_finalize"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Description: safe string updates
 This patch renames the update function to unsafe_update_substring and
 introduces new functions update_string and update_substring that
 include range checks.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-16
---

Index: ocaml-sha-1.7/sha512.mli
===================================================================
--- ocaml-sha-1.7.orig/sha512.mli	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha512.mli	2012-03-16 18:51:44.000000000 +0100
@@ -26,10 +26,18 @@
 (** Create a new context *)
 external init: unit -> ctx = "stub_sha512_init"
 
-(** Sha512.update ctx s ofs len updates the context with the substring
-    of s starting at character number ofs and containing len
-    characters. Unsafe: No range checking! *)
-external update: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+(** Sha512.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+
+(** Sha512.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha512.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
 
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha512_finalize"
Index: ocaml-sha-1.7/sha256.ml
===================================================================
--- ocaml-sha-1.7.orig/sha256.ml	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha256.ml	2012-03-16 18:53:15.000000000 +0100
@@ -17,7 +17,7 @@
 type t
 
 external init: unit -> ctx = "stub_sha256_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha256_update"
 external finalize: ctx -> t = "stub_sha256_finalize"
 external copy : ctx -> ctx = "stub_sha256_copy"
 external to_bin: t -> string = "stub_sha256_to_bin"
@@ -29,16 +29,24 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
 let channel chan len =
@@ -53,7 +61,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Index: ocaml-sha-1.7/sha256_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha256_stubs.c	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha256_stubs.c	2012-03-16 18:51:44.000000000 +0100
@@ -45,6 +45,7 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
 #include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha256_ctx *) a)
@@ -69,6 +70,19 @@
 	CAMLreturn(Val_unit);
 }
 
+CAMLprim value stub_sha256_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha256_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
+
 CAMLprim value stub_sha256_finalize(value ctx)
 {
 	CAMLparam1(ctx);
Index: ocaml-sha-1.7/sha512.ml
===================================================================
--- ocaml-sha-1.7.orig/sha512.ml	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha512.ml	2012-03-16 18:53:30.000000000 +0100
@@ -17,7 +17,7 @@
 type t
 
 external init: unit -> ctx = "stub_sha512_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha512_update"
 external finalize: ctx -> t = "stub_sha512_finalize"
 external copy : ctx -> ctx = "stub_sha512_copy"
 external to_bin: t -> string = "stub_sha512_to_bin"
@@ -29,16 +29,24 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
 let channel chan len =
@@ -53,7 +61,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Index: ocaml-sha-1.7/sha256.mli
===================================================================
--- ocaml-sha-1.7.orig/sha256.mli	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha256.mli	2012-03-16 18:51:44.000000000 +0100
@@ -26,10 +26,18 @@
 (** Create a new context *)
 external init: unit -> ctx = "stub_sha256_init"
 
-(** Sha256.update ctx s ofs len updates the context with the substring
-    of s starting at character number ofs and containing len
-    characters. Unsafe: No range checking! *)
-external update: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+(** Sha256.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+
+(** Sha256.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha256.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
 
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha256_finalize"
Index: ocaml-sha-1.7/sha1.mli
===================================================================
--- ocaml-sha-1.7.orig/sha1.mli	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha1.mli	2012-03-16 18:51:44.000000000 +0100
@@ -26,10 +26,18 @@
 (** Create a new context *)
 external init: unit -> ctx = "stub_sha1_init"
 
-(** Sha1.update ctx s ofs len updates the context with the substring
-    of s starting at character number ofs and containing len
-    characters. Unsafe: No range checking! *)
-external update: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+(** Sha1.unsafe_update_substring ctx s ofs len updates the context
+    with the substring of s starting at character number ofs and
+    containing len characters. Unsafe: No range checking! *)
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+
+(** Sha1.update_substring ctx s ofs len updates the context with the
+    substring of s starting at character number ofs and containing len
+    characters. *)
+val update_substring: ctx -> string -> int -> int -> unit
+
+(** Sha1.update_string ctx s updates the context with s. *)
+val update_string: ctx -> string -> unit
 
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha1_finalize"
Index: ocaml-sha-1.7/sha1.ml
===================================================================
--- ocaml-sha-1.7.orig/sha1.ml	2012-03-16 18:45:10.000000000 +0100
+++ ocaml-sha-1.7/sha1.ml	2012-03-16 18:52:42.000000000 +0100
@@ -17,7 +17,7 @@
 type t
 
 external init: unit -> ctx = "stub_sha1_init"
-external update: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha1_update"
 external finalize: ctx -> t = "stub_sha1_finalize"
 external copy : ctx -> ctx = "stub_sha1_copy"
 external to_bin: t -> string = "stub_sha1_to_bin"
@@ -29,16 +29,24 @@
 
 let blksize = 4096
 
+let update_substring ctx s ofs len =
+	if len <= 0 && String.length s < ofs + len then
+		invalid_arg "substring";
+	unsafe_update_substring ctx s ofs len
+
+let update_string ctx s =
+	unsafe_update_substring ctx s 0 (String.length s)
+
 let string s =
 	let ctx = init () in
-	update ctx s 0 (String.length s);
+	unsafe_update_substring ctx s 0 (String.length s);
 	finalize ctx
 
 let substring s ofs len =
 	if len <= 0 && String.length s < ofs + len then
 		invalid_arg "substring";
 	let ctx = init () in
-	update ctx s ofs len;
+	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
 let channel chan len =
@@ -53,7 +61,7 @@
 		if readed = 0 then
 			eof := true
 		else (
-			update ctx buf 0 readed;
+			unsafe_update_substring ctx buf 0 readed;
 			if !left <> -1 then left := !left - readed
 		)
 	done;
Description: Multithread file function
 Change file functions so it can release the runtime system while
 calculating checksum of a file.
 .
 Also add O_CLOEXEC to prevent filedescriptors leaking when another
 thread calls exec.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-16

---

Index: ocaml-sha-1.7/sha1_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha1_stubs.c	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha1_stubs.c	2012-03-16 18:12:05.000000000 +0100
@@ -13,6 +13,7 @@
  * SHA1 implementation as describe in wikipedia.
  */
 
+#define _GNU_SOURCE
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -25,7 +26,7 @@
 	int fd; ssize_t n;
 	struct sha1_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha1_init(&ctx);
@@ -44,6 +45,7 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha1_ctx *) a)
 
@@ -79,14 +81,26 @@
 	CAMLreturn(result);
 }
 
+#ifndef strdupa
+#define strdupa(s) strcpy(alloca(strlen(s)+1),s)
+#endif
+
 CAMLprim value stub_sha1_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdupa(String_val(name));
+	sha1_digest digest;
+
+	caml_release_runtime_system();
+	if (sha1_file(name_dup, &digest)) {
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha1_digest), Abstract_tag);
-	if (sha1_file(String_val(name), (sha1_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha1_digest *)result, &digest, sizeof(sha1_digest));
 
 	CAMLreturn(result);
 }
Index: ocaml-sha-1.7/sha256_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha256_stubs.c	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha256_stubs.c	2012-03-16 18:12:14.000000000 +0100
@@ -13,6 +13,7 @@
  * SHA256 implementation
  */
 
+#define _GNU_SOURCE
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -25,7 +26,7 @@
 	int fd; ssize_t n;
 	struct sha256_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha256_init(&ctx);
@@ -44,6 +45,7 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha256_ctx *) a)
 
@@ -78,14 +80,26 @@
 	CAMLreturn(result);
 }
 
+#ifndef strdupa
+#define strdupa(s) strcpy(alloca(strlen(s)+1),s)
+#endif
+
 CAMLprim value stub_sha256_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdupa(String_val(name));
+	sha256_digest digest;
+
+	caml_release_runtime_system();
+	if (sha256_file(name_dup, &digest)) {
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha256_digest), Abstract_tag);
-	if (sha256_file(String_val(name), (sha256_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha256_digest *)result, &digest, sizeof(sha256_digest));
 
 	CAMLreturn(result);
 }
Index: ocaml-sha-1.7/sha512_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha512_stubs.c	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha512_stubs.c	2012-03-16 18:12:24.000000000 +0100
@@ -13,6 +13,7 @@
  * SHA512 implementation
  */
 
+#define _GNU_SOURCE
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -25,7 +26,7 @@
 	int fd; ssize_t n;
 	struct sha512_ctx ctx;
 
-	fd = open(filename, O_RDONLY);
+	fd = open(filename, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 1;
 	sha512_init(&ctx);
@@ -44,6 +45,7 @@
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha512_ctx *) a)
 
@@ -78,14 +80,26 @@
 	CAMLreturn(result);
 }
 
+#ifndef strdupa
+#define strdupa(s) strcpy(alloca(strlen(s)+1),s)
+#endif
+
 CAMLprim value stub_sha512_file(value name)
 {
 	CAMLparam1(name);
 	CAMLlocal1(result);
 
+	char *name_dup = strdupa(String_val(name));
+	sha512_digest digest;
+
+	caml_release_runtime_system();
+	if (sha512_file(name_dup, &digest)) {
+	    caml_acquire_runtime_system();
+	    caml_failwith("file error");
+	}
+	caml_acquire_runtime_system();
 	result = caml_alloc(sizeof(sha512_digest), Abstract_tag);
-	if (sha512_file(String_val(name), (sha512_digest *) result))
-		caml_failwith("file error");
+	memcpy((sha512_digest *)result, &digest, sizeof(sha512_digest));
 
 	CAMLreturn(result);
 }
Description: bigarray support
 This patch adds support to generate checksums using bigarrays instead
 of strings. One advantage is that this can be done without holding
 the runtime system and therefore benefits from multithreading.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-16

---

--- ocaml-sha-1.7.orig/sha512.mli
+++ ocaml-sha-1.7/sha512.mli
@@ -17,6 +17,9 @@
 (** context type - opaque *)
 type ctx
 
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
@@ -39,6 +42,10 @@ val update_substring: ctx -> string -> i
 (** Sha512.update_string ctx s updates the context with s. *)
 val update_string: ctx -> string -> unit
 
+(** Sha512.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha512_update_bigarray"
+
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha512_finalize"
 
@@ -52,6 +59,9 @@ val string : string -> t
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha512.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha512.channel ic
--- ocaml-sha-1.7.orig/sha256.ml
+++ ocaml-sha-1.7/sha256.ml
@@ -14,10 +14,12 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha256_init"
 external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha256_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha256_update_bigarray"
 external finalize: ctx -> t = "stub_sha256_finalize"
 external copy : ctx -> ctx = "stub_sha256_copy"
 external to_bin: t -> string = "stub_sha256_to_bin"
@@ -49,6 +51,11 @@ let substring s ofs len =
 	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
+	finalize ctx
+
 let channel chan len =
 	let ctx = init ()
 	and buf = String.create blksize in
--- ocaml-sha-1.7.orig/sha1_stubs.c
+++ ocaml-sha-1.7/sha1_stubs.c
@@ -45,6 +45,7 @@ static inline int sha1_file(char *filena
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
 #include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha1_ctx *) a)
@@ -69,6 +70,19 @@ CAMLprim value stub_sha1_update(value ct
 
 	CAMLreturn(Val_unit);
 }
+
+CAMLprim value stub_sha1_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha1_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
 
 CAMLprim value stub_sha1_finalize(value ctx)
 {
--- ocaml-sha-1.7.orig/sha512.ml
+++ ocaml-sha-1.7/sha512.ml
@@ -14,10 +14,12 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha512_init"
 external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha512_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha512_update_bigarray"
 external finalize: ctx -> t = "stub_sha512_finalize"
 external copy : ctx -> ctx = "stub_sha512_copy"
 external to_bin: t -> string = "stub_sha512_to_bin"
@@ -49,6 +51,11 @@ let substring s ofs len =
 	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
+	finalize ctx
+
 let channel chan len =
 	let ctx = init ()
 	and buf = String.create blksize in
--- ocaml-sha-1.7.orig/sha512_stubs.c
+++ ocaml-sha-1.7/sha512_stubs.c
@@ -45,6 +45,7 @@ static inline int sha512_file(char *file
 #include <caml/alloc.h>
 #include <caml/custom.h>
 #include <caml/fail.h>
+#include <caml/bigarray.h>
 #include <caml/threads.h>
 
 #define GET_CTX_STRUCT(a) ((struct sha512_ctx *) a)
@@ -69,6 +70,19 @@ CAMLprim value stub_sha512_update(value
 	CAMLreturn(Val_unit);
 }
 
+CAMLprim value stub_sha512_update_bigarray(value ctx, value buf)
+{
+	CAMLparam2(ctx, buf);
+	unsigned char *data = Data_bigarray_val(buf);
+	size_t len = Bigarray_val(buf)->dim[0];
+
+	caml_release_runtime_system();
+	sha512_update(GET_CTX_STRUCT(ctx), data, len);
+	caml_acquire_runtime_system();
+
+	CAMLreturn(Val_unit);
+}
+
 CAMLprim value stub_sha512_finalize(value ctx)
 {
 	CAMLparam1(ctx);
--- ocaml-sha-1.7.orig/sha256.mli
+++ ocaml-sha-1.7/sha256.mli
@@ -17,6 +17,9 @@
 (** context type - opaque *)
 type ctx
 
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
@@ -39,6 +42,10 @@ val update_substring: ctx -> string -> i
 (** Sha256.update_string ctx s updates the context with s. *)
 val update_string: ctx -> string -> unit
 
+(** Sha256.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha256_update_bigarray"
+
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha256_finalize"
 
@@ -52,6 +59,9 @@ val string : string -> t
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha256.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha256.channel ic
--- ocaml-sha-1.7.orig/sha1.mli
+++ ocaml-sha-1.7/sha1.mli
@@ -17,6 +17,9 @@
 (** context type - opaque *)
 type ctx
 
+(** buffer type *)
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
+
 (** digest type - opaque *)
 type t
 
@@ -39,6 +42,10 @@ val update_substring: ctx -> string -> i
 (** Sha1.update_string ctx s updates the context with s. *)
 val update_string: ctx -> string -> unit
 
+(** Sha1.update_buffer ctx a updates the context with a.
+    Runs parallel to other threads if any exist. *)
+external update_buffer: ctx -> buf -> unit = "stub_sha1_update_bigarray"
+
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha1_finalize"
 
@@ -52,6 +59,9 @@ val string : string -> t
 at character number ofs and containing len characters. *)
 val substring : string -> int -> int -> t
 
+(** Return the digest of the given buffer. *)
+val buffer : buf -> t
+
 (** If len is nonnegative, Sha1.channel ic len reads len characters from
 channel ic and returns their digest, or raises End_of_file if end-of-file is
 reached before len characters are read. If len is negative, Sha1.channel ic
--- ocaml-sha-1.7.orig/sha1.ml
+++ ocaml-sha-1.7/sha1.ml
@@ -14,10 +14,12 @@
  *)
 
 type ctx
+type buf = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
 type t
 
 external init: unit -> ctx = "stub_sha1_init"
 external unsafe_update_substring: ctx -> string -> int -> int -> unit = "stub_sha1_update"
+external update_buffer: ctx -> buf -> unit = "stub_sha1_update_bigarray"
 external finalize: ctx -> t = "stub_sha1_finalize"
 external copy : ctx -> ctx = "stub_sha1_copy"
 external to_bin: t -> string = "stub_sha1_to_bin"
@@ -49,6 +51,11 @@ let substring s ofs len =
 	unsafe_update_substring ctx s ofs len;
 	finalize ctx
 
+let buffer buf =
+	let ctx = init () in
+	update_buffer ctx buf;
+	finalize ctx
+
 let channel chan len =
 	let ctx = init ()
 	and buf = String.create blksize in
Description: add copy function
 This patch adds a function to copy a context.
Author: Goswin von Brederlow <goswin-v-b@web.de>
Last-Update: 2012-03-16

---

Index: ocaml-sha-1.7/sha1_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha1_stubs.c	2012-03-16 18:12:05.000000000 +0100
+++ ocaml-sha-1.7/sha1_stubs.c	2012-03-16 18:45:10.000000000 +0100
@@ -81,6 +81,17 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha1_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha1_ctx), Abstract_tag);
+	sha1_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 #ifndef strdupa
 #define strdupa(s) strcpy(alloca(strlen(s)+1),s)
 #endif
Index: ocaml-sha-1.7/sha1.mli
===================================================================
--- ocaml-sha-1.7.orig/sha1.mli	2012-03-16 18:30:03.000000000 +0100
+++ ocaml-sha-1.7/sha1.mli	2012-03-16 18:45:10.000000000 +0100
@@ -34,6 +34,9 @@
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha1_finalize"
 
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha1_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Index: ocaml-sha-1.7/sha1.ml
===================================================================
--- ocaml-sha-1.7.orig/sha1.ml	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha1.ml	2012-03-16 18:45:10.000000000 +0100
@@ -19,6 +19,7 @@
 external init: unit -> ctx = "stub_sha1_init"
 external update: ctx -> string -> int -> int -> unit = "stub_sha1_update"
 external finalize: ctx -> t = "stub_sha1_finalize"
+external copy : ctx -> ctx = "stub_sha1_copy"
 external to_bin: t -> string = "stub_sha1_to_bin"
 external to_hex: t -> string = "stub_sha1_to_hex"
 external file_fast: string -> t = "stub_sha1_file"
Index: ocaml-sha-1.7/sha1.c
===================================================================
--- ocaml-sha-1.7.orig/sha1.c	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha1.c	2012-03-16 18:43:24.000000000 +0100
@@ -33,6 +33,14 @@
 	ctx->h[4] = 0xC3D2E1F0;
 }
 
+/**
+ * sha1_copy - Copy SHA1 context
+ */
+void sha1_copy(struct sha1_ctx *dst, struct sha1_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 #define f1(x, y, z)   (z ^ (x & (y ^ z)))         /* x ? y : z */
 #define f2(x, y, z)   (x ^ y ^ z)                 /* XOR */
 #define f3(x, y, z)   ((x & y) + (z & (x ^ y)))   /* majority */
Index: ocaml-sha-1.7/sha1.h
===================================================================
--- ocaml-sha-1.7.orig/sha1.h	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha1.h	2012-03-16 18:43:24.000000000 +0100
@@ -25,6 +25,7 @@
 typedef struct { unsigned int digest[5]; } sha1_digest;
 
 void sha1_init(struct sha1_ctx *ctx);
+void sha1_copy(struct sha1_ctx *dst, struct sha1_ctx *src);
 void sha1_update(struct sha1_ctx *ctx, unsigned char *data, int len);
 void sha1_finalize(struct sha1_ctx *ctx, sha1_digest *out);
 void sha1_to_bin(sha1_digest *digest, char *out);
Index: ocaml-sha-1.7/sha256_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha256_stubs.c	2012-03-16 18:12:14.000000000 +0100
+++ ocaml-sha-1.7/sha256_stubs.c	2012-03-16 18:45:10.000000000 +0100
@@ -80,6 +80,17 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha256_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha256_ctx), Abstract_tag);
+	sha256_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 #ifndef strdupa
 #define strdupa(s) strcpy(alloca(strlen(s)+1),s)
 #endif
Index: ocaml-sha-1.7/sha256.mli
===================================================================
--- ocaml-sha-1.7.orig/sha256.mli	2012-03-16 18:30:45.000000000 +0100
+++ ocaml-sha-1.7/sha256.mli	2012-03-16 18:45:10.000000000 +0100
@@ -34,6 +34,9 @@
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha256_finalize"
 
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha256_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Index: ocaml-sha-1.7/sha256.ml
===================================================================
--- ocaml-sha-1.7.orig/sha256.ml	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha256.ml	2012-03-16 18:45:10.000000000 +0100
@@ -19,6 +19,7 @@
 external init: unit -> ctx = "stub_sha256_init"
 external update: ctx -> string -> int -> int -> unit = "stub_sha256_update"
 external finalize: ctx -> t = "stub_sha256_finalize"
+external copy : ctx -> ctx = "stub_sha256_copy"
 external to_bin: t -> string = "stub_sha256_to_bin"
 external to_hex: t -> string = "stub_sha256_to_hex"
 external file_fast: string -> t = "stub_sha256_file"
Index: ocaml-sha-1.7/sha256.c
===================================================================
--- ocaml-sha-1.7.orig/sha256.c	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha256.c	2012-03-16 18:43:24.000000000 +0100
@@ -36,6 +36,14 @@
 	ctx->h[7] = 0x5be0cd19;
 }
 
+/**
+ * sha256_copy - Copy SHA256 context
+ */
+void sha256_copy(struct sha256_ctx *dst, struct sha256_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 /* 232 times the cube root of the first 64 primes 2..311 */
 static const unsigned int k[] = {
 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
Index: ocaml-sha-1.7/sha256.h
===================================================================
--- ocaml-sha-1.7.orig/sha256.h	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha256.h	2012-03-16 18:43:24.000000000 +0100
@@ -25,6 +25,7 @@
 typedef struct { unsigned int digest[8]; } sha256_digest;
 
 void sha256_init(struct sha256_ctx *ctx);
+void sha256_copy(struct sha256_ctx *dst, struct sha256_ctx *src);
 void sha256_update(struct sha256_ctx *ctx, unsigned char *data, int len);
 void sha256_finalize(struct sha256_ctx *ctx, sha256_digest *out);
 void sha256_to_bin(sha256_digest *digest, char *out);
Index: ocaml-sha-1.7/sha512_stubs.c
===================================================================
--- ocaml-sha-1.7.orig/sha512_stubs.c	2012-03-16 18:12:24.000000000 +0100
+++ ocaml-sha-1.7/sha512_stubs.c	2012-03-16 18:45:10.000000000 +0100
@@ -80,6 +80,17 @@
 	CAMLreturn(result);
 }
 
+CAMLprim value stub_sha512_copy(value ctx)
+{
+	CAMLparam1(ctx);
+	CAMLlocal1(result);
+
+	result = caml_alloc(sizeof(struct sha512_ctx), Abstract_tag);
+	sha512_copy(GET_CTX_STRUCT(result), GET_CTX_STRUCT(ctx));
+
+	CAMLreturn(result);
+}
+
 #ifndef strdupa
 #define strdupa(s) strcpy(alloca(strlen(s)+1),s)
 #endif
Index: ocaml-sha-1.7/sha512.mli
===================================================================
--- ocaml-sha-1.7.orig/sha512.mli	2012-03-16 18:31:10.000000000 +0100
+++ ocaml-sha-1.7/sha512.mli	2012-03-16 18:45:10.000000000 +0100
@@ -34,6 +34,9 @@
 (** Finalize the context and return digest *)
 external finalize: ctx -> t = "stub_sha512_finalize"
 
+(** Return an copy of the context *)
+external copy : ctx -> ctx = "stub_sha512_copy"
+
 (** Return the digest of the given string. *)
 val string : string -> t
 
Index: ocaml-sha-1.7/sha512.ml
===================================================================
--- ocaml-sha-1.7.orig/sha512.ml	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha512.ml	2012-03-16 18:45:10.000000000 +0100
@@ -19,6 +19,7 @@
 external init: unit -> ctx = "stub_sha512_init"
 external update: ctx -> string -> int -> int -> unit = "stub_sha512_update"
 external finalize: ctx -> t = "stub_sha512_finalize"
+external copy : ctx -> ctx = "stub_sha512_copy"
 external to_bin: t -> string = "stub_sha512_to_bin"
 external to_hex: t -> string = "stub_sha512_to_hex"
 external file_fast: string -> t = "stub_sha512_file"
Index: ocaml-sha-1.7/sha512.c
===================================================================
--- ocaml-sha-1.7.orig/sha512.c	2012-03-16 18:00:05.000000000 +0100
+++ ocaml-sha-1.7/sha512.c	2012-03-16 18:43:24.000000000 +0100
@@ -35,6 +35,14 @@
 	ctx->h[7] = 0x5be0cd19137e2179ULL;
 }
 
+/**
+ * sha512_copy - Copy SHA512 context
+ */
+void sha512_copy(struct sha512_ctx *dst, struct sha512_ctx *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
 /* 232 times the cube root of the first 64 primes 2..311 */
 static const uint64_t k[] = {
 	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
Index: ocaml-sha-1.7/sha512.h
===================================================================
--- ocaml-sha-1.7.orig/sha512.h	2012-03-16 18:00:06.000000000 +0100
+++ ocaml-sha-1.7/sha512.h	2012-03-16 18:43:24.000000000 +0100
@@ -27,6 +27,7 @@
 typedef struct { uint64_t digest[8]; } sha512_digest;
 
 void sha512_init(struct sha512_ctx *ctx);
+void sha512_copy(struct sha512_ctx *dst, struct sha512_ctx *src);
 void sha512_update(struct sha512_ctx *ctx, unsigned char *data, int len);
 void sha512_finalize(struct sha512_ctx *ctx, sha512_digest *out);
 void sha512_to_bin(sha512_digest *digest, char *out);

Reply to: