version 2.3, 2005/02/15 08:21:13
|
version 2.4, 2005/02/15 09:34:28
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ | */ |
| |
//#include <windows.h> |
|
#include <stdlib.h> | #include <stdlib.h> |
#include <string.h> | #include <string.h> |
//#include <io.h> |
|
//#include <fcntl.h> |
|
//#include <dos.h> |
|
#include <sys/stat.h> | #include <sys/stat.h> |
| |
#ifndef STANDALONE | #ifndef STANDALONE |
|
|
#include <winerror.h> | #include <winerror.h> |
#include <fdi.h> | #include <fdi.h> |
#include <fcntl.h> | #include <fcntl.h> |
|
#include "cabinet_files.h" |
| |
/* Do malloc and free output debug messages? | /* Do malloc and free output debug messages? |
#define DEBUG_ALLOC | #define DEBUG_ALLOC |
*/ | */ |
| |
/* What is our "Fake" Filedescriptor? */ |
/* What is our "Fake" Filedescriptors? */ |
static int fakeFD = 22881; |
static int fakeFD_simple = 22881; |
|
static int fakeFD_complexzip2 = 22882; |
|
static int fakeFD_complexlzw2 = 22883; |
|
static int fakeFD_broken = 22884; |
| |
/* | /* |
This hex data is the output of makecab.exe (Windows Cabinet SDK/bin) | This hex data is the output of makecab.exe (Windows Cabinet SDK/bin) |
|
|
The cab file is mirrored in the file system as simple.cab | The cab file is mirrored in the file system as simple.cab |
| |
The 'test.txt' in the cab file contains the string 'So long, and thanks for all the fish.' | The 'test.txt' in the cab file contains the string 'So long, and thanks for all the fish.' |
*/ |
|
static unsigned char compressed_file[] = |
|
{0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x75,0x00, |
|
0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,0x00, |
|
0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x01,0x00, |
|
0x00,0x00,0x39,0x30,0x00,0x00,0x45,0x00,0x00,0x00, |
|
0x01,0x00,0x01,0x00,0x26,0x00,0x00,0x00,0x00,0x00, |
|
0x00,0x00,0x00,0x00,0x4A,0x32,0xB2,0xBE,0x20,0x00, |
|
0x74,0x65,0x73,0x74,0x2E,0x74,0x78,0x74,0x00,0x9C, |
|
0x74,0xD0,0x75,0x28,0x00,0x26,0x00,0x43,0x4B,0x0B, |
|
0xCE,0x57,0xC8,0xC9,0xCF,0x4B,0xD7,0x51,0x48,0xCC, |
|
0x4B,0x51,0x28,0xC9,0x48,0xCC,0xCB,0x2E,0x56,0x48, |
|
0xCB,0x2F,0x52,0x48,0xCC,0xC9,0x01,0x72,0x53,0x15, |
|
0xD2,0x32,0x8B,0x33,0xF4,0xB8,0x00}; |
|
static int szcompressed_file = sizeof(compressed_file); |
|
| |
|
The files in the "cabinet_files.h" were created with hexify.sh |
|
*/ |
/* | /* |
Multiple File Cabs are included, as cabinet.dll supports multiple file archive types. | Multiple File Cabs are included, as cabinet.dll supports multiple file archive types. |
The compressed file size had to be greater than 50k, cabarc restricts 'diskette spanning' to | The compressed file size had to be greater than 50k, cabarc restricts 'diskette spanning' to |
|
|
} | } |
| |
FNOPEN(fake_open) { | FNOPEN(fake_open) { |
printf(" FNOPEN (fake) just called with %d, %d, %d\n",pszFile, oflag, pmode); |
printf(" FNOPEN (virtual) just called with %d, %d, %d\n",pszFile, oflag, pmode); |
printf(" Returning %d as file descriptor\n",fakeFD); |
printf(" Returning %d as file descriptor\n",12); |
return 12; | return 12; |
} | } |
| |
|
|
| |
/* Doesn't keep virtual file location pointer */ | /* Doesn't keep virtual file location pointer */ |
FNREAD(fake_read) { | FNREAD(fake_read) { |
printf(" FNREAD (fake) just called with %d, %d, %d\n",hf, pv, cb); |
printf(" FNREAD (virtual) just called with %d, %d, %d\n",hf, pv, cb); |
if (hf == fakeFD) { |
switch (hf) |
printf (" Called with fake file descriptor, populating buffer and size (%d)\n",cb); |
{ |
memcpy (pv, compressed_file ,cb); |
/* Const int doesnt count as constant for cases --- why? */ |
|
case 22881: |
|
{ |
|
printf (" Called fake file descriptor %d (file_simple_cab),\n\tpopulating buffer and size (%d)\n",hf,cb); |
|
memcpy (pv, file_simple_cab ,cb); |
|
break; |
|
} |
|
case 22882: |
|
{ |
|
printf (" Called fake file descriptor %d (file_complex_zip2_cab),\n\tpopulating buffer and size (%d)\n",hf,cb); |
|
memcpy (pv, file_complex_zip2_cab ,cb); |
|
break; |
|
} |
|
case 22883: |
|
{ |
|
printf (" Called fake file descriptor %d (file_complex_lzw2_cab),\n\tpopulating buffer and size (%d)\n",hf,cb); |
|
memcpy (pv, file_complex_lzw2_cab ,cb); |
|
break; |
|
} |
|
case 22884: |
|
{ |
|
printf (" Called fake file descriptor %d (file_broken_cab),\n\tpopulating buffer and size (%d)\n",hf,cb); |
|
memcpy (pv, file_broken_cab ,cb); |
|
break; |
|
} |
|
default: |
|
{ |
|
printf (" FNREAD (virtual) was called with the unknown file handler. Failed!\n",hf); |
|
return -1; |
} | } |
else { |
|
printf (" FNREAD (fake) was called with the unknown file handler. Failed!\n",hf); |
|
} | } |
|
printf(" Returning %d\n",cb); |
return cb; | return cb; |
} | } |
| |
|
|
FNREAD(real_read) { | FNREAD(real_read) { |
int szBuffer = _read(hf,pv,cb); | int szBuffer = _read(hf,pv,cb); |
printf(" FNREAD (read) just called with %d, %d, %d\n",hf, pv, cb); | printf(" FNREAD (read) just called with %d, %d, %d\n",hf, pv, cb); |
|
|
} | } |
| |
FNCLOSE(fake_close) { | FNCLOSE(fake_close) { |
printf(" FNCLOSE (fake) just called with %d - returning %d\n",hf,0); |
printf(" FNCLOSE (virtual) just called with %d - returning %d\n",hf,0); |
return 0; | return 0; |
} | } |
| |
|
|
| |
static void printCabInfo(FDICABINETINFO cabinfo){ | static void printCabInfo(FDICABINETINFO cabinfo){ |
//printf("INSIDE PRINT CABINFO\n"); | //printf("INSIDE PRINT CABINFO\n"); |
printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n", |
printf(" Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %d hp %d hn %d\n", |
cabinfo.cbCabinet, | cabinfo.cbCabinet, |
cabinfo.cFolders , | cabinfo.cFolders , |
cabinfo.cFiles , | cabinfo.cFiles , |
|
|
cabinfo.hasnext ); | cabinfo.hasnext ); |
} | } |
| |
|
|
static void CheckCabInfo(char * cabname, | static void CheckCabInfo(char * cabname, |
FDICABINETINFO cabinfo, | FDICABINETINFO cabinfo, |
long TcbCabinet, | long TcbCabinet, |
|
|
BOOL TfReserve, | BOOL TfReserve, |
BOOL Thasprev, | BOOL Thasprev, |
BOOL Thasnext){ | BOOL Thasnext){ |
|
|
ok2 ( cabinfo.cbCabinet == TcbCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); | ok2 ( cabinfo.cbCabinet == TcbCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
ok2 ( cabinfo.cFolders == TcFolders, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); | ok2 ( cabinfo.cFolders == TcFolders, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
ok2 ( cabinfo.cFiles == TcFiles, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); | ok2 ( cabinfo.cFiles == TcFiles, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n", cabname); |
|
|
} | } |
| |
| |
|
/* Tried to enhance functionality with : |
|
|
|
|
|
ok4 ( cabinfo.cbCabinet == TcbCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for cbCabinet\n", cabname, TcbCabinet, cabinfo.cbCabinet ); |
|
ok4 ( cabinfo.cFolders == TcFolders, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for cFolders\n", cabname,TcFolders,cabinfo.cFolders); |
|
ok4 ( cabinfo.cFiles == TcFiles, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for cFiles\n", cabname,TcFiles,cabinfo.cFiles); |
|
ok4 ( cabinfo.setID == TsetID, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for setID\n", cabname,TsetID.cabinfo.setID); |
|
ok4 ( cabinfo.iCabinet == TiCabinet, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for iCabinet\n", cabname,TiCabinet,cabinfo.iCabinet); |
|
ok4 ( cabinfo.fReserve == TfReserve, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for fReserve\n", cabname,TfReserve,cabinfo.fReserve); |
|
ok4 ( cabinfo.hasprev == Thasprev, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for hasprev\n", cabname,Thasprev,cabinfo.hasprev ); |
|
ok4 ( cabinfo.hasnext == Thasnext, "FDIIsCabinet,cabinfo %s data did not match! Failed!\n\tExpected %d, got %d for Thasnext\n", cabname,Thasnext,cabinfo.hasnext); |
|
#define ok4(condition, msg, arg, arb, arc) \ |
|
do { if(!(condition)) { \ |
|
fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__, arg, arb, arc); \ |
|
exit(1); \ |
|
} } while(0) |
|
|
|
|
|
But it didn't really work, and its too late to fix it for now */ |
|
|
| |
| |
HFDI hfdi_unknown_dummy, hfdi_unknown_fake,hfdi_unknown_real; | HFDI hfdi_unknown_dummy, hfdi_unknown_fake,hfdi_unknown_real; |
|
|
"FDIIsCabinet (File = Error) failed!\n"); | "FDIIsCabinet (File = Error) failed!\n"); |
| |
/* TEST : Fake filehandle associated, memory manually copied, should return TRUE */ | /* TEST : Fake filehandle associated, memory manually copied, should return TRUE */ |
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD, &fdi_cabinfo_simple) == TRUE, |
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD_simple, &fdi_cabinfo_simple) == TRUE, |
"FDIIsCabinet (FakeFile = Cabinet) failed!\n"); |
"FDIIsCabinet (Virtual File = Cabinet) failed!\n"); |
| |
CheckCabInfo("simple.cab",fdi_cabinfo_simple,117,1,1,12345,0,0,0,0); | CheckCabInfo("simple.cab",fdi_cabinfo_simple,117,1,1,12345,0,0,0,0); |
| |
/* simply this with macros? |
/* |
yes, make one macro with inputs (cabname, testname, [expected values] ) --- using lambda notation |
|
add checks for cabinfo data! |
|
Is it ok to reuse the same hfdi_unknown_real ? */ | Is it ok to reuse the same hfdi_unknown_real ? */ |
| |
/* TEST : Opened filehandle associated, corrupted cab loaded, should return FALSE */ | /* TEST : Opened filehandle associated, corrupted cab loaded, should return FALSE */ |
/* We can see that the Windows implementation only reads the first 36 bytes - what if we corrupted a CAB after 36 bytes?*/ | /* We can see that the Windows implementation only reads the first 36 bytes - what if we corrupted a CAB after 36 bytes?*/ |
| |
realfd = real_open( "broken.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
|
| |
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == FALSE, |
/* Testing broken cab - using virtual file reads */ |
"FDIIsCabinet (File = Bad-Cabinet) broken.cab failed!\n"); |
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD_broken, &fdi_cabinfo_simple) == FALSE, |
real_close(realfd); |
"FDIIsCabinet (Virtual File = Bad-Cabinet) failed!\n"); |
| |
realfd = real_open( "cabinet_fdi.c" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); | realfd = real_open( "cabinet_fdi.c" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
| |
|
|
real_close(realfd); | real_close(realfd); |
| |
| |
|
CheckCabInfo("simple.cab",fdi_cabinfo_simple,117,1,1,12345,0,0,0,0); |
|
|
|
|
/* TEST : Opened filehandle associated, valid cab loaded, should return TRUE */ | /* TEST : Opened filehandle associated, valid cab loaded, should return TRUE */ |
realfd = real_open( "complex_lzw.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); | realfd = real_open( "complex_lzw.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
| |
|
|
| |
printCabInfo(fdi_cabinfo_complex); | printCabInfo(fdi_cabinfo_complex); |
| |
realfd = real_open( "complex_lzw2.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
|
| |
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, |
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD_complexlzw2, &fdi_cabinfo_complex) == TRUE, |
"FDIIsCabinet (File = Cabinet) complex_lzw2.cab failed!\n"); |
"FDIIsCabinet (Virtual File = Cabinet) complex_lzw2.cab failed!\n"); |
real_close(realfd); |
|
| |
printCabInfo(fdi_cabinfo_complex); | printCabInfo(fdi_cabinfo_complex); |
| |
|
CheckCabInfo("complex_lzw2",fdi_cabinfo_complex,3513,1,1,32356,1,0,1,0); |
|
|
|
|
|
|
realfd = real_open( "complex_zip.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); | realfd = real_open( "complex_zip.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
| |
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, | ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, |
|
|
| |
printCabInfo(fdi_cabinfo_complex); | printCabInfo(fdi_cabinfo_complex); |
| |
realfd = real_open( "complex_zip2.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
|
|
|
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, |
|
"FDIIsCabinet (File = Cabinet) complex_zip2.cab failed!\n"); |
|
real_close(realfd); |
|
| |
|
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD_complexzip2, &fdi_cabinfo_complex) == TRUE, |
|
"FDIIsCabinet (Virtual File = Cabinet) complex_zip2.cab failed!\n"); |
| |
printCabInfo(fdi_cabinfo_complex); | printCabInfo(fdi_cabinfo_complex); |
| |
|
CheckCabInfo("complex_zip2",fdi_cabinfo_complex,6995,1,4,32356,1,0,1,0); |
|
|
|
|
realfd = real_open( "complex_none.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); | realfd = real_open( "complex_none.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
| |
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, | ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, |
|
|
| |
} | } |
| |
|
/* Peer cooment : really_shouldn't use relative paths in FDICopy call --- doing // doesn't work as a comment in C fyi |
|
*/ |
|
|
static void TestCopy(void){ | static void TestCopy(void){ |
printf("Starting TestCopy()\n"); | printf("Starting TestCopy()\n"); |
printf("---simple.cab\n"); | printf("---simple.cab\n"); |
|
|
{ | { |
TestCreate(); | TestCreate(); |
TestInfo(); | TestInfo(); |
|
|
TestCopy(); | TestCopy(); |
|
|
TestDestroy(); | TestDestroy(); |
} | } |