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