File indexing completed on 2024-05-12 04:51:05
0001 /* 0002 SPDX-FileCopyrightText: 1998-2007 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "k3bfilecompilationsizehandler.h" 0007 #include "k3bfileitem.h" 0008 0009 #include <QDebug> 0010 #include <QFile> 0011 #include <QMap> 0012 #include <QList> 0013 0014 0015 // TODO: remove the items from the project if the savedSize differs 0016 // with some info-widget: "Files xxx have changed on disk. Removing them from the project." 0017 // or we just update the sizes! 0018 0019 0020 static long usedBlocks( const KIO::filesize_t& bytes ) 0021 { 0022 if( bytes % 2048 ) 0023 return bytes/2048 + 1; 0024 else 0025 return bytes/2048; 0026 } 0027 0028 0029 class InodeInfo 0030 { 0031 public: 0032 InodeInfo() { 0033 number = 0; 0034 savedSize = 0; 0035 } 0036 0037 /** 0038 * How often has the file with 0039 * the corresponding inode been added 0040 */ 0041 int number; 0042 0043 /** 0044 * The size of the first added file. This has to be saved 0045 * to check further addings and to avoid the following situation: 0046 * A file with inode 1 is added, then deleted. Another file is created 0047 * at inode 1 and added to the project. Now the first file gets 0048 * removed and then the second. If we had not saved the size we would 0049 * have added the size of the first and removed the size of the second 0050 * file resulting in a corrupted project size. 0051 * This way we always use the size of the first added file and may 0052 * warn the user if sizes differ. 0053 */ 0054 KIO::filesize_t savedSize; 0055 0056 KIO::filesize_t completeSize() const { return savedSize*number; } 0057 0058 /** 0059 * In an iso9660 filesystem a file occupies complete blocks of 2048 bytes. 0060 */ 0061 K3b::Msf blocks() const { return K3b::Msf( usedBlocks(savedSize) ); } 0062 0063 QList<K3b::DataItem*> items; 0064 }; 0065 0066 0067 class K3b::FileCompilationSizeHandler::Private 0068 { 0069 public: 0070 Private() 0071 : size(0) { 0072 } 0073 0074 void clear() { 0075 inodeMap.clear(); 0076 size = 0; 0077 blocks = 0; 0078 } 0079 0080 void addFile( K3b::FileItem* item, bool followSymlinks ) { 0081 InodeInfo& inodeInfo = inodeMap[item->localId(followSymlinks)]; 0082 0083 inodeInfo.items.append( item ); 0084 0085 if( inodeInfo.number == 0 ) { 0086 inodeInfo.savedSize = item->itemSize( followSymlinks ); 0087 0088 size += inodeInfo.savedSize; 0089 blocks += inodeInfo.blocks(); 0090 } 0091 0092 inodeInfo.number++; 0093 } 0094 0095 void addSpecialItem( K3b::DataItem* item ) { 0096 // special files do not have a corresponding local file 0097 // so we just add their k3bSize 0098 size += item->size(); 0099 blocks += usedBlocks(item->size()); 0100 specialItems.append( item ); 0101 } 0102 0103 void removeFile( K3b::FileItem* item, bool followSymlinks ) { 0104 InodeInfo& inodeInfo = inodeMap[item->localId(followSymlinks)]; 0105 0106 if( !inodeInfo.items.contains( item ) ) { 0107 qCritical() << "(K3b::FileCompilationSizeHandler) " 0108 << item->localPath() 0109 << " has been removed without being added!" << Qt::endl; 0110 } 0111 else { 0112 if( item->itemSize(followSymlinks) != inodeInfo.savedSize ) { 0113 qCritical() << "(K3b::FileCompilationSizeHandler) savedSize differs!" << Qt::endl; 0114 } 0115 0116 inodeInfo.items.removeOne( item ); 0117 inodeInfo.number--; 0118 if( inodeInfo.number == 0 ) { 0119 size -= inodeInfo.savedSize; 0120 blocks -= inodeInfo.blocks(); 0121 } 0122 } 0123 } 0124 0125 void removeSpecialItem( K3b::DataItem* item ) { 0126 // special files do not have a corresponding local file 0127 // so we just subtract their k3bSize 0128 if( !specialItems.contains( item ) ) { 0129 qCritical() << "(K3b::FileCompilationSizeHandler) Special item " 0130 << item->k3bName() 0131 << " has been removed without being added!" << Qt::endl; 0132 } 0133 else { 0134 specialItems.removeOne( item ); 0135 size -= item->size(); 0136 blocks -= usedBlocks(item->size()); 0137 } 0138 } 0139 0140 0141 /** 0142 * This maps from inodes to the number of occurrences of the inode. 0143 */ 0144 QMap<K3b::FileItem::Id, InodeInfo> inodeMap; 0145 0146 KIO::filesize_t size; 0147 K3b::Msf blocks; 0148 0149 QList<K3b::DataItem*> specialItems; 0150 }; 0151 0152 0153 0154 K3b::FileCompilationSizeHandler::FileCompilationSizeHandler() 0155 { 0156 d_symlinks = new Private; 0157 d_noSymlinks = new Private; 0158 } 0159 0160 K3b::FileCompilationSizeHandler::~FileCompilationSizeHandler() 0161 { 0162 delete d_symlinks; 0163 delete d_noSymlinks; 0164 } 0165 0166 0167 const KIO::filesize_t& K3b::FileCompilationSizeHandler::size( bool followSymlinks ) const 0168 { 0169 if( followSymlinks ) 0170 return d_noSymlinks->size; 0171 else 0172 return d_symlinks->size; 0173 } 0174 0175 0176 const K3b::Msf& K3b::FileCompilationSizeHandler::blocks( bool followSymlinks ) const 0177 { 0178 if( followSymlinks ) 0179 return d_noSymlinks->blocks; 0180 else 0181 return d_symlinks->blocks; 0182 } 0183 0184 0185 void K3b::FileCompilationSizeHandler::addFile( K3b::DataItem* item ) 0186 { 0187 if( item->isSpecialFile() ) { 0188 d_symlinks->addSpecialItem( item ); 0189 d_noSymlinks->addSpecialItem( item ); 0190 } 0191 else if( item->isFile() ) { 0192 K3b::FileItem* fileItem = static_cast<K3b::FileItem*>( item ); 0193 d_symlinks->addFile( fileItem, false ); 0194 d_noSymlinks->addFile( fileItem, true ); 0195 } 0196 } 0197 0198 0199 void K3b::FileCompilationSizeHandler::removeFile( K3b::DataItem* item ) 0200 { 0201 if( item->isSpecialFile() ) { 0202 d_symlinks->removeSpecialItem( item ); 0203 d_noSymlinks->removeSpecialItem( item ); 0204 } 0205 else if( item->isFile() ) { 0206 K3b::FileItem* fileItem = static_cast<K3b::FileItem*>( item ); 0207 d_symlinks->removeFile( fileItem, false ); 0208 d_noSymlinks->removeFile( fileItem, true ); 0209 } 0210 } 0211 0212 0213 void K3b::FileCompilationSizeHandler::clear() 0214 { 0215 d_symlinks->clear(); 0216 d_noSymlinks->clear(); 0217 }