summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2024-08-16 19:06:07 +0200
committerdzwdz2024-08-16 19:06:07 +0200
commit39f5404c5394802e107347e6014297c05951202a (patch)
tree085d8320ec2a93758168f1489485598da9cf19da /src
parentf1bab6b74d84b972a9e817e5028b8e438bf5e83d (diff)
kernel/pcpy: minor cleanup, implement pcpy_from_str
might potentially be used in a reworked open(), mount() etc interface
Diffstat (limited to 'src')
-rw-r--r--src/kernel/pcpy.c67
-rw-r--r--src/kernel/proc.h4
2 files changed, 45 insertions, 26 deletions
diff --git a/src/kernel/pcpy.c b/src/kernel/pcpy.c
index 9cf7c37..5b9efef 100644
--- a/src/kernel/pcpy.c
+++ b/src/kernel/pcpy.c
@@ -12,7 +12,6 @@
struct virt_iter {
void *frag;
size_t frag_len;
- size_t prior; // sum of all prior frag_lens
bool error;
void __user *_virt;
@@ -22,10 +21,6 @@ struct virt_iter {
bool _writeable;
};
-struct virt_cpy_error { // unused
- bool read_fail, write_fail;
-};
-
/* if pages == NULL, creates an iterator over physical memory. */
static void virt_iter_new(
struct virt_iter *iter, void __user *virt, size_t length,
@@ -35,7 +30,7 @@ static bool virt_iter_next(struct virt_iter *);
static size_t virt_cpy(
Pagedir *dest_pages, void __user *dest,
Pagedir *src_pages, const void __user *src,
- size_t length, struct virt_cpy_error *err
+ size_t length
);
@@ -46,7 +41,6 @@ virt_iter_new(
) {
iter->frag = NULL;
iter->frag_len = 0;
- iter->prior = 0;
iter->error = false;
iter->_virt = virt;
iter->_remaining = length;
@@ -58,13 +52,7 @@ virt_iter_new(
static bool
virt_iter_next(struct virt_iter *iter)
{
- /* note: While i'm pretty sure that this should always work, this
- * was only tested in cases where the pages were consecutive both in
- * virtual and physical memory, which might not always be the case.
- * TODO test this */
-
size_t partial = iter->_remaining;
- iter->prior += iter->frag_len;
if (partial <= 0) return false;
if (iter->_pages) { // if iterating over virtual memory
@@ -95,15 +83,14 @@ static size_t
virt_cpy(
Pagedir *dest_pages, void __user *dest,
Pagedir *src_pages, const void __user *src,
- size_t length, struct virt_cpy_error *err
+ size_t length
) {
struct virt_iter dest_iter, src_iter;
size_t total = 0, partial;
+ /* user write */
virt_iter_new(&dest_iter, dest, length, dest_pages, true, true);
virt_iter_new( &src_iter, (userptr_t)src, length, src_pages, true, false);
- dest_iter.frag_len = 0;
- src_iter.frag_len = 0;
for (;;) {
if (dest_iter.frag_len <= 0 && !virt_iter_next(&dest_iter)) break;
@@ -119,14 +106,11 @@ virt_cpy(
src_iter.frag += partial;
}
- if (err) {
- err->read_fail = src_iter.error;
- err->write_fail = dest_iter.error;
- }
- if (src_iter.error || dest_iter.error)
- assert(total != length);
- else
+ if (src_iter.error || dest_iter.error) {
+ assert(total < length);
+ } else {
assert(total == length);
+ }
return total;
}
@@ -135,7 +119,7 @@ pcpy_to(Proc *p, __user void *dst, const void *src, size_t len)
{
assert(p);
if (!p->pages) return 0;
- return virt_cpy(p->pages, dst, NULL, (__user void*)src, len, NULL);
+ return virt_cpy(p->pages, dst, NULL, (__user void*)src, len);
}
size_t
@@ -143,7 +127,7 @@ pcpy_from(Proc *p, void *dst, const __user void *src, size_t len)
{
assert(p);
if (!p->pages) return 0;
- return virt_cpy(NULL, (__user void*)dst, p->pages, src, len, NULL);
+ return virt_cpy(NULL, (__user void*)dst, p->pages, src, len);
}
size_t
@@ -155,5 +139,36 @@ pcpy_bi(
assert(dstp && srcp);
if (!dstp->pages) return 0;
if (!srcp->pages) return 0;
- return virt_cpy(dstp->pages, dst, srcp->pages, src, len, NULL);
+ return virt_cpy(dstp->pages, dst, srcp->pages, src, len);
+}
+
+// XXX: not used atm
+size_t
+pcpy_from_str(Proc *p, char *dst, const __user char *src, size_t len)
+{
+ struct virt_iter iter;
+ size_t pos = 0;
+
+ assert(p);
+ if (p->pages == NULL) return 0;
+
+ virt_iter_new(&iter, (userptr_t)src, len, p->pages, true, false);
+ for (;;) {
+ assert(iter.frag_len == 0);
+ if (!virt_iter_next(&iter)) {
+ return 0;
+ }
+
+ char *c = iter.frag;
+ for (size_t i = 0; i < iter.frag_len; i++) {
+ dst[pos++] = c[i];
+ if (c[i] == '\0') {
+ assert(pos <= len);
+ return pos;
+ }
+ }
+
+ iter.frag += iter.frag_len;
+ iter.frag_len = 0;
+ }
}
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index 0de740f..4ad6580 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -145,3 +145,7 @@ size_t pcpy_bi(
Proc *srcp, const __user void *src,
size_t len
);
+/* Copies a NUL-terminated string from the process.
+ * Returns the size of the string including the NUL terminator,
+ * and 0 on error or if the string didn't fit in dst. */
+size_t pcpy_from_str(Proc *p, char *dst, const __user char *src, size_t len);