File indexing completed on 2025-03-16 04:29:29
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 #include <config-k3b.h> 0006 0007 #include "k3bclonetocreader.h" 0008 #include "k3bdeviceglobals.h" 0009 #include "k3bglobals.h" 0010 0011 #include <QDebug> 0012 #include <QFile> 0013 #include <QFileInfo> 0014 0015 0016 class K3b::CloneTocReader::Private 0017 { 0018 public: 0019 Private() 0020 : size(0) { 0021 } 0022 0023 K3b::Msf size; 0024 QString tocFile; 0025 }; 0026 0027 0028 0029 K3b::CloneTocReader::CloneTocReader( const QString& filename ) 0030 : K3b::ImageFileReader() 0031 { 0032 d = new Private; 0033 openFile( filename ); 0034 } 0035 0036 0037 K3b::CloneTocReader::~CloneTocReader() 0038 { 0039 delete d; 0040 } 0041 0042 0043 K3b::Msf K3b::CloneTocReader::imageSize() const 0044 { 0045 return d->size; 0046 } 0047 0048 0049 void K3b::CloneTocReader::readFile() 0050 { 0051 // first of all we check if we find the image file which contains the data for this toc 0052 // cdrecord always uses this strange file naming: 0053 // somedata 0054 // somedata.toc 0055 0056 // filename should always be the toc file 0057 if( filename().right( 4 ) == ".toc" ) 0058 d->tocFile = filename(); 0059 else 0060 d->tocFile = filename() + ".toc"; 0061 0062 // now get rid of the ".toc" extension 0063 QString imageFileName = d->tocFile.left( d->tocFile.length()-4 ); 0064 if( !QFile::exists( imageFileName ) ) { 0065 qDebug() << "(K3b::CloneTocReader) could not find image file " << imageFileName; 0066 return; 0067 } 0068 0069 setImageFilename( imageFileName ); 0070 0071 d->size = 0; 0072 0073 QFile f( d->tocFile ); 0074 if( f.open( QIODevice::ReadOnly ) ) { 0075 // 0076 // Inspired by clone.c from the cdrecord sources 0077 // 0078 char buffer[2048]; 0079 int read = f.read( buffer, 2048 ); 0080 f.close(); 0081 0082 if( read == 2048 ) { 0083 qDebug() << "(K3b::CloneTocReader) TOC too large."; 0084 return; 0085 } 0086 0087 // the toc starts with a tocheader 0088 struct tocheader { 0089 unsigned char len[2]; 0090 unsigned char first; // first session 0091 unsigned char last; // last session 0092 }; 0093 0094 struct tocheader* th = (struct tocheader*)buffer; 0095 int dataLen = K3b::Device::from2Byte( th->len ) + 2; // the len field does not include it's own length 0096 0097 if( th->first != 1 ) { 0098 qDebug() << "(K3b::CloneTocReader) first session != 1"; 0099 return; 0100 } 0101 0102 // the following bytes are multiple instances of 0103 struct ftrackdesc { 0104 unsigned char sess_number; 0105 #ifdef WORDS_BIGENDIAN // __BYTE_ORDER == __BIG_ENDIAN 0106 unsigned char adr : 4; 0107 unsigned char control : 4; 0108 #else 0109 unsigned char control : 4; 0110 unsigned char adr : 4; 0111 #endif 0112 unsigned char track; 0113 unsigned char point; 0114 unsigned char amin; 0115 unsigned char asec; 0116 unsigned char aframe; 0117 unsigned char res7; 0118 unsigned char pmin; 0119 unsigned char psec; 0120 unsigned char pframe; 0121 }; 0122 0123 for( int i = 4; i < dataLen; i += 11) { 0124 struct ftrackdesc* ft = (struct ftrackdesc*)&buffer[i]; 0125 0126 if( ft->sess_number != 1 ) { 0127 qDebug() << "(K3b::CloneTocReader} session number != 1"; 0128 return; 0129 } 0130 0131 // now we check some of the values 0132 if( ft->point >= 0x1 && ft->point <= 0x63 ) { 0133 if( ft->adr == 1 ) { 0134 // check track starttime 0135 if( ft->psec > 60 || ft->pframe > 75 ) { 0136 qDebug() << "(K3b::CloneTocReader) invalid track start: " 0137 << (int)ft->pmin << "." 0138 << (int)ft->psec << "." 0139 << (int)ft->pframe << Qt::endl; 0140 return; 0141 } 0142 } 0143 } 0144 else { 0145 switch( ft->point ) { 0146 case 0xa0: 0147 if( ft->adr != 1 ) { 0148 qDebug() << "(K3b::CloneTocReader) adr != 1"; 0149 return; 0150 } 0151 0152 // disk type in psec 0153 if( ft->psec != 0x00 && ft->psec != 0x10 && ft->psec != 0x20 ) { 0154 qDebug() << "(K3b::CloneTocReader) invalid disktype: " << ft->psec; 0155 return; 0156 } 0157 0158 if( ft->pmin != 1 ) { 0159 qDebug() << "(K3b::CloneTocReader) first track number != 1 "; 0160 return; 0161 } 0162 0163 if( ft->pframe != 0x0 ) { 0164 qDebug() << "(K3b::CloneTocReader) found data when there should be 0x0"; 0165 return; 0166 } 0167 break; 0168 0169 case 0xa1: 0170 if( ft->adr != 1 ) { 0171 qDebug() << "(K3b::CloneTocReader) adr != 1"; 0172 return; 0173 } 0174 0175 if( !(ft->pmin >= 1) ) { 0176 qDebug() << "(K3b::CloneTocReader) last track number needs to be >= 1."; 0177 return; 0178 } 0179 if( ft->psec != 0x0 || ft->pframe != 0x0 ) { 0180 qDebug() << "(K3b::CloneTocReader) found data when there should be 0x0"; 0181 return; 0182 } 0183 break; 0184 0185 case 0xa2: 0186 if( ft->adr != 1 ) { 0187 qDebug() << "(K3b::CloneTocReader) adr != 1"; 0188 return; 0189 } 0190 0191 // start of the leadout = size of the image 0192 // subtract 2 seconds since in cdrecord other than in K3b lba 0 = msf 2:00 0193 // (the cdrecord way is actually more accurate but we use k3b::Msf for many 0194 // things and it is simpler this way.) 0195 d->size = K3b::Msf( ft->pmin, ft->psec, ft->pframe ) - K3b::Msf( 0, 2, 0 ); 0196 0197 // leadout... no check so far... 0198 break; 0199 0200 default: 0201 if( ft->adr != 5 ) { 0202 qDebug() << "(K3b::CloneTocReader) adr != 5"; 0203 return; 0204 } 0205 break; 0206 } 0207 } 0208 } 0209 0210 if( d->size.rawBytes() != KIO::filesize_t(QFileInfo(imageFileName).size()) ) { 0211 qDebug() << "(K3b::CloneTocReader) image file size invalid."; 0212 return; 0213 } 0214 0215 // ok, could be a cdrecord toc file 0216 setValid(true); 0217 } 0218 else { 0219 qDebug() << "(K3b::CloneTocReader) could not open file " << d->tocFile; 0220 } 0221 }