#include "compound-file.h" #include "compound-file-difat.h" #include "compound-file-header.h" #include "compound-file-fat.h" #include "compound-file-common.h" #include "emb-logging.h" #include #include #include #include static unsigned int sizeOfDirectoryEntry = 128; static unsigned int sectorSize(bcf_file* bcfFile) { /* version 3 uses 512 byte */ if(bcfFile->header.majorVersion == 3) { return 512; } else if(bcfFile->header.majorVersion == 4) { return 4096; } return 4096; } static int haveExtraDIFATSectors(bcf_file* file) { return (int)(numberOfEntriesInDifatSector(file->difat) > 0); } static int seekToOffset(EmbFile* file, const unsigned int offset) { return embFile_seek(file, offset, SEEK_SET); } static int seekToSector(bcf_file* bcfFile, EmbFile* file, const unsigned int sector) { unsigned int offset = sector * sectorSize(bcfFile) + sectorSize(bcfFile); return seekToOffset(file, offset); } static void parseDIFATSectors(EmbFile* file, bcf_file* bcfFile) { unsigned int numberOfDifatEntriesStillToRead = bcfFile->header.numberOfFATSectors - NumberOfDifatEntriesInHeader; unsigned int difatSectorNumber = bcfFile->header.firstDifatSectorLocation; while((difatSectorNumber != CompoundFileSector_EndOfChain) && (numberOfDifatEntriesStillToRead > 0 )) { seekToSector(bcfFile, file, difatSectorNumber); difatSectorNumber = readFullSector(file, bcfFile->difat, &numberOfDifatEntriesStillToRead); } } int bcfFile_read(EmbFile* file, bcf_file* bcfFile) { unsigned int i, numberOfDirectoryEntriesPerSector, directorySectorToReadFrom; bcfFile->header = bcfFileHeader_read(file); if(!bcfFileHeader_isValid(bcfFile->header)) { printf( "Failed to parse header\n" ); return 0; } bcfFile->difat = bcf_difat_create(file, bcfFile->header.numberOfFATSectors, sectorSize(bcfFile)); if(haveExtraDIFATSectors(bcfFile)) { parseDIFATSectors(file, bcfFile); } bcfFile->fat = bcfFileFat_create(sectorSize(bcfFile)); for(i = 0; i < bcfFile->header.numberOfFATSectors; ++i) { unsigned int fatSectorNumber = bcfFile->difat->fatSectorEntries[i]; seekToSector(bcfFile, file, fatSectorNumber); loadFatFromSector(bcfFile->fat, file); } numberOfDirectoryEntriesPerSector = sectorSize(bcfFile) / sizeOfDirectoryEntry; bcfFile->directory = CompoundFileDirectory(numberOfDirectoryEntriesPerSector); directorySectorToReadFrom = bcfFile->header.firstDirectorySectorLocation; while(directorySectorToReadFrom != CompoundFileSector_EndOfChain) { seekToSector(bcfFile, file, directorySectorToReadFrom); readNextSector(file, bcfFile->directory); directorySectorToReadFrom = bcfFile->fat->fatEntries[directorySectorToReadFrom]; } return 1; } EmbFile* GetFile(bcf_file* bcfFile, EmbFile* file, char* fileToFind) { int filesize, sectorSize, currentSector, sizeToWrite, currentSize, totalSectors, i; char* input = 0; EmbFile* fileOut = embFile_tmpfile(); bcf_directory_entry* pointer = bcfFile->directory->dirEntries; while(pointer) { if(strcmp(fileToFind, pointer->directoryEntryName) == 0) break; pointer = pointer->next; } filesize = pointer->streamSize; sectorSize = bcfFile->difat->sectorSize; input = (char*)malloc(sectorSize); if(!input) { embLog_error("compound-file.c GetFile(), cannot allocate memory for input\n"); } /* TODO: avoid crashing. null pointer will be accessed */ currentSize = 0; currentSector = pointer->startingSectorLocation; totalSectors = (int)ceil((float)filesize / sectorSize); for(i = 0; i < totalSectors; i++) { seekToSector(bcfFile, file, currentSector); sizeToWrite = filesize - currentSize; if(sectorSize < sizeToWrite) { sizeToWrite = sectorSize; } embFile_read(input, 1, sizeToWrite, file); embFile_write(input, 1, sizeToWrite, fileOut); currentSize += sizeToWrite; currentSector = bcfFile->fat->fatEntries[currentSector]; } free(input); input = 0; return fileOut; } void bcf_file_free(bcf_file* bcfFile) { bcf_file_difat_free(bcfFile->difat); bcfFile->difat = 0; bcf_file_fat_free(bcfFile->fat); bcfFile->fat = 0; bcf_directory_free(bcfFile->directory); bcfFile->directory = 0; free(bcfFile); bcfFile = 0; } /* kate: bom off; indent-mode cstyle; indent-width 4; replace-trailing-space-save on; */