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

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