Rizin
unix-like reverse engineering framework and cli tools
chmextract.c
Go to the documentation of this file.
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <mspack.h>
9 #include <sys/stat.h>
10 
11 #include <error.h>
12 
13 #if HAVE_MKDIR
14 # if MKDIR_TAKES_ONE_ARG
15 # define mkdir(a, b) mkdir(a)
16 # endif
17 #else
18 # if HAVE__MKDIR
19 # define mkdir(a, b) _mkdir(a)
20 # else
21 # error "Don't know how to create a directory on this system."
22 # endif
23 #endif
24 
26 
35 static int ensure_filepath(char *path) {
36  struct stat st_buf;
37  char *p;
38  int ok;
39 
40  for (p = &path[1]; *p; p++) {
41  if (*p != '/') continue;
42  *p = '\0';
43  ok = (stat(path, &st_buf) == 0) && S_ISDIR(st_buf.st_mode);
44  if (!ok) ok = (mkdir(path, 0777 & ~user_umask) == 0);
45  *p = '/';
46  if (!ok) return 0;
47  }
48  return 1;
49 }
50 
51 char *create_output_name(char *fname) {
52  char *out, *p;
53  if ((out = malloc(strlen(fname) + 1))) {
54  /* remove leading slashes */
55  while (*fname == '/' || *fname == '\\') fname++;
56  /* if that removes all characters, just call it "x" */
57  strcpy(out, (*fname) ? fname : "x");
58 
59  /* change "../" to "xx/" */
60  for (p = out; *p; p++) {
61  if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\\')) {
62  p[0] = p[1] = 'x';
63  }
64  }
65  }
66  return out;
67 }
68 
69 static int sortfunc(const void *a, const void *b) {
70  off_t diff =
71  ((* ((struct mschmd_file **) a))->offset) -
72  ((* ((struct mschmd_file **) b))->offset);
73  return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
74 }
75 
76 int main(int argc, char *argv[]) {
77  struct mschm_decompressor *chmd;
78  struct mschmd_header *chm;
79  struct mschmd_file *file, **f;
80  unsigned int numf, i;
81 
82  setbuf(stdout, NULL);
83  setbuf(stderr, NULL);
85 
87  if (i) return 0;
88 
89  if ((chmd = mspack_create_chm_decompressor(NULL))) {
90  for (argv++; *argv; argv++) {
91  printf("%s\n", *argv);
92  if ((chm = chmd->open(chmd, *argv))) {
93 
94  /* build an ordered list of files for maximum extraction speed */
95  for (numf=0, file=chm->files; file; file = file->next) numf++;
96  if ((f = (struct mschmd_file **) calloc(numf, sizeof(struct mschmd_file *)))) {
97  for (i=0, file=chm->files; file; file = file->next) f[i++] = file;
98  qsort(f, numf, sizeof(struct mschmd_file *), &sortfunc);
99 
100  for (i = 0; i < numf; i++) {
101  char *outname = create_output_name(f[i]->filename);
102  printf("Extracting %s\n", outname);
103  ensure_filepath(outname);
104  if (chmd->extract(chmd, f[i], outname)) {
105  printf("%s: extract error on \"%s\": %s\n",
106  *argv, f[i]->filename, ERROR(chmd));
107  }
108  free(outname);
109  }
110  free(f);
111  }
112  chmd->close(chmd, chm);
113  }
114  else {
115  printf("%s: can't open -- %s\n", *argv, ERROR(chmd));
116  }
117  }
119  }
120  return 0;
121 }
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define MSPACK_SYS_SELFTEST(result)
Definition: mspack.h:191
void mspack_destroy_chm_decompressor(struct mschm_decompressor *self)
Definition: chmd.c:104
struct mschm_decompressor * mspack_create_chm_decompressor(struct mspack_system *sys)
Definition: chmd.c:78
int main(int argc, char *argv[])
Definition: chmextract.c:76
mode_t user_umask
Definition: chmextract.c:25
static int ensure_filepath(char *path)
Definition: chmextract.c:35
static int sortfunc(const void *a, const void *b)
Definition: chmextract.c:69
char * create_output_name(char *fname)
Definition: chmextract.c:51
#define S_ISDIR(mode)
Definition: compat.h:187
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz umask
Definition: sflib.h:65
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
void * p
Definition: libc.cpp:67
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig mkdir
Definition: sflib.h:66
static stat
Definition: sflib.h:131
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
@ ok
Definition: lz4.c:1706
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
int mode_t
Definition: sftypes.h:42
int off_t
Definition: sftypes.h:41
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define a(i)
Definition: sha256.c:41
Definition: gzappend.c:170
z_const unsigned char * next
Definition: gzappend.c:175
void(* close)(struct mschm_decompressor *self, struct mschmd_header *chm)
Definition: mspack.h:1618
int(* extract)(struct mschm_decompressor *self, struct mschmd_file *file, const char *filename)
Definition: mspack.h:1639
struct mschmd_header *(* open)(struct mschm_decompressor *self, const char *filename)
Definition: mspack.h:1598
struct mschmd_file * files
Definition: mspack.h:1301
Definition: sftypes.h:80
static int file
Definition: z80asm.c:58