source: rtems/cpukit/libdl/rtl-obj-comp.c @ 3feb372

4.115
Last change on this file since 3feb372 was ae5fe7e6, checked in by Chris Johns <chrisj@…>, on 10/27/14 at 01:09:41

cpukit: Add libdl with the Runtime Loader (RTL) code.

This is a merge of the RTL project.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012 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.com/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#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <errno.h>
22#include <string.h>
23#include <unistd.h>
24
25#include <rtems/rtl/rtl-allocator.h>
26#include "rtl-obj-comp.h"
27#include "rtl-error.h"
28
29#include "fastlz.h"
30
31#include <stdio.h>
32
33bool
34rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t*  comp,
35                         size_t                 size)
36{
37  comp->cache  = NULL;
38  comp->fd = -1;
39  comp->compression = RTEMS_RTL_COMP_LZ77;
40  comp->offset = 0;
41  comp->size   = size;
42  comp->level  = 0;
43  comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
44  if (!comp->buffer)
45  {
46    rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
47    return false;
48  }
49  comp->read = 0;
50  return true;
51}
52
53void
54rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp)
55{
56  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
57  comp->cache = NULL;
58  comp->fd = -1;
59  comp->compression = RTEMS_RTL_COMP_LZ77;
60  comp->level = 0;
61  comp->size = 0;
62  comp->offset = 0;
63  comp->read = 0;
64}
65
66void
67rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t*  comp,
68                        rtems_rtl_obj_cache_t* cache,
69                        int                    fd,
70                        int                    compression,
71                        off_t                  offset)
72{
73  comp->cache = cache;
74  comp->fd = fd;
75  comp->compression = compression;
76  comp->offset = offset;
77  comp->level = 0;
78  comp->read = 0;
79}
80
81bool
82rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
83                         void*                 buffer,
84                         size_t                length)
85{
86  uint8_t* bin = buffer;
87
88  if (!comp->cache)
89  {
90    rtems_rtl_set_error (EINVAL, "not open");
91    return false;
92  }
93
94  if (comp->fd != comp->cache->fd)
95  {
96    comp->level = 0;
97  }
98
99  while (length)
100  {
101    size_t buffer_level;
102
103    buffer_level = length > comp->level ? comp->level : length;
104
105    if (buffer_level)
106    {
107      memcpy (bin, comp->buffer, buffer_level);
108
109      if ((comp->level - buffer_level) != 0)
110      {
111        memmove (comp->buffer,
112                 comp->buffer + buffer_level,
113                 comp->level - buffer_level);
114      }
115
116      bin += buffer_level;
117      length -= buffer_level;
118      comp->level -= buffer_level;
119      comp->read += buffer_level;
120    }
121
122    if (length)
123    {
124      uint8_t* input = NULL;
125      uint16_t block_size;
126      size_t   in_length = sizeof (block_size);
127      int      decompressed;
128
129      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
130                                     (void**) &input, &in_length))
131        return false;
132
133      block_size = (input[0] << 8) | input[1];
134
135      comp->offset += sizeof (block_size);
136
137      in_length = block_size;
138
139      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
140                                     (void**) &input, &in_length))
141        return false;
142
143      if (in_length != block_size)
144      {
145        rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%u",
146                             block_size, in_length);
147        return false;
148      }
149
150      switch (comp->compression)
151      {
152        case RTEMS_RTL_COMP_NONE:
153          memcpy (comp->buffer, input, in_length);
154          decompressed = in_length;
155          break;
156
157        case RTEMS_RTL_COMP_LZ77:
158          decompressed = fastlz_decompress (input, in_length,
159                                            comp->buffer, comp->size);
160          if (decompressed == 0)
161          {
162            rtems_rtl_set_error (EBADF, "decompression failed");
163            return false;
164          }
165          break;
166
167        default:
168          rtems_rtl_set_error (EINVAL, "bad compression type");
169          return false;
170      }
171
172      comp->offset += block_size;
173
174      comp->level = decompressed;
175    }
176  }
177
178  return true;
179}
Note: See TracBrowser for help on using the repository browser.