1 /* radare - LGPL - Copyright 2008-2017 - pancake */
2
3 #include "r_io.h"
4 #include "r_lib.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/types.h>
8
9 typedef struct {
10 ut8 *buf;
11 ut32 size;
12 ut64 offset;
13 } RIOGzip;
14
_io_malloc_sz(RIODesc * desc)15 static inline ut32 _io_malloc_sz(RIODesc *desc) {
16 if (!desc) {
17 return 0;
18 }
19 RIOGzip *mal = (RIOGzip*)desc->data;
20 return mal? mal->size: 0;
21 }
22
_io_malloc_set_sz(RIODesc * desc,ut32 sz)23 static inline void _io_malloc_set_sz(RIODesc *desc, ut32 sz) {
24 if (!desc) {
25 return;
26 }
27 RIOGzip *mal = (RIOGzip*)desc->data;
28 if (mal) {
29 mal->size = sz;
30 }
31 }
32
_io_malloc_buf(RIODesc * desc)33 static inline ut8* _io_malloc_buf(RIODesc *desc) {
34 if (!desc) {
35 return NULL;
36 }
37 RIOGzip *mal = (RIOGzip*)desc->data;
38 return mal->buf;
39 }
40
41
_io_malloc_set_buf(RIODesc * desc,ut8 * buf)42 static inline ut8* _io_malloc_set_buf(RIODesc *desc, ut8* buf) {
43 if (!desc) {
44 return NULL;
45 }
46 RIOGzip *mal = (RIOGzip*)desc->data;
47 return mal->buf = buf;
48 }
49
_io_malloc_off(RIODesc * desc)50 static inline ut64 _io_malloc_off(RIODesc *desc) {
51 if (!desc) {
52 return 0;
53 }
54 RIOGzip *mal = (RIOGzip*)desc->data;
55 return mal->offset;
56 }
57
_io_malloc_set_off(RIODesc * desc,ut64 off)58 static inline void _io_malloc_set_off(RIODesc *desc, ut64 off) {
59 if (!desc) {
60 return;
61 }
62 RIOGzip *mal = (RIOGzip*)desc->data;
63 mal->offset = off;
64 }
65
__write(RIO * io,RIODesc * fd,const ut8 * buf,int count)66 static int __write(RIO *io, RIODesc *fd, const ut8 *buf, int count) {
67 if (!fd || !buf || count < 0 || !fd->data) {
68 return -1;
69 }
70 if (_io_malloc_off (fd) > _io_malloc_sz (fd)) {
71 return -1;
72 }
73 if (_io_malloc_off (fd) + count > _io_malloc_sz (fd)) {
74 count -= (_io_malloc_off (fd) + count -_io_malloc_sz (fd));
75 }
76 if (count > 0) {
77 memcpy (_io_malloc_buf (fd) + _io_malloc_off (fd), buf, count);
78 _io_malloc_set_off (fd, _io_malloc_off (fd) + count);
79 return count;
80 }
81 return -1;
82 }
83
__resize(RIO * io,RIODesc * fd,ut64 count)84 static bool __resize(RIO *io, RIODesc *fd, ut64 count) {
85 ut8 * new_buf = NULL;
86 if (!fd || !fd->data || count == 0) {
87 return false;
88 }
89 ut32 mallocsz = _io_malloc_sz (fd);
90 if (_io_malloc_off (fd) > mallocsz) {
91 return false;
92 }
93 new_buf = malloc (count);
94 if (!new_buf) {
95 return false;
96 }
97 memcpy (new_buf, _io_malloc_buf (fd), R_MIN (count, mallocsz));
98 if (count > mallocsz) {
99 memset (new_buf + mallocsz, 0, count - mallocsz);
100 }
101 free (_io_malloc_buf (fd));
102 _io_malloc_set_buf (fd, new_buf);
103 _io_malloc_set_sz (fd, count);
104 return true;
105 }
106
__read(RIO * io,RIODesc * fd,ut8 * buf,int count)107 static int __read(RIO *io, RIODesc *fd, ut8 *buf, int count) {
108 memset (buf, 0xff, count);
109 if (!fd || !fd->data) {
110 return -1;
111 }
112 ut32 mallocsz = _io_malloc_sz (fd);
113 if (_io_malloc_off (fd) > mallocsz) {
114 return -1;
115 }
116 if (_io_malloc_off (fd) + count >= mallocsz) {
117 count = mallocsz - _io_malloc_off (fd);
118 }
119 memcpy (buf, _io_malloc_buf (fd) + _io_malloc_off (fd), count);
120 return count;
121 }
122
__close(RIODesc * fd)123 static int __close(RIODesc *fd) {
124 RIOGzip *riom;
125 if (!fd || !fd->data) {
126 return -1;
127 }
128 riom = fd->data;
129 R_FREE (riom->buf);
130 R_FREE (fd->data);
131 eprintf ("TODO: Writing changes into gzipped files is not yet supported\n");
132 return 0;
133 }
134
__lseek(RIO * io,RIODesc * fd,ut64 offset,int whence)135 static ut64 __lseek(RIO* io, RIODesc *fd, ut64 offset, int whence) {
136 ut64 r_offset = offset;
137 if (!fd || !fd->data) {
138 return offset;
139 }
140 ut32 mallocsz = _io_malloc_sz (fd);
141 switch (whence) {
142 case SEEK_SET:
143 r_offset = (offset <= mallocsz) ? offset : mallocsz;
144 break;
145 case SEEK_CUR:
146 r_offset = (_io_malloc_off (fd) + offset <= mallocsz ) ? _io_malloc_off (fd) + offset : mallocsz;
147 break;
148 case SEEK_END:
149 r_offset = _io_malloc_sz (fd);
150 break;
151 }
152 _io_malloc_set_off (fd, r_offset);
153 return r_offset;
154 }
155
__plugin_open(RIO * io,const char * pathname,bool many)156 static bool __plugin_open(RIO *io, const char *pathname, bool many) {
157 return (!strncmp (pathname, "gzip://", 7));
158 }
159
__open(RIO * io,const char * pathname,int rw,int mode)160 static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) {
161 if (__plugin_open (io, pathname, 0)) {
162 RIOGzip *mal = R_NEW0 (RIOGzip);
163 if (!mal) {
164 return NULL;
165 }
166 size_t len;
167 ut8 *data = (ut8 *)r_file_slurp (pathname+7, &len); //memleak here?
168 int *size = (int*)&mal->size;
169 mal->buf = r_inflate (data, (int)len, NULL, size);
170 if (mal->buf) {
171 return r_io_desc_new (io, &r_io_plugin_gzip, pathname, rw, mode, mal);
172 }
173 free (data);
174 eprintf ("Cannot allocate (%s) %d byte(s)\n", pathname+9, mal->size);
175 free (mal);
176 }
177 return NULL;
178 }
179
180 RIOPlugin r_io_plugin_gzip = {
181 .name = "gzip",
182 .desc = "Read/write gzipped files",
183 .license = "LGPL3",
184 .uris = "gzip://",
185 .open = __open,
186 .close = __close,
187 .read = __read,
188 .check = __plugin_open,
189 .lseek = __lseek,
190 .write = __write,
191 .resize = __resize,
192 };
193
194 #ifndef R2_PLUGIN_INCORE
195 R_API RLibStruct radare_plugin = {
196 .type = R_LIB_TYPE_IO,
197 .data = &r_io_plugin_gzip,
198 .version = R2_VERSION
199 };
200 #endif
201