source: rtems/cpukit/libdl/rtl-obj-comp.c @ 3635d6a

5
Last change on this file since 3635d6a was 3635d6a, checked in by Chris Johns <chrisj@…>, on 05/05/20 at 04:57:34

libdl/obj-comp: Add trace prints when decompressing

Updates #3969

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtl
12 *
13 * @brief RTEMS Run-Time Linker Object Compression manages a compress
14 *        stream of data.
15 */
16
17#ifdef HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <errno.h>
22#include <string.h>
23#include <unistd.h>
24#include <inttypes.h>
25#include <rtems/inttypes.h>
26
27#include <rtems/rtl/rtl-allocator.h>
28#include <rtems/rtl/rtl-obj-comp.h>
29#include "rtl-error.h"
30#include <rtems/rtl/rtl-trace.h>
31
32#include "fastlz.h"
33
34#include <stdio.h>
35
36bool
37rtems_rtl_obj_comp_open (rtems_rtl_obj_comp* comp,
38                         size_t              size)
39{
40  comp->cache  = NULL;
41  comp->fd = -1;
42  comp->compression = RTEMS_RTL_COMP_LZ77;
43  comp->offset = 0;
44  comp->size   = size;
45  comp->level  = 0;
46  comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
47  if (!comp->buffer)
48  {
49    rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
50    return false;
51  }
52  comp->read = 0;
53  return true;
54}
55
56void
57rtems_rtl_obj_comp_close (rtems_rtl_obj_comp* comp)
58{
59  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
60  comp->cache = NULL;
61  comp->fd = -1;
62  comp->compression = RTEMS_RTL_COMP_LZ77;
63  comp->level = 0;
64  comp->size = 0;
65  comp->offset = 0;
66  comp->read = 0;
67}
68
69void
70rtems_rtl_obj_comp_set (rtems_rtl_obj_comp*  comp,
71                        rtems_rtl_obj_cache* cache,
72                        int                  fd,
73                        int                  compression,
74                        off_t                offset)
75{
76  comp->cache = cache;
77  comp->fd = fd;
78  comp->compression = compression;
79  comp->offset = offset;
80  comp->level = 0;
81  comp->read = 0;
82}
83
84bool
85rtems_rtl_obj_comp_read (rtems_rtl_obj_comp* comp,
86                         void*               buffer,
87                         size_t              length)
88{
89  uint8_t* bin = buffer;
90
91  if (!comp->cache)
92  {
93    rtems_rtl_set_error (EINVAL, "not open");
94    return false;
95  }
96
97  if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
98    printf ("rtl:  comp: %2d: fd=%d length=%zu level=%u offset=%" PRIdoff_t " area=[%"
99            PRIdoff_t ",%" PRIdoff_t "] read=%" PRIu32 " size=%zu\n",
100            comp->fd, comp->cache->fd, length, comp->level, comp->offset,
101            comp->offset, comp->offset + length,
102            comp->read, comp->size);
103
104  if (comp->fd != comp->cache->fd)
105  {
106    comp->level = 0;
107  }
108
109  while (length)
110  {
111    size_t buffer_level;
112
113    buffer_level = length > comp->level ? comp->level : length;
114
115    if (buffer_level)
116    {
117      if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
118        printf ("rtl:  comp: copy: length=%zu\n",
119                buffer_level);
120
121      memcpy (bin, comp->buffer, buffer_level);
122
123      if ((comp->level - buffer_level) != 0)
124      {
125        if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
126          printf ("rtl:  comp: copy-down: level=%u length=%zu\n",
127                  comp->level, comp->level - buffer_level);
128
129        memmove (comp->buffer,
130                 comp->buffer + buffer_level,
131                 comp->level - buffer_level);
132      }
133
134      bin += buffer_level;
135      length -= buffer_level;
136      comp->level -= buffer_level;
137      comp->read += buffer_level;
138    }
139
140    if (length)
141    {
142      uint8_t* input = NULL;
143      uint16_t block_size;
144      size_t   in_length = sizeof (block_size);
145      int      decompressed;
146
147      if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
148        printf ("rtl:  comp: read block-size: offset=%" PRIdoff_t "\n",
149                comp->offset);
150
151      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
152                                     (void**) &input, &in_length))
153        return false;
154
155      block_size = (input[0] << 8) | input[1];
156
157      comp->offset += sizeof (block_size);
158
159      in_length = block_size;
160
161      if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
162        printf ("rtl:  comp: read block: offset=%" PRIdoff_t " size=%u\n",
163                comp->offset, block_size);
164
165      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
166                                     (void**) &input, &in_length))
167        return false;
168
169      if (in_length != block_size)
170      {
171        rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%zu",
172                             block_size, in_length);
173        return false;
174      }
175
176      switch (comp->compression)
177      {
178        case RTEMS_RTL_COMP_NONE:
179          memcpy (comp->buffer, input, in_length);
180          decompressed = in_length;
181          break;
182
183        case RTEMS_RTL_COMP_LZ77:
184          decompressed = fastlz_decompress (input, in_length,
185                                            comp->buffer, comp->size);
186          if (decompressed == 0)
187          {
188            rtems_rtl_set_error (EBADF, "decompression failed");
189            return false;
190          }
191          break;
192
193        default:
194          rtems_rtl_set_error (EINVAL, "bad compression type");
195          return false;
196      }
197
198      comp->offset += block_size;
199
200      comp->level = decompressed;
201
202      if (rtems_rtl_trace (RTEMS_RTL_TRACE_COMP))
203        printf ("rtl:  comp: expand: offset=%" PRIdoff_t \
204                " level=%u read=%" PRIu32 "\n",
205                comp->offset, comp->level, comp->read);
206    }
207  }
208
209  return true;
210}
Note: See TracBrowser for help on using the repository browser.