Source Code (Use browser search to find items of interest.)

Class Index

kdat'File (./kdeadmin/kdat/File.h:32)

class File {
    bool _stubbed;
    union {
        struct {
            int _size;
            int _mtime;
            int _startRecord;
            int _endRecord;
        } _data;
        struct {
            FILE* _fptr;
            int   _offset;
        } _stub;
    } _union;
    QString     _name;
    File*       _parent;
    QList<File> _children;
    RangeList   _ranges;
public:
    /**
     * Create a new file entry.
     *
     * @param parent      The directory file entry that contains this file.
     * @param size        The size of the file in bytes.
     * @param mtime       The last modification time of the file in seconds since
     *                    the Epoch.
     * @param startRecord The first tar record number in the file.
     * @param endRecord   The last tar record number in the file.
     * @param name        The file name.  If the file name ends with a '/' then it
     *                    is assumed to be a directory name.  Only the last part of
     *                    the file's path name should be passed in.  The rest of the
     *                    path is determined by this file entry's ancestors.
     */
    File( File* parent, int size, int mtime, int startRecord, int endRecord, const char* name );
    
    /**
     * Create a new stubbed instance of a file entry.  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 parent The directory file entry that contains this file.
     * @param fptr   The open index file containing this file entry.  The file
     *               must be left open so that the file entry information can
     *               be read at a later time.
     * @param offset The offset that will be seeked to when reading the file
     *               entry information.
     */
    File( File* parent, FILE* fptr, int offset );

    /**
     * Destroy the file entry and all of its children.
     */
    ~File();
    
    /**
     * Insure that all of the data fields for this file entry have been read
     * in.  If the file entry is a stub then the actual data is read from the
     * index file.  If the file 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 for this file 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 file entry to the open file.  Entries for each of its
     * children will also be written.
     */
    void write( FILE* fptr );

    /**
     * Determine whether this file entry represents a directory.  If the file
     * name ends in a '/' then it is assumed that it is a directory.
     *
     * @return TRUE if the file represents a directory, or FALSE if it is an
     *         ordinary file.
     */
    bool isDirectory();

    /**
     * Get the size of the file.
     *
     * @return The size, in bytes, of the file.
     */
    int getSize();

    /**
     * Get the last modification time for the file.
     *
     * @ return The last time the file was modified, in seconds since the Epoch.
     */
    int getMTime();

    /**
     * Get the tar record number for the file.  This is the number of 512-byte
     * tar blocks that must be read before getting to this file.
     *
     * @return The tar record number for the file.
     */
    int getStartRecord();

    /**
     * Get the tar record number that is just past the end of the file.  This
     * number minus the start record gives the number of 512-byte tar blocks
     * that this file occupies in the archive.
     *
     * @return The last tar record number for the file.
     */
    int getEndRecord();

    /**
     * Get the name of this file.  Only the last component of the full path
     * name is returned.
     *
     * @return The file's name.
     */
    QString getName();

    /**
     * Get the full path name of the file.
     *
     * @return The full path to the file.
     */
    QString getFullPathName();

    /**
     * Get the file entry's parent.  A NULL parent indicates that this is one
     * of (possibly) many top level directories within the tar archive.
     *
     * @return A pointer to the file entry that contains this file entry.
     */
    File* getParent();

    /**
     * Get the children of this file entry.  A normal file will never have any
     * children.  A directory may or may not have children.
     *
     * @return A list of the immediate children of this file entry.
     */
    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();

    /**
     * Add a new file entry as a child of this file entry.
     *
     * @param file The file to add.
     */
    void addChild( File* file );

    /**
     * Recursively calculate the list of ranges for all of the file's children.
     */
    void calcRanges();
};

kdat'File::File() (./kdeadmin/kdat/File.cpp:23)

File::File( File* parent, int size, int mtime, int startRecord, int endRecord, const char* name )
        : _stubbed( FALSE ),
          _name( name ),
          _parent( parent )
{
    assert( endRecord >= startRecord );

    _union._data._size        = size;
    _union._data._mtime       = mtime;
    _union._data._startRecord = startRecord;
    _union._data._endRecord   = endRecord;
}


kdat'File::File() (./kdeadmin/kdat/File.cpp:36)

File::File( File* parent, FILE* fptr, int offset )
        : _stubbed( TRUE ),
          _parent( parent )
{
    _union._stub._fptr   = fptr;
    _union._stub._offset = offset;
}


kdat'File::~File() (./kdeadmin/kdat/File.cpp:44)

File::~File()
{
    while ( _children.first() ) {
        delete _children.first();
        _children.removeFirst();
    }
}


kdat'File::read() (./kdeadmin/kdat/File.cpp:52)

