1 // KDat - a tar-based DAT archiver
2 // Copyright (C) 1998-2000 Sean Vyain, svyain@mail.tds.net
3 // Copyright (C) 2001-2002 Lawrence Widman, kdat@cardiothink.com
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 File::File( File
* parent
, int size
, int mtime
, int startRecord
, int endRecord
, const QString
& name
)
31 assert( endRecord
>= startRecord
);
33 _union
._data
._size
= size
;
34 _union
._data
._mtime
= mtime
;
35 _union
._data
._startRecord
= startRecord
;
36 _union
._data
._endRecord
= endRecord
;
39 File::File( File
* parent
, FILE* fptr
, int offset
)
43 _union
._stub
._fptr
= fptr
;
44 _union
._stub
._offset
= offset
;
49 while ( _children
.first() ) {
50 delete _children
.first();
51 _children
.removeFirst();
55 void File::read( int version
)
63 FILE* fptr
= _union
._stub
._fptr
;
65 fseek( fptr
, _union
._stub
._offset
, SEEK_SET
);
67 // File name (4 bytes + n chars).
69 fread( &ival
, sizeof( ival
), 1, fptr
);
71 char * buf
= new char[ival
+1];
73 fread( buf
, sizeof( char ), ival
, fptr
);
78 // File size (4 bytes).
79 fread( &ival
, sizeof( ival
), 1, fptr
);
80 _union
._data
._size
= ival
;
82 // File modification time (4 bytes).
83 fread( &ival
, sizeof( ival
), 1, fptr
);
84 _union
._data
._mtime
= ival
;
86 // Start record number.
87 fread( &ival
, sizeof( ival
), 1, fptr
);
88 _union
._data
._startRecord
= ival
;
91 fread( &ival
, sizeof( ival
), 1, fptr
);
92 _union
._data
._endRecord
= ival
;
94 //%%% This is a kludge to cope with some screwed up tape indexes.
95 //%%% Hopefully the file with the zero end record is *always* at
96 //%%% the end of the archive.
97 if ( ( _union
._data
._endRecord
<= 0 ) && ( _union
._data
._startRecord
!= _union
._data
._endRecord
) ) {
98 _union
._data
._endRecord
= MAXINT
;
102 fread( &ival
, sizeof( ival
), 1, fptr
);
106 for ( int ii
= 0; ii
< rc
; ii
++ ) {
107 fread( &ival
, sizeof( ival
), 1, fptr
);
109 fread( &ival
, sizeof( ival
), 1, fptr
);
111 _ranges
.addRange( start
, end
);
115 //===== Read files =====
116 fread( &ival
, sizeof( ival
), 1, fptr
);
117 for ( int count
= ival
; count
> 0; count
-- ) {
118 fread( &ival
, sizeof( ival
), 1, fptr
);
119 addChild( new File( this, fptr
, ival
) );
123 void File::readAll( int version
)
127 Q3PtrListIterator
<File
> i( getChildren() );
128 for ( ; i
.current(); ++i
) {
129 i
.current()->readAll( version
);
133 void File::write( FILE* fptr
)
137 // File name (4 bytes + n chars).
138 int ival
= getName().length();
139 fwrite( &ival
, sizeof( ival
), 1, fptr
);
140 fwrite( getName().ascii(), sizeof( char ), ival
, fptr
);
142 // File size (4 bytes).
144 fwrite( &ival
, sizeof( ival
), 1, fptr
);
146 // File modification time (4 bytes).
148 fwrite( &ival
, sizeof( ival
), 1, fptr
);
150 // Start record number.
151 ival
= getStartRecord();
152 fwrite( &ival
, sizeof( ival
), 1, fptr
);
154 // End record number.
155 ival
= getEndRecord();
156 fwrite( &ival
, sizeof( ival
), 1, fptr
);
159 ival
= _ranges
.getRanges().count();
160 fwrite( &ival
, sizeof( ival
), 1, fptr
);
161 Q3PtrListIterator
<Range
> it( _ranges
.getRanges() );
162 for ( ; it
.current(); ++it
) {
163 ival
= it
.current()->getStart();
164 fwrite( &ival
, sizeof( ival
), 1, fptr
);
165 ival
= it
.current()->getEnd();
166 fwrite( &ival
, sizeof( ival
), 1, fptr
);
169 // Number of immediate children (4 bytes).
170 ival
= getChildren().count();
171 fwrite( &ival
, sizeof( ival
), 1, fptr
);
173 // Fill in file offsets later...
174 int fileTable
= ftell( fptr
);
175 for ( ; ival
> 0; ival
-- ) {
176 fwrite( &zero
, sizeof( zero
), 1, fptr
);
179 //===== Write files =====
180 ival
= _children
.count();
181 fwrite( &ival
, sizeof( ival
), 1, fptr
);
183 Q3PtrListIterator
<File
> i( _children
);
185 for ( ; i
.current(); ++i
, count
++ ) {
186 // Fill in the file offset.
187 int here
= ftell( fptr
);
188 fseek( fptr
, fileTable
+ 4*count
, SEEK_SET
);
189 fwrite( &here
, sizeof( here
), 1, fptr
);
190 fseek( fptr
, here
, SEEK_SET
);
192 i
.current()->write( fptr
);
196 bool File::isDirectory()
200 return _name
[ _name
.length() - 1 ] == '/';
207 return _union
._data
._size
;
214 return _union
._data
._mtime
;
217 int File::getStartRecord()
221 return _union
._data
._startRecord
;
224 int File::getEndRecord()
228 return _union
._data
._endRecord
;
231 QString
File::getName()
238 QString
File::getFullPathName()
240 QString tmp
= _name
.copy();
241 for ( File
* parent
= getParent(); parent
; parent
= parent
->getParent() ) {
242 tmp
.prepend( parent
->getName() );
248 File
* File::getParent()
253 const Q3PtrList
<File
>& File::getChildren()
260 const Q3PtrList
<Range
>& File::getRanges()
264 return _ranges
.getRanges();
267 void File::addChild( File
* file
)
271 _children
.append( file
);
274 void File::calcRanges()
279 _ranges
.addRange( getStartRecord(), getEndRecord() );
281 Q3PtrListIterator
<File
> it( getChildren() );
282 for ( ; it
.current(); ++it
) {
283 it
.current()->calcRanges();
284 Q3PtrListIterator
<Range
> it2( it
.current()->getRanges() );
285 for ( ; it2
.current(); ++it2
) {
286 _ranges
.addRange( it2
.current()->getStart(), it2
.current()->getEnd() );