Source Code (Use browser search to find items of interest.)
Class Index
kdat'Archive (./kdeadmin/kdat/Archive.h:33)
class Archive {
bool _stubbed;
int _endBlock;
int _ctime;
FILE* _fptr;
int _offset;
QString _name;
QList<File> _children;
RangeList _ranges;
Tape* _tape;
public:
/**
* Create a new archive.
*
* @param tape The tape containing this archive.
* @param ctime The create time of the archive.
* @param name The name given to this archive by the user.
*/
Archive( Tape* tape, int ctime, const char* name );
/**
* Create a new stubbed instance of an archive. The file pointer and
* offset specify where the actual instance data can be found. The real
* data is read on demand when one of the accessor functions is called.
*
* @param tape The tape containing this archive.
* @param fptr The open index file containing this archive entry. The file
* must be left open so that the archive entry information can
* be read at a later time.
* @param offset The offset that will be seeked to when reading the archive
* entry information.
*/
Archive( Tape* tape, FILE* fptr, int offset );
/**
* Destroy the archive entry and all of its children.
*/
~Archive();
/**
* Insure that all of the data fields for this archive entry have been read
* in. If the archive entry is a stub then the actual data is read from the
* index file. If the archive entry is not a stub then no action is taken.
*
* @param version The version of the old tape index.
*/
void read( int version = KDAT_INDEX_FILE_VERSION );
/**
* Recursively read the instance data for this archive entry and all of it's
* children. This method is used when converting from an older index format.
*
* @param version The version of the old tape index.
*/
void readAll( int version );
/**
* Write out the archive entry to the open file. Entries for each of its
* children will also be written.
*/
void write( FILE* fptr );
/**
* Get the creation time for this archive.
*
* @return The creation time in seconds since the Epoch.
*/
int getCTime();
/**
* Get the last tape block of this archive.
*
* @return The last tape block used by this archive.
*/
int getEndBlock();
/**
* Get the name of this archive.
*
* @return The name of this archive.
*/
QString getName();
/**
* Get the tape that contains this archive.
*
* @return A pointer to the tape containing this archive.
*/
Tape* getTape();
/**
* Get the list of top-level files in this archive.
*
* @return A list of the immediate children of this archive.
*/
const QList<File>& getChildren();
/**
* Get the list of ranges of this file and all of its children.
*
* @return A list of ranges.
*/
const QList<Range>& getRanges();
/**
* Set the ending tape block for this archive.
*
* @param endBlock The last tape block used by this archive.
*/
void setEndBlock( int endBlock );
/**
* Set the name of this archive.
*
* @param name The new archive name.
*/
void setName( const char* name );
/**
* Add a new top level file as a child of this archive.
*
* @param file The file to add.
*/
void addChild( File* file );
/**
* Create a new file entry, and add it to the archive. Based on the
* full path name of the file, an appropriate parent is found. The parent
* may be this archive or another file entry. File entries will be created
* on demand if some or all of the file's path does not yet exist in this
* archive.
*
* @param size The size, in bytes, of the file.
* @param mtime The last modification time for the file, in seconds since
* the Epoch.
* @param startRecord The first tar record number of this file.
* @param endRecord The last tar record number of this file.
* @param name The full path name for the file.
*
* @return A pointer to the newly created file entry.
*/
File* addFile( int size, int mtime, int startRecord, int endRecord, const char* name );
/**
* Recursively calculate the list of ranges for all of the archive's children.
*/
void calcRanges();
};
kdat'Archive::Archive() (./kdeadmin/kdat/Archive.cpp:26)
Archive::Archive( Tape* tape, int ctime, const char* name )
: _stubbed( FALSE ),
_fptr( 0 ),
_offset( 0 ),
_name( name ),
_tape( tape )
{
assert( _tape );
_ctime = ctime;
}
kdat'Archive::Archive() (./kdeadmin/kdat/Archive.cpp:38)
Archive::Archive( Tape* tape, FILE* fptr, int offset )
: _stubbed( TRUE ),
_tape( tape )
{
assert( _tape );
_fptr = fptr;
_offset = offset;
}
kdat'Archive::~Archive() (./kdeadmin/kdat/Archive.cpp:48)
Archive::~Archive()
{
}
kdat'Archive::read() (./kdeadmin/kdat/Archive.cpp:52)
void Archive::read( int version )
{
if ( !_stubbed ) {
return;
}
_stubbed = FALSE;
fseek( _fptr, _offset, SEEK_SET );
// Archive name (4 bytes + n chars).
int ival;
fread( &ival, sizeof( ival ), 1, _fptr );
char *buf = new char[ival + 1];
buf[ival] = '\0';
fread( buf, sizeof( char ), ival, _fptr );
_name = buf;
delete [] buf;
// Archive creation time (4 bytes).
fread( &ival, sizeof( ival ), 1, _fptr );
_ctime = ival;
// Archive ending block (4 bytes).
fread( &ival, sizeof( ival ), 1, _fptr );
_endBlock = ival;
if ( version > 3 ) {
fread( &ival, sizeof( ival ), 1, _fptr );
int rc = ival;
int start = 0;
int end = 0;
for ( int ii = 0; ii < rc; ii++ ) {
fread( &ival, sizeof( ival ), 1, _fptr );
start = ival;
fread( &ival, sizeof( ival ), 1, _fptr );
end = ival;
_ranges.addRange( start, end );
}
}
// Number of immediate children (4 bytes).
fread( &ival, sizeof( ival ), 1, _fptr );
//===== Read files =====
for ( int count = ival; count > 0; count-- ) {
fread( &ival, sizeof( ival ), 1, _fptr );
addChild( new File( 0, _fptr, ival ) );
}
}
kdat'Archive::readAll() (./kdeadmin/kdat/Archive.cpp:104)
void Archive::readAll( int version )
{
read( version );
QListIterator<File> i( getChildren() );
for ( ; i.current(); ++i ) {
i.current()->readAll( version );
}
}
kdat'Archive::write() (./kdeadmin/kdat/Archive.cpp:114)
void Archive::write( FILE* fptr )
{
_fptr = fptr;
_offset = ftell( _fptr );
int zero = 0;
// Archive name (4 bytes + n chars).
int ival = 4096;
fwrite( &ival, sizeof( ival ), 1, _fptr );
char buf[4096];
memset( buf, 0, 4096 );
memcpy( buf, _name.data(), _name.length() > 4095 ? 4095 : _name.length() );
fwrite( buf, sizeof( char ), 4096, _fptr );
// Archive creation time (4 bytes).
ival = getCTime();
fwrite( &ival, sizeof( ival ), 1, _fptr );
// Archive ending block (4 bytes).
ival = getEndBlock();
fwrite( &ival, sizeof( ival ), 1, _fptr );
// Child range list.
ival = _ranges.getRanges().count();
fwrite( &ival, sizeof( ival ), 1, _fptr );
QListIterator<Range> it( _ranges.getRanges() );
for ( ; it.current(); ++it ) {
ival = it.current()->getStart();
fwrite( &ival, sizeof( ival ), 1, _fptr );
ival = it.current()->getEnd();
fwrite( &ival, sizeof( ival ), 1, _fptr );
}
// Number of immediate children (4 bytes).
ival = getChildren().count();
fwrite( &ival, sizeof( ival ), 1, _fptr );
// Fill in file offsets later...
int fileTable = ftell( _fptr );
for ( ; ival > 0; ival-- ) {
fwrite( &zero, sizeof( zero ), 1, _fptr );
}
//===== Write files =====
QListIterator<File> i( getChildren() );
int count = 0;
for ( ; i.current(); ++i, count++ ) {
// Fill in the file offset.
int here = ftell( _fptr );
fseek( _fptr, fileTable + 4*count, SEEK_SET );
fwrite( &here, sizeof( here ), 1, _fptr );
fseek( _fptr, here, SEEK_SET );
i.current()->write( _fptr );
}
}
kdat'Archive::getCTime() (./kdeadmin/kdat/Archive.cpp:172)
int Archive::getCTime()
{
read();
return _ctime;
}
kdat'Archive::getEndBlock() (./kdeadmin/kdat/Archive.cpp:179)
int Archive::getEndBlock()
{
read();
return _endBlock;
}
kdat'Archive::getName() (./kdeadmin/kdat/Archive.cpp:186)
QString Archive::getName()
{
read();
return _name;
}
kdat'Archive::getTape() (./kdeadmin/kdat/Archive.cpp:193)
Tape* Archive::getTape()
{
return _tape;
}
kdat'Archive::getChildren() (./kdeadmin/kdat/Archive.cpp:198)
const QList<File>& Archive::getChildren()
{
read();
return _children;
}
kdat'Archive::getRanges() (./kdeadmin/kdat/Archive.cpp:205)
const QList<Range>& Archive::getRanges()
{
read();
return _ranges.getRanges();
}
kdat'Archive::setEndBlock() (./kdeadmin/kdat/Archive.cpp:212)
void Archive::setEndBlock( int endBlock )
{
read();
_endBlock = endBlock;
if ( _fptr ) {
fseek( _fptr, _offset + 4 + 4096 + 4, SEEK_SET );
fwrite( &_endBlock, sizeof( _endBlock ), 1, _fptr );
}
TapeManager::instance()->tapeModified( _tape );
}
kdat'Archive::setName() (./kdeadmin/kdat/Archive.cpp:226)
void Archive::setName( const char* name )
{
read();
_name = name;
if ( _fptr ) {
char buf[4096];
fseek( _fptr, _offset + 4, SEEK_SET );
memset( buf, 0, 4096 );
memcpy( buf, _name.data(), _name.length() > 4095 ? 4095 : _name.length() );
fwrite( buf, sizeof( char ), 4096, _fptr );
fflush( _fptr );
}
TapeManager::instance()->tapeModified( _tape );
}
kdat'Archive::addChild() (./kdeadmin/kdat/Archive.cpp:244)
void Archive::addChild( File* file )
{
read();
_children.append( file );
}
kdat'Archive::addFile() (./kdeadmin/kdat/Archive.cpp:251)
File* Archive::addFile( int size, int mtime, int startRecord, int endRecord, const char* name )
{
read();
QStrList path;
QString fn( name );
int idx = 0;
while ( ( idx = fn.find( '/' ) ) > -1 ) {
path.append( fn.left( idx + 1 ) );
fn.remove( 0, idx + 1 );
}
if ( fn.length() == 0 ) {
fn = path.last();
path.removeLast();
}
File* file = 0;
if ( path.count() == 0 ) {
// Top level file/directory.
file = new File( 0, size, mtime, startRecord, endRecord, fn );
addChild( file );
return file;
}
QString dir = path.first();
path.removeFirst();
QListIterator<File> i( getChildren() );
File* parent = 0;
for ( ; i.current() ; ++i ) {
if ( i.current()->getName() == dir ) {
parent = i.current();
break;
}
}
if ( parent == 0 ) {
parent = new File( 0, 0, 0, startRecord, endRecord, dir );
addChild( parent );
}
QStrListIterator j( path );
for ( ; j.current(); ++j ) {
QString dir = j.current();
File* pparent = parent;
QListIterator<File> i( pparent->getChildren() );
for ( parent = 0; i.current() ; ++i ) {
if ( i.current()->getName() == dir ) {
parent = i.current();
break;
}
}
if ( parent == 0 ) {
parent = new File( pparent, 0, 0, 0, 0, dir );
pparent->addChild( parent );
}
}
file = new File( parent, size, mtime, startRecord, endRecord, fn );
parent->addChild( file );
return file;
}
kdat'Archive::calcRanges() (./kdeadmin/kdat/Archive.cpp:318)
void Archive::calcRanges()
{
assert( !_stubbed );
_ranges.clear();
QListIterator<File> it( getChildren() );
for ( ; it.current(); ++it ) {
it.current()->calcRanges();
QListIterator<Range> it2( it.current()->getRanges() );
for ( ; it2.current(); ++it2 ) {
_ranges.addRange( it2.current()->getStart(), it2.current()->getEnd() );
}
}
//%%% This is a kludge to cope with a bug that I haven't found yet.
//%%% If there is more than one range, then all of the ranges are merged
//%%% into one big contiguous range.
if ( _ranges.getRanges().count() > 1 ) {
debug( "Archive::calcRanges() -- extra ranges detected, fixing..." );
QListIterator<Range> iter( _ranges.getRanges() );
for ( ; iter.current(); ++iter ) {
debug( "Archive::calcRanges() -- range = %d to %d", iter.current()->getStart(), iter.current()->getEnd() );
}
int start = _ranges.getRanges().getFirst()->getStart();
int end = _ranges.getRanges().getLast()->getEnd();
_ranges.clear();
_ranges.addRange( start, end );
}
assert( _ranges.getRanges().count() <= 1 );
_endBlock = _ranges.getRanges().getFirst()->getEnd() / ( Options::instance()->getTapeBlockSize() / 512 );
}