/* basic parameter failures */ void cabd_merge_test_01() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab1, *cab2; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cab1 = cabd->open(cabd, "test_files/cabd/multi_basic_pt1.cab"); cab2 = cabd->open(cabd, "test_files/cabd/multi_basic_pt2.cab"); TEST(cab1 != NULL); TEST(cab2 != NULL); TEST(cabd->append(cabd, cab1, NULL) != MSPACK_ERR_OK); TEST(cabd->append(cabd, NULL, cab1) != MSPACK_ERR_OK); TEST(cabd->append(cabd, cab1, cab1) != MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab1, NULL) != MSPACK_ERR_OK); TEST(cabd->prepend(cabd, NULL, cab1) != MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab1, cab1) != MSPACK_ERR_OK); /* merge cabs, then try merging again every other way */ TEST(cabd->append(cabd, cab1, cab2) == MSPACK_ERR_OK); TEST(cabd->append(cabd, cab2, cab1) != MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab1, cab2) != MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab2, cab1) != MSPACK_ERR_OK); TEST(cabd->append(cabd, cab1, cab2) != MSPACK_ERR_OK); cabd->close(cabd, cab1); mspack_destroy_cab_decompressor(cabd); }
/* cabs with reserve headers set, ensure they all load correctly */ void cabd_open_test_03() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; unsigned int i; const char *files[] = { "test_files/cabd/reserve_---.cab", "test_files/cabd/reserve_--D.cab", "test_files/cabd/reserve_-F-.cab", "test_files/cabd/reserve_-FD.cab", "test_files/cabd/reserve_H--.cab", "test_files/cabd/reserve_H-D.cab", "test_files/cabd/reserve_HF-.cab", "test_files/cabd/reserve_HFD.cab" }; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); for (i = 0; i < (sizeof(files)/sizeof(char *)); i++) { cab = cabd->open(cabd, files[i]); TEST(cab != NULL); TEST(cab->files != NULL); TEST(cab->files->next != NULL); TEST(strcmp(cab->files->filename, "test1.txt") == 0); TEST(strcmp(cab->files->next->filename, "test2.txt") == 0); cabd->close(cabd, cab); } mspack_destroy_cab_decompressor(cabd); }
/* search file using 1-byte buffer */ void cabd_search_test_02() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cabd->set_param(cabd, MSCABD_PARAM_SEARCHBUF, 1); cab = cabd->search(cabd, "test_files/cabd/search_basic.cab"); cabd->set_param(cabd, MSCABD_PARAM_SEARCHBUF, 32768); TEST(cab != NULL); TEST(cab->files != NULL); TEST(cab->base_offset == 6); TEST(cab->files->next != NULL); TEST(strcmp(cab->files->filename, "hello.c") == 0); TEST(strcmp(cab->files->next->filename, "welcome.c") == 0); TEST(cab->next != NULL); TEST(cab->next->base_offset == 265); TEST(cab->next->files != NULL); TEST(cab->next->files->next != NULL); TEST(strcmp(cab->next->files->filename, "hello.c") == 0); TEST(strcmp(cab->next->files->next->filename, "welcome.c") == 0); TEST(cab->next->next == NULL); cabd->close(cabd, cab); mspack_destroy_cab_decompressor(cabd); }
/* some bad cabs, should not load */ void cabd_open_test_04() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); /* cab has enough data for a header, but does not contain real cab data * result should be MSPACK_ERR_SIGNATURE */ cab = cabd->open(cabd, "test_files/cabd/bad_signature.cab"); TEST(cab == NULL); /* cab has 0 folders */ cab = cabd->open(cabd, "test_files/cabd/bad_nofolders.cab"); TEST(cab == NULL); /* cab has 0 files */ cab = cabd->open(cabd, "test_files/cabd/bad_nofiles.cab"); TEST(cab == NULL); /* second file in the cab has a folder index for a non-existant folder */ cab = cabd->open(cabd, "test_files/cabd/bad_folderindex.cab"); TEST(cab == NULL); mspack_destroy_cab_decompressor(cabd); }
/* open where search file doesn't exist */ void cabd_search_test_01() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cab = cabd->search(cabd, "!!!FILE_WHICH_DOES_NOT_EXIST"); TEST(cab == NULL); TEST(cabd->last_error(cabd) == MSPACK_ERR_OPEN); mspack_destroy_cab_decompressor(cabd); }
/* open cab with 255 character filename (maximum allowed) */ void cabd_open_test_06() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cab = cabd->open(cabd, "test_files/cabd/normal_255c_filename.cab"); TEST(cab != NULL); cabd->close(cabd, cab); mspack_destroy_cab_decompressor(cabd); }
int main() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; struct mscabd_file *file; struct mem_buf source = { &embedded_cab[0], sizeof(embedded_cab) }; struct mem_buf output; int err; /* if self-test reveals an error */ MSPACK_SYS_SELFTEST(err); if (err) return 1; /* create a cab decompressor using our custom mspack_system interface */ if ((cabd = mspack_create_cab_decompressor(&mem_system))) { /* open a cab file direct from memory */ if ((cab = cabd->open(cabd, (char *) &source))) { /* for all files */ for (file = cab->files; file; file = file->next) { /* fill out our "filename" (memory pointer and length) */ output.data = (char *) malloc(file->length); output.length = file->length; /* let cabd extract this file to our memory buffer */ if (output.data && cabd->extract(cabd, file, (char *) &output)) { exit(1); } /* dump the memory buffer to stdout (for display purposes) */ printf("Filename: %s\nContents:\n", file->filename); fwrite(output.data, 1, output.length, stdout); /* free our buffer */ free(output.data); } cabd->close(cabd, cab); } else { fprintf(stderr, "can't open cabinet (%d)\n", cabd->last_error(cabd)); } mspack_destroy_cab_decompressor(cabd); } else { fprintf(stderr, "can't make decompressor\n"); } return 0; }
/* normal cab file with 2 files and one folder. * check ALL headers are read correctly */ void cabd_open_test_02() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; struct mscabd_folder *folder; struct mscabd_file *file; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cab = cabd->open(cabd, "test_files/cabd/normal_2files_1folder.cab"); TEST(cab != NULL); TEST(cab->next == NULL); TEST(cab->base_offset == 0); TEST(cab->length == 253); TEST(cab->prevcab == NULL); TEST(cab->nextcab == NULL); TEST(cab->prevname == NULL); TEST(cab->nextname == NULL); TEST(cab->previnfo == NULL); TEST(cab->nextinfo == NULL); TEST(cab->set_id = 1570); TEST(cab->set_index == 0); TEST(cab->header_resv == 0); TEST(cab->flags == 0); folder = cab->folders; TEST(folder != NULL); TEST(folder->next == NULL); TEST(folder->comp_type == 0); TEST(folder->num_blocks == 1); file = cab->files; TEST(file != NULL); TEST(strcmp(file->filename, "hello.c") == 0); TEST(file->length == 77); TEST(file->attribs == 0x20); TEST(file->time_h == 11);TEST(file->time_m == 13);TEST(file->time_s == 52); TEST(file->date_d == 12);TEST(file->date_m == 3);TEST(file->date_y == 1997); TEST(file->folder == folder); TEST(file->offset == 0); file = file->next; TEST(file != NULL); TEST(strcmp(file->filename, "welcome.c") == 0); TEST(file->length == 74); TEST(file->attribs == 0x20); TEST(file->time_h == 11);TEST(file->time_m == 15);TEST(file->time_s == 14); TEST(file->date_d == 12);TEST(file->date_m == 3);TEST(file->date_y == 1997); TEST(file->folder == folder); TEST(file->offset == 77); cabd->close(cabd, cab); mspack_destroy_cab_decompressor(cabd); }
/* cabs which have been cut short * result should be MSPACK_ERR_READ for missing headers or * MSPACK_ERR_DATAFORMAT for missing/partial strings. * If only data blocks are missing, the cab should open() */ void cabd_open_test_05() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; unsigned int i; const char *files[] = { "test_files/cabd/partial_shortheader.cab", "test_files/cabd/partial_shortextheader.cab", "test_files/cabd/partial_nofolder.cab", "test_files/cabd/partial_shortfolder.cab", "test_files/cabd/partial_nofiles.cab", "test_files/cabd/partial_shortfile1.cab", "test_files/cabd/partial_shortfile2.cab" }; const char *str_files[] = { "test_files/cabd/partial_str_nopname.cab", "test_files/cabd/partial_str_shortpname.cab", "test_files/cabd/partial_str_nopinfo.cab", "test_files/cabd/partial_str_shortpinfo.cab", "test_files/cabd/partial_str_nonname.cab", "test_files/cabd/partial_str_shortnname.cab", "test_files/cabd/partial_str_noninfo.cab", "test_files/cabd/partial_str_shortninfo.cab", "test_files/cabd/partial_str_nofname.cab", "test_files/cabd/partial_str_shortfname.cab", }; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); for (i = 0; i < (sizeof(files)/sizeof(char *)); i++) { cab = cabd->open(cabd, files[i]); TEST(cab == NULL); TEST(cabd->last_error(cabd) == MSPACK_ERR_READ); } for (i = 0; i < (sizeof(str_files)/sizeof(char *)); i++) { cab = cabd->open(cabd, str_files[i]); TEST(cab == NULL); TEST(cabd->last_error(cabd) == MSPACK_ERR_DATAFORMAT); } /* lack of data blocks should NOT be a problem for merely reading */ cab = cabd->open(cabd, "test_files/cabd/partial_nodata.cab"); TEST(cab != NULL); cabd->close(cabd, cab); mspack_destroy_cab_decompressor(cabd); }
int main(int argc, char *argv[]) { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab, *c; int err; MSPACK_SYS_SELFTEST(err); if (err) return 0; if ((cabd = mspack_create_cab_decompressor(NULL))) { for (argv++; *argv; argv++) { if ((cab = cabd->search(cabd, *argv))) { for (c = cab; c; c = c->next) rip(*argv, c->base_offset, c->length); cabd->close(cabd, cab); } } mspack_destroy_cab_decompressor(cabd); } return 0; }
/* test merging a normal 5 part single folder cabinet set with slightly * haphazard ordering. should still merge fine */ void cabd_merge_test_02() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab[5]; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); cab[0] = cabd->open(cabd, "test_files/cabd/multi_basic_pt1.cab"); cab[1] = cabd->open(cabd, "test_files/cabd/multi_basic_pt2.cab"); cab[2] = cabd->open(cabd, "test_files/cabd/multi_basic_pt3.cab"); cab[3] = cabd->open(cabd, "test_files/cabd/multi_basic_pt4.cab"); cab[4] = cabd->open(cabd, "test_files/cabd/multi_basic_pt5.cab"); TEST(cab[0] != NULL); TEST(cab[1] != NULL); TEST(cab[2] != NULL); TEST(cab[3] != NULL); TEST(cab[4] != NULL); TEST(cabd->append(cabd, cab[0], cab[1]) == MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab[2], cab[1]) == MSPACK_ERR_OK); TEST(cabd->append(cabd, cab[3], cab[4]) == MSPACK_ERR_OK); TEST(cabd->prepend(cabd, cab[3], cab[2]) == MSPACK_ERR_OK); TEST(cab[0]->files != NULL); TEST(cab[0]->files->next != NULL); TEST(cab[0]->files->next->next != NULL); TEST(cab[0]->files->next->next->next == NULL); TEST(cab[0]->files == cab[1]->files); TEST(cab[1]->files == cab[2]->files); TEST(cab[2]->files == cab[3]->files); TEST(cab[3]->files == cab[4]->files); TEST(cab[0]->folders != NULL); TEST(cab[0]->folders->next == NULL); TEST(cab[0]->folders == cab[1]->folders); TEST(cab[1]->folders == cab[2]->folders); TEST(cab[2]->folders == cab[3]->folders); TEST(cab[3]->folders == cab[4]->folders); cabd->close(cabd, cab[0]); mspack_destroy_cab_decompressor(cabd); }
/* tricky searches */ void cabd_search_test_03() { struct mscab_decompressor *cabd; struct mscabd_cabinet *cab; cabd = mspack_create_cab_decompressor(NULL); TEST(cabd != NULL); /* there is only ONE cab in this file. it is prepended by 4 bytes, "MSCF" * (heh) and reserved fields in the real cab are filled in so the fake one * looks real to the scanner but not the real reader */ cab = cabd->search(cabd, "test_files/cabd/search_tricky1.cab"); TEST(cab != NULL); TEST(cab->next == NULL); TEST(cab->files != NULL); TEST(cab->base_offset == 4); TEST(cab->files->next != NULL); TEST(strcmp(cab->files->filename, "hello.c") == 0); TEST(strcmp(cab->files->next->filename, "welcome.c") == 0); cabd->close(cabd, cab); mspack_destroy_cab_decompressor(cabd); }
int main(int argc, char **argv) { struct mscab_decompressor* decomp; struct mscabd_cabinet *cab; struct mscabd_file *file; char *cabfile; char targetfile[1024]; char *targetdir = ""; int n, len; for (n=1; n<argc; n++) { if (argv[n][0] == '-' && argv[n][1] == 'd' && (n+1) < argc) targetdir = argv[++n]; else break; } if (n == argc) { fprintf(stderr, "unpack [-d directory] filename\n"); exit(1); } cabfile = argv[n]; decomp = mspack_create_cab_decompressor( NULL ); if (!decomp) { fprintf(stderr, "failed to create decompressor\n"); exit(1); } cab = decomp->open( decomp, cabfile ); if (!cab) { fprintf(stderr, "failed to open %s\n", cabfile ); exit(1); } file = cab->files; if (!file) { fprintf(stderr, "no files in archive!\n"); exit(1); } if (file->next) { fprintf(stderr, "unpack doesn't handle multiple files\n"); exit(1); } len = strlen( targetdir ); if (len) { strcpy( targetfile, targetdir ); if (targetfile[len-1] != '/') targetfile[len++] = '/'; } strcpy( targetfile+len, file->filename ); strlower( targetfile+len ); decomp->extract( decomp, file, targetfile ); decomp->close( decomp, cab ); return 0; }
/** * * Expands all files in the cabinet into the specified directory. Also returns * the command that is specified in the VMware defined header. * * @param cabFileName IN: Cabinet file name * @param destDirectory IN: Destination directory to uncab * * @return * On success LINUXCAB_SUCCESS * On Error LINUXCAB_ERROR, LINUXCAB_ERR_OPEN, LINUXCAB_ERR_DECOMPRESS, * LINUXCAB_EXTRACT, LINUXCAB_ERR_HEADER **/ unsigned int ExpandAllFilesInCab (const char* cabFileName, const char* destDirectory) { // set the state as success int returnState = LINUXCAB_SUCCESS; struct mscabd_cabinet* cab; struct mscabd_cabinet* cabToClose; // Create decompressor instance // Note : I am using NULL for reading file operations meaning requesting it // to use the default routines. It may be a good idea to write that up in the // future struct mscab_decompressor* deflator = mspack_create_cab_decompressor (NULL); // deflator error ? if (!deflator) { return LINUXCAB_ERR_DECOMPRESSOR; } // Search for the specified file cab = deflator->search (deflator, (char*)cabFileName); cabToClose = cab; // was the file found ? if (!cab) { return LINUXCAB_ERR_OPEN; } /* * Extract file by file * NOTE: open call cannot be used as cab can span multiple files. Hence * search call has to be used. */ // Iterate through the cabinets. while(cab) { // Get all files in the cab struct mscabd_file* file = cab->files; // iterate through the files while(file) { returnState = ExtractFile(deflator, file, destDirectory); // error extracting ? if (returnState != LINUXCAB_SUCCESS) { break; } file = file->next; } // Break - if error if (returnState != LINUXCAB_SUCCESS) { break; } #ifdef VMX86_DEBUG sLog(log_debug, "flag = %i \n", cab->flags); #endif // move to next cab file - in case of multi file cabs cab = cab->next; } deflator->close (deflator, cabToClose); // close & destroy instance - clean up mspack_destroy_cab_decompressor(deflator); #ifdef VMX86_DEBUG sLog(log_info, "Done extracting files. \n"); #endif return returnState; }