X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=visor;a=blobdiff_plain;f=libvisor%2Fsrc%2Fvisor.c;h=12b5a02ab0b730b54a80395d7eb98763269ea3a2;hp=cefc924618d2445571873b100d0362c2d38377bf;hb=94c867869ece77f27cf3c8b637d44e13d86f5b88;hpb=a4536cf08230dba14f221b661abd7804fcc1ebbc diff --git a/libvisor/src/visor.c b/libvisor/src/visor.c index cefc924..12b5a02 100644 --- a/libvisor/src/visor.c +++ b/libvisor/src/visor.c @@ -186,20 +186,44 @@ struct vi_buffer *vi_prev_buf(struct visor *vi) * It can't fail, because it's always called with the span array having at * least two empty slots (see: add_span). */ -void split_span(struct vi_buffer *vb, struct vi_span *sp, vi_addr at, unsigned long size) +void split_span(struct vi_buffer *vb, struct vi_span *sp, vi_addr spoffs, unsigned long size) { - struct vi_span *tail = sp + (size ? 2 : 1); + int newseg = size > 0 ? 1 : 0; + struct vi_span *tail = sp + newseg + 1; int num_move = vb->spans + vb->num_spans - sp - 1; - memmove(tail + 1, sp + 1, num_move); + memmove(tail + 1, sp + 1, num_move * sizeof *sp); vb->num_spans += tail - sp; + *tail = *sp; + sp->size = spoffs; + tail->start += spoffs; + tail->size -= spoffs; + + sp = tail; + for(;;) { + if(size <= tail->size) { + tail->size -= size; + break; + } + size -= tail->size; + tail->size = 0; + tail++; + } + + if(tail > sp) { + /* we produced one or more zero-sized spans, drop them */ + num_move = vb->num_spans - (tail - sp); + memmove(sp, tail, num_move * sizeof *sp); + vb->num_spans -= num_move; + } } static int add_span(struct vi_buffer *vb, vi_addr at, int src, vi_addr start, unsigned long size) { struct visor *vi = vb->vi; struct vi_span *sp; + vi_addr spoffs; /* make sure we have space for at least two new spans (split + add) */ if(vb->num_spans + 1 >= vb->max_spans) { @@ -210,8 +234,12 @@ static int add_span(struct vi_buffer *vb, vi_addr at, int src, vi_addr start, un vb->max_spans = newmax; } - if((sp = vi_buf_find_span(vb, at))) { - split_span(vb, sp++, at, size); + if((sp = vi_buf_find_span(vb, at, &spoffs))) { + if(spoffs > 0) { + split_span(vb, sp++, spoffs, 1); + } else { + split_span(vb, sp++, 0, 0); + } } else { sp = vb->spans + vb->num_spans; } @@ -243,6 +271,7 @@ void vi_buf_reset(struct vi_buffer *vb) memset(vb, 0, sizeof *vb); vb->prev = prev; vb->next = next; + vb->vi = vi; } int vi_buf_read(struct vi_buffer *vb, const char *path) @@ -344,14 +373,16 @@ long vi_buf_size(struct vi_buffer *vb) return sz; } -struct vi_span *vi_buf_find_span(struct vi_buffer *vb, vi_addr at) +struct vi_span *vi_buf_find_span(struct vi_buffer *vb, vi_addr at, vi_addr *soffs) { int i; - long sz = 0; + long sz = 0, prev_sz; for(i=0; inum_spans; i++) { + prev_sz = sz; sz += vb->spans[i].size; if(sz > at) { + if(soffs) *soffs = at - prev_sz; return vb->spans + i; } }