29 #include <sys/types.h>
57 # include <sys/time.h>
62 # if MKDIR_TAKES_ONE_ARG
63 # define mkdir(a, b) mkdir(a)
67 # define mkdir(a, b) _mkdir(a)
69 # error "Don't know how to create a directory on this system."
74 # define FNM_CASEFOLD (0)
84 {
"directory", 1,
NULL,
'd' },
86 {
"encoding", 1,
NULL,
'e' },
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' },
102 const char *
OPTSTRING =
"d:e:fF:hlLpqstv";
135 0, 0, 0, 0, 0, 0, 0, 0,
140 iconv_t converter =
NULL;
171 int lower,
int isunix,
int unicode);
178 static void convert_utf8_to_latin1(
char *
str);
215 char *utf8_names[] = {
230 "en_US.UTF-8",
"en_GB.UTF8",
"de_DE.UTF-8",
"UTF-8",
"UTF8"
232 for (
i = 0;
i < (
sizeof(locales)/
sizeof(*locales));
i++) {
233 if (setlocale(LC_CTYPE, locales[
i]))
break;
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",
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");
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"
274 " -e --encoding assume non-UTF8 filenames have the given encoding\n"
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",
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]);
296 fprintf(stderr,
"%s: No cabinet files specified.\nTry '%s --help' "
297 "for more information.\n",
argv[0],
argv[0]);
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);
321 fprintf(stderr,
"FATAL ERROR: libmspack self-test returned %d\n",
err);
327 fprintf(stderr,
"can't create libmspack CAB decompressor\n");
343 for (
i = 0;
i < (
sizeof(utf8_names)/
sizeof(*utf8_names));
i++) {
345 if (converter != (iconv_t) -1)
break;
347 if (converter == (iconv_t) -1) {
348 fprintf(stderr,
"FATAL ERROR: encoding '%s' is not recognised\n",
362 if (
err)
printf(
"\nAll done, errors in processing %d file(s)\n",
err);
363 else printf(
"\nAll done, no errors.\n");
368 iconv_close(converter);
380 return err ? EXIT_FAILURE : EXIT_SUCCESS;
394 int isunix, fname_offset, viewhdr = 0;
415 fprintf(stderr,
"%s: no valid cabinets found\n",
basename);
421 for (cab = basecab; cab; cab = cab->
next) {
428 if (converter) convert_filenames(cab->
files);
438 printf(
" File size | Date Time | Name\n");
439 printf(
"-----------+---------------------+-------------\n");
485 printf(
"%10u | %02d.%02d.%04d %02d:%02d:%02d | %s\n",
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",
528 fprintf(stderr,
"%s: can't create file path\n",
name);
582 fprintf(stderr,
"%s: can't prepend %s: %s\n",
basename,
602 fprintf(stderr,
"%s: can't append %s: %s\n",
basename,
630 if (!cabname || !cabname[0])
return NULL;
633 tail = origcab ? strrchr(origcab,
'/') :
NULL;
634 len = (tail - origcab) + 1;
637 if (!(cab =
malloc((tail ?
len : 2) + strlen(cabname) + 1)))
return NULL;
640 if (tail)
memcpy(cab, origcab, (
size_t)
len);
641 else cab[0]=
'.', cab[1]=
'/',
len=2;
645 strcpy(&cab[
len], cabname);
646 if (
stat(cab, &st_buf) == 0) {
652 if ((dir = opendir(cab))) {
654 if (strcasecmp(cabname,
entry->d_name) == 0) {
655 strcat(cab,
entry->d_name);
692 char slash=0, backslash=0, *oldname;
698 if (*
p ==
'/') slash = 1;
699 if (*
p ==
'\\') backslash = 1;
701 if (slash && backslash)
break;
706 if (!backslash)
return 1;
717 if (
c ==
'\\')
return 0;
718 if (
c ==
'/')
return 1;
735 if (
len && (
len == oldlen)) {
736 if (strncmp(
name, oldname, (
size_t)
len) == 0)
737 return (
name[
len-1] ==
'\\') ? 0 : 1;
762 int lower,
int isunix,
int utf8)
764 char sep = (isunix) ?
'/' :
'\\';
765 char slash = (isunix) ?
'\\' :
'/';
767 size_t dirlen = dir ? strlen(dir) + 1 : 0;
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;
778 fprintf(stderr,
"Can't allocate output filename\n");
785 name[dirlen - 1] =
'/';
796 if ((
c = *
i++) < 0x80) {
799 else if (
c >= 0xC2 &&
c < 0xE0 &&
i <= iend && (
i[0] & 0xC0) == 0x80) {
803 else if (
c >= 0xE0 &&
c < 0xF0 &&
i+1 <= iend && (
i[0] & 0xC0) == 0x80 &&
804 (
i[1] & 0xC0) == 0x80)
806 x = (
c & 0x0F) << 12;
807 x |= (*
i++ & 0x3F) << 6;
810 else if (
c >= 0xF0 &&
c < 0xF5 &&
i+2 <= iend && (
i[0] & 0xC0) == 0x80 &&
811 (
i[1] & 0xC0) == 0x80 && (
i[2] & 0xC0) == 0x80)
813 x = (
c & 0x07) << 18;
814 x |= (*
i++ & 0x3F) << 12;
815 x |= (*
i++ & 0x3F) << 6;
822 if (x <= 0 || x > 0x10FFFF || (
x >= 0xD800 &&
x <= 0xDFFF) ||
823 x == 0xFFFE ||
x == 0xFFFF)
829 if (lower)
x = towlower(
x);
836 if (
x == sep)
x =
'/';
else if (
x == slash)
x =
'\\';
840 *o++ = (
unsigned char)
x;
842 else if (
x < 0x800) {
843 *o++ = 0xC0 | (
x >> 6);
844 *o++ = 0x80 | (
x & 0x3F);
846 else if (
x < 0x10000) {
847 *o++ = 0xE0 | (
x >> 12);
848 *o++ = 0x80 | ((
x >> 6) & 0x3F);
849 *o++ = 0x80 | (
x & 0x3F);
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);
865 convert_utf8_to_latin1(&
name[dirlen]);
872 if (lower)
c = (
unsigned char)
tolower((
int)
c);
873 if (
c == sep)
c =
'/';
else if (
c == slash)
c =
'\\';
881 o = (
unsigned char *) &
name[dirlen];
882 for (
i = o; *
i ==
'/' || *
i ==
'\\';
i++);
884 size_t len = strlen((
char *)
i);
886 memmove(o,
i,
len + 1);
890 strcpy((
char *) o,
"x");
897 if ((o[0] ==
'.') && (o[1] ==
'.') && (o[2] ==
'/' || o[2] ==
'\\')) {
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;
933 utb.actime = utb.modtime = mktime(&tm);
936 tv[0].tv_sec =
tv[1].tv_sec = mktime(&tm);
937 tv[0].tv_usec =
tv[1].tv_usec = 0;
949 static char *convert_filename(
char *
name) {
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;
957 fprintf(stderr,
"WARNING: out of memory converting filename\n");
963 while (iconv(converter, &
i, &ilen, (
char **) &o, &olen) == (
size_t) -1) {
964 if (errno == EILSEQ || errno ==
EINVAL) {
967 *o++ = 0xEF; *o++ = 0xBF; *o++ = 0xBD; olen += 3;
971 fprintf(stderr,
"WARNING: error while converting filename: %s",
983 char *newname = convert_filename(fi->
filename);
1002 #if LATIN1_FILENAMES
1004 static void convert_utf8_to_latin1(
char *
str) {
1005 unsigned char *
i = (
unsigned char *)
str, *o =
i,
c;
1006 while ((
c = *
i++)) {
1010 else if (
c == 0xC2 ||
c == 0xC3) {
1011 *o++ = ((
c << 6) & 0x03) | (*
i++ | 0x3F);
1015 i += (
c >= 0xF0) ? 3 : (
c >= 0xE0) ? 2 : 1;
1037 if (
stat(
name, &st_buf) != 0)
return;
1039 fm->
st_dev = st_buf.st_dev;
1040 fm->
st_ino = st_buf.st_ino;
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)) {
1080 for (fm = *fml; fm; fm =
next) {
1129 if (*
p !=
'/')
continue;
1147 switch (
cd->last_error(
cd)) {
1149 return errno ? strerror(errno) :
"file open error";
1151 return errno ? strerror(errno) :
"file read error";
1153 return errno ? strerror(errno) :
"file write error";
1155 return errno ? strerror(errno) :
"file seek error";
1157 return "out of memory";
1159 return "bad CAB signature";
1161 return "error in CAB data format";
1163 return "checksum error";
1165 return "decompression error";
1167 return "unknown error";
1199 default:
return NULL;
1206 fh->regular_file = 0;
1211 fh->regular_file = 0;
1218 fh->regular_file = 1;
1246 if (!ferror(this->
fh))
return (
int)
count;
1261 if (!ferror(this->
fh))
return (
int)
count;
1279 return fseek(this->
fh, offset,
mode);
1299 va_start(ap, format);
1300 vfprintf(stderr, format, ap);
1302 fputc((
int)
'\n', stderr);
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
static static fork const void static count static fd const char const char static newpath const char static path const char path
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
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
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz umask
static static fork const void static count static fd const char const char static newpath const char static path chmod
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
int fnmatch(char *pattern, const char *string, int flags) const
RZ_API void Ht_() free(HtName_(Ht) *ht)
RZ_API const KEY_TYPE bool * found
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
const char * spaces(int count)
void * malloc(size_t size)
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
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
static static fork const void static count static fd const char const char static newpath char char argv
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
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
z_const unsigned char * next
int(* append)(struct mscab_decompressor *self, struct mscabd_cabinet *cab, struct mscabd_cabinet *nextcab)
struct mscabd_cabinet *(* search)(struct mscab_decompressor *self, const char *filename)
int(* last_error)(struct mscab_decompressor *self)
struct mscabd_cabinet *(* open)(struct mscab_decompressor *self, const char *filename)
int(* extract)(struct mscab_decompressor *self, struct mscabd_file *file, const char *filename)
int(* prepend)(struct mscab_decompressor *self, struct mscabd_cabinet *cab, struct mscabd_cabinet *prevcab)
void(* close)(struct mscab_decompressor *self, struct mscabd_cabinet *cab)
int(* set_param)(struct mscab_decompressor *self, int param, int value)
struct mscabd_cabinet * next
struct mscabd_cabinet * prevcab
struct mscabd_file * files
struct mscabd_cabinet * nextcab
struct mscabd_file * next