Maybe I've been just looking at this code for too long (I guess that happens to everyone) but I just can't seem to find the problem. I've tested my methods of opening a file up and storing the information in a buffer; but I can't seem to write it to my archive file. I end up with just the file header; some more eyes looking at it will usually uncover problems!
Source
//j: save one of our beautiful archive files; yay! fun! fun!
bool CFileArchive::Save(Archive_T& p) {
m_Files.Sort();
if(m_bTouched) {
// check this now!!
if(p.pHandle==NULL)
p.pHandle = new fstream_t(p.szPath.c_str(),std::ios::binary|std::ios::out|std::ios::in);
SysLog(__FUNCTION__,"Path %s; Files %d",p.szPath.c_str(),m_Files.size());
// we need to store the current position
long iPos=0;
// start at the top and write the header
p.pHandle->seekp(0,std::ios::beg);
p.pHandle->write( reinterpret_cast<char*> (&p.pHeader), sizeof(p.pHeader) );
// write the offset
p.pHandle->write( 0, sizeof(byte_t)*ARCHIVE_FILE_OFFSET );
iPos = p.pHandle->tellp();
if(m_Files.size() > 0) {
m_iNumFiles = static_cast<unsigned int> (m_Files.size());
// run through and determine if who's going to need to be rewritten and realign the data
for(uint i=0; i < m_iNumFiles; i++) {
// we need to check to make sure that we've been touched first
// also need to make sure that there's something in the buffer to go by
if( m_Files->GetTouched() && (m_Files->GetSizeofBuffer() > 0)) {
if( m_Files->GetPosition() > 0) {
// Offset = File Position + ( Sizeof[Buffer] - Original Size )
long iOffset = m_Files->GetPosition() +
(m_Files->GetSizeofBuffer() - m_Files->GetSize());
// since everything is in proper order; we only need to poll the files under this one
for(uint j = i; j < m_iNumFiles; j++) {
Archive_FileTable_T* h = m_Files[j]->GetFormatted();
byte_t* buffer=m_Files[j]->GetBuffer();
if(buffer[0] == '\0') {
// go to the position of the current header location and read in
p.pHandle->seekg(h->iPosition,std::ios_base::beg);
p.pHandle->read( reinterpret_cast<char*> (&buffer), sizeof(h->iSize) );
}
// setup the position with the offset
h->iPosition = iOffset;
p.pHandle->seekp(h->iPosition,std::ios_base::beg);
p.pHandle->write( reinterpret_cast<char*> (&buffer), sizeof(buffer) );
iOffset += h->iSize;
// update the file table; free the buffer; move on
m_Files[j]->Update(*h);
m_Files[j]->Close(); // if this needed to be written; free write!
delete h; h=NULL;
}
}
// we need to start writing data now!
p.pHandle->seekp( iPos, std::ios::beg );
long iSizeOfBuffer = sizeof(m_Files->GetSizeofBuffer());
p.pHandle->write( reinterpret_cast<char*> (m_Files->GetBuffer()), iSizeOfBuffer);
iPos = p.pHandle->tellp();
}
}
// write a byte offset between the file data and file table
p.pHandle->seekp( iPos, std::ios_base::beg );
p.pHandle->write( 0, sizeof(byte_t)*ARCHIVE_FILE_OFFSET );
iPos = p.pHandle->tellp();
// go to the header's start position and run amuck!
p.pHandle->seekp( iPos, std::ios_base::beg );
for(uint j=0; j < m_iNumFiles; j++) {
Archive_FileTable_T* h=m_Files[j]->GetFormatted();
p.pHandle->write( reinterpret_cast<char*> (&h), sizeof(h) );
}
}
// close up shop; we're done!
p.pHandle->close();
p.pHandle->clear();
return true;
}
// nothing changed; nothing saved
return true;
}
void CFileArchive::AddFile(string_t szFilepath) {
// check to make sure we have a path to work with
if(szFilepath[0] == '\0') {
SysBug(__FUNCTION__,"File path is NULL; cannot add file to archive %s",m_szPath.c_str());
return;
}
// we need to open up a stream to grab the buffer
fstream_t stream; stream.open(szFilepath.c_str(),std::ios::binary|std::ios::in);
unsigned long size;
// lip smacking good!
stream.seekg(0,std::ios::end);
size=stream.tellg();
// reposition for reading
stream.seekg(0,std::ios::beg);
byte_t* buffer = new byte_t[size]; // allocate proper amount of memory
stream.read( reinterpret_cast<char*> (buffer), size);
stream.close();
stream.open("blah.zip",std::ios::binary|std::ios::out);
stream.seekp(0,std::ios::beg);
stream.write( reinterpret_cast<char*> (buffer), size);
stream.close();
// let's create the file table entry for this item!
Archive_FileTable_T h;
h.iFlags = 0;
h.iPosition = 0;
h.iSize = size;
h.szPath = szFilepath;
h.szHash = MD5String((char*)buffer); // grab the hash data
SysLog(__FUNCTION__,"Hash %s; Path %s; Size %d",h.szHash,h.szPath.c_str(),size);
// throw onto the table
m_bTouched=true;
m_Files.push_back( new CFile( h, buffer ) );
return;
}
Header
typedef CFile* ffile_t;
class CFileArray : public array_t<ffile_t> {
public:
~CFileArray(void) {
for(iterator p=begin(); p != end(); p++)
delete *p;
}
inline void Sort(void) {
std::sort(begin(),end(), Sort_By_Position() );
}
private:
struct Sort_By_Position {
bool operator() (ffile_t& start,ffile_t& end) {
return (start->GetPosition() < end->GetPosition());
}
};
};
Now let me explain some of this; "Touched" means that the file has been opened or added to the archive since the last save; when a file is added (or opened) the archive is also flagged as being "touched." "Position" is the position (bytes) where it should be located in a file; a new file added has a position of 0 (not yet written). This is what my logger brings up:
CFileArchive::AddFile 02-12-2005 12:05 PM Hash a681c6a002989832645ed26b766c7afa; Path k8v_audio.zip; Size 24184662
CFileArchive::Save 02-12-2005 12:05 PM Path test.eaf; Files 1
commandInterpret 02-12-2005 12:05 PM eafpack -p test.eaf k8v_audio.zip