From f93c918aa53093a1cfdc35084b876233aa7699c1 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Tue, 5 Nov 2019 00:50:39 +1100 Subject: [PATCH] [porthole] added memory copy utility functions --- porthole/CMakeLists.txt | 1 + porthole/include/porthole/client.h | 19 +--- porthole/include/porthole/util.h | 52 ++++++++++ porthole/src/util.c | 152 +++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 18 deletions(-) create mode 100644 porthole/include/porthole/util.h create mode 100644 porthole/src/util.c diff --git a/porthole/CMakeLists.txt b/porthole/CMakeLists.txt index 7d777326..abee01b8 100644 --- a/porthole/CMakeLists.txt +++ b/porthole/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories( add_library(porthole STATIC src/porthole.c + src/util.c ) if(WIN32) diff --git a/porthole/include/porthole/client.h b/porthole/include/porthole/client.h index 8435a0b8..ec88a46c 100644 --- a/porthole/include/porthole/client.h +++ b/porthole/include/porthole/client.h @@ -17,27 +17,10 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include +#include "types.h" typedef struct PortholeClient *PortholeClient; -typedef struct -{ - unsigned int size; - void * data; -} -PortholeSegment; - -typedef struct -{ - uint32_t id; - unsigned int size; - unsigned int num_segments; - PortholeSegment segments[0]; -} -PortholeMap; - /** * Memory map event callback. * diff --git a/porthole/include/porthole/util.h b/porthole/include/porthole/util.h new file mode 100644 index 00000000..f5816b38 --- /dev/null +++ b/porthole/include/porthole/util.h @@ -0,0 +1,52 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2017-2019 Geoffrey McRae +https://looking-glass.hostfission.com + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "types.h" +#include + +/** + * Copy from memory to a PortholeMap + * + * @param src The source buffer + * @param dst The destination map + * @param len The data length to copy + * @param off The offset into the dst PortholeMap + */ +void porthole_copy_mem_to_map(void * src, PortholeMap * dst, size_t len, off_t off); + +/** + * Copy from a PortholeMap to memory + * + * @param src The source buffer + * @param dst The destination buffer + * @param len The data length to copy + * @param off The offset into the src PortholeMap + */ +void porthole_copy_map_to_mem(PortholeMap * src, void * dst, size_t len, off_t off); + +/** + * Copy from a PortholeMap to a PortholeMap + * + * @param src The source buffer + * @param dst The destination buffer + * @param len The data length to copy + * @param src_off The offset into the src PortholeMap + * @param dst_off The offset into the dst PortholeMap + */ +void porthole_copy_map_to_map(PortholeMap * src, PortholeMap * dst, size_t len, off_t src_off, off_t dst_off); \ No newline at end of file diff --git a/porthole/src/util.c b/porthole/src/util.c new file mode 100644 index 00000000..57ee7def --- /dev/null +++ b/porthole/src/util.c @@ -0,0 +1,152 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2017-2019 Geoffrey McRae +https://looking-glass.hostfission.com + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "porthole/util.h" +#include "common/debug.h" + +#include + +void porthole_copy_mem_to_map(void * src, PortholeMap * dst, size_t len, off_t off) +{ + if (off + len > dst->size) + DEBUG_FATAL("Attempt to write beyond the length of destination mapping"); + + /* find the start segment */ + PortholeSegment * seg = &dst->segments[0]; + while(off) + { + if (seg->size > off) + break; + + off -= seg->size; + ++seg; + } + + /* copy into each segment until the length has been satisfied */ + while(len) + { + char * buf = (char *)seg->data + off; + size_t avail = seg->size - off; + off = 0; + + if (avail > len) + avail = len; + + memcpy(buf, src, avail); + + src = (char *)src + avail; + len -= avail; + ++seg; + } +} + +void porthole_copy_map_to_mem(PortholeMap * src, void * dst, size_t len, off_t off) +{ + if (off + len > src->size) + DEBUG_FATAL("Attempt to read beyond the length of the source mapping"); + + /* find the start segment */ + PortholeSegment * seg = &src->segments[0]; + while(off) + { + if (seg->size > off) + break; + + off -= seg->size; + ++seg; + } + + /* copy from each segment until the length has been satisfied */ + while(len) + { + char * buf = (char *)seg->data + off; + size_t avail = seg->size - off; + off = 0; + + if (avail > len) + avail = len; + + memcpy(dst, buf, avail); + + dst = (char *)dst + avail; + len -= avail; + ++seg; + } +} + +void porthole_copy_map_to_map(PortholeMap * src, PortholeMap * dst, size_t len, off_t src_off, off_t dst_off) +{ + if (src_off + len > src->size) + DEBUG_FATAL("Attempt to read beyond th elength of the source mapping"); + + if (dst_off + len > dst->size) + DEBUG_FATAL("Attempt to write beyond the length of the destination mapping"); + + /* find the start segments */ + PortholeSegment * src_seg = &src->segments[0]; + while(src_off) + { + if (src_seg->size > src_off) + break; + + src_off -= src_seg->size; + ++src_seg; + } + + PortholeSegment * dst_seg = &dst->segments[0]; + while(dst_off) + { + if (dst_seg->size > dst_off) + break; + + dst_off -= dst_seg->size; + ++dst_seg; + } + + while(len) + { + char * src_buf = (char *)src_seg->data + src_off; + char * dst_buf = (char *)dst_seg->data + dst_off; + size_t src_avail = src_seg->size - src_off; + size_t dst_avail = dst_seg->size - dst_off; + src_off = 0; + dst_off = 0; + + size_t avail = src_avail > dst_avail ? dst_avail : src_avail; + if (avail > len) + avail = len; + + memcpy(dst_buf, src_buf, avail); + + src_avail -= avail; + dst_avail -= avail; + + if (src_avail == 0) + ++src_seg; + else + src_off = src_avail; + + if (dst_avail == 0) + ++dst_seg; + else + dst_off = dst_avail; + + len -= avail; + } +} \ No newline at end of file