summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-12-18 20:31:37 +1100
committerChris Johns <chrisj@rtems.org>2012-12-18 20:31:37 +1100
commit39993d58eaf41159ee18110542a2c5f88e0df82c (patch)
tree2b093a9f58f960ba0f51cb9e251c0a868b445865
parentba2c4d7ed3e7b02b704647c64b5c67a0f075e734 (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.c55
-rw-r--r--rtl-obj-cache.h1
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