summaryrefslogtreecommitdiffstats
path: root/crypto_buffer_put.c
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2010-07-09 12:32:17 +0200
committerJérémy Zurcher <jeremy@asynk.ch>2010-07-09 12:32:17 +0200
commit6c027b4de25a529908be895e7ff19236f4002a57 (patch)
treef70d3a400bbb9ba8a83e9d4ffcaa4b6e367fc8bb /crypto_buffer_put.c
downloadcrypto-6c027b4de25a529908be895e7ff19236f4002a57.zip
crypto-6c027b4de25a529908be895e7ff19236f4002a57.tar.gz
initial commit, resurrect one of my realy old projects
Diffstat (limited to 'crypto_buffer_put.c')
-rw-r--r--crypto_buffer_put.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/crypto_buffer_put.c b/crypto_buffer_put.c
new file mode 100644
index 0000000..74f30a0
--- /dev/null
+++ b/crypto_buffer_put.c
@@ -0,0 +1,112 @@
+#include <errno.h>
+#include <string.h>
+
+#include "crypto_buffer.h"
+
+
+/* s->data_st must have been set */
+/* after this s->e_ptr is updated */
+static int allwrite(crypto_buffer *s)
+{
+ u8 *buffer;
+ int w, bytes;
+
+ buffer = s->e_buffer;
+ bytes = s->data_st.bytes + (s->block_size << 1);
+ s->cipher(&s->ctx,(u8*)s->e_data,(u8*)&s->data_st);
+ while (bytes) {
+ w = s->op(s->fd,buffer,bytes);
+ if (w == -1) {
+ if (errno == EINTR) continue;
+ return -1; /* note that some data may have been written */
+ }
+ if (w == 0) ; /* luser's fault */
+ buffer += w;
+ bytes -= w;
+ }
+ s->e_ptr = (u8*)s->e_data + s->block_size;
+ return 0;
+}
+
+
+/* after this s->e_ptr and s->c_ptr are updated */
+int crypto_buffer_flush(crypto_buffer *s)
+{
+ register u32 len, len2;
+ register u8* e_ptr;
+
+ len = s->e_len;
+ e_ptr = s->e_ptr;
+ if(e_ptr == s->e_end) {
+ s->data_st.bytes = s->data_st.strlen = len;
+ if (allwrite(s) == -1) return -1;
+ e_ptr = s->e_ptr;
+ }
+ len2 = len = e_ptr + s->e_len - s->e_end; /* used bytes in e_buffer */
+ if(s->c_ptr != s->c_buffer){
+ s->cipher(&s->ctx, e_ptr, s->c_buffer);
+ len += s->block_size;
+ len2 += s->c_ptr - s->c_buffer;
+ }
+ s->data_st.bytes = len;
+ s->data_st.strlen = len2;
+ if (allwrite(s) == -1) return -1;
+ s->c_ptr = s->c_buffer;
+ return 0;
+}
+
+int crypto_buffer_put(crypto_buffer *s,const u8 *buf,u32 len)
+{
+ register u32 size;
+ register u8* e_ptr;
+ register u8* e_end;
+ u32 free;
+
+ free = s->c_end - s->c_ptr;
+ if (len > free) {
+ if(free){
+ memcpy(s->c_ptr, buf, free);
+ buf += free;
+ len -= free;
+ }
+ /* now c_buffer is full */
+ e_ptr = s->e_ptr;
+ e_end = s->e_end;
+ size = s->block_size;
+ if(e_ptr == e_end) {
+ /* e_buffer full */
+ s->data_st.bytes = s->data_st.strlen = s->e_len;
+ if (allwrite(s) == -1) return -1;
+ e_ptr = s->e_ptr;
+ }
+ s->cipher(&s->ctx, e_ptr, s->c_buffer);
+ e_ptr += size;
+ s->c_ptr = s->c_buffer;
+ /* now c_buffer is empty */
+ while(len > size){
+ if(e_ptr == e_end) {
+ s->data_st.bytes = s->data_st.strlen = s->e_len;
+ if (allwrite(s) == -1) return -1;
+ e_ptr = s->e_ptr;
+ }
+ s->cipher(&s->ctx, e_ptr, buf);
+ e_ptr += size;
+ buf += size;
+ len -= size;
+ }
+ /* don't forget */
+ s->e_ptr = e_ptr;
+ }
+ /* now len < s->block_size + s->c_buffer - s->c_ptr */
+ if(len){
+ memcpy(s->c_ptr, buf, len);
+ s->c_ptr += len;
+ }
+ return 0;
+}
+
+int crypto_buffer_putflush(crypto_buffer *s,const u8 *buf,u32 len)
+{
+ if (crypto_buffer_put(s, buf, len) == -1) return -1;
+ return crypto_buffer_flush(s);
+}