File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <errno.h>
0042 #include <stdio.h>
0043 #include <string.h>
0044 #include <unistd.h>
0045 #include <inttypes.h>
0046 #include <rtems/inttypes.h>
0047
0048 #include <rtems/rtl/rtl-allocator.h>
0049 #include <rtems/rtl/rtl-obj-cache.h>
0050 #include "rtl-error.h"
0051 #include <rtems/rtl/rtl-trace.h>
0052
0053 bool
0054 rtems_rtl_obj_cache_open (rtems_rtl_obj_cache* cache, size_t size)
0055 {
0056 cache->fd = -1;
0057 cache->file_size = 0;
0058 cache->offset = 0;
0059 cache->size = size;
0060 cache->level = 0;
0061 cache->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
0062 if (!cache->buffer)
0063 {
0064 rtems_rtl_set_error (ENOMEM, "no memory for cache buffer");
0065 return false;
0066 }
0067 return true;
0068 }
0069
0070 void
0071 rtems_rtl_obj_cache_close (rtems_rtl_obj_cache* cache)
0072 {
0073 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0074 printf ("rtl: cache: %2d: close\n", cache->fd);
0075 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
0076 cache->buffer = NULL;
0077 cache->fd = -1;
0078 cache->file_size = 0;
0079 cache->level = 0;
0080 }
0081
0082 void
0083 rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache* cache)
0084 {
0085 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0086 printf ("rtl: cache: %2d: flush\n", cache->fd);
0087 cache->fd = -1;
0088 cache->file_size = 0;
0089 cache->offset = 0;
0090 cache->level = 0;
0091 }
0092
0093 bool
0094 rtems_rtl_obj_cache_read (rtems_rtl_obj_cache* cache,
0095 int fd,
0096 off_t offset,
0097 void** buffer,
0098 size_t* length)
0099 {
0100 struct stat sb;
0101
0102 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0103 printf ("rtl: cache: %2d: fd=%d offset=%" PRIdoff_t " length=%zu area=[%"
0104 PRIdoff_t ",%" PRIdoff_t "] cache=[%" PRIdoff_t ",%" PRIdoff_t "] size=%zu\n",
0105 fd, cache->fd, offset, *length,
0106 offset, offset + *length,
0107 cache->offset, cache->offset + cache->level,
0108 cache->file_size);
0109
0110 if (*length > cache->size)
0111 {
0112 rtems_rtl_set_error (EINVAL, "read size larger than cache size");
0113 return false;
0114 }
0115
0116 if (cache->fd == fd)
0117 {
0118 if (offset >= cache->file_size)
0119 {
0120 rtems_rtl_set_error (EINVAL, "offset past end of file: offset=%i size=%i",
0121 (int) offset, (int) cache->file_size);
0122 return false;
0123 }
0124
0125
0126
0127
0128 if ((offset + *length) > cache->file_size)
0129 {
0130 *length = cache->file_size - offset;
0131 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0132 printf ("rtl: cache: %2d: truncate length=%d\n", fd, (int) *length);
0133
0134 }
0135 }
0136
0137 while (true)
0138 {
0139 size_t buffer_offset = 0;
0140 size_t buffer_read = cache->size;
0141
0142
0143
0144
0145 if (fd == cache->fd)
0146 {
0147
0148
0149
0150 if ((offset + buffer_read) > cache->file_size)
0151 buffer_read = cache->file_size - offset;
0152
0153
0154
0155
0156 if ((offset >= cache->offset) &&
0157 (offset < (cache->offset + cache->level)))
0158 {
0159 size_t size;
0160
0161 buffer_offset = offset - cache->offset;
0162 size = cache->level - buffer_offset;
0163
0164
0165
0166
0167 *buffer = cache->buffer + buffer_offset;
0168
0169
0170
0171
0172 if (*length <= size)
0173 return true;
0174
0175 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0176 printf ("rtl: cache: %2d: copy-down: buffer_offset=%d size=%d level=%d\n",
0177 fd, (int) buffer_offset, (int) size, (int) cache->level);
0178
0179
0180
0181
0182
0183 memmove (cache->buffer, cache->buffer + buffer_offset, size);
0184
0185 cache->offset = offset;
0186 cache->level = size;
0187 buffer_read = cache->size - cache->level;
0188 buffer_offset = size;
0189
0190
0191
0192
0193 if ((offset + buffer_offset + buffer_read) > cache->file_size)
0194 buffer_read = cache->file_size - (offset + buffer_offset);
0195 }
0196 }
0197
0198 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0199 printf ("rtl: cache: %2d: seek: offset=%" PRIdoff_t " buffer_offset=%zu"
0200 " read=%zu cache=[%" PRIdoff_t ",%" PRIdoff_t "] "
0201 "dist=%" PRIdoff_t "\n",
0202 fd, offset + buffer_offset, buffer_offset, buffer_read,
0203 offset, offset + buffer_read,
0204 (cache->file_size - offset));
0205
0206 if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
0207 {
0208 rtems_rtl_set_error (errno, "file seek failed");
0209 return false;
0210 }
0211
0212
0213
0214
0215
0216
0217
0218 cache->level = buffer_offset + buffer_read;
0219
0220 while (buffer_read)
0221 {
0222 int r = read (fd, cache->buffer + buffer_offset, buffer_read);
0223 if (r < 0)
0224 {
0225 rtems_rtl_set_error (errno, "file read failed");
0226 return false;
0227 }
0228 if ((r == 0) && buffer_read)
0229 {
0230 if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
0231 printf ("rtl: cache: %2d: read: past end by=%d\n", fd, (int) buffer_read);
0232 cache->level = cache->level - buffer_read;
0233 buffer_read = 0;
0234 }
0235 else
0236 {
0237 buffer_read -= r;
0238 buffer_offset += r;
0239 }
0240 }
0241
0242 cache->offset = offset;
0243
0244 if (cache->fd != fd)
0245 {
0246 cache->fd = fd;
0247
0248 if (fstat (cache->fd, &sb) < 0)
0249 {
0250 rtems_rtl_set_error (errno, "file stat failed");
0251 return false;
0252 }
0253
0254 cache->file_size = sb.st_size;
0255 }
0256 }
0257
0258 return false;
0259 }
0260
0261 bool
0262 rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache* cache,
0263 int fd,
0264 off_t offset,
0265 void* buffer,
0266 size_t length)
0267 {
0268 void* cbuffer = 0;
0269 size_t len = length;
0270 bool ok = rtems_rtl_obj_cache_read (cache, fd, offset, &cbuffer, &len);
0271 if (ok && (len != length))
0272 ok = false;
0273 if (ok)
0274 memcpy (buffer, cbuffer, length);
0275 return ok;
0276 }