File indexing completed on 2024-04-28 04:49:51
0001 /* 0002 SPDX-FileCopyrightText: 2006-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "k3bfilesplitter.h" 0009 #include "k3bfilesysteminfo.h" 0010 0011 #include <QDebug> 0012 #include <QFile> 0013 #include <QFileInfo> 0014 0015 0016 class K3b::FileSplitter::Private 0017 { 0018 public: 0019 Private( K3b::FileSplitter* splitter ) 0020 : m_splitter( splitter ) { 0021 } 0022 0023 QString filename; 0024 QFile file; 0025 int counter; 0026 0027 qint64 maxFileSize; 0028 0029 qint64 size; 0030 qint64 currentOverallPos; 0031 qint64 currentFilePos; 0032 0033 void determineMaxFileSize() { 0034 if( maxFileSize == 0 ) { 0035 if( K3b::FileSystemInfo( filename ).type() == K3b::FileSystemInfo::FS_FAT ) 0036 maxFileSize = 1024ULL*1024ULL*1024ULL; // 1GB 0037 else 0038 maxFileSize = 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL; // incredibly big, 1024 TB 0039 } 0040 } 0041 0042 QString buildFileName( int counter ) { 0043 if( counter > 0 ) 0044 return filename + '.' + QString::number(counter).rightJustified( 3, '0' ); 0045 else 0046 return filename; 0047 } 0048 0049 qint64 partFileSize( int counter ) { 0050 QFileInfo fi( buildFileName( counter ) ); 0051 if ( fi.exists() ) 0052 return fi.size(); 0053 else 0054 return 0; 0055 } 0056 0057 QString currentFileName() { 0058 return buildFileName( counter ); 0059 } 0060 0061 bool openPrevFile() { 0062 return openFile( --counter ); 0063 } 0064 0065 bool openNextFile() { 0066 return openFile( ++counter ); 0067 } 0068 0069 bool openFile( int counter ) { 0070 file.close(); 0071 file.setFileName( buildFileName( counter ) ); 0072 currentFilePos = 0; 0073 if( file.open( m_splitter->openMode() ) ) { 0074 return true; 0075 } 0076 else { 0077 m_splitter->close(); 0078 return false; 0079 } 0080 } 0081 0082 private: 0083 K3b::FileSplitter* m_splitter; 0084 }; 0085 0086 0087 K3b::FileSplitter::FileSplitter() 0088 { 0089 d = new Private( this ); 0090 } 0091 0092 0093 K3b::FileSplitter::FileSplitter( const QString& filename ) 0094 { 0095 d = new Private( this ); 0096 setName( filename ); 0097 } 0098 0099 0100 K3b::FileSplitter::~FileSplitter() 0101 { 0102 delete d; 0103 } 0104 0105 0106 QString K3b::FileSplitter::name() const 0107 { 0108 return d->filename; 0109 } 0110 0111 0112 void K3b::FileSplitter::setName( const QString& filename ) 0113 { 0114 close(); 0115 d->maxFileSize = 0; 0116 d->filename = filename; 0117 } 0118 0119 0120 bool K3b::FileSplitter::open( OpenMode mode ) 0121 { 0122 qDebug() << mode; 0123 close(); 0124 0125 d->determineMaxFileSize(); 0126 0127 d->counter = 0; 0128 d->currentFilePos = 0; 0129 d->currentOverallPos = 0; 0130 d->size = 0; 0131 if ( QIODevice::open( mode ) ) { 0132 return d->openFile( 0 ); 0133 } 0134 else { 0135 return false; 0136 } 0137 } 0138 0139 0140 void K3b::FileSplitter::close() 0141 { 0142 QIODevice::close(); 0143 d->file.close(); 0144 d->counter = 0; 0145 d->currentFilePos = 0; 0146 d->currentOverallPos = 0; 0147 } 0148 0149 0150 void K3b::FileSplitter::flush() 0151 { 0152 d->file.flush(); 0153 } 0154 0155 0156 qint64 K3b::FileSplitter::size() const 0157 { 0158 if ( d->size == 0 ) { 0159 int i = 0; 0160 forever { 0161 qint64 s = d->partFileSize( i++ ); 0162 d->size += s; 0163 if ( s == 0 ) 0164 break; 0165 } 0166 } 0167 0168 return d->size; 0169 } 0170 0171 0172 qint64 K3b::FileSplitter::pos() const 0173 { 0174 return d->currentOverallPos; 0175 } 0176 0177 0178 bool K3b::FileSplitter::seek( qint64 pos ) 0179 { 0180 qDebug() << pos; 0181 // FIXME: implement me (although not used yet) 0182 return QIODevice::seek( pos ); 0183 } 0184 0185 0186 bool K3b::FileSplitter::atEnd() const 0187 { 0188 return d->file.atEnd() && !QFile::exists( d->buildFileName( d->counter+1 ) ); 0189 } 0190 0191 0192 qint64 K3b::FileSplitter::readData( char *data, qint64 maxlen ) 0193 { 0194 qint64 r = d->file.read( data, maxlen ); 0195 if( r == 0 ) { 0196 if( atEnd() ) { 0197 return r; 0198 } 0199 else if( d->openNextFile() ) { 0200 // recursively call us 0201 return readData( data, maxlen ); 0202 } 0203 } 0204 else if( r > 0 ) { 0205 d->currentOverallPos += r; 0206 d->currentFilePos += r; 0207 } 0208 else { 0209 qDebug() << "Read failed from" << d->file.fileName(); 0210 setErrorString( d->file.errorString() ); 0211 } 0212 return r; 0213 } 0214 0215 0216 qint64 K3b::FileSplitter::writeData( const char *data, qint64 len ) 0217 { 0218 qint64 max = qMin( len, d->maxFileSize - d->currentFilePos ); 0219 0220 qint64 r = d->file.write( data, max ); 0221 0222 if( r < 0 ) { 0223 setErrorString( d->file.errorString() ); 0224 return r; 0225 } 0226 0227 d->currentOverallPos += r; 0228 d->currentFilePos += r; 0229 0230 // recursively call us 0231 if( r < len ) { 0232 if( d->openNextFile() ) 0233 return r + writeData( data+r, len-r ); 0234 else 0235 return -1; 0236 } 0237 else 0238 return r; 0239 } 0240 0241 0242 // int K3b::FileSplitter::getch() 0243 // { 0244 // int r = d->file.getch(); 0245 // if( r == -1 ) { 0246 // if( !d->file.atEnd() ) { 0247 // return -1; 0248 // } 0249 // else if( !atEnd() ) { 0250 // if( !d->openNextFile() ) 0251 // return -1; 0252 // else 0253 // return getch(); 0254 // } 0255 // } 0256 0257 // d->currentOverallPos++; 0258 // d->currentFilePos++; 0259 0260 // return r; 0261 // } 0262 0263 0264 // int K3b::FileSplitter::putch( int c ) 0265 // { 0266 // if( d->currentFilePos < d->maxFileSize ) { 0267 // d->currentOverallPos++; 0268 // d->currentFilePos++; 0269 // return d->file.putch( c ); 0270 // } 0271 // else if( d->openNextFile() ) { 0272 // // recursively call us 0273 // return putch( c ); 0274 // } 0275 // else 0276 // return -1; 0277 // } 0278 0279 0280 // int K3b::FileSplitter::ungetch( int c ) 0281 // { 0282 // if( d->currentFilePos > 0 ) { 0283 // int r = d->file.ungetch( c ); 0284 // if( r != -1 ) { 0285 // d->currentOverallPos--; 0286 // d->currentFilePos--; 0287 // } 0288 // return r; 0289 // } 0290 // else if( d->counter > 0 ) { 0291 // // open prev file 0292 // if( d->openPrevFile() ) { 0293 // // seek to the end 0294 // d->file.at( d->file.size() ); 0295 // d->currentFilePos = d->file.at(); 0296 // return getch(); 0297 // } 0298 // else 0299 // return -1; 0300 // } 0301 // else 0302 // return -1; 0303 // } 0304 0305 0306 void K3b::FileSplitter::remove() 0307 { 0308 close(); 0309 int i = 0; 0310 while( QFile::exists( d->buildFileName( i ) ) ) 0311 QFile::remove( d->buildFileName( i++ ) ); 0312 } 0313 0314 0315 void K3b::FileSplitter::setMaxFileSize( qint64 size ) 0316 { 0317 d->maxFileSize = size; 0318 } 0319 0320 0321 bool K3b::FileSplitter::waitForBytesWritten( int ) 0322 { 0323 if ( isOpen() && isWritable() ) { 0324 return true; 0325 } 0326 else { 0327 return false; 0328 } 0329 } 0330 0331 0332 bool K3b::FileSplitter::waitForReadyRead( int ) 0333 { 0334 if ( isOpen() && isReadable() ) { 0335 return !atEnd(); 0336 } 0337 else { 0338 return false; 0339 } 0340 } 0341 0342 #include "moc_k3bfilesplitter.cpp"