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 <string.h>
0043 #include <unistd.h>
0044 #include <inttypes.h>
0045 #include <rtems/inttypes.h>
0046
0047 #include <rtems/rtl/rtl-allocator.h>
0048 #include <rtems/rtl/rtl-obj-comp.h>
0049 #include "rtl-error.h"
0050 #include <rtems/rtl/rtl-trace.h>
0051
0052 #include "fastlz.h"
0053
0054 #include <stdio.h>
0055
0056 bool
0057 rtems_rtl_obj_comp_open (rtems_rtl_obj_comp* comp,
0058 size_t size)
0059 {
0060 comp->cache = NULL;
0061 comp->fd = -1;
0062 comp->compression = RTEMS_RTL_COMP_LZ77;
0063 comp->offset = 0;
0064 comp->size = size;
0065 comp->level = 0;
0066 comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
0067 if (!comp->buffer)
0068 {
0069 rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
0070 return false;
0071 }
0072 comp->read = 0;
0073 return true;
0074 }
0075
0076 void
0077 rtems_rtl_obj_comp_close (rtems_rtl_obj_comp* comp)
0078 {
0079 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
0080 comp->cache = NULL;
0081 comp->fd = -1;
0082 comp->compression = RTEMS_RTL_COMP_LZ77;
0083 comp->level = 0;
0084 comp->size = 0;
0085 comp->offset = 0;
0086 comp->read = 0;
0087 }
0088
0089 void
0090 rtems_rtl_obj_comp_set (rtems_rtl_obj_comp* comp,
0091 rtems_rtl_obj_cache* cache,
0092 int fd,
0093 int compression,
0094 off_t offset)
0095 {
0096 comp->cache = cache;
0097 comp->fd = fd;
0098 comp->compression = compression;
0099 comp->offset = offset;
0100 comp->level = 0;
0101 comp->read = 0;
0102 }
0103
0104 bool
0105 rtems_rtl_obj_comp_read (rtems_rtl_obj_comp* comp,
0106 void* buffer,
0107 size_t length)
0108 {
0109 uint8_t* bin = buffer;
0110
0111 if (!comp->cache)
0112 {
0113 rtems_rtl_set_error (EINVAL, "not open");
0114 return false;
0115 }
0116
0117 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0118 printf ("rtl: comp: %2d: fd=%d length=%zu level=%zu offset=%" PRIdoff_t " area=[%"
0119 PRIdoff_t ",%" PRIdoff_t "] read=%" PRIu32 " size=%zu\n",
0120 comp->fd, comp->cache->fd, length, comp->level, comp->offset,
0121 comp->offset, comp->offset + length,
0122 comp->read, comp->size);
0123
0124 if (comp->fd != comp->cache->fd)
0125 {
0126 comp->level = 0;
0127 }
0128
0129 while (length)
0130 {
0131 size_t buffer_level;
0132
0133 buffer_level = length > comp->level ? comp->level : length;
0134
0135 if (buffer_level)
0136 {
0137 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0138 printf ("rtl: comp: copy: length=%zu\n",
0139 buffer_level);
0140
0141 memcpy (bin, comp->buffer, buffer_level);
0142
0143 if ((comp->level - buffer_level) != 0)
0144 {
0145 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0146 printf ("rtl: comp: copy-down: level=%zu length=%zu\n",
0147 comp->level, comp->level - buffer_level);
0148
0149 memmove (comp->buffer,
0150 comp->buffer + buffer_level,
0151 comp->level - buffer_level);
0152 }
0153
0154 bin += buffer_level;
0155 length -= buffer_level;
0156 comp->level -= buffer_level;
0157 comp->read += buffer_level;
0158 }
0159
0160 if (length)
0161 {
0162 uint8_t* input = NULL;
0163 uint16_t block_size;
0164 size_t in_length = sizeof (block_size);
0165 int decompressed;
0166
0167 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0168 printf ("rtl: comp: read block-size: offset=%" PRIdoff_t "\n",
0169 comp->offset);
0170
0171 if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
0172 (void**) &input, &in_length))
0173 return false;
0174
0175 block_size = (input[0] << 8) | input[1];
0176
0177 comp->offset += sizeof (block_size);
0178
0179 in_length = block_size;
0180
0181 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0182 printf ("rtl: comp: read block: offset=%" PRIdoff_t " size=%u\n",
0183 comp->offset, block_size);
0184
0185 if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
0186 (void**) &input, &in_length))
0187 return false;
0188
0189 if (in_length != block_size)
0190 {
0191 rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%zu",
0192 block_size, in_length);
0193 return false;
0194 }
0195
0196 switch (comp->compression)
0197 {
0198 case RTEMS_RTL_COMP_NONE:
0199 memcpy (comp->buffer, input, in_length);
0200 decompressed = in_length;
0201 break;
0202
0203 case RTEMS_RTL_COMP_LZ77:
0204 decompressed = fastlz_decompress (input, in_length,
0205 comp->buffer, comp->size);
0206 if (decompressed == 0)
0207 {
0208 rtems_rtl_set_error (EBADF, "decompression failed");
0209 return false;
0210 }
0211 break;
0212
0213 default:
0214 rtems_rtl_set_error (EINVAL, "bad compression type");
0215 return false;
0216 }
0217
0218 comp->offset += block_size;
0219
0220 comp->level = decompressed;
0221
0222 if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
0223 printf ("rtl: comp: expand: offset=%" PRIdoff_t \
0224 " level=%zu read=%" PRIu32 "\n",
0225 comp->offset, comp->level, comp->read);
0226 }
0227 }
0228
0229 return true;
0230 }