diff options
Diffstat (limited to 'buffer.c')
-rw-r--r-- | buffer.c | 172 |
1 files changed, 93 insertions, 79 deletions
@@ -23,11 +23,8 @@ #include "buffer.h" typedef struct Buffer_t { - Class_t *Class; - int refs; - Stream_t *Next; - Stream_t *Buffer; - + struct Stream_t head; + size_t size; /* size of read/write buffer */ int dirty; /* is the buffer dirty? */ @@ -38,11 +35,28 @@ typedef struct Buffer_t { int ever_dirty; /* was the buffer ever dirty? */ size_t dirty_pos; size_t dirty_end; - mt_off_t current; /* first sector in buffer */ - size_t cur_size; /* the current size */ + mt_off_t current; /* first sector in buffer */ + size_t cur_size; /* the current size */ char *buf; /* disk read/write buffer */ } Buffer_t; +/* Convert position relative to buffer to absolute position */ +static mt_off_t abs_pos(Buffer_t *Buffer, size_t rel) { + return Buffer->current + (mt_off_t) rel; +} + +/* End of currently valid buffer */ +static mt_off_t cur_end(Buffer_t *Buffer) { + return abs_pos(Buffer, Buffer->cur_size); +} + +/* distance from absolute position until next full cylinder. If position already + * *is* on a full cylinder boundary, return size of full cylinder */ +static size_t pos_to_next_full_cyl(Buffer_t *Buffer, mt_off_t pos) { + return Buffer->cylinderSize - + (size_t) (pos % (mt_off_t) Buffer->cylinderSize); +} + /* * Flush a dirty buffer to disk. Resets Buffer->dirty to zero. * All errors are fatal. @@ -50,14 +64,14 @@ typedef struct Buffer_t { static int _buf_flush(Buffer_t *Buffer) { - int ret; + ssize_t ret; - if (!Buffer->Next || !Buffer->dirty) +#ifdef HAVE_ASSERT_H + assert(Buffer->head.Next != NULL); +#endif + + if (!Buffer->dirty) return 0; - if(Buffer->current < 0L) { - fprintf(stderr,"Should not happen\n"); - return -1; - } #ifdef DEBUG fprintf(stderr, "write %08x -- %02x %08x %08x\n", Buffer, @@ -66,15 +80,17 @@ static int _buf_flush(Buffer_t *Buffer) Buffer->dirty_end - Buffer->dirty_pos); #endif - ret = force_write(Buffer->Next, - Buffer->buf + Buffer->dirty_pos, - Buffer->current + Buffer->dirty_pos, - Buffer->dirty_end - Buffer->dirty_pos); - if(ret != (signed int) (Buffer->dirty_end - Buffer->dirty_pos)) { - if(ret < 0) - perror("buffer_flush: write"); - else - fprintf(stderr,"buffer_flush: short write\n"); + ret = force_pwrite(Buffer->head.Next, + Buffer->buf + Buffer->dirty_pos, + Buffer->current + (mt_off_t) Buffer->dirty_pos, + Buffer->dirty_end - Buffer->dirty_pos); + if(ret < 0) { + perror("buffer_flush: write"); + return -1; + } + + if((size_t) ret != Buffer->dirty_end - Buffer->dirty_pos) { + fprintf(stderr,"buffer_flush: short write\n"); return -1; } Buffer->dirty = 0; @@ -91,13 +107,13 @@ static int invalidate_buffer(Buffer_t *Buffer, mt_off_t start) /* start reading at the beginning of start's sector * don't start reading too early, or we might not even reach * start */ - Buffer->current = ROUND_DOWN(start, Buffer->sectorSize); + Buffer->current = ROUND_DOWN(start, (mt_off_t) Buffer->sectorSize); Buffer->cur_size = 0; return 0; } #undef OFFSET -#define OFFSET (start - This->current) +#define OFFSET ((size_t)(start - This->current)) typedef enum position_t { OUTSIDE, @@ -108,11 +124,10 @@ typedef enum position_t { static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len) { - if(start >= This->current && - start < This->current + (mt_off_t) This->cur_size) { + if(start >= This->current && start < cur_end(This)) { maximize(*len, This->cur_size - OFFSET); return INSIDE; - } else if(start == This->current + (mt_off_t) This->cur_size && + } else if(start == cur_end(This) && This->cur_size < This->size && *len >= This->sectorSize) { /* append to the buffer for this, three conditions have to @@ -129,39 +144,39 @@ static position_t isInBuffer(Buffer_t *This, mt_off_t start, size_t *len) if(invalidate_buffer(This, start) < 0) return ERROR; maximize(*len, This->cylinderSize - OFFSET); - maximize(*len, This->cylinderSize - This->current % This->cylinderSize); + maximize(*len, pos_to_next_full_cyl(This, This->current)); return OUTSIDE; } } -static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len) +static ssize_t buf_pread(Stream_t *Stream, char *buf, + mt_off_t start, size_t len) { size_t length; - mt_off_t offset; + size_t offset; char *disk_ptr; - int ret; - DeclareThis(Buffer_t); + ssize_t ret; + DeclareThis(Buffer_t); if(!len) - return 0; + return 0; /*fprintf(stderr, "buf read %x %x %x\n", Stream, start, len);*/ switch(isInBuffer(This, start, &len)) { case OUTSIDE: case APPEND: /* always load until the end of the cylinder */ - length = This->cylinderSize - - (This->current + This->cur_size) % This->cylinderSize; + length = pos_to_next_full_cyl(This, cur_end(This)); maximize(length, This->size - This->cur_size); /* read it! */ - ret=READS(This->Next, - This->buf + This->cur_size, - This->current + This->cur_size, - length); + ret=PREADS(This->head.Next, + This->buf + This->cur_size, + This->current + (mt_off_t) This->cur_size, + length); if ( ret < 0 ) return ret; - This->cur_size += ret; + This->cur_size += (size_t) ret; if (This->current+(mt_off_t)This->cur_size < start) { fprintf(stderr, "Short buffer fill\n"); exit(1); @@ -178,13 +193,14 @@ static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len) disk_ptr = This->buf + offset; maximize(len, This->cur_size - offset); memcpy(buf, disk_ptr, len); - return len; + return (ssize_t) len; } -static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) +static ssize_t buf_pwrite(Stream_t *Stream, char *buf, + mt_off_t start, size_t len) { char *disk_ptr; - DeclareThis(Buffer_t); + DeclareThis(Buffer_t); size_t offset=0; if(!len) @@ -206,27 +222,30 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) #ifdef DEBUG fprintf(stderr, "outside\n"); #endif - if(start % This->cylinderSize || + if(start % (mt_off_t) This->cylinderSize || len < This->sectorSize) { size_t readSize; - int ret; + ssize_t ret; + size_t bytes_read; readSize = This->cylinderSize - - This->current % This->cylinderSize; + (size_t)(This->current % (mt_off_t) This->cylinderSize); - ret=READS(This->Next, This->buf, This->current, readSize); + ret=PREADS(This->head.Next, This->buf, + (mt_off_t)This->current, readSize); /* read it! */ if ( ret < 0 ) return ret; - if(ret % This->sectorSize) { - fprintf(stderr, "Weird: read size (%d) not a multiple of sector size (%d)\n", ret, (int) This->sectorSize); - ret -= ret % This->sectorSize; - if(ret == 0) { + bytes_read = (size_t) ret; + if(bytes_read % This->sectorSize) { + fprintf(stderr, "Weird: read size (%zd) not a multiple of sector size (%d)\n", bytes_read, (int) This->sectorSize); + bytes_read -= bytes_read % This->sectorSize; + if(bytes_read == 0) { fprintf(stderr, "Nothing left\n"); exit(1); } } - This->cur_size = ret; + This->cur_size = bytes_read; /* for dosemu. Autoextend size */ if(!This->cur_size) { memset(This->buf,0,readSize); @@ -244,9 +263,8 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) offset = OFFSET; maximize(len, This->size - offset); This->cur_size += len; - if(This->Next->Class->pre_allocate) - PRE_ALLOCATE(This->Next, - This->current + This->cur_size); + if(This->head.Next->Class->pre_allocate) + PRE_ALLOCATE(This->head.Next, cur_end(This)); break; case INSIDE: /* nothing to do */ @@ -278,7 +296,7 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) This->dirty_pos = ROUND_DOWN(offset, This->sectorSize); if(!This->dirty || offset + len > This->dirty_end) This->dirty_end = ROUND_UP(offset + len, This->sectorSize); - + if(This->dirty_end > This->cur_size) { fprintf(stderr, "Internal error, dirty end too big dirty_end=%x cur_size=%x len=%x offset=%d sectorSize=%x\n", @@ -296,7 +314,7 @@ static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) } This->dirty = 1; - return len; + return (ssize_t) len; } static int buf_flush(Stream_t *Stream) @@ -324,8 +342,10 @@ static int buf_free(Stream_t *Stream) } static Class_t BufferClass = { - buf_read, - buf_write, + 0, + 0, + buf_pread, + buf_pwrite, buf_flush, buf_free, 0, /* set_geom */ @@ -335,13 +355,18 @@ static Class_t BufferClass = { 0, /* discard */ }; -Stream_t *buf_init(Stream_t *Next, int size, - int cylinderSize, - int sectorSize) +Stream_t *buf_init(Stream_t *Next, size_t size, + size_t cylinderSize, + size_t sectorSize) { Buffer_t *Buffer; - Stream_t *Stream; +#ifdef HAVE_ASSERT_H + assert(size != 0); + assert(cylinderSize != 0); + assert(sectorSize != 0); + assert(Next != NULL); +#endif if(size % cylinderSize != 0) { fprintf(stderr, "size not multiple of cylinder size\n"); @@ -352,19 +377,13 @@ Stream_t *buf_init(Stream_t *Next, int size, exit(1); } - if(Next->Buffer){ - Next->refs--; - Next->Buffer->refs++; - return Next->Buffer; - } - - Stream = (Stream_t *) malloc (sizeof(Buffer_t)); - if(!Stream) + Buffer = New(Buffer_t); + if(!Buffer) return 0; - Buffer = (Buffer_t *) Stream; + init_head(&Buffer->head, &BufferClass, Next); Buffer->buf = malloc(size); if ( !Buffer->buf){ - Free(Stream); + Free(Buffer); return 0; } Buffer->size = size; @@ -378,11 +397,6 @@ Stream_t *buf_init(Stream_t *Next, int size, Buffer->current = 0L; Buffer->cur_size = 0; /* buffer currently empty */ - Buffer->Next = Next; - Buffer->Class = &BufferClass; - Buffer->refs = 1; - Buffer->Buffer = 0; - Buffer->Next->Buffer = (Stream_t *) Buffer; - return Stream; + return &Buffer->head; } |