Rizin
unix-like reverse engineering framework and cli tools
multifh.c
Go to the documentation of this file.
1 /* An implementation of the mspack_system interface which can access many
2  * things:
3  * - regular disk files
4  * - already opened stdio FILE* file pointers
5  * - open file descriptors
6  * - blocks of memory
7  */
8 
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <mspack.h>
18 
19 /* definitions */
20 
21 #define MTYPE_DISKFILE (0x01)
22 #define MTYPE_STDIOFH (0x02)
23 #define MTYPE_FILEDESC (0x03)
24 #define MTYPE_MEMORY (0x04)
25 
26 struct m_filename {
27  unsigned char type; /* one of MTYPE_DISKFILE, STDIOFH, FILEDESC or MEMORY */
28  const char *filename; /* the user-friendly printable filename (may be NULL) */
29  union {
30  const char *diskfile; /* char *filename for MTYPE_DISKFILE */
31  FILE *stdiofh; /* FILE *existing_fh for MTYPE_STDIOFH */
32  int filedesc; /* int file_descriptor for MTYPE_FILEDESC */
33  struct {
34  unsigned char *data;
35  size_t length;
36  } memory;
37  } x;
38 };
39 
40 struct m_file {
41  struct m_filename *file; /* pointer back to the m_filename data */
42  union {
43  FILE *fh; /* only used in DISKFILE, STDIOFH and FILEDESC types */
44  size_t position; /* only used in MEMORY types */
45  } x;
46 };
47 
48 /* ------------------------------------------------------------------------ */
49 /* mspack_system implementation */
50 
51 static void *m_alloc(struct mspack_system *self, size_t bytes) {
52  return malloc(bytes);
53 }
54 
55 static void m_free(void *buffer) {
56  free(buffer);
57 }
58 
59 static void m_copy(void *src, void *dest, size_t bytes) {
60  memcpy(dest, src, bytes);
61 }
62 
63 /* A message printer that prints to stderr */
64 static void m_msg(struct m_file *file, const char *format, ...) {
65  va_list ap;
66  if (file && file->file && file->file->filename) {
67  fprintf(stderr, "%s: ", file->file->filename);
68  }
69  va_start(ap, format);
70  vfprintf(stderr, format, ap);
71  va_end(ap);
72  fputc((int) '\n', stderr);
73  fflush(stderr);
74 }
75 
76 
77 static struct m_file *m_open_mem(struct mspack_system *self,
78  struct m_filename *fn, int mode)
79 {
80  struct m_file *fh;
81 
82  /* validate arguments of the filename */
83  if (!fn->x.memory.data) return NULL;
84  if (!fn->x.memory.length) return NULL;
85 
86  if ((fh = (struct m_file *) m_alloc(self, sizeof(struct m_file)))) {
87  fh->x.position = (mode == MSPACK_SYS_OPEN_APPEND) ?
88  fn->x.memory.length : 0;
89  fh->file = fn;
90  }
91  return fh;
92 }
93 
94 static struct m_file *m_open_file(struct mspack_system *self,
95  struct m_filename *fn, int mode)
96 {
97  struct m_file *fh;
98  const char *fmode;
99  int fd;
100 
101  switch (mode) {
102  case MSPACK_SYS_OPEN_READ: fmode = "rb"; break;
103  case MSPACK_SYS_OPEN_WRITE: fmode = "wb"; break;
104  case MSPACK_SYS_OPEN_UPDATE: fmode = "r+b"; break;
105  case MSPACK_SYS_OPEN_APPEND: fmode = "ab"; break;
106  default: return NULL;
107  }
108 
109  /* validate the arguments in the provided filename */
110  switch (fn->type) {
111  case MTYPE_DISKFILE: if (!fn->x.diskfile) return NULL; break;
112  case MTYPE_STDIOFH: if (!fn->x.stdiofh) return NULL; break;
113  case MTYPE_FILEDESC: if (fn->x.filedesc < 0) return NULL; break;
114  }
115 
116  /* allocate memory for the file handle */
117  if (!(fh = (struct m_file *) m_alloc(self, sizeof(struct m_file)))) return NULL;
118 
119  /* open or duplicate the filehandle */
120  switch (fn->type) {
121  case MTYPE_DISKFILE:
122  fh->x.fh = fopen(fn->x.diskfile, fmode);
123  break;
124 
125  case MTYPE_STDIOFH:
126  fd = fileno(fn->x.stdiofh);
127  fh->x.fh = (fd >= 0) ? fdopen(fd, fmode) : NULL;
128  break;
129 
130  case MTYPE_FILEDESC:
131  fh->x.fh = fdopen(fn->x.filedesc, fmode);
132  break;
133  }
134 
135  /* validate the new stdio filehandle */
136  if (fh->x.fh) {
137  fh->file = fn;
138  }
139  else {
140  free(fh);
141  fh = NULL;
142  }
143 
144  return fh;
145 }
146 
147 static struct m_file *m_open(struct mspack_system *self,
148  struct m_filename *fn, int mode)
149 {
150  if (!self || !fn) return NULL;
151 
152  switch (fn->type) {
153  case MTYPE_DISKFILE:
154  case MTYPE_STDIOFH:
155  case MTYPE_FILEDESC:
156  return m_open_file(self, fn, mode);
157 
158  case MTYPE_MEMORY:
159  return m_open_mem(self, fn, mode);
160  }
161  return NULL;
162 }
163 
164 static void m_close(struct m_file *fh) {
165  if (!fh || !fh->file) return;
166  if (fh->file->type != MTYPE_MEMORY) fclose(fh->x.fh);
167  m_free(fh);
168 }
169 
170 
171 static int m_read(struct m_file *fh, void *buffer, int bytes) {
172  if (!fh || !fh->file || !buffer || bytes < 0) return -1;
173 
174  if (fh->file->type == MTYPE_MEMORY) {
175  int count = fh->file->x.memory.length - fh->x.position;
176  if (count > bytes) count = bytes;
177  if (count > 0) {
178  m_copy(&fh->file->x.memory.data[fh->x.position], buffer, (size_t) count);
179  }
180  fh->x.position += count;
181  return count;
182  }
183  else {
184  size_t count = fread(buffer, 1, (size_t) bytes, fh->x.fh);
185  if (!ferror(fh->x.fh)) return (int) count;
186  }
187  return -1;
188 }
189 
190 
191 static int m_write(struct m_file *fh, void *buffer, int bytes) {
192  if (!fh || !fh->file || !buffer || bytes < 0) return -1;
193 
194  if (fh->file->type == MTYPE_MEMORY) {
195  int count = fh->file->x.memory.length - fh->x.position;
196  if (count > bytes) count = bytes;
197  if (count > 0) {
198  m_copy(buffer, &fh->file->x.memory.data[fh->x.position], (size_t) count);
199  }
200  fh->x.position += count;
201  return count;
202  }
203  else {
204  size_t count = fwrite(buffer, 1, (size_t) bytes, fh->x.fh);
205  if (!ferror(fh->x.fh)) return (int) count;
206  }
207  return -1;
208 }
209 
210 
211 static int m_seek(struct m_file *fh, off_t offset, int mode) {
212  if (!fh || !fh->file) return 1;
213 
214  if (fh->file->type == MTYPE_MEMORY) {
215  switch (mode) {
217  break;
218  case MSPACK_SYS_SEEK_CUR:
219  offset += (off_t) fh->x.position;
220  break;
221  case MSPACK_SYS_SEEK_END:
222  offset += (off_t) fh->file->x.memory.length;
223  break;
224  default:
225  return 1;
226  }
227 
228  if (offset < 0) return 1;
229  if (offset > (off_t) fh->file->x.memory.length) return 1;
230  fh->x.position = (size_t) offset;
231  return 0;
232  }
233 
234  /* file IO based method */
235  switch (mode) {
236  case MSPACK_SYS_SEEK_START: mode = SEEK_SET; break;
237  case MSPACK_SYS_SEEK_CUR: mode = SEEK_CUR; break;
238  case MSPACK_SYS_SEEK_END: mode = SEEK_END; break;
239  default: return 1;
240  }
241 #if HAVE_FSEEKO
242  return fseeko(fh->x.fh, offset, mode);
243 #else
244  return fseek(fh->x.fh, offset, mode);
245 #endif
246 }
247 
248 
249 static off_t m_tell(struct m_file *fh) {
250  if (!fh || !fh->file) return -1;
251  if (fh->file->type == MTYPE_MEMORY) {
252  return (off_t) fh->x.position;
253  }
254 #if HAVE_FSEEKO
255  return (off_t) ftello(fh->x.fh);
256 #else
257  return (off_t) ftell(fh->x.fh);
258 #endif
259 }
260 
261 
262 static struct mspack_system multi_system = {
263  (struct mspack_file * (*)(struct mspack_system *, const char *, int)) &m_open,
264  (void (*)(struct mspack_file *)) &m_close,
265  (int (*)(struct mspack_file *, void *, int)) &m_read,
266  (int (*)(struct mspack_file *, void *, int)) &m_write,
267  (int (*)(struct mspack_file *, off_t, int)) &m_seek,
268  (off_t (*)(struct mspack_file *)) &m_tell,
269  (void (*)(struct mspack_file *, const char *, ...)) &m_msg,
270  &m_alloc,
271  &m_free,
272  &m_copy,
273  NULL
274 };
275 
276 /* ------------------------------------------------------------------------ */
277 /* constructors and destructor */
278 
279 const char *create_filename(const char *filename) {
280  struct m_filename *fn;
281 
282  if (!filename) return NULL; /* filename must not be null */
283 
284  if ((fn = (struct m_filename *) malloc(sizeof(struct m_filename)))) {
285  fn->type = MTYPE_DISKFILE;
286  fn->filename = filename; /* pretty-printable filename */
287  fn->x.diskfile = filename;
288  }
289  return (const char *) fn;
290 }
291 
293  struct m_filename *fn;
294 
295  if (!fh) return NULL; /* file handle must not be null */
296 
297  if ((fn = (struct m_filename *) malloc(sizeof(struct m_filename)))) {
298  fn->type = MTYPE_STDIOFH;
299  fn->filename = NULL; /* pretty-printable filename */
300  fn->x.stdiofh = fh;
301  }
302  return (const char *) fn;
303 }
304 
306  struct m_filename *fn;
307 
308  if (fd < 0) return NULL; /* file descriptor must be valid */
309 
310  if ((fn = (struct m_filename *) malloc(sizeof(struct m_filename)))) {
311  fn->type = MTYPE_FILEDESC;
312  fn->filename = NULL; /* pretty-printable filename */
313  fn->x.filedesc = fd;
314  }
315  return (const char *) fn;
316 }
317 
318 const char *create_filename_from_memory(void *data, size_t length) {
319  struct m_filename *fn;
320 
321  if (!data) return NULL; /* data pointer must not be NULL */
322  if (length == 0) return NULL; /* length must not be zero */
323 
324  if ((fn = (struct m_filename *) malloc(sizeof(struct m_filename)))) {
325  fn->type = MTYPE_MEMORY;
326  fn->filename = NULL; /* pretty-printable filename */
327  fn->x.memory.data = (unsigned char *) data;
328  fn->x.memory.length = length;
329  }
330  return (const char *) fn;
331 }
332 
333 void set_filename_printable_name(const char *filename, const char *name) {
334  struct m_filename *fn = (struct m_filename *) filename;
335  if (!fn) return;
336  /* very basic validation of structure */
337  if ((fn->type < MTYPE_DISKFILE) || (fn->type > MTYPE_MEMORY)) return;
338  fn->filename = name;
339 }
340 
341 void free_filename(const char *filename) {
342  free((void *) filename);
343 }
344 
345 /* ------------------------------------------------------------------------ */
346 /* example of usage with mscab_decompressor */
347 
348 /* a simple cabinet */
349 static unsigned char memory_cab[] = {
350  0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,
351  0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x02,0x00,
352  0x00,0x00,0x22,0x06,0x00,0x00,0x5E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4D,
353  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x22,0xBA,0x59,0x20,0x00,
354  0x68,0x65,0x6C,0x6C,0x6F,0x2E,0x63,0x00,0x4A,0x00,0x00,0x00,0x4D,0x00,0x00,
355  0x00,0x00,0x00,0x6C,0x22,0xE7,0x59,0x20,0x00,0x77,0x65,0x6C,0x63,0x6F,0x6D,
356  0x65,0x2E,0x63,0x00,0xBD,0x5A,0xA6,0x30,0x97,0x00,0x97,0x00,0x23,0x69,0x6E,
357  0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,0x68,0x3E,
358  0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,0x28,0x76,
359  0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,0x70,0x72,
360  0x69,0x6E,0x74,0x66,0x28,0x22,0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,
361  0x72,0x6C,0x64,0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x23,
362  0x69,0x6E,0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,
363  0x68,0x3E,0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,
364  0x28,0x76,0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,
365  0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x22,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,
366  0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x0D,0x0A
367 };
368 
369 int main() {
370  const char *mem_cab, *std_out, *std_err, *example;
371  struct mscab_decompressor *cabd;
372  struct mscabd_cabinet *cab;
373  struct mscabd_file *file;
374  int err;
375 
376  mem_cab = create_filename_from_memory(&memory_cab[0], sizeof(memory_cab));
377  if (!mem_cab) exit(1);
378 
379  std_out = create_filename_from_descriptor(1);
380  if (!std_out) exit(1);
381 
382  std_err = create_filename_from_handle(stderr);
383  if (!std_err) exit(1);
384 
385  example = create_filename("example.txt");
386  if (!example) exit(1);
387 
388  set_filename_printable_name(mem_cab, "internal");
389  set_filename_printable_name(std_out, "stdout");
390  set_filename_printable_name(std_err, "stderr");
391 
392  /* if self-test reveals an error */
394  if (err) exit(1);
395 
396  /* create a cab decompressor using our custom mspack_system interface */
398 
399  /* open a cab file direct from memory */
400  if ((cab = cabd->open(cabd, mem_cab))) {
401 
402  /* first file in the cabinet: print it to stdout */
403  file = cab->files;
404  if (cabd->extract(cabd, file, std_out)) {
405  exit(1);
406  }
407 
408  /* second file in the cabinet: print it to stderr */
409  file = file->next;
410  if (cabd->extract(cabd, file, std_err)) {
411  exit(1);
412  }
413  /* also write it to "example.txt" */
414  if (cabd->extract(cabd, file, example)) {
415  exit(1);
416  }
417  cabd->close(cabd, cab);
418  }
419  else {
420  fprintf(stderr, "can't open cabinet (%d)\n", cabd->last_error(cabd));
421  }
423  }
424  else {
425  fprintf(stderr, "can't make decompressor\n");
426  }
427 
428  free_filename(example);
429  free_filename(std_err);
430  free_filename(std_out);
431  free_filename(mem_cab);
432 
433  return 0;
434 
435 }
lzma_index * src
Definition: index.h:567
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
#define MSPACK_SYS_OPEN_APPEND
Definition: mspack.h:464
#define MSPACK_SYS_SEEK_END
Definition: mspack.h:471
#define MSPACK_SYS_SELFTEST(result)
Definition: mspack.h:191
#define MSPACK_SYS_OPEN_WRITE
Definition: mspack.h:460
#define MSPACK_SYS_SEEK_START
Definition: mspack.h:467
#define MSPACK_SYS_OPEN_READ
Definition: mspack.h:458
#define MSPACK_SYS_SEEK_CUR
Definition: mspack.h:469
#define MSPACK_SYS_OPEN_UPDATE
Definition: mspack.h:462
struct mscab_decompressor * cabd
Definition: cabextract.c:126
FILE * fh
Definition: cabinfo.c:52
#define fseeko(s, o, w)
Definition: compat.h:121
#define ftello(s)
Definition: compat.h:125
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void mspack_destroy_cab_decompressor(struct mscab_decompressor *base)
Definition: cabd.c:173
struct mscab_decompressor * mspack_create_cab_decompressor(struct mspack_system *sys)
Definition: cabd.c:140
void * malloc(size_t size)
Definition: malloc.c:123
static const char struct stat static buf struct stat static buf static idle const char static path static fd const char static len const void static prot const char struct module static image struct kernel_sym static table unsigned char static buf static fsuid unsigned struct dirent unsigned static count const struct iovec static count static pid const void static len static flags const struct sched_param static p static pid static policy struct timespec static tp static suid unsigned fn
Definition: sflib.h:186
char * dest
Definition: lz4.h:697
static struct m_file * m_open(struct mspack_system *self, struct m_filename *fn, int mode)
Definition: multifh.c:147
static void m_free(void *buffer)
Definition: multifh.c:55
static void m_msg(struct m_file *file, const char *format,...)
Definition: multifh.c:64
static void * m_alloc(struct mspack_system *self, size_t bytes)
Definition: multifh.c:51
const char * create_filename_from_memory(void *data, size_t length)
Definition: multifh.c:318
static struct m_file * m_open_mem(struct mspack_system *self, struct m_filename *fn, int mode)
Definition: multifh.c:77
static struct m_file * m_open_file(struct mspack_system *self, struct m_filename *fn, int mode)
Definition: multifh.c:94
static int m_read(struct m_file *fh, void *buffer, int bytes)
Definition: multifh.c:171
static struct mspack_system multi_system
Definition: multifh.c:262
const char * create_filename(const char *filename)
Definition: multifh.c:279
static void m_copy(void *src, void *dest, size_t bytes)
Definition: multifh.c:59
static int m_write(struct m_file *fh, void *buffer, int bytes)
Definition: multifh.c:191
#define MTYPE_DISKFILE
Definition: multifh.c:21
const char * create_filename_from_handle(FILE *fh)
Definition: multifh.c:292
#define MTYPE_FILEDESC
Definition: multifh.c:23
void set_filename_printable_name(const char *filename, const char *name)
Definition: multifh.c:333
const char * create_filename_from_descriptor(int fd)
Definition: multifh.c:305
void free_filename(const char *filename)
Definition: multifh.c:341
static unsigned char memory_cab[]
Definition: multifh.c:349
static void m_close(struct m_file *fh)
Definition: multifh.c:164
static int m_seek(struct m_file *fh, off_t offset, int mode)
Definition: multifh.c:211
static off_t m_tell(struct m_file *fh)
Definition: multifh.c:249
#define MTYPE_STDIOFH
Definition: multifh.c:22
int main()
Definition: multifh.c:369
#define MTYPE_MEMORY
Definition: multifh.c:24
string FILE
Definition: benchmark.py:21
const char * name
Definition: op.c:541
static int
Definition: sfsocketcall.h:114
int size_t
Definition: sftypes.h:40
int off_t
Definition: sftypes.h:41
Definition: buffer.h:15
Definition: gzappend.c:170
z_const unsigned char * next
Definition: gzappend.c:175
Definition: multifh.c:40
size_t position
Definition: multifh.c:44
union m_file::@392 x
FILE * fh
Definition: multifh.c:43
struct m_filename * file
Definition: multifh.c:41
unsigned char type
Definition: multifh.c:27
const char * diskfile
Definition: multifh.c:30
struct m_filename::@390::@391 memory
const char * filename
Definition: multifh.c:28
union m_filename::@390 x
FILE * stdiofh
Definition: multifh.c:31
int filedesc
Definition: multifh.c:32
unsigned char * data
Definition: multifh.c:34
size_t length
Definition: multifh.c:35
int(* last_error)(struct mscab_decompressor *self)
Definition: mspack.h:1179
struct mscabd_cabinet *(* open)(struct mscab_decompressor *self, const char *filename)
Definition: mspack.h:978
int(* extract)(struct mscab_decompressor *self, struct mscabd_file *file, const char *filename)
Definition: mspack.h:1138
void(* close)(struct mscab_decompressor *self, struct mscabd_cabinet *cab)
Definition: mspack.h:1010
struct mscabd_file * files
Definition: mspack.h:743
Definition: z80asm.h:102
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int file
Definition: z80asm.c:58
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
#define SEEK_END
Definition: zip.c:84