File indexing completed on 2024-04-28 04:49:51
0001 /* 0002 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include <config-k3b.h> 0008 #include "k3bglobals.h" 0009 0010 #include "k3biso9660.h" 0011 #include "k3biso9660backend.h" 0012 0013 #include "k3bdevice.h" 0014 0015 #include "libisofs/isofs.h" 0016 0017 #include <QDebug> 0018 #include <QDir> 0019 #include <QFile> 0020 0021 0022 /* callback function for libisofs */ 0023 int K3b::Iso9660::read_callback( char* buf, sector_t start, int len, void* udata ) 0024 { 0025 K3b::Iso9660* isoF = static_cast<K3b::Iso9660*>(udata); 0026 0027 return isoF->read( start, buf, len ); 0028 } 0029 0030 /* callback function for libisofs */ 0031 int K3b::Iso9660::isofs_callback( struct iso_directory_record *idr, void *udata ) 0032 { 0033 K3b::Iso9660 *iso = static_cast<K3b::Iso9660*> (udata); 0034 QString path, isoPath,user,group,symlink; 0035 int i; 0036 int access; 0037 int time,cdate,adate; 0038 rr_entry rr; 0039 bool special=false; 0040 K3b::Iso9660Entry *entry=0; 0041 //K3b::Iso9660Entry *oldentry=0; 0042 char z_algo[2],z_params[2]; 0043 int z_size=0; 0044 0045 if (isonum_711(idr->name_len)==1) { 0046 switch (idr->name[0]) { 0047 case 0: 0048 path+=("."); 0049 special=true; 0050 break; 0051 case 1: 0052 path+=(".."); 0053 special=true; 0054 break; 0055 } 0056 } 0057 // 0058 // First extract the raw iso9660 name 0059 // 0060 if( !special ) { 0061 for( i = 0; i < isonum_711( idr->name_len ); ++i ) { 0062 if( idr->name[i] ) 0063 isoPath += idr->name[i]; 0064 } 0065 } 0066 else 0067 isoPath = path; 0068 0069 // 0070 // Now see if we have RockRidge 0071 // 0072 if( !iso->plainIso9660() && ParseRR(idr,&rr) > 0 ) { 0073 iso->m_rr = true; 0074 if (!special) 0075 path = QString::fromLocal8Bit( rr.name ); 0076 symlink=rr.sl; 0077 access=rr.mode; 0078 time=0;//rr.st_mtime; 0079 adate=0;//rr.st_atime; 0080 cdate=0;//rr.st_ctime; 0081 user.setNum(rr.uid); 0082 group.setNum(rr.gid); 0083 z_algo[0]=rr.z_algo[0];z_algo[1]=rr.z_algo[1]; 0084 z_params[0]=rr.z_params[0];z_params[1]=rr.z_params[1]; 0085 z_size=rr.z_size; 0086 } 0087 else { 0088 access=iso->dirent->permissions() & ~S_IFMT; 0089 adate=cdate=time=isodate_915(idr->date,0); 0090 user=iso->dirent->user(); 0091 group=iso->dirent->group(); 0092 if (idr->flags[0] & 2) access |= S_IFDIR; else access |= S_IFREG; 0093 if (!special) { 0094 if( !iso->plainIso9660() && iso->jolietLevel() ) { 0095 for (i=0;i<(isonum_711(idr->name_len)-1);i+=2) { 0096 QChar ch( be2me_16(*((ushort*)&(idr->name[i]))) ); 0097 if (ch==';') break; 0098 path+=ch; 0099 } 0100 } 0101 else { 0102 // no RR, no Joliet, just plain iso9660 0103 path = isoPath; 0104 0105 // remove the version field 0106 int pos = path.indexOf( ';' ); 0107 if( pos > 0 ) 0108 path.truncate( pos ); 0109 } 0110 if (path.endsWith('.')) path.truncate(path.length()-1); 0111 } 0112 } 0113 0114 if( !iso->plainIso9660() ) 0115 FreeRR(&rr); 0116 0117 if (idr->flags[0] & 2) { 0118 entry = new K3b::Iso9660Directory( iso, isoPath, path, access | S_IFDIR, time, adate, cdate, 0119 user, group, symlink, 0120 special ? 0 : isonum_733(idr->extent), 0121 special ? 0 : isonum_733(idr->size) ); 0122 } 0123 else { 0124 entry = new K3b::Iso9660File( iso, isoPath, path, access, time, adate, cdate, 0125 user, group, symlink, isonum_733(idr->extent), isonum_733(idr->size) ); 0126 if (z_size) 0127 (static_cast<K3b::Iso9660File*>(entry))->setZF( z_algo, z_params, z_size ); 0128 } 0129 iso->dirent->addEntry(entry); 0130 0131 return 0; 0132 } 0133 0134 0135 0136 K3b::Iso9660Entry::Iso9660Entry( K3b::Iso9660* archive, 0137 const QString& isoName, 0138 const QString& name, 0139 int access, 0140 int date, 0141 int adate, 0142 int cdate, 0143 const QString& user, 0144 const QString& group, 0145 const QString& symlink ) 0146 : m_adate( adate ), 0147 m_cdate( cdate ), 0148 m_name( name ), 0149 m_isoName( isoName ), 0150 m_date( date ), 0151 m_access( access ), 0152 m_user( user ), 0153 m_group( group ), 0154 m_symlink( symlink ), 0155 m_archive( archive ) 0156 { 0157 } 0158 0159 0160 K3b::Iso9660Entry::~Iso9660Entry() 0161 { 0162 } 0163 0164 0165 0166 0167 0168 0169 K3b::Iso9660File::Iso9660File( K3b::Iso9660* archive, 0170 const QString& isoName, 0171 const QString& name, 0172 int access, 0173 int date, 0174 int adate, 0175 int cdate, 0176 const QString& user, 0177 const QString& group, 0178 const QString& symlink, 0179 unsigned int pos, 0180 unsigned int size ) 0181 : K3b::Iso9660Entry( archive, isoName, name, access, date, adate, cdate, user, group, symlink ), 0182 m_startSector(pos), 0183 m_size(size) 0184 { 0185 m_algo[0] = 0; 0186 m_algo[1] = 0; 0187 m_parms[0] = 0; 0188 m_parms[1] = 0; 0189 m_realsize = 0; 0190 } 0191 0192 K3b::Iso9660File::~Iso9660File() 0193 { 0194 } 0195 0196 void K3b::Iso9660File::setZF(char algo[2],char parms[2],int realsize) 0197 { 0198 m_algo[0]=algo[0];m_algo[1]=algo[1]; 0199 m_parms[0]=parms[0];m_parms[1]=parms[1]; 0200 m_realsize=realsize; 0201 } 0202 0203 0204 int K3b::Iso9660File::read( unsigned int pos, char* data, int maxlen ) const 0205 { 0206 if( pos >= size() ) 0207 return 0; 0208 0209 unsigned long startSec = m_startSector + pos/2048; 0210 int startSecOffset = pos%2048; 0211 char* buffer = data; 0212 bool buffered = false; 0213 unsigned long bufferLen = maxlen+startSecOffset; 0214 0215 // cut to size 0216 if( pos + maxlen > size() ) 0217 bufferLen = size() - pos + startSecOffset; 0218 0219 // pad to 2048 0220 if( bufferLen%2048 ) 0221 bufferLen += (2048-(bufferLen%2048)); 0222 0223 // we need to buffer if we changed the startSec or need a bigger buffer 0224 if( startSecOffset || bufferLen > (unsigned int)maxlen ) { 0225 buffered = true; 0226 buffer = new char[bufferLen]; 0227 } 0228 0229 int read = archive()->read( startSec, buffer, bufferLen/2048 )*2048; 0230 0231 if( buffered ) { 0232 if( read > 0 ) { 0233 // cut to requested data 0234 read -= startSecOffset; 0235 if( read + pos > size() ) 0236 read = size() - pos; 0237 if( read > maxlen ) 0238 read = maxlen; 0239 0240 ::memcpy( data, buffer+startSecOffset, read ); 0241 } 0242 delete [] buffer; 0243 0244 return read; 0245 } 0246 else { 0247 // cut read data 0248 if( read + pos > size() ) 0249 read = size() - pos; 0250 0251 return read; 0252 } 0253 } 0254 0255 0256 bool K3b::Iso9660File::copyTo( const QString& url ) const 0257 { 0258 QFile of( url ); 0259 if( of.open( QIODevice::WriteOnly ) ) { 0260 char buffer[2048*10]; 0261 unsigned int pos = 0; 0262 int r = 0; 0263 while( ( r = read( pos, buffer, 2048*10 ) ) > 0 ) { 0264 of.write( buffer, r ); 0265 pos += r; 0266 } 0267 0268 return !r; 0269 } 0270 else { 0271 qDebug() << "(K3b::Iso9660File) could not open " << url << " for writing."; 0272 return false; 0273 } 0274 } 0275 0276 0277 K3b::Iso9660Directory::Iso9660Directory( K3b::Iso9660* archive, 0278 const QString& isoName, 0279 const QString& name, 0280 int access, 0281 int date, 0282 int adate, 0283 int cdate, 0284 const QString& user, 0285 const QString& group, 0286 const QString& symlink, 0287 unsigned int pos, 0288 unsigned int size ) 0289 : K3b::Iso9660Entry( archive, isoName, name, access, date, adate, cdate, user, group, symlink ), 0290 m_bExpanded( size == 0 ), // we can only expand entries that represent an actual directory 0291 m_startSector(pos), 0292 m_size(size) 0293 { 0294 } 0295 0296 K3b::Iso9660Directory::~Iso9660Directory() 0297 { 0298 qDeleteAll( m_entries ); 0299 } 0300 0301 0302 void K3b::Iso9660Directory::expand() 0303 { 0304 if( !m_bExpanded ) { 0305 archive()->dirent = this; 0306 if( ProcessDir( &K3b::Iso9660::read_callback, m_startSector, m_size, &K3b::Iso9660::isofs_callback, archive() ) ) 0307 qDebug() << "(K3b::Iso9660) failed to expand dir: " << name() << " with size: " << m_size; 0308 0309 m_bExpanded = true; 0310 } 0311 } 0312 0313 0314 QStringList K3b::Iso9660Directory::entries() const 0315 { 0316 // create a fake const method to fool the user ;) 0317 const_cast<K3b::Iso9660Directory*>(this)->expand(); 0318 0319 QStringList l; 0320 0321 QHashIterator<QString, K3b::Iso9660Entry*> it( m_entries ); 0322 while ( it.hasNext() ) { 0323 it.next(); 0324 l.append( it.key() ); 0325 } 0326 0327 return l; 0328 } 0329 0330 0331 QStringList K3b::Iso9660Directory::iso9660Entries() const 0332 { 0333 // create a fake const method to fool the user ;) 0334 const_cast<K3b::Iso9660Directory*>(this)->expand(); 0335 0336 QStringList l; 0337 0338 QHashIterator<QString, K3b::Iso9660Entry*> it( m_iso9660Entries ); 0339 while ( it.hasNext() ) { 0340 it.next(); 0341 l.append( it.key() ); 0342 } 0343 0344 return l; 0345 } 0346 0347 0348 K3b::Iso9660Entry* K3b::Iso9660Directory::entry( const QString& n ) 0349 { 0350 if( n.isEmpty() ) 0351 return 0; 0352 0353 expand(); 0354 0355 QString name(n); 0356 0357 // trailing slash ? -> remove 0358 if( name.length() > 1 && name[name.length()-1] == '/' ) { 0359 name.truncate( name.length()-1 ); 0360 } 0361 0362 int pos = name.indexOf( '/' ); 0363 while( pos == 0 ) { 0364 if( name.length() > 1 ) { 0365 name = name.mid( 1 ); // remove leading slash 0366 pos = name.indexOf( '/' ); // look again 0367 } 0368 else // "/" 0369 return this; 0370 } 0371 0372 if ( pos != -1 ) { 0373 QString left = name.left( pos ); 0374 QString right = name.mid( pos + 1 ); 0375 0376 K3b::Iso9660Entry* e = m_entries[ left ]; 0377 if ( !e || !e->isDirectory() ) 0378 return 0; 0379 return static_cast<K3b::Iso9660Directory*>(e)->entry( right ); 0380 } 0381 0382 return m_entries[ name ]; 0383 } 0384 0385 0386 K3b::Iso9660Entry* K3b::Iso9660Directory::iso9660Entry( const QString& n ) 0387 { 0388 if( n.isEmpty() ) 0389 return 0; 0390 0391 expand(); 0392 0393 QString name(n); 0394 0395 // trailing slash ? -> remove 0396 if( name.length() > 1 && name[name.length()-1] == '/' ) { 0397 name.truncate( name.length()-1 ); 0398 } 0399 0400 int pos = name.indexOf( '/' ); 0401 while( pos == 0 ) { 0402 if( name.length() > 1 ) { 0403 name = name.mid( 1 ); // remove leading slash 0404 pos = name.indexOf( '/' ); // look again 0405 } 0406 else // "/" 0407 return this; 0408 } 0409 0410 if ( pos != -1 ) { 0411 QString left = name.left( pos ); 0412 QString right = name.mid( pos + 1 ); 0413 0414 K3b::Iso9660Entry* e = m_iso9660Entries[ left ]; 0415 if ( !e || !e->isDirectory() ) 0416 return 0; 0417 return static_cast<K3b::Iso9660Directory*>(e)->iso9660Entry( right ); 0418 } 0419 0420 return m_iso9660Entries[ name ]; 0421 } 0422 0423 0424 const K3b::Iso9660Entry* K3b::Iso9660Directory::entry( const QString& name ) const 0425 { 0426 return const_cast<K3b::Iso9660Directory*>(this)->entry( name ); 0427 } 0428 0429 0430 const K3b::Iso9660Entry* K3b::Iso9660Directory::iso9660Entry( const QString& name ) const 0431 { 0432 return const_cast<K3b::Iso9660Directory*>(this)->iso9660Entry( name ); 0433 } 0434 0435 0436 void K3b::Iso9660Directory::addEntry( K3b::Iso9660Entry* entry ) 0437 { 0438 m_entries.insert( entry->name(), entry ); 0439 m_iso9660Entries.insert( entry->isoName(), entry ); 0440 } 0441 0442 0443 0444 0445 0446 class K3b::Iso9660::Private 0447 { 0448 public: 0449 Private() 0450 : cdDevice(0), 0451 fd(-1), 0452 isOpen(false), 0453 startSector(0), 0454 plainIso9660(false), 0455 backend(0) { 0456 } 0457 0458 QList<K3b::Iso9660Directory*> elToritoDirs; 0459 QList<K3b::Iso9660Directory*> jolietDirs; 0460 QList<K3b::Iso9660Directory*> isoDirs; 0461 QList<K3b::Iso9660Directory*> rrDirs; // RockRidge 0462 0463 K3b::Iso9660SimplePrimaryDescriptor primaryDesc; 0464 0465 K3b::Device::Device* cdDevice; 0466 int fd; 0467 0468 bool isOpen; 0469 0470 // only used for direkt K3b::Device::Device access 0471 unsigned int startSector; 0472 0473 bool plainIso9660; 0474 0475 K3b::Iso9660Backend* backend; 0476 }; 0477 0478 0479 K3b::Iso9660::Iso9660( const QString& filename ) 0480 : m_filename( filename ) 0481 { 0482 d = new Private(); 0483 } 0484 0485 0486 K3b::Iso9660::Iso9660( int fd ) 0487 { 0488 d = new Private(); 0489 d->fd = fd; 0490 } 0491 0492 0493 K3b::Iso9660::Iso9660( K3b::Iso9660Backend* backend ) 0494 { 0495 d = new Private(); 0496 d->backend = backend; 0497 } 0498 0499 0500 K3b::Iso9660::Iso9660( K3b::Device::Device* dev, unsigned int startSector ) 0501 { 0502 d = new Private(); 0503 d->cdDevice = dev; 0504 d->startSector = startSector; 0505 } 0506 0507 0508 K3b::Iso9660::~Iso9660() 0509 { 0510 close(); 0511 delete d->backend; 0512 delete d; 0513 } 0514 0515 0516 void K3b::Iso9660::setStartSector( unsigned int startSector ) 0517 { 0518 d->startSector = startSector; 0519 } 0520 0521 0522 void K3b::Iso9660::setPlainIso9660( bool b ) 0523 { 0524 d->plainIso9660 = b; 0525 } 0526 0527 0528 bool K3b::Iso9660::plainIso9660() const 0529 { 0530 return d->plainIso9660; 0531 } 0532 0533 0534 int K3b::Iso9660::read( unsigned int sector, char* data, int count ) 0535 { 0536 if( count == 0 ) 0537 return 0; 0538 else 0539 return d->backend->read( sector, data, count ); 0540 } 0541 0542 0543 void K3b::Iso9660::addBoot(struct el_torito_boot_descriptor* bootdesc) 0544 { 0545 int i,size; 0546 boot_head boot; 0547 boot_entry *be; 0548 QString path; 0549 K3b::Iso9660File *entry; 0550 0551 entry=new K3b::Iso9660File( this, "Catalog", "Catalog", dirent->permissions() & ~S_IFDIR, 0552 dirent->date(), dirent->adate(), dirent->cdate(), 0553 dirent->user(), dirent->group(), QString(), 0554 isonum_731(bootdesc->boot_catalog), 2048 ); 0555 dirent->addEntry(entry); 0556 if (!ReadBootTable(&K3b::Iso9660::read_callback,isonum_731(bootdesc->boot_catalog),&boot,this)) { 0557 i=1; 0558 be=boot.defentry; 0559 while (be) { 0560 size=BootImageSize(&K3b::Iso9660::read_callback, 0561 isonum_711(((struct default_entry*) be->data)->media), 0562 isonum_731(((struct default_entry*) be->data)->start), 0563 isonum_721(((struct default_entry*) be->data)->seccount), 0564 this); 0565 path="Default Image"; 0566 if (i>1) path += " (" + QString::number(i) + ')'; 0567 entry=new K3b::Iso9660File( this, path, path, dirent->permissions() & ~S_IFDIR, 0568 dirent->date(), dirent->adate(), dirent->cdate(), 0569 dirent->user(), dirent->group(), QString(), 0570 isonum_731(((struct default_entry*) be->data)->start), size<<9 ); 0571 dirent->addEntry(entry); 0572 be=be->next; 0573 i++; 0574 } 0575 0576 FreeBootTable(&boot); 0577 } 0578 } 0579 0580 0581 bool K3b::Iso9660::open() 0582 { 0583 if( d->isOpen ) 0584 return true; 0585 0586 if( !d->backend ) { 0587 // create a backend 0588 0589 if( !m_filename.isEmpty() ) 0590 d->backend = new K3b::Iso9660FileBackend( m_filename ); 0591 0592 else if( d->fd > 0 ) 0593 d->backend = new K3b::Iso9660FileBackend( d->fd ); 0594 0595 else if( d->cdDevice ) { 0596 // now check if we have a scrambled video dvd 0597 if( d->cdDevice->copyrightProtectionSystemType() == K3b::Device::COPYRIGHT_PROTECTION_CSS ) { 0598 0599 qDebug() << "(K3b::Iso9660) found encrypted dvd. using libdvdcss."; 0600 0601 // open the libdvdcss stuff 0602 d->backend = new K3b::Iso9660LibDvdCssBackend( d->cdDevice ); 0603 if( !d->backend->open() ) { 0604 // fallback to devicebackend 0605 delete d->backend; 0606 d->backend = new K3b::Iso9660DeviceBackend( d->cdDevice ); 0607 } 0608 } 0609 else 0610 d->backend = new K3b::Iso9660DeviceBackend( d->cdDevice ); 0611 } 0612 else 0613 return false; 0614 } 0615 0616 d->isOpen = d->backend->open(); 0617 if( !d->isOpen ) 0618 return false; 0619 0620 iso_vol_desc *desc; 0621 QString path,tmp,uid,gid; 0622 k3b_struct_stat buf; 0623 int access,c_i,c_j; 0624 struct el_torito_boot_descriptor* bootdesc; 0625 0626 // TODO implement win32 support 0627 0628 /* We'll use the permission and user/group of the 'host' file except 0629 * in Rock Ridge, where the permissions are stored on the file system 0630 */ 0631 if ( k3b_stat( QFile::encodeName(m_filename), &buf ) < 0 ) { 0632 /* defaults, if stat fails */ 0633 memset(&buf,0,sizeof(k3b_struct_stat)); 0634 buf.st_mode=0777; 0635 } 0636 uid.setNum(buf.st_uid); 0637 gid.setNum(buf.st_gid); 0638 access = buf.st_mode & ~S_IFMT; 0639 0640 0641 int c_b=1; 0642 c_i=1;c_j=1; 0643 0644 desc = ReadISO9660( &K3b::Iso9660::read_callback, d->startSector, this ); 0645 0646 if (!desc) { 0647 qDebug() << "K3b::Iso9660::openArchive no volume descriptors"; 0648 close(); 0649 return false; 0650 } 0651 0652 while (desc) { 0653 0654 m_rr = false; 0655 0656 switch (isonum_711(desc->data.type)) { 0657 case ISO_VD_BOOT: 0658 0659 bootdesc=(struct el_torito_boot_descriptor*) &(desc->data); 0660 if( !memcmp( EL_TORITO_ID, bootdesc->system_id, ISODCL(8,39) ) ) { 0661 path="El Torito Boot"; 0662 if( c_b > 1 ) 0663 path += " (" + QString::number(c_b) + ')'; 0664 0665 dirent = new K3b::Iso9660Directory( this, path, path, access | S_IFDIR, 0666 buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString() ); 0667 d->elToritoDirs.append( dirent ); 0668 0669 addBoot(bootdesc); 0670 c_b++; 0671 } 0672 break; 0673 0674 case ISO_VD_PRIMARY: 0675 createSimplePrimaryDesc( (struct iso_primary_descriptor*)&desc->data ); 0676 // fall through 0677 case ISO_VD_SUPPLEMENTARY: 0678 { 0679 struct iso_primary_descriptor* primaryDesc = (struct iso_primary_descriptor*)&desc->data; 0680 struct iso_directory_record* idr = (struct iso_directory_record*)&primaryDesc->root_directory_record; 0681 0682 m_joliet = JolietLevel(&desc->data); 0683 0684 // skip joliet in plain iso mode 0685 if( m_joliet && plainIso9660() ) 0686 break; 0687 0688 if (m_joliet) { 0689 path = "Joliet level " + QString::number(m_joliet); 0690 if( c_j > 1 ) 0691 path += " (" + QString::number(c_j) + ')'; 0692 } 0693 else { 0694 path = QString::fromLocal8Bit( primaryDesc->volume_id, 32 ); 0695 if( c_i > 1 ) 0696 path += " (" + QString::number(c_i) + ')'; 0697 } 0698 0699 dirent = new K3b::Iso9660Directory( this, path, path, access | S_IFDIR, 0700 buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString() ); 0701 0702 // expand the root entry 0703 ProcessDir( &K3b::Iso9660::read_callback, isonum_733(idr->extent),isonum_733(idr->size),&K3b::Iso9660::isofs_callback,this); 0704 0705 if (m_joliet) 0706 c_j++; 0707 else 0708 c_i++; 0709 0710 if( m_joliet ) 0711 d->jolietDirs.append( dirent ); 0712 else { 0713 if( m_rr ) 0714 d->rrDirs.append( dirent ); 0715 d->isoDirs.append( dirent ); 0716 } 0717 0718 break; 0719 } 0720 } 0721 desc = desc->next; 0722 } 0723 0724 FreeISO9660(desc); 0725 0726 return true; 0727 } 0728 0729 0730 bool K3b::Iso9660::isOpen() const 0731 { 0732 return d->isOpen; 0733 } 0734 0735 0736 void K3b::Iso9660::createSimplePrimaryDesc( struct iso_primary_descriptor* desc ) 0737 { 0738 d->primaryDesc.volumeId = QString::fromLocal8Bit( desc->volume_id, 32 ).trimmed(); 0739 d->primaryDesc.systemId = QString::fromLocal8Bit( desc->system_id, 32 ).trimmed(); 0740 d->primaryDesc.volumeSetId = QString::fromLocal8Bit( desc->volume_set_id, 128 ).trimmed(); 0741 d->primaryDesc.publisherId = QString::fromLocal8Bit( desc->publisher_id, 128 ).trimmed(); 0742 d->primaryDesc.preparerId = QString::fromLocal8Bit( desc->preparer_id, 128 ).trimmed(); 0743 d->primaryDesc.applicationId = QString::fromLocal8Bit( desc->application_id, 128 ).trimmed(); 0744 d->primaryDesc.volumeSetSize = isonum_723(desc->volume_set_size); 0745 d->primaryDesc.volumeSetNumber = isonum_723(desc->volume_set_size); 0746 d->primaryDesc.logicalBlockSize = isonum_723(desc->logical_block_size); 0747 d->primaryDesc.volumeSpaceSize = isonum_733(desc->volume_space_size); 0748 } 0749 0750 0751 void K3b::Iso9660::close() 0752 { 0753 if( d->isOpen ) { 0754 d->backend->close(); 0755 0756 // Since the first isoDir is the KArchive 0757 // root we must not delete it but all the 0758 // others. 0759 0760 qDeleteAll( d->elToritoDirs ); 0761 qDeleteAll( d->jolietDirs ); 0762 qDeleteAll( d->isoDirs ); 0763 d->elToritoDirs.clear(); 0764 d->jolietDirs.clear(); 0765 d->isoDirs.clear(); 0766 0767 d->isOpen = false; 0768 } 0769 } 0770 0771 0772 const K3b::Iso9660Directory* K3b::Iso9660::firstJolietDirEntry() const 0773 { 0774 if ( !d->jolietDirs.isEmpty() ) 0775 return d->jolietDirs.first(); 0776 else 0777 return 0; 0778 } 0779 0780 0781 const K3b::Iso9660Directory* K3b::Iso9660::firstIsoDirEntry() const 0782 { 0783 if ( !d->isoDirs.isEmpty() ) 0784 return d->isoDirs.first(); 0785 else 0786 return 0; 0787 } 0788 0789 0790 const K3b::Iso9660Directory* K3b::Iso9660::firstElToritoEntry() const 0791 { 0792 if ( !d->elToritoDirs.isEmpty() ) 0793 return d->elToritoDirs.first(); 0794 else 0795 return 0; 0796 } 0797 0798 0799 const K3b::Iso9660Directory* K3b::Iso9660::firstRRDirEntry() const 0800 { 0801 if ( !d->rrDirs.isEmpty() ) 0802 return d->rrDirs.first(); 0803 else 0804 return 0; 0805 } 0806 0807 0808 const K3b::Iso9660SimplePrimaryDescriptor& K3b::Iso9660::primaryDescriptor() const 0809 { 0810 return d->primaryDesc; 0811 } 0812 0813 0814 void K3b::Iso9660::debug() const 0815 { 0816 if( isOpen() ) { 0817 qDebug() << "System Id: " << primaryDescriptor().systemId; 0818 qDebug() << "Volume Id: " << primaryDescriptor().volumeId; 0819 qDebug() << "Volume Set Id: " << primaryDescriptor().volumeSetId; 0820 qDebug() << "Preparer Id: " << primaryDescriptor().preparerId; 0821 qDebug() << "Publisher Id: " << primaryDescriptor().publisherId; 0822 qDebug() << "Application Id: " << primaryDescriptor().applicationId; 0823 qDebug() << "Volume Set Size: " << primaryDescriptor().volumeSetSize; 0824 qDebug() << "Volume Set Number: " << primaryDescriptor().volumeSetNumber; 0825 0826 if( firstIsoDirEntry() ) { 0827 qDebug() << "First ISO Dir entry:"; 0828 qDebug() << "----------------------------------------------"; 0829 debugEntry( firstIsoDirEntry(), 0 ); 0830 qDebug() << "----------------------------------------------"; 0831 } 0832 if( firstRRDirEntry() ) { 0833 qDebug() << "First RR Dir entry:"; 0834 qDebug() << "----------------------------------------------"; 0835 debugEntry( firstRRDirEntry(), 0 ); 0836 qDebug() << "----------------------------------------------"; 0837 } 0838 if( firstJolietDirEntry() ) { 0839 qDebug() << "First Joliet Dir entry:"; 0840 qDebug() << "----------------------------------------------"; 0841 debugEntry( firstJolietDirEntry(), 0 ); 0842 qDebug() << "----------------------------------------------"; 0843 } 0844 } 0845 } 0846 0847 0848 void K3b::Iso9660::debugEntry( const K3b::Iso9660Entry* entry, int depth ) const 0849 { 0850 if( !entry ) { 0851 qDebug() << "(K3b::Iso9660::debugEntry) null entry."; 0852 return; 0853 } 0854 0855 QString spacer; 0856 spacer.fill( ' ', depth*3 ); 0857 qDebug() << spacer << "- " << entry->name() << " (" << entry->isoName() << ")"; 0858 if( entry->isDirectory() ) { 0859 const K3b::Iso9660Directory* dir = dynamic_cast<const K3b::Iso9660Directory*>(entry); 0860 const QStringList entries = dir->entries(); 0861 for( QStringList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it ) { 0862 debugEntry( dir->entry( *it ), depth+1 ); 0863 } 0864 } 0865 } 0866 0867 0868 K3b::Iso9660SimplePrimaryDescriptor::Iso9660SimplePrimaryDescriptor() 0869 : volumeSetSize(0), 0870 volumeSetNumber(0), 0871 logicalBlockSize(0), 0872 volumeSpaceSize(0) 0873 { 0874 } 0875 0876 0877 bool K3b::operator==( const K3b::Iso9660SimplePrimaryDescriptor& d1, 0878 const K3b::Iso9660SimplePrimaryDescriptor& d2 ) 0879 { 0880 return( d1.volumeId == d2.volumeId && 0881 d1.systemId == d2.systemId && 0882 d1.volumeSetId == d2.volumeSetId && 0883 d1.publisherId == d2.publisherId && 0884 d1.preparerId == d2.preparerId && 0885 d1.applicationId == d2.applicationId && 0886 d1.volumeSetSize == d2.volumeSetSize && 0887 d1.volumeSetNumber == d2.volumeSetNumber && 0888 d1.logicalBlockSize == d2.logicalBlockSize && 0889 d1.volumeSpaceSize == d2.volumeSpaceSize ); 0890 } 0891 0892 0893 bool K3b::operator!=( const K3b::Iso9660SimplePrimaryDescriptor& d1, 0894 const K3b::Iso9660SimplePrimaryDescriptor& d2 ) 0895 { 0896 return( d1.volumeId != d2.volumeId || 0897 d1.systemId != d2.systemId || 0898 d1.volumeSetId != d2.volumeSetId || 0899 d1.publisherId != d2.publisherId || 0900 d1.preparerId != d2.preparerId || 0901 d1.applicationId != d2.applicationId || 0902 d1.volumeSetSize != d2.volumeSetSize || 0903 d1.volumeSetNumber != d2.volumeSetNumber || 0904 d1.logicalBlockSize != d2.logicalBlockSize || 0905 d1.volumeSpaceSize != d2.volumeSpaceSize ); 0906 }