summaryrefslogtreecommitdiffstats
path: root/assoc_buf.h
diff options
context:
space:
mode:
Diffstat (limited to 'assoc_buf.h')
-rw-r--r--assoc_buf.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/assoc_buf.h b/assoc_buf.h
new file mode 100644
index 0000000..e9e7fbc
--- /dev/null
+++ b/assoc_buf.h
@@ -0,0 +1,72 @@
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+struct asbuf {
+ unsigned long ino;
+ char *buf;
+ size_t alloc;
+};
+
+
+ssize_t asbuf_free_alloc(struct asbuf *buf, size_t size) {
+ char *mem;
+
+ mem = kmalloc(size, GFP_KERNEL);
+ if (!mem)
+ return -ENOMEM;
+
+ if (buf->alloc)
+ kfree(buf->buf);
+
+ buf->buf = mem;
+ buf->alloc = size;
+ return 0;
+}
+
+void asbuf_free(struct asbuf *buf) {
+ kfree(buf->buf);
+}
+
+ssize_t asbuf_to_user(struct asbuf *buf,
+ char __user *user_buf,
+ size_t len,
+ loff_t *offset) {
+
+ size_t chars_left, request;
+ ssize_t uncopied, copied;
+
+ if (!buf->alloc)
+ return -EINVAL;
+
+ if (*offset > buf->alloc)
+ return -EINVAL;
+
+ chars_left = buf->alloc - *offset;
+ request = min(len, chars_left);
+
+ printk(KERN_INFO "buf: %p\t alloc: %zu\t request: %zu\n", buf, buf->alloc, request);
+
+ uncopied = copy_to_user(user_buf, buf->buf + *offset, request);
+ copied = request - uncopied;
+
+ *offset += copied;
+ return copied;
+}
+
+ssize_t asbuf_from_user(struct asbuf *buf,
+ const char __user *user_buf,
+ size_t len,
+ loff_t *offset) {
+ ssize_t rc = 0;
+ size_t uncopied, copied;
+ rc = asbuf_free_alloc(buf, len);
+ if (rc != 0)
+ return rc;
+
+ uncopied = copy_from_user(buf->buf, user_buf, len);
+ copied = len - uncopied;
+
+ *offset = 0;
+
+ return copied;
+}