void File::read( int version )
{
    if ( !_stubbed ) {
        return;
    }

    _stubbed = FALSE;

    FILE* fptr = _union._stub._fptr;

    fseek( fptr, _union._stub._offset, SEEK_SET );
    
    // File 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;
 
    // File size (4 bytes).
    fread( &ival, sizeof( ival ), 1, fptr );
    _union._data._size = ival;

    // File modification time (4 bytes).
    fread( &ival, sizeof( ival ), 1, fptr );
    _union._data._mtime = ival;

    // Start record number.
    fread( &ival, sizeof( ival ), 1, fptr );
    _union._data._startRecord = ival;
    
    // End record number.
    fread( &ival, sizeof( ival ), 1, fptr );
    _union._data._endRecord = ival;

    //%%% This is a kludge to cope with some screwed up tape indexes.
    //%%% Hopefully the file with the zero end record is *always* at
    //%%% the end of the archive.
    if ( ( _union._data._endRecord <= 0 ) && ( _union._data._startRecord != _union._data._endRecord ) ) {
        _union._data._endRecord = MAXINT;
    }

    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 );
        }
    }

    //===== Read files =====
    fread( &ival, sizeof( ival ), 1, fptr );
    for ( int count = ival; count > 0; count-- ) {
        fread( &ival, sizeof( ival ), 1, fptr );
        addChild( new File( this, fptr, ival ) );
    }
}


kdat'File::readAll() (./kdeadmin/kdat/File.cpp:120)

void File::readAll( int version )
{
    read( version );

    QListIterator<File> i( getChildren() );
    for ( ; i.current(); ++i ) {
        i.current()->readAll( version );
    }
}


kdat'File::write() (./kdeadmin/kdat/File.cpp:130)

void File::write( FILE* fptr )
{
    int zero = 0;

    // File name (4 bytes + n chars).
    int ival = getName().length();
    fwrite( &ival, sizeof( ival ), 1, fptr );
    fwrite( getName().data(), sizeof( char ), ival, fptr );

    // File size (4 bytes).
    ival = getSize();
    fwrite( &ival, sizeof( ival ), 1, fptr );

    // File modification time (4 bytes).
    ival = getMTime();
    fwrite( &ival, sizeof( ival ), 1, fptr );

    // Start record number.
    ival = getStartRecord();
    fwrite( &ival, sizeof( ival ), 1, fptr );

    // End record number.
    ival = getEndRecord();
    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 =====
    ival = _children.count();
    fwrite( &ival, sizeof( ival ), 1, fptr );

    QListIterator<File> i( _children );
    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'File::isDirectory() (./kdeadmin/kdat/File.cpp:193)

bool File::isDirectory()
{
    read();

    return _name[ _name.length() - 1 ] == '/';
}


kdat'File::getSize() (./kdeadmin/kdat/File.cpp:200)

int File::getSize()
{
    read();

    return _union._data._size;
}


kdat'File::getMTime() (./kdeadmin/kdat/File.cpp:207)

int File::getMTime()
{
    read();

    return _union._data._mtime;
}


kdat'File::getStartRecord() (./kdeadmin/kdat/File.cpp:214)

int File::getStartRecord()
{
    read();

    return _union._data._startRecord;
}


kdat'File::getEndRecord() (./kdeadmin/kdat/File.cpp:221)

int File::getEndRecord()
{
    read();

    return _union._data._endRecord;
}


kdat'File::getName() (./kdeadmin/kdat/File.cpp:228)

QString File::getName()
{
    read();

    return _name;
}


kdat'File::getFullPathName() (./kdeadmin/kdat/File.cpp:235)

QString File::getFullPathName()
{
    QString tmp = _name.copy();
    for ( File* parent = getParent(); parent; parent = parent->getParent() ) {
        tmp.prepend( parent->getName() );
    }

    return tmp;
}


kdat'File::getParent() (./kdeadmin/kdat/File.cpp:245)

File* File::getParent()
{
    return _parent;
}


kdat'File::getChildren() (./kdeadmin/kdat/File.cpp:250)

const QList<File>& File::getChildren()
{
    read();

    return _children;
}


kdat'File::getRanges() (./kdeadmin/kdat/File.cpp:257)

const QList<Range>& File::getRanges()
{
    read();

    return _ranges.getRanges();
}


kdat'File::addChild() (./kdeadmin/kdat/File.cpp:264)

void File::addChild( File* file )
{
    read();

    _children.append( file );
}


kdat'File::calcRanges() (./kdeadmin/kdat/File.cpp:271)

void File::calcRanges()
{
    assert( !_stubbed );

    _ranges.clear();
    _ranges.addRange( getStartRecord(), getEndRecord() );

    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() );
        }
    }
}