File indexing completed on 2024-04-28 04:49:51
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #ifndef _K3B_ISO9660_H_ 0007 #define _K3B_ISO9660_H_ 0008 0009 #include "k3b_export.h" 0010 0011 #include <QDateTime> 0012 #include <QHash> 0013 #include <QString> 0014 #include <QStringList> 0015 0016 #include <sys/stat.h> 0017 #include <sys/types.h> 0018 0019 0020 struct iso_directory_record; 0021 struct el_torito_boot_descriptor; 0022 struct iso_primary_descriptor; 0023 typedef long sector_t; 0024 0025 namespace K3b { 0026 namespace Device { 0027 class Device; 0028 } 0029 0030 class Iso9660; 0031 class Iso9660Backend; 0032 0033 0034 /** 0035 * Simplified primary descriptor which just contains the fields 0036 * used by K3b. 0037 */ 0038 class LIBK3B_EXPORT Iso9660SimplePrimaryDescriptor 0039 { 0040 public: 0041 /** 0042 * Creates an empty descriptor 0043 */ 0044 Iso9660SimplePrimaryDescriptor(); 0045 0046 QString volumeId; 0047 QString systemId; 0048 QString volumeSetId; 0049 QString publisherId; 0050 QString preparerId; 0051 QString applicationId; 0052 int volumeSetSize; 0053 int volumeSetNumber; 0054 long logicalBlockSize; 0055 long long volumeSpaceSize; 0056 }; 0057 0058 0059 LIBK3B_EXPORT bool operator==( const Iso9660SimplePrimaryDescriptor& d1, 0060 const Iso9660SimplePrimaryDescriptor& d2 ); 0061 LIBK3B_EXPORT bool operator!=( const Iso9660SimplePrimaryDescriptor& d1, 0062 const Iso9660SimplePrimaryDescriptor& d2 ); 0063 0064 0065 /** 0066 * Base class for all entries in a Iso9660 archive. A lot has been copied 0067 * from KArchive. 0068 */ 0069 class LIBK3B_EXPORT Iso9660Entry 0070 { 0071 public: 0072 Iso9660Entry( Iso9660* archive, 0073 const QString& isoName, 0074 const QString& name, 0075 int access, 0076 int date, 0077 int adate, 0078 int cdate, 0079 const QString& user, 0080 const QString& group, 0081 const QString& symlink ); 0082 virtual ~Iso9660Entry(); 0083 0084 int adate() const { return m_adate; } 0085 int cdate() const { return m_cdate; } 0086 0087 /** 0088 * Creation date of the file. 0089 * @return the creation date 0090 */ 0091 QDateTime datetime() const; 0092 0093 /** 0094 * Creation date of the file. 0095 * @return the creation date in seconds since 1970 0096 */ 0097 int date() const { return m_date; } 0098 0099 /** 0100 * Name of the file without path. 0101 * @return The file name without path. 0102 */ 0103 QString name() const { return m_name; } 0104 0105 /** 0106 * \return The raw name as saved in the ISO9660 tree 0107 */ 0108 QString isoName() const { return m_isoName; } 0109 0110 /** 0111 * The permissions and mode flags as returned by the stat() function 0112 * in st_mode. 0113 * @return the permissions 0114 */ 0115 mode_t permissions() const { return m_access; } 0116 0117 /** 0118 * User who created the file. 0119 * @return the owner of the file 0120 */ 0121 QString user() const { return m_user; } 0122 0123 /** 0124 * Group of the user who created the file. 0125 * @return the group of the file 0126 */ 0127 QString group() const { return m_group; } 0128 0129 /** 0130 * Symlink if there is one. 0131 * @return the symlink, or QString() 0132 */ 0133 QString symlink() const { return m_symlink; } 0134 0135 /** 0136 * Checks whether the entry is a file. 0137 * @return true if this entry is a file 0138 */ 0139 virtual bool isFile() const { return false; } 0140 0141 /** 0142 * Checks whether the entry is a directory. 0143 * @return true if this entry is a directory 0144 */ 0145 virtual bool isDirectory() const { return false; } 0146 0147 Iso9660* archive() const { return m_archive; } 0148 0149 private: 0150 int m_adate; 0151 int m_cdate; 0152 QString m_name; 0153 QString m_isoName; 0154 int m_date; 0155 mode_t m_access; 0156 QString m_user; 0157 QString m_group; 0158 QString m_symlink; 0159 Iso9660* m_archive; 0160 }; 0161 0162 0163 class LIBK3B_EXPORT Iso9660Directory : public Iso9660Entry 0164 { 0165 public: 0166 Iso9660Directory( Iso9660* archive, 0167 const QString& isoName, 0168 const QString& name, 0169 int access, 0170 int date, 0171 int adate, 0172 int cdate, 0173 const QString& user, 0174 const QString& group, 0175 const QString& symlink, 0176 unsigned int pos = 0, 0177 unsigned int size = 0 ); 0178 ~Iso9660Directory() override; 0179 0180 /** 0181 * Returns a list of sub-entries. 0182 * @return the names of all entries in this directory (filenames, no path). 0183 */ 0184 QStringList entries() const; 0185 0186 /** 0187 * Returns the entry with the given name. 0188 * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. 0189 * @return a pointer to the entry in the directory. 0190 */ 0191 Iso9660Entry* entry( const QString& name ); 0192 0193 /** 0194 * Returns the entry with the given name. 0195 * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. 0196 * @return a pointer to the entry in the directory. 0197 */ 0198 const Iso9660Entry* entry( const QString& name ) const; 0199 0200 /** 0201 * Returns a list of sub-entries. 0202 * Searches for Iso9660 names. 0203 * @return the names of all entries in this directory (filenames, no path). 0204 */ 0205 QStringList iso9660Entries() const; 0206 0207 /** 0208 * Returns the entry with the given name. 0209 * Searches for Iso9660 names. 0210 * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. 0211 * @return a pointer to the entry in the directory. 0212 */ 0213 Iso9660Entry* iso9660Entry( const QString& name ); 0214 0215 /** 0216 * Returns the entry with the given name. 0217 * Searches for Iso9660 names. 0218 * @param name may be "test1", "mydir/test3", "mydir/mysubdir/test3", etc. 0219 * @return a pointer to the entry in the directory. 0220 */ 0221 const Iso9660Entry* iso9660Entry( const QString& name ) const; 0222 0223 /** 0224 * @internal 0225 * Adds a new entry to the directory. 0226 */ 0227 void addEntry( Iso9660Entry* ); 0228 0229 /** 0230 * Checks whether this entry is a directory. 0231 * @return true, since this entry is a directory 0232 */ 0233 bool isDirectory() const override { return true; } 0234 0235 private: 0236 void expand(); 0237 0238 QHash<QString, Iso9660Entry*> m_entries; 0239 QHash<QString, Iso9660Entry*> m_iso9660Entries; 0240 0241 bool m_bExpanded; 0242 unsigned int m_startSector; 0243 unsigned int m_size; 0244 }; 0245 0246 0247 class LIBK3B_EXPORT Iso9660File : public Iso9660Entry 0248 { 0249 public: 0250 /** 0251 * @param pos start sector 0252 */ 0253 Iso9660File( Iso9660* archive, 0254 const QString& isoName, 0255 const QString& name, 0256 int access, 0257 int date, 0258 int adate, 0259 int cdate, 0260 const QString& user, 0261 const QString& group, 0262 const QString& symlink, 0263 unsigned int pos, 0264 unsigned int size ); 0265 ~Iso9660File() override; 0266 0267 bool isFile() const override { return true; } 0268 0269 void setZF( char algo[2], char parms[2], int realsize ); 0270 int realsize() const { return m_realsize; } 0271 0272 /** 0273 * @return size in bytes. 0274 */ 0275 unsigned int size() const { return m_size; } 0276 0277 /** 0278 * Returns the startSector of the file. 0279 */ 0280 unsigned int startSector() const { return m_startSector; } 0281 0282 /** 0283 * Returns the startOffset of the file in bytes. 0284 */ 0285 unsigned long long startPostion() const { return (unsigned long long)m_startSector * 2048; } 0286 0287 /** 0288 * @param pos offset in bytes 0289 * @param len max number of bytes to read 0290 */ 0291 int read( unsigned int pos, char* data, int len ) const; 0292 0293 /** 0294 * Copy this file to a url. 0295 */ 0296 bool copyTo( const QString& url ) const; 0297 0298 private: 0299 char m_algo[2]; 0300 char m_parms[2]; 0301 int m_realsize; 0302 0303 unsigned int m_curpos; 0304 unsigned int m_startSector; 0305 unsigned int m_size; 0306 }; 0307 0308 0309 /** 0310 * This class is based on the KIso class by 0311 * Gy�gy Szombathelyi <gyurco@users.sourceforge.net>. 0312 * A lot has been changed and bugfixed. 0313 * The API has been improved to be useful. 0314 * 0315 * Due to the stupid Qt which does not support large files as default 0316 * we cannot use QIODevice with DVDs! That's why we have our own 0317 * reading code which is not allowed by KArchive (which is limited to int 0318 * by the way... who the hell designed this?) 0319 * I also removed the KArchive inheritance because of the named reasons. 0320 * So this stuff contains a lot KArchive code which has been made usable. 0321 * 0322 * That does not mean that this class is well designed. No, it's not. :) 0323 * 0324 * Opening a Iso9660 object should be fast since creation of the directory 0325 * and file entries is not done until a call to Iso9660Directory::entries. 0326 */ 0327 class LIBK3B_EXPORT Iso9660 0328 { 0329 public: 0330 /** 0331 * Creates an instance that operates on the given filename. 0332 * using the compression filter associated to given mimetype. 0333 * 0334 * @param filename is a local path (e.g. "/home/weis/myfile.tgz") 0335 */ 0336 explicit Iso9660( const QString& filename ); 0337 0338 /** 0339 * Special case which always reads the TOC from the specified sector 0340 * thus supporting multisession CDs. 0341 */ 0342 explicit Iso9660( Device::Device* dev, unsigned int startSector = 0 ); 0343 0344 /** 0345 * @param fd open file descriptor 0346 */ 0347 explicit Iso9660( int fd ); 0348 0349 /** 0350 * Directly specify the backend to read from. 0351 * Iso9660 will take ownership of the backend and delete it. 0352 */ 0353 explicit Iso9660( Iso9660Backend* ); 0354 0355 /** 0356 * If the .iso is still opened, then it will be 0357 * closed automatically by the destructor. 0358 */ 0359 virtual ~Iso9660(); 0360 0361 /** 0362 * Set where to start reading in the source. 0363 */ 0364 void setStartSector( unsigned int startSector ); 0365 0366 /** 0367 * If set to true before opening Iso9660 will ignore RR and joliet extensions 0368 * and only create plain iso9660 names. 0369 */ 0370 void setPlainIso9660( bool ); 0371 0372 bool plainIso9660() const; 0373 0374 /** 0375 * Opens the archive for reading. 0376 * Parses the directory listing of the archive 0377 * and creates the Iso9660Directory/Iso9660File entries. 0378 */ 0379 bool open(); 0380 0381 bool isOpen() const; 0382 0383 /** 0384 * Closes everything. 0385 * This is also called in the destructor 0386 */ 0387 void close(); 0388 0389 /** 0390 * @param sector startsector 0391 * @param len number of sectors 0392 * @return number of sectors read or -1 on error 0393 */ 0394 int read( unsigned int sector, char* data, int len ); 0395 0396 /** 0397 * The name of the os file, as passed to the constructor 0398 * Null if you did not use the QString constructor. 0399 */ 0400 QString fileName() { return m_filename; } 0401 0402 const Iso9660Directory* firstJolietDirEntry() const; 0403 const Iso9660Directory* firstRRDirEntry() const; 0404 const Iso9660Directory* firstIsoDirEntry() const; 0405 const Iso9660Directory* firstElToritoEntry() const; 0406 0407 /** 0408 * @returns 0 if no joliet desc could be found 0409 * the joliet level (1-3) otherwise 0410 */ 0411 int jolietLevel() const { return m_joliet; } 0412 0413 const Iso9660SimplePrimaryDescriptor& primaryDescriptor() const; 0414 0415 void debug() const; 0416 0417 private: 0418 /** 0419 * @internal 0420 */ 0421 void addBoot( struct el_torito_boot_descriptor* bootdesc ); 0422 void createSimplePrimaryDesc( struct iso_primary_descriptor* desc ); 0423 0424 void debugEntry( const Iso9660Entry*, int depth ) const; 0425 0426 int m_joliet; 0427 0428 // only used for creation 0429 static int read_callback( char* buf, sector_t start, int len, void* udata ); 0430 static int isofs_callback( struct iso_directory_record* idr, void *udata ); 0431 Iso9660Directory *dirent; 0432 bool m_rr; 0433 friend class Iso9660Directory; 0434 0435 private: 0436 QString m_filename; 0437 0438 class Private; 0439 Private * d; 0440 }; 0441 } 0442 0443 #endif