File indexing completed on 2024-06-16 07:42:25

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"