diff options
author | Chris Johns <chrisj@rtems.org> | 2012-12-18 20:31:37 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2012-12-18 20:31:37 +1100 |
commit | 39993d58eaf41159ee18110542a2c5f88e0df82c (patch) | |
tree | 2b093a9f58f960ba0f51cb9e251c0a868b445865 | |
parent | ba2c4d7ed3e7b02b704647c64b5c67a0f075e734 (diff) |
Fix reading to the end of the file.
Stat the file and keep the size to limit requesting pasting the
end of the file.
-rw-r--r-- | rtl-obj-cache.c | 55 | ||||
-rw-r--r-- | rtl-obj-cache.h | 1 |
2 files changed, 37 insertions, 19 deletions
diff --git a/rtl-obj-cache.c b/rtl-obj-cache.c index 5a8df5d..e71bbcb 100644 --- a/rtl-obj-cache.c +++ b/rtl-obj-cache.c @@ -29,11 +29,12 @@ bool rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size) { - cache->fd = -1; - cache->offset = 0; - cache->size = size; - cache->level = 0; - cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false); + cache->fd = -1; + cache->file_size = 0; + cache->offset = 0; + cache->size = size; + cache->level = 0; + cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false); if (!cache->buffer) { rtems_rtl_set_error (ENOMEM, "no memory for cache buffer"); @@ -46,15 +47,17 @@ void rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer); - cache->fd = -1; - cache->level = 0; + cache->fd = -1; + cache->file_size = 0; + cache->level = 0; } void rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache) { - cache->fd = -1; - cache->level = 0; + cache->fd = -1; + cache->file_size = -1; + cache->level = 0; } bool @@ -64,17 +67,29 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache, void** buffer, size_t* length) { + struct stat sb; + if (*length > cache->size) { rtems_rtl_set_error (EINVAL, "read size larger than cache size"); return false; } + if (offset > cache->file_size) + { + rtems_rtl_set_error (EINVAL, "offset past end of file: offset=%i size=%i", + (int) offset, (int) cache->file_size); + return false; + } + + if ((offset + *length) > cache->file_size) + *length = cache->file_size - offset; + while (true) { size_t buffer_offset = 0; size_t buffer_read = cache->size; - + /* * Is the data in the cache for this file ? */ @@ -87,23 +102,17 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache, (offset < (cache->offset + cache->level))) { buffer_offset = offset - cache->offset; - + /* * Return the location of the data in the cache. */ *buffer = cache->buffer + buffer_offset; - + /* * Is all the data in the cache or just a part ? */ - if (*length < (cache->level - buffer_offset)) - return true; - else if (cache->level < cache->size) + if (*length <= (cache->level - buffer_offset)) { - /* - * This is the remaining data in the file. - */ - *length = cache->level - buffer_offset; return true; } @@ -154,6 +163,14 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache, cache->fd = fd; cache->offset = offset; + + if (fstat (cache->fd, &sb) < 0) + { + rtems_rtl_set_error (errno, "file stat failed"); + return false; + } + + cache->file_size = sb.st_size; } return false; diff --git a/rtl-obj-cache.h b/rtl-obj-cache.h index 65031c2..8abb7f3 100644 --- a/rtl-obj-cache.h +++ b/rtl-obj-cache.h @@ -53,6 +53,7 @@ extern "C" { typedef struct rtems_rtl_obj_cache_s { int fd; /**< The file descriptor of the data in the cache. */ + size_t file_size; /**< The size of the file. */ off_t offset; /**< The base offset of the buffer. */ size_t size; /**< The size of the cache. */ size_t level; /**< The amount of data in the cache. A file can be |