Rizin
unix-like reverse engineering framework and cli tools
cabextract.c
Go to the documentation of this file.
1 /* cabextract - a program to extract Microsoft Cabinet files
2  * (C) 2000-2019 Stuart Caie <kyzer@cabextract.org.uk>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 /* cabextract uses libmspack to access cabinet files. libmspack is
20  * available from https://www.cabextract.org.uk/libmspack/
21  */
22 
23 #define _GNU_SOURCE 1
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <sys/types.h>
30 
31 #include <ctype.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <fnmatch.h>
35 #include <limits.h>
36 #include <locale.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #ifdef HAVE_STRINGS_H
42 # include <strings.h> /* BSD defines strcasecmp() here */
43 #endif
44 #include <sys/stat.h>
45 #include <time.h>
46 
47 #if HAVE_ICONV
48 # include <iconv.h>
49 #endif
50 #if HAVE_TOWLOWER
51 # include <wctype.h>
52 #endif
53 #if HAVE_UTIME
54 # include <utime.h>
55 #endif
56 #if HAVE_UTIMES
57 # include <sys/time.h>
58 #endif
59 
60 /* ensure mkdir(pathname, mode) exists */
61 #if HAVE_MKDIR
62 # if MKDIR_TAKES_ONE_ARG
63 # define mkdir(a, b) mkdir(a)
64 # endif
65 #else
66 # if HAVE__MKDIR
67 # define mkdir(a, b) _mkdir(a)
68 # else
69 # error "Don't know how to create a directory on this system."
70 # endif
71 #endif
72 
73 #ifndef FNM_CASEFOLD
74 # define FNM_CASEFOLD (0)
75 #endif
76 
77 #include "getopt.h"
78 
79 #include <mspack.h>
80 #include <md5.h>
81 
82 /* structures and global variables */
83 struct option optlist[] = {
84  { "directory", 1, NULL, 'd' },
85 #if HAVE_ICONV
86  { "encoding", 1, NULL, 'e' },
87 #endif
88  { "fix", 0, NULL, 'f' },
89  { "filter", 1, NULL, 'F' },
90  { "help", 0, NULL, 'h' },
91  { "list", 0, NULL, 'l' },
92  { "lowercase", 0, NULL, 'L' },
93  { "pipe", 0, NULL, 'p' },
94  { "quiet", 0, NULL, 'q' },
95  { "single", 0, NULL, 's' },
96  { "test", 0, NULL, 't' },
97  { "version", 0, NULL, 'v' },
98  { NULL, 0, NULL, 0 }
99 };
100 
101 #if HAVE_ICONV
102 const char *OPTSTRING = "d:e:fF:hlLpqstv";
103 #else
104 const char *OPTSTRING = "d:fF:hlLpqstv";
105 #endif
106 
107 struct file_mem {
108  struct file_mem *next;
110  ino_t st_ino;
111  char *from;
112 };
113 
114 struct filter {
115  struct filter *next;
116  char *filter;
117 };
118 
121  char *dir, *encoding;
122  struct filter *filters;
123 };
124 
125 /* global variables */
127 
131 
133 
134 struct cabextract_args args = {
135  0, 0, 0, 0, 0, 0, 0, 0,
136  NULL, NULL, NULL
137 };
138 
139 #if HAVE_ICONV
140 iconv_t converter = NULL;
141 #endif
142 
148 const char *STDOUT_FNAME = "stdout";
149 
155 const char *TEST_FNAME = "test";
156 
158 struct md5_ctx md5_context;
159 
161 unsigned char md5_result[16];
162 
163 /* prototypes */
164 static int process_cabinet(char *cabname);
165 
166 static void load_spanning_cabinets(struct mscabd_cabinet *basecab,
167  char *basename);
168 static char *find_cabinet_file(char *origcab, char *cabname);
169 static int unix_path_seperators(struct mscabd_file *files);
170 static char *create_output_name(const char *fname, const char *dir,
171  int lower, int isunix, int unicode);
172 static void set_date_and_perm(struct mscabd_file *file, char *filename);
173 
174 #if HAVE_ICONV
175 static void convert_filenames(struct mscabd_file *files);
176 #endif
177 #if LATIN1_FILENAMES
178 static void convert_utf8_to_latin1(char *str);
179 #endif
180 
181 static void memorise_file(struct file_mem **fml, char *name, char *from);
182 static int recall_file(struct file_mem *fml, char *name, char **from);
183 static void forget_files(struct file_mem **fml);
184 static void add_filter(char *arg);
185 static void free_filters();
186 static int ensure_filepath(char *path);
187 static char *cab_error(struct mscab_decompressor *cd);
188 
189 static struct mspack_file *cabx_open(struct mspack_system *this,
190  const char *filename, int mode);
191 static void cabx_close(struct mspack_file *file);
192 static int cabx_read(struct mspack_file *file, void *buffer, int bytes);
193 static int cabx_write(struct mspack_file *file, void *buffer, int bytes);
194 static int cabx_seek(struct mspack_file *file, off_t offset, int mode);
195 static off_t cabx_tell(struct mspack_file *file);
196 static void cabx_msg(struct mspack_file *file, const char *format, ...);
197 static void *cabx_alloc(struct mspack_system *this, size_t bytes);
198 static void cabx_free(void *buffer);
199 static void cabx_copy(void *src, void *dest, size_t bytes);
200 
206 static struct mspack_system cabextract_system = {
209 };
210 
211 int main(int argc, char *argv[]) {
212  int i, err;
213 
214  /* names for the UTF-8 charset recognised by different iconv_open()s */
215  char *utf8_names[] = {
216  "UTF-8", /* glibc, libiconv, FreeBSD, Solaris, not newlib or HPUX */
217  "UTF8", /* glibc, libiconv (< 1.13), newlib, HPUX */
218  "UTF_8", /* newlib, Solaris */
219  };
220 
221  /* attempt to set a UTF8-based locale, so that tolower()/towlower()
222  * in create_output_name() lowercase more than just A-Z in ASCII.
223  *
224  * We don't attempt to pick up the system default locale, "",
225  * because it might not be compatible with ASCII/ISO-8859-1/Unicode
226  * character codes and would mess up lowercased filenames
227  */
228  char *locales[] = {
229  "C.UTF-8", /* https://sourceware.org/glibc/wiki/Proposals/C.UTF-8 */
230  "en_US.UTF-8", "en_GB.UTF8", "de_DE.UTF-8", "UTF-8", "UTF8"
231  };
232  for (i = 0; i < (sizeof(locales)/sizeof(*locales)); i++) {
233  if (setlocale(LC_CTYPE, locales[i])) break;
234  }
235 
236  /* parse options */
237  while ((i = getopt_long(argc, argv, OPTSTRING, optlist, NULL)) != -1) {
238  switch (i) {
239  case 'd': args.dir = optarg; break;
240  case 'e': args.encoding = optarg; break;
241  case 'f': args.fix = 1; break;
242  case 'F': add_filter(optarg); break;
243  case 'h': args.help = 1; break;
244  case 'l': args.view = 1; break;
245  case 'L': args.lower = 1; break;
246  case 'p': args.pipe = 1; break;
247  case 'q': args.quiet = 1; break;
248  case 's': args.single = 1; break;
249  case 't': args.test = 1; break;
250  case 'v': args.view = 1; break;
251  }
252  }
253 
254  if (args.help) {
255  fprintf(stderr,
256  "Usage: %s [options] [-d dir] <cabinet file(s)>\n\n"
257  "This will extract all files from a cabinet or executable cabinet.\n"
258  "For multi-part cabinets, only specify the first file in the set.\n\n",
259  argv[0]);
260  fprintf(stderr,
261  "Options:\n"
262  " -v --version print version / list cabinet\n"
263  " -h --help show this help page\n"
264  " -l --list list contents of cabinet\n"
265  " -t --test test cabinet integrity\n"
266  " -q --quiet only print errors and warnings\n"
267  " -L --lowercase make filenames lowercase\n"
268  " -f --fix salvage as much as possible from corrupted cabinets\n");
269  fprintf(stderr,
270  " -p --pipe pipe extracted files to stdout\n"
271  " -s --single restrict search to cabs on the command line\n"
272  " -F --filter extract only files that match the given pattern\n"
273 #if HAVE_ICONV
274  " -e --encoding assume non-UTF8 filenames have the given encoding\n"
275 #endif
276  " -d --directory extract all files to the given directory\n\n"
277  "cabextract %s (C) 2000-2019 Stuart Caie <kyzer@cabextract.org.uk>\n"
278  "This is free software with ABSOLUTELY NO WARRANTY.\n",
279  VERSION);
280  return EXIT_FAILURE;
281  }
282 
283  if (args.test && args.view) {
284  fprintf(stderr, "%s: You cannot use --test and --list at the same time.\n"
285  "Try '%s --help' for more information.\n", argv[0], argv[0]);
286  return EXIT_FAILURE;
287  }
288 
289  if (optind == argc) {
290  /* no arguments other than the options */
291  if (args.view) {
292  printf("cabextract version %s\n", VERSION);
293  return 0;
294  }
295  else {
296  fprintf(stderr, "%s: No cabinet files specified.\nTry '%s --help' "
297  "for more information.\n", argv[0], argv[0]);
298  return EXIT_FAILURE;
299  }
300  }
301 
302  /* memorise command-line cabs if necessary */
303  if (args.single) {
304  for (i = optind; i < argc; i++) memorise_file(&cab_args, argv[i], NULL);
305  }
306 
307  /* extracting to stdout implies shutting up on stdout */
308  if (args.pipe && !args.view) args.quiet = 1;
309 
310  /* open libmspack */
312  if (err) {
313  if (err == MSPACK_ERR_SEEK) {
314  fprintf(stderr,
315  "FATAL ERROR: libmspack is compiled for %d-bit file IO,\n"
316  " cabextract is compiled for %d-bit file IO.\n",
317  (sizeof(off_t) == 4) ? 64 : 32,
318  (sizeof(off_t) == 4) ? 32 : 64);
319  }
320  else {
321  fprintf(stderr, "FATAL ERROR: libmspack self-test returned %d\n", err);
322  }
323  return EXIT_FAILURE;
324  }
325 
327  fprintf(stderr, "can't create libmspack CAB decompressor\n");
328  return EXIT_FAILURE;
329  }
330 
331  /* obtain user's umask */
332 #if HAVE_UMASK
333  umask(user_umask = umask(0));
334 #endif
335 
336  /* turn on/off 'fix MSZIP' and 'salvage' mode */
339 
340 #if HAVE_ICONV
341  /* set up converter from given encoding to UTF-8 */
342  if (args.encoding) {
343  for (i = 0; i < (sizeof(utf8_names)/sizeof(*utf8_names)); i++) {
344  converter = iconv_open(utf8_names[i], args.encoding);
345  if (converter != (iconv_t) -1) break;
346  }
347  if (converter == (iconv_t) -1) {
348  fprintf(stderr, "FATAL ERROR: encoding '%s' is not recognised\n",
349  args.encoding);
350  return EXIT_FAILURE;
351  }
352  }
353 #endif
354 
355  /* process cabinets */
356  for (i = optind, err = 0; i < argc; i++) {
357  err += process_cabinet(argv[i]);
358  }
359 
360  /* error summary */
361  if (!args.quiet) {
362  if (err) printf("\nAll done, errors in processing %d file(s)\n", err);
363  else printf("\nAll done, no errors.\n");
364  }
365 
366 #if HAVE_ICONV
367  if (converter) {
368  iconv_close(converter);
369  }
370 #endif
371 
372  /* close libmspack */
374 
375  /* empty file-memory lists */
379 
380  return err ? EXIT_FAILURE : EXIT_SUCCESS;
381 }
382 
391 static int process_cabinet(char *basename) {
392  struct mscabd_cabinet *basecab, *cab, *cab2;
393  struct mscabd_file *file;
394  int isunix, fname_offset, viewhdr = 0;
395  char *from, *name;
396  int errors = 0;
397 
398  /* do not process repeat cabinets */
399  if (recall_file(cab_seen, basename, &from) ||
401  if (!args.quiet) {
402  if (!from) printf("%s: skipping known cabinet\n", basename);
403  else printf("%s: skipping known cabinet (from %s)\n", basename, from);
404  }
405  return 0; /* return success */
406  }
408 
409  /* search the file for cabinets */
410  if (!(basecab = cabd->search(cabd, basename))) {
411  if (cabd->last_error(cabd)) {
412  fprintf(stderr, "%s: %s\n", basename, cab_error(cabd));
413  }
414  else {
415  fprintf(stderr, "%s: no valid cabinets found\n", basename);
416  }
417  return 1;
418  }
419 
420  /* iterate over all cabinets found in that file */
421  for (cab = basecab; cab; cab = cab->next) {
422 
423  /* load all spanning cabinets */
425 
426 #if HAVE_ICONV
427  /* convert all non-UTF8 filenames to UTF8 using given encoding */
428  if (converter) convert_filenames(cab->files);
429 #endif
430 
431  /* determine whether UNIX or MS-DOS path seperators are used */
432  isunix = unix_path_seperators(cab->files);
433 
434  /* print headers */
435  if (!viewhdr) {
436  if (args.view) {
437  if (!args.quiet) printf("Viewing cabinet: %s\n", basename);
438  printf(" File size | Date Time | Name\n");
439  printf("-----------+---------------------+-------------\n");
440  }
441  else {
442  if (!args.quiet) {
443  printf("%s cabinet: %s\n", args.test ? "Testing" : "Extracting",
444  basename);
445  }
446  }
447  viewhdr = 1;
448  }
449 
450  /* the full UNIX output filename includes the output
451  * directory. However, for filtering purposes, we don't want to
452  * include that. So, we work out where the filename part of the
453  * output name begins. This is the same for every extracted file.
454  */
455  fname_offset = args.dir ? (strlen(args.dir) + 1) : 0;
456 
457  /* process all files */
458  for (file = cab->files; file; file = file->next) {
459  /* create the full UNIX output filename */
460  if (!(name = create_output_name(file->filename, args.dir,
461  args.lower, isunix, file->attribs & MSCAB_ATTRIB_UTF_NAME)))
462  {
463  errors++;
464  continue;
465  }
466 
467  /* if filtering, do so now. skip if file doesn't match any filter */
468  if (args.filters) {
469  int matched = 0;
470  struct filter *f;
471  for (f = args.filters; f; f = f->next) {
472  if (!fnmatch(f->filter, &name[fname_offset], FNM_CASEFOLD)) {
473  matched = 1;
474  break;
475  }
476  }
477  if (!matched) {
478  free(name);
479  continue;
480  }
481  }
482 
483  /* view, extract or test the file */
484  if (args.view) {
485  printf("%10u | %02d.%02d.%04d %02d:%02d:%02d | %s\n",
486  file->length, file->date_d, file->date_m, file->date_y,
487  file->time_h, file->time_m, file->time_s, name);
488  }
489  else if (args.test) {
490  if (cabd->extract(cabd, file, TEST_FNAME)) {
491  /* file failed to extract */
492  printf(" %s failed (%s)\n", name, cab_error(cabd));
493  errors++;
494  }
495  else {
496  /* file extracted OK, print the MD5 checksum in md5_result. Print
497  * the checksum right-aligned to 79 columns if that's possible,
498  * otherwise just print it 2 spaces after the filename and "OK" */
499 
500  /* " filename OK " is 8 chars + the length of filename,
501  * the MD5 checksum itself is 32 chars. */
502  int spaces = 79 - (strlen(name) + 8 + 32);
503  printf(" %s OK ", name);
504  while (spaces-- > 0) putchar(' ');
505  printf("%02x%02x%02x%02x%02x%02x%02x%02x"
506  "%02x%02x%02x%02x%02x%02x%02x%02x\n",
509  md5_result[8], md5_result[9], md5_result[10],md5_result[11],
510  md5_result[12],md5_result[13],md5_result[14],md5_result[15]);
511  }
512  }
513  else {
514  /* extract the file */
515  if (args.pipe) {
516  /* extracting to stdout */
517  if (cabd->extract(cabd, file, STDOUT_FNAME)) {
518  fprintf(stderr, "%s(%s): %s\n", STDOUT_FNAME, name,
519  cab_error(cabd));
520  errors++;
521  }
522  }
523  else {
524  /* extracting to a regular file */
525  if (!args.quiet) printf(" extracting %s\n", name);
526 
527  if (!ensure_filepath(name)) {
528  fprintf(stderr, "%s: can't create file path\n", name);
529  errors++;
530  }
531  else {
532  if (cabd->extract(cabd, file, name)) {
533  fprintf(stderr, "%s: %s\n", name, cab_error(cabd));
534  errors++;
535  }
536  else {
538  }
539  }
540  }
541  }
542  free(name);
543  } /* for (all files in cab) */
544 
545  /* free the spanning cabinet filenames [not freed by cabd->close()] */
546  for (cab2 = cab->prevcab; cab2; cab2 = cab2->prevcab) free((void*)cab2->filename);
547  for (cab2 = cab->nextcab; cab2; cab2 = cab2->nextcab) free((void*)cab2->filename);
548  } /* for (all cabs) */
549 
550  /* free all loaded cabinets */
551  cabd->close(cabd, basecab);
552  return errors;
553 }
554 
564 static void load_spanning_cabinets(struct mscabd_cabinet *basecab,
565  char *basename)
566 {
567  struct mscabd_cabinet *cab, *cab2;
568  char *name;
569 
570  /* load any spanning cabinets -- backwards */
571  for (cab = basecab; cab->flags & MSCAB_HDR_PREVCAB; cab = cab->prevcab) {
572  if (!(name = find_cabinet_file(basename, cab->prevname))) {
573  fprintf(stderr, "%s: can't find %s\n", basename, cab->prevname);
574  break;
575  }
576  if (args.single && !recall_file(cab_args, name, NULL)) break;
577  if (!args.quiet) {
578  printf("%s: extends backwards to %s (%s)\n", basename,
579  cab->prevname, cab->previnfo);
580  }
581  if (!(cab2 = cabd->open(cabd,name)) || cabd->prepend(cabd, cab, cab2)) {
582  fprintf(stderr, "%s: can't prepend %s: %s\n", basename,
583  cab->prevname, cab_error(cabd));
584  if (cab2) cabd->close(cabd, cab2);
585  break;
586  }
588  }
589 
590  /* load any spanning cabinets -- forwards */
591  for (cab = basecab; cab->flags & MSCAB_HDR_NEXTCAB; cab = cab->nextcab) {
592  if (!(name = find_cabinet_file(basename, cab->nextname))) {
593  fprintf(stderr, "%s: can't find %s\n", basename, cab->nextname);
594  break;
595  }
596  if (args.single && !recall_file(cab_args, name, NULL)) break;
597  if (!args.quiet) {
598  printf("%s: extends to %s (%s)\n", basename,
599  cab->nextname, cab->nextinfo);
600  }
601  if (!(cab2 = cabd->open(cabd,name)) || cabd->append(cabd, cab, cab2)) {
602  fprintf(stderr, "%s: can't append %s: %s\n", basename,
603  cab->nextname, cab_error(cabd));
604  if (cab2) cabd->close(cabd, cab2);
605  break;
606  }
608  }
609 }
610 
622 static char *find_cabinet_file(char *origcab, char *cabname) {
623  struct dirent *entry;
624  struct stat st_buf;
625  int found = 0, len;
626  char *tail, *cab;
627  DIR *dir;
628 
629  /* ensure we have a cabinet name at all */
630  if (!cabname || !cabname[0]) return NULL;
631 
632  /* find if there's a directory path in the origcab */
633  tail = origcab ? strrchr(origcab, '/') : NULL;
634  len = (tail - origcab) + 1;
635 
636  /* allocate memory for our copy */
637  if (!(cab = malloc((tail ? len : 2) + strlen(cabname) + 1))) return NULL;
638 
639  /* add the directory path from the original cabinet name, or "." */
640  if (tail) memcpy(cab, origcab, (size_t) len);
641  else cab[0]='.', cab[1]='/', len=2;
642  cab[len] = '\0';
643 
644  /* try accessing the cabinet with its current name (case-sensitive) */
645  strcpy(&cab[len], cabname);
646  if (stat(cab, &st_buf) == 0) {
647  found = 1;
648  }
649  else {
650  /* cabinet was not found, look for it in the current dir */
651  cab[len] = '\0';
652  if ((dir = opendir(cab))) {
653  while ((entry = readdir(dir))) {
654  if (strcasecmp(cabname, entry->d_name) == 0) {
655  strcat(cab, entry->d_name);
656  found = (stat(cab, &st_buf) == 0);
657  break;
658  }
659  }
660  closedir(dir);
661  }
662  }
663 
664  if (!found || !S_ISREG(st_buf.st_mode)) {
665  /* cabinet not found, or not a regular file */
666  free(cab);
667  cab = NULL;
668  }
669 
670  return cab;
671 }
672 
691  struct mscabd_file *fi;
692  char slash=0, backslash=0, *oldname;
693  int oldlen;
694 
695  for (fi = files; fi; fi = fi->next) {
696  char *p;
697  for (p = fi->filename; *p; p++) {
698  if (*p == '/') slash = 1;
699  if (*p == '\\') backslash = 1;
700  }
701  if (slash && backslash) break;
702  }
703 
704  if (slash) {
705  /* slashes, but no backslashes = UNIX */
706  if (!backslash) return 1;
707  }
708  else {
709  /* no slashes = MS-DOS */
710  return 0;
711  }
712 
713  /* special case if there's only one file - just take the first slash */
714  if (!files->next) {
715  char c, *p = fi->filename;
716  while ((c = *p++)) {
717  if (c == '\\') return 0; /* backslash = MS-DOS */
718  if (c == '/') return 1; /* slash = UNIX */
719  }
720  /* should not happen - at least one slash was found! */
721  return 0;
722  }
723 
724  oldname = NULL;
725  oldlen = 0;
726  for (fi = files; fi; fi = fi->next) {
727  char *name = fi->filename;
728  int len = 0;
729  while (name[len]) {
730  if ((name[len] == '\\') || (name[len] == '/')) break;
731  len++;
732  }
733  if (!name[len]) len = 0; else len++;
734 
735  if (len && (len == oldlen)) {
736  if (strncmp(name, oldname, (size_t) len) == 0)
737  return (name[len-1] == '\\') ? 0 : 1;
738  }
739  oldname = name;
740  oldlen = len;
741  }
742 
743  /* default */
744  return 0;
745 }
746 
761 static char *create_output_name(const char *fname, const char *dir,
762  int lower, int isunix, int utf8)
763 {
764  char sep = (isunix) ? '/' : '\\'; /* the path-seperator */
765  char slash = (isunix) ? '\\' : '/'; /* the other slash */
766 
767  size_t dirlen = dir ? strlen(dir) + 1 : 0; /* length of dir + '/' */
768  size_t filelen = strlen(fname);
769 
770  /* worst case, UTF-8 processing expands all chars to 4 bytes */
771  char *name = malloc(dirlen + (filelen * 4) + 2);
772 
773  unsigned char *i = (unsigned char *) &fname[0];
774  unsigned char *iend = (unsigned char *) &fname[filelen];
775  unsigned char *o = (unsigned char *) &name[dirlen], c;
776 
777  if (!name) {
778  fprintf(stderr, "Can't allocate output filename\n");
779  return NULL;
780  }
781 
782  /* copy directory prefix if needed */
783  if (dir) {
784  strcpy(name, dir);
785  name[dirlen - 1] = '/';
786  }
787 
788  /* copy cab filename to output name, converting MS-DOS slashes to UNIX
789  * slashes as we go. Also lowercases characters if needed. */
790  if (utf8) {
791  /* handle UTF-8 encoded filenames (see RFC 3629). This doesn't reject bad
792  * UTF-8 with overlong encodings, but does re-encode it as valid UTF-8. */
793  while (i < iend) {
794  /* get next UTF-8 character */
795  int x;
796  if ((c = *i++) < 0x80) {
797  x = c;
798  }
799  else if (c >= 0xC2 && c < 0xE0 && i <= iend && (i[0] & 0xC0) == 0x80) {
800  x = (c & 0x1F) << 6;
801  x |= *i++ & 0x3F;
802  }
803  else if (c >= 0xE0 && c < 0xF0 && i+1 <= iend && (i[0] & 0xC0) == 0x80 &&
804  (i[1] & 0xC0) == 0x80)
805  {
806  x = (c & 0x0F) << 12;
807  x |= (*i++ & 0x3F) << 6;
808  x |= *i++ & 0x3F;
809  }
810  else if (c >= 0xF0 && c < 0xF5 && i+2 <= iend && (i[0] & 0xC0) == 0x80 &&
811  (i[1] & 0xC0) == 0x80 && (i[2] & 0xC0) == 0x80)
812  {
813  x = (c & 0x07) << 18;
814  x |= (*i++ & 0x3F) << 12;
815  x |= (*i++ & 0x3F) << 6;
816  x |= *i++ & 0x3F;
817  }
818  else {
819  x = 0xFFFD; /* bad first byte */
820  }
821 
822  if (x <= 0 || x > 0x10FFFF || (x >= 0xD800 && x <= 0xDFFF) ||
823  x == 0xFFFE || x == 0xFFFF)
824  {
825  x = 0xFFFD; /* invalid code point or cheeky null byte */
826  }
827 
828 #if HAVE_TOWLOWER
829  if (lower) x = towlower(x);
830 #else
831  if (lower && x < 256) x = tolower(x);
832 #endif
833 
834  /* whatever is the path separator -> '/'
835  * whatever is the other slash -> '\' */
836  if (x == sep) x = '/'; else if (x == slash) x = '\\';
837 
838  /* convert unicode character back to UTF-8 */
839  if (x < 0x80) {
840  *o++ = (unsigned char) x;
841  }
842  else if (x < 0x800) {
843  *o++ = 0xC0 | (x >> 6);
844  *o++ = 0x80 | (x & 0x3F);
845  }
846  else if (x < 0x10000) {
847  *o++ = 0xE0 | (x >> 12);
848  *o++ = 0x80 | ((x >> 6) & 0x3F);
849  *o++ = 0x80 | (x & 0x3F);
850  }
851  else if (x <= 0x10FFFF) {
852  *o++ = 0xF0 | (x >> 18);
853  *o++ = 0x80 | ((x >> 12) & 0x3F);
854  *o++ = 0x80 | ((x >> 6) & 0x3F);
855  *o++ = 0x80 | (x & 0x3F);
856  }
857  else {
858  *o++ = 0xEF; /* unicode replacement character in UTF-8 */
859  *o++ = 0xBF;
860  *o++ = 0xBD;
861  }
862  }
863  *o++ = '\0';
864 #if LATIN1_FILENAMES
865  convert_utf8_to_latin1(&name[dirlen]);
866 #endif
867  }
868  else {
869  /* non UTF-8 version */
870  while (i < iend) {
871  c = *i++;
872  if (lower) c = (unsigned char) tolower((int) c);
873  if (c == sep) c = '/'; else if (c == slash) c = '\\';
874  *o++ = c;
875  }
876  *o++ = '\0';
877  }
878 
879  /* remove any leading slashes in the cab filename part.
880  * This prevents unintended absolute file path access. */
881  o = (unsigned char *) &name[dirlen];
882  for (i = o; *i == '/' || *i == '\\'; i++);
883  if (i != o) {
884  size_t len = strlen((char *) i);
885  if (len > 0) {
886  memmove(o, i, len + 1);
887  }
888  else {
889  /* change filename composed entirely of leading slashes to "x" */
890  strcpy((char *) o, "x");
891  }
892  }
893 
894  /* search for "../" or "..\" in cab filename part and change to "xx"
895  * This prevents unintended directory traversal. */
896  for (; *o; o++) {
897  if ((o[0] == '.') && (o[1] == '.') && (o[2] == '/' || o[2] == '\\')) {
898  o[0] = o[1] = 'x';
899  o += 2;
900  }
901  }
902 
903  return name;
904 }
905 
914 static void set_date_and_perm(struct mscabd_file *file, char *filename) {
915  mode_t mode;
916  struct tm tm;
917 #if HAVE_UTIME
918  struct utimbuf utb;
919 #elif HAVE_UTIMES
920  struct timeval tv[2];
921 #endif
922 
923  /* set last modified date */
924  tm.tm_sec = file->time_s;
925  tm.tm_min = file->time_m;
926  tm.tm_hour = file->time_h;
927  tm.tm_mday = file->date_d;
928  tm.tm_mon = file->date_m - 1;
929  tm.tm_year = file->date_y - 1900;
930  tm.tm_isdst = -1;
931 
932 #if HAVE_UTIME
933  utb.actime = utb.modtime = mktime(&tm);
934  utime(filename, &utb);
935 #elif HAVE_UTIMES
936  tv[0].tv_sec = tv[1].tv_sec = mktime(&tm);
937  tv[0].tv_usec = tv[1].tv_usec = 0;
938  utimes(filename, &tv[0]);
939 #endif
940 
941  /* set permissions */
942  mode = 0444;
943  if ( file->attribs & MSCAB_ATTRIB_EXEC) mode |= 0111;
944  if (!(file->attribs & MSCAB_ATTRIB_RDONLY)) mode |= 0222;
946 }
947 
948 #if HAVE_ICONV
949 static char *convert_filename(char *name) {
950  /* worst case: all characters expand from 1 to 4 bytes */
951  size_t ilen = strlen(name) + 1, olen = ilen * 4;
952  ICONV_CONST char *i = name;
953  char *newname = malloc(olen);
954  unsigned char *o = (unsigned char *) newname;
955 
956  if (!newname) {
957  fprintf(stderr, "WARNING: out of memory converting filename\n");
958  return NULL;
959  }
960 
961  /* convert filename to UTF8 */
962  iconv(converter, NULL, NULL, NULL, NULL);
963  while (iconv(converter, &i, &ilen, (char **) &o, &olen) == (size_t) -1) {
964  if (errno == EILSEQ || errno == EINVAL) {
965  /* invalid or incomplete multibyte sequence: skip it */
966  i++; ilen--;
967  *o++ = 0xEF; *o++ = 0xBF; *o++ = 0xBD; olen += 3;
968  }
969  else /* E2BIG: should be impossible to get here */ {
970  free(newname);
971  fprintf(stderr, "WARNING: error while converting filename: %s",
972  strerror(errno));
973  return NULL;
974  }
975  }
976  return newname;
977 }
978 
979 static void convert_filenames(struct mscabd_file *files) {
980  struct mscabd_file *fi;
981  for (fi = files; fi; fi = fi->next) {
982  if (!(fi->attribs & MSCAB_ATTRIB_UTF_NAME)) {
983  char *newname = convert_filename(fi->filename);
984  if (newname) {
985  /* replace filename with converted filename - this is a dirty
986  * hack to avoid having to convert filenames twice (first for
987  * unix_path_seperators(), then again for create_output_name())
988  * Instead of obeying the libmspack API and treating
989  * fi->filename as read only, we know libmspack allocated it
990  * using cabx_alloc() which uses malloc(), so we can free() it
991  * and replace it with other memory allocated with malloc()
992  */
993  free(fi->filename);
994  fi->filename = newname;
996  }
997  }
998  }
999 }
1000 #endif
1001 
1002 #if LATIN1_FILENAMES
1003 /* converts _valid_ UTF-8 to ISO-8859-1 in-place */
1004 static void convert_utf8_to_latin1(char *str) {
1005  unsigned char *i = (unsigned char *) str, *o = i, c;
1006  while ((c = *i++)) {
1007  if (c < 0x80) {
1008  *o++ = c;
1009  }
1010  else if (c == 0xC2 || c == 0xC3) {
1011  *o++ = ((c << 6) & 0x03) | (*i++ | 0x3F);
1012  }
1013  else {
1014  *o++ = '?';
1015  i += (c >= 0xF0) ? 3 : (c >= 0xE0) ? 2 : 1;
1016  }
1017  }
1018  *o = '\0';
1019 }
1020 #endif
1021 
1022 /* ------- support functions ------- */
1023 
1034 static void memorise_file(struct file_mem **fml, char *name, char *from) {
1035  struct file_mem *fm;
1036  struct stat st_buf;
1037  if (stat(name, &st_buf) != 0) return;
1038  if (!(fm = malloc(sizeof(struct file_mem)))) return;
1039  fm->st_dev = st_buf.st_dev;
1040  fm->st_ino = st_buf.st_ino;
1041  fm->from = (from) ? malloc(strlen(from)+1) : NULL;
1042  if (fm->from) strcpy(fm->from, from);
1043  fm->next = *fml;
1044  *fml = fm;
1045 }
1046 
1059 static int recall_file(struct file_mem *fml, char *name, char **from) {
1060  struct file_mem *fm;
1061  struct stat st_buf;
1062  if (stat(name, &st_buf) != 0) return 0;
1063  for (fm = fml; fm; fm = fm->next) {
1064  if ((st_buf.st_ino == fm->st_ino) && (st_buf.st_dev == fm->st_dev)) {
1065  if (from) *from = fm->from;
1066  return 1;
1067  }
1068  }
1069  return 0;
1070 }
1071 
1078 static void forget_files(struct file_mem **fml) {
1079  struct file_mem *fm, *next;
1080  for (fm = *fml; fm; fm = next) {
1081  next = fm->next;
1082  free(fm->from);
1083  free(fm);
1084  }
1085  *fml = NULL;
1086 }
1087 
1094 static void add_filter(char *arg) {
1095  struct filter *f = malloc(sizeof(struct filter));
1096  if (f) {
1097  if (!args.filters) {
1098  atexit(free_filters);
1099  }
1100  f->next = args.filters;
1101  f->filter = arg;
1102  args.filters = f;
1103  }
1104 }
1105 
1107 static void free_filters() {
1108  struct filter *f, *next;
1109  for (f = args.filters; f; f = next) {
1110  next = f->next;
1111  free(f);
1112  }
1113 }
1114 
1123 static int ensure_filepath(char *path) {
1124  struct stat st_buf;
1125  char *p;
1126  int ok;
1127 
1128  for (p = &path[1]; *p; p++) {
1129  if (*p != '/') continue;
1130  *p = '\0';
1131  ok = (stat(path, &st_buf) == 0) && S_ISDIR(st_buf.st_mode);
1132  if (!ok) ok = (mkdir(path, 0777 & ~user_umask) == 0);
1133  *p = '/';
1134  if (!ok) return 0;
1135  }
1136  return 1;
1137 }
1138 
1146 static char *cab_error(struct mscab_decompressor *cd) {
1147  switch (cd->last_error(cd)) {
1148  case MSPACK_ERR_OPEN:
1149  return errno ? strerror(errno) : "file open error";
1150  case MSPACK_ERR_READ:
1151  return errno ? strerror(errno) : "file read error";
1152  case MSPACK_ERR_WRITE:
1153  return errno ? strerror(errno) : "file write error";
1154  case MSPACK_ERR_SEEK:
1155  return errno ? strerror(errno) : "file seek error";
1156  case MSPACK_ERR_NOMEMORY:
1157  return "out of memory";
1158  case MSPACK_ERR_SIGNATURE:
1159  return "bad CAB signature";
1160  case MSPACK_ERR_DATAFORMAT:
1161  return "error in CAB data format";
1162  case MSPACK_ERR_CHECKSUM:
1163  return "checksum error";
1164  case MSPACK_ERR_DECRUNCH:
1165  return "decompression error";
1166  }
1167  return "unknown error";
1168 }
1169 
1170 struct mspack_file_p {
1171  FILE *fh;
1172  const char *name;
1174 };
1175 
1176 static struct mspack_file *cabx_open(struct mspack_system *this,
1177  const char *filename, int mode)
1178 {
1179  struct mspack_file_p *fh;
1180  const char *fmode;
1181 
1182  /* Use of the STDOUT_FNAME pointer for a filename means the file should
1183  * actually be extracted to stdout. Use of the TEST_FNAME pointer for a
1184  * filename means the file should only be MD5-summed.
1185  */
1186  if (filename == STDOUT_FNAME || filename == TEST_FNAME) {
1187  /* only WRITE mode is valid for these special files */
1188  if (mode != MSPACK_SYS_OPEN_WRITE) {
1189  return NULL;
1190  }
1191  }
1192 
1193  /* ensure that mode is one of READ, WRITE, UPDATE or APPEND */
1194  switch (mode) {
1195  case MSPACK_SYS_OPEN_READ: fmode = "rb"; break;
1196  case MSPACK_SYS_OPEN_WRITE: fmode = "wb"; break;
1197  case MSPACK_SYS_OPEN_UPDATE: fmode = "r+b"; break;
1198  case MSPACK_SYS_OPEN_APPEND: fmode = "ab"; break;
1199  default: return NULL;
1200  }
1201 
1202  if ((fh = malloc(sizeof(struct mspack_file_p)))) {
1203  fh->name = filename;
1204 
1205  if (filename == STDOUT_FNAME) {
1206  fh->regular_file = 0;
1207  fh->fh = stdout;
1208  return (struct mspack_file *) fh;
1209  }
1210  else if (filename == TEST_FNAME) {
1211  fh->regular_file = 0;
1212  fh->fh = NULL;
1214  return (struct mspack_file *) fh;
1215  }
1216  else {
1217  /* regular file - simply attempt to open it */
1218  fh->regular_file = 1;
1219  if ((fh->fh = fopen(filename, fmode))) {
1220  return (struct mspack_file *) fh;
1221  }
1222  }
1223  /* error - free file handle and return NULL */
1224  free(fh);
1225  }
1226  return NULL;
1227 }
1228 
1229 static void cabx_close(struct mspack_file *file) {
1230  struct mspack_file_p *this = (struct mspack_file_p *) file;
1231  if (this) {
1232  if (this->name == TEST_FNAME) {
1233  md5_finish_ctx(&md5_context, (void *) &md5_result);
1234  }
1235  else if (this->regular_file) {
1236  fclose(this->fh);
1237  }
1238  free(this);
1239  }
1240 }
1241 
1242 static int cabx_read(struct mspack_file *file, void *buffer, int bytes) {
1243  struct mspack_file_p *this = (struct mspack_file_p *) file;
1244  if (this && this->regular_file && buffer && bytes >= 0) {
1245  size_t count = fread(buffer, 1, (size_t) bytes, this->fh);
1246  if (!ferror(this->fh)) return (int) count;
1247  }
1248  return -1;
1249 }
1250 
1251 static int cabx_write(struct mspack_file *file, void *buffer, int bytes) {
1252  struct mspack_file_p *this = (struct mspack_file_p *) file;
1253  if (this && buffer && bytes >= 0) {
1254  if (this->name == TEST_FNAME) {
1256  return bytes;
1257  }
1258  else {
1259  /* regular files and the stdout writer */
1260  size_t count = fwrite(buffer, 1, (size_t) bytes, this->fh);
1261  if (!ferror(this->fh)) return (int) count;
1262  }
1263  }
1264  return -1;
1265 }
1266 
1267 static int cabx_seek(struct mspack_file *file, off_t offset, int mode) {
1268  struct mspack_file_p *this = (struct mspack_file_p *) file;
1269  if (this && this->regular_file) {
1270  switch (mode) {
1271  case MSPACK_SYS_SEEK_START: mode = SEEK_SET; break;
1272  case MSPACK_SYS_SEEK_CUR: mode = SEEK_CUR; break;
1273  case MSPACK_SYS_SEEK_END: mode = SEEK_END; break;
1274  default: return -1;
1275  }
1276 #if HAVE_FSEEKO
1277  return fseeko(this->fh, offset, mode);
1278 #else
1279  return fseek(this->fh, offset, mode);
1280 #endif
1281  }
1282  return -1;
1283 }
1284 
1285 static off_t cabx_tell(struct mspack_file *file) {
1286  struct mspack_file_p *this = (struct mspack_file_p *) file;
1287 #if HAVE_FSEEKO
1288  return (this && this->regular_file) ? (off_t) ftello(this->fh) : 0;
1289 #else
1290  return (this && this->regular_file) ? (off_t) ftell(this->fh) : 0;
1291 #endif
1292 }
1293 
1294 static void cabx_msg(struct mspack_file *file, const char *format, ...) {
1295  va_list ap;
1296  if (file) {
1297  fprintf(stderr, "%s: ", ((struct mspack_file_p *) file)->name);
1298  }
1299  va_start(ap, format);
1300  vfprintf(stderr, format, ap);
1301  va_end(ap);
1302  fputc((int) '\n', stderr);
1303  fflush(stderr);
1304 }
1305 static void *cabx_alloc(struct mspack_system *this, size_t bytes) {
1306  return malloc(bytes);
1307 }
1308 static void cabx_free(void *buffer) {
1309  free(buffer);
1310 }
1311 static void cabx_copy(void *src, void *dest, size_t bytes) {
1312  memcpy(dest, src, bytes);
1313 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
static csh cd
Definition: asm_mips_cs.c:10
#define VERSION
Definition: config.h:54
#define MSPACK_SYS_OPEN_APPEND
Definition: mspack.h:464
#define MSPACK_ERR_SEEK
Definition: mspack.h:495
#define MSCAB_ATTRIB_EXEC
Definition: mspack.h:927
#define MSCAB_HDR_NEXTCAB
Definition: mspack.h:793
#define MSPACK_SYS_SEEK_END
Definition: mspack.h:471
#define MSCAB_ATTRIB_UTF_NAME
Definition: mspack.h:929
#define MSPACK_SYS_SELFTEST(result)
Definition: mspack.h:191
#define MSPACK_ERR_OPEN
Definition: mspack.h:489
#define MSPACK_ERR_WRITE
Definition: mspack.h:493
#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 MSCAB_HDR_PREVCAB
Definition: mspack.h:791
#define MSCABD_PARAM_FIXMSZIP
Definition: mspack.h:934
#define MSPACK_ERR_CHECKSUM
Definition: mspack.h:503
#define MSPACK_ERR_SIGNATURE
Definition: mspack.h:499
#define MSPACK_SYS_SEEK_CUR
Definition: mspack.h:469
#define MSCABD_PARAM_SALVAGE
Definition: mspack.h:943
#define MSCAB_ATTRIB_RDONLY
Definition: mspack.h:919
#define MSPACK_ERR_DATAFORMAT
Definition: mspack.h:501
#define MSPACK_ERR_DECRUNCH
Definition: mspack.h:507
#define MSPACK_ERR_READ
Definition: mspack.h:491
#define MSPACK_SYS_OPEN_UPDATE
Definition: mspack.h:462
#define MSPACK_ERR_NOMEMORY
Definition: mspack.h:497
struct cabextract_args args
Definition: cabextract.c:134
static char * create_output_name(const char *fname, const char *dir, int lower, int isunix, int unicode)
Definition: cabextract.c:761
static void set_date_and_perm(struct mscabd_file *file, char *filename)
Definition: cabextract.c:914
int main(int argc, char *argv[])
Definition: cabextract.c:211
struct mscab_decompressor * cabd
Definition: cabextract.c:126
static int unix_path_seperators(struct mscabd_file *files)
Definition: cabextract.c:690
static off_t cabx_tell(struct mspack_file *file)
Definition: cabextract.c:1285
unsigned char md5_result[16]
Definition: cabextract.c:161
static void cabx_free(void *buffer)
Definition: cabextract.c:1308
static int cabx_write(struct mspack_file *file, void *buffer, int bytes)
Definition: cabextract.c:1251
const char * OPTSTRING
Definition: cabextract.c:104
struct option optlist[]
Definition: cabextract.c:83
const char * STDOUT_FNAME
Definition: cabextract.c:148
mode_t user_umask
Definition: cabextract.c:132
struct file_mem * cab_seen
Definition: cabextract.c:130
static int ensure_filepath(char *path)
Definition: cabextract.c:1123
static void load_spanning_cabinets(struct mscabd_cabinet *basecab, char *basename)
Definition: cabextract.c:564
static void forget_files(struct file_mem **fml)
Definition: cabextract.c:1078
static void cabx_close(struct mspack_file *file)
Definition: cabextract.c:1229
static void memorise_file(struct file_mem **fml, char *name, char *from)
Definition: cabextract.c:1034
static void add_filter(char *arg)
Definition: cabextract.c:1094
static int cabx_read(struct mspack_file *file, void *buffer, int bytes)
Definition: cabextract.c:1242
struct file_mem * cab_exts
Definition: cabextract.c:129
struct md5_ctx md5_context
Definition: cabextract.c:158
static int recall_file(struct file_mem *fml, char *name, char **from)
Definition: cabextract.c:1059
static void * cabx_alloc(struct mspack_system *this, size_t bytes)
Definition: cabextract.c:1305
const char * TEST_FNAME
Definition: cabextract.c:155
static struct mspack_system cabextract_system
Definition: cabextract.c:206
struct file_mem * cab_args
Definition: cabextract.c:128
static void cabx_copy(void *src, void *dest, size_t bytes)
Definition: cabextract.c:1311
static char * cab_error(struct mscab_decompressor *cd)
Definition: cabextract.c:1146
static char * find_cabinet_file(char *origcab, char *cabname)
Definition: cabextract.c:622
static void free_filters()
Definition: cabextract.c:1107
static struct mspack_file * cabx_open(struct mspack_system *this, const char *filename, int mode)
Definition: cabextract.c:1176
static void cabx_msg(struct mspack_file *file, const char *format,...)
Definition: cabextract.c:1294
static int cabx_seek(struct mspack_file *file, off_t offset, int mode)
Definition: cabextract.c:1267
#define FNM_CASEFOLD
Definition: cabextract.c:74
static int process_cabinet(char *cabname)
Definition: cabextract.c:391
FILE * fh
Definition: cabinfo.c:52
FILELEN filelen
Definition: cabinfo.c:54
const char * optarg
Definition: getopt.h:9
int optind
Definition: getopt.h:6
#define S_ISDIR(mode)
Definition: compat.h:187
#define fseeko(s, o, w)
Definition: compat.h:121
#define ftello(s)
Definition: compat.h:125
#define S_ISREG(mode)
Definition: compat.h:191
#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 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 tv
Definition: sflib.h:79
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 umask
Definition: sflib.h:65
static static fork const void static count static fd const char const char static newpath const char static path chmod
Definition: sflib.h:35
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n output MIME type special files
Definition: file_opts.h:46
int fnmatch(char *pattern, const char *string, int flags) const
Definition: fnmatch.c:60
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
int getopt_long()
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
#define basename
Definition: libiberty.h:109
const char * spaces(int count)
void * malloc(size_t size)
Definition: malloc.c:123
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 char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds utime
Definition: sflib.h:57
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list const char const char static newpath const char static library readdir
Definition: sflib.h:120
@ ok
Definition: lz4.c:1706
char * dest
Definition: lz4.h:697
int x
Definition: mipsasm.c:20
string FILE
Definition: benchmark.py:21
const char * name
Definition: op.c:541
#define tolower(c)
Definition: safe-ctype.h:149
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
int dev_t
Definition: sftypes.h:61
int mode_t
Definition: sftypes.h:42
#define EINVAL
Definition: sftypes.h:132
int off_t
Definition: sftypes.h:41
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
Definition: buffer.h:15
struct filter * filters
Definition: cabextract.c:122
Definition: sftypes.h:48
Definition: zipcmp.c:77
char * from
Definition: cabextract.c:111
ino_t st_ino
Definition: cabextract.c:110
struct file_mem * next
Definition: cabextract.c:108
dev_t st_dev
Definition: cabextract.c:109
Definition: gzappend.c:170
z_const unsigned char * next
Definition: gzappend.c:175
char * filter
Definition: cabextract.c:116
struct filter * next
Definition: cabextract.c:115
Definition: md5.h:87
int(* append)(struct mscab_decompressor *self, struct mscabd_cabinet *cab, struct mscabd_cabinet *nextcab)
Definition: mspack.h:1090
struct mscabd_cabinet *(* search)(struct mscab_decompressor *self, const char *filename)
Definition: mspack.h:1047
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
int(* prepend)(struct mscab_decompressor *self, struct mscabd_cabinet *cab, struct mscabd_cabinet *prevcab)
Definition: mspack.h:1112
void(* close)(struct mscab_decompressor *self, struct mscabd_cabinet *cab)
Definition: mspack.h:1010
int(* set_param)(struct mscab_decompressor *self, int param, int value)
Definition: mspack.h:1164
const char * filename
Definition: mspack.h:712
char * prevname
Definition: mspack.h:727
struct mscabd_cabinet * next
Definition: mspack.h:705
struct mscabd_cabinet * prevcab
Definition: mspack.h:721
char * previnfo
Definition: mspack.h:735
char * nextinfo
Definition: mspack.h:740
char * nextname
Definition: mspack.h:730
struct mscabd_file * files
Definition: mspack.h:743
struct mscabd_cabinet * nextcab
Definition: mspack.h:724
int attribs
Definition: mspack.h:895
struct mscabd_file * next
Definition: mspack.h:868
char * filename
Definition: mspack.h:878
FILE * fh
Definition: system.c:112
const char * name
Definition: system.c:113
Definition: z80asm.h:102
Definition: getopt.h:84
Definition: sftypes.h:80
void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
Definition: md5.c:216
void md5_init_ctx(struct md5_ctx *ctx)
Definition: md5.c:71
void * md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
Definition: md5.c:104
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