Warning, file /frameworks/kservice/src/sycoca/kmemfile.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kmemfile_p.h" 0009 0010 #ifndef QT_NO_SHAREDMEMORY 0011 0012 #include <QCoreApplication> 0013 #include <QCryptographicHash> 0014 #include <QDir> 0015 #include <QFile> 0016 #include <QSharedMemory> 0017 0018 class KMemFile::Private 0019 { 0020 public: 0021 struct sharedInfoData { 0022 int shmCounter; 0023 qint64 shmDataSize; 0024 0025 sharedInfoData() 0026 { 0027 memset(this, 0, sizeof(*this)); 0028 } 0029 }; 0030 Private(KMemFile *_parent) 0031 : readWritePos(0) 0032 , shmDataSize(0) 0033 , parent(_parent) 0034 { 0035 } 0036 0037 QString getShmKey(int iCounter = -1); 0038 static QString getShmKey(const QString &filename, int iCounter = -1); 0039 bool loadContentsFromFile(); 0040 void close(); 0041 0042 QString filename; 0043 QSharedMemory shmInfo; 0044 QSharedMemory shmData; 0045 qint64 readWritePos; 0046 qint64 shmDataSize; 0047 0048 KMemFile *parent; 0049 }; 0050 0051 QString KMemFile::Private::getShmKey(int iCounter) 0052 { 0053 return getShmKey(filename, iCounter); 0054 } 0055 0056 QString KMemFile::Private::getShmKey(const QString &filename, int iCounter) 0057 { 0058 QByteArray tmp = QString(QDir(filename).canonicalPath() + QString::number(iCounter)).toUtf8(); 0059 return QString::fromLatin1(QCryptographicHash::hash(tmp, QCryptographicHash::Sha1)); 0060 } 0061 0062 bool KMemFile::Private::loadContentsFromFile() 0063 { 0064 QFile f(filename); 0065 if (!f.exists()) { 0066 close(); 0067 parent->setErrorString(QCoreApplication::translate("", "File %1 does not exist").arg(filename)); 0068 return false; 0069 } 0070 if (!f.open(QIODevice::ReadOnly)) { 0071 close(); 0072 parent->setErrorString(QCoreApplication::translate("", "Cannot open %1 for reading").arg(filename)); 0073 return false; 0074 } 0075 0076 sharedInfoData *infoPtr = static_cast<sharedInfoData *>(shmInfo.data()); 0077 0078 infoPtr->shmDataSize = f.size(); 0079 shmData.setKey(getShmKey(infoPtr->shmCounter)); 0080 if (!shmData.create(infoPtr->shmDataSize)) { 0081 close(); 0082 parent->setErrorString(QCoreApplication::translate("", "Cannot create memory segment for file %1").arg(filename)); 0083 return false; 0084 } 0085 shmData.lock(); 0086 qint64 size = 0; 0087 qint64 bytesRead; 0088 char *data = static_cast<char *>(shmData.data()); 0089 bytesRead = f.read(data, infoPtr->shmDataSize); 0090 if (bytesRead != infoPtr->shmDataSize) { 0091 close(); 0092 parent->setErrorString(QCoreApplication::translate("", "Could not read data from %1 into shm").arg(filename)); 0093 return false; 0094 } 0095 shmDataSize = size; 0096 shmData.unlock(); 0097 return true; 0098 } 0099 0100 void KMemFile::Private::close() 0101 { 0102 shmData.unlock(); 0103 shmData.detach(); 0104 shmInfo.unlock(); 0105 shmInfo.detach(); 0106 readWritePos = 0; 0107 shmDataSize = 0; 0108 } 0109 0110 KMemFile::KMemFile(const QString &filename, QObject *parent) 0111 : QIODevice(parent) 0112 , d(new Private(this)) 0113 { 0114 d->filename = filename; 0115 } 0116 0117 KMemFile::~KMemFile() 0118 { 0119 close(); 0120 } 0121 0122 void KMemFile::close() 0123 { 0124 QIODevice::close(); 0125 if (!isOpen()) { 0126 return; 0127 } 0128 d->close(); 0129 } 0130 0131 bool KMemFile::isSequential() const 0132 { 0133 return false; 0134 } 0135 0136 bool KMemFile::open(OpenMode mode) 0137 { 0138 if (isOpen()) { 0139 QIODevice::open(mode); 0140 return false; 0141 } 0142 0143 if (mode != QIODevice::ReadOnly) { 0144 setErrorString(QCoreApplication::translate("", "Only 'ReadOnly' allowed")); 0145 return false; 0146 } 0147 0148 if (!QFile::exists(d->filename)) { 0149 setErrorString(QCoreApplication::translate("", "File %1 does not exist").arg(d->filename)); 0150 return false; 0151 } 0152 0153 QSharedMemory lock(QDir(d->filename).canonicalPath()); 0154 lock.lock(); 0155 0156 Private::sharedInfoData *infoPtr; 0157 d->shmInfo.setKey(d->getShmKey()); 0158 // see if it's already in memory 0159 if (!d->shmInfo.attach(QSharedMemory::ReadWrite)) { 0160 if (!d->shmInfo.create(sizeof(Private::sharedInfoData))) { 0161 lock.unlock(); 0162 setErrorString(QCoreApplication::translate("", "Cannot create memory segment for file %1").arg(d->filename)); 0163 return false; 0164 } 0165 d->shmInfo.lock(); 0166 // no -> create it 0167 infoPtr = static_cast<Private::sharedInfoData *>(d->shmInfo.data()); 0168 memset(infoPtr, 0, sizeof(Private::sharedInfoData)); 0169 infoPtr->shmCounter = 1; 0170 if (!d->loadContentsFromFile()) { 0171 d->shmInfo.unlock(); 0172 d->shmInfo.detach(); 0173 lock.unlock(); 0174 return false; 0175 } 0176 } else { 0177 d->shmInfo.lock(); 0178 infoPtr = static_cast<Private::sharedInfoData *>(d->shmInfo.data()); 0179 d->shmData.setKey(d->getShmKey(infoPtr->shmCounter)); 0180 if (!d->shmData.attach(QSharedMemory::ReadOnly)) { 0181 if (!d->loadContentsFromFile()) { 0182 d->shmInfo.unlock(); 0183 d->shmInfo.detach(); 0184 lock.unlock(); 0185 return false; 0186 } 0187 } 0188 } 0189 d->shmDataSize = infoPtr->shmDataSize; 0190 d->shmInfo.unlock(); 0191 lock.unlock(); 0192 0193 setOpenMode(mode); 0194 return true; 0195 } 0196 0197 bool KMemFile::seek(qint64 pos) 0198 { 0199 if (d->shmDataSize < pos) { 0200 setErrorString(QCoreApplication::translate("", "Cannot seek past eof")); 0201 return false; 0202 } 0203 d->readWritePos = pos; 0204 QIODevice::seek(pos); 0205 return true; 0206 } 0207 0208 qint64 KMemFile::size() const 0209 { 0210 return d->shmDataSize; 0211 } 0212 0213 qint64 KMemFile::readData(char *data, qint64 maxSize) 0214 { 0215 if ((openMode() & QIODevice::ReadOnly) == 0) { 0216 return -1; 0217 } 0218 0219 qint64 maxRead = size() - d->readWritePos; 0220 qint64 bytesToRead = qMin(maxRead, maxSize); 0221 const char *src = static_cast<const char *>(d->shmData.data()); 0222 memcpy(data, &src[d->readWritePos], bytesToRead); 0223 d->readWritePos += bytesToRead; 0224 return bytesToRead; 0225 } 0226 0227 qint64 KMemFile::writeData(const char *, qint64) 0228 { 0229 return -1; 0230 } 0231 0232 void KMemFile::fileContentsChanged(const QString &filename) 0233 { 0234 QSharedMemory lock(QDir(filename).canonicalPath()); 0235 lock.lock(); 0236 0237 QSharedMemory shmData(Private::getShmKey(filename)); 0238 if (!shmData.attach()) { 0239 return; 0240 } 0241 shmData.lock(); 0242 Private::sharedInfoData *infoPtr = static_cast<Private::sharedInfoData *>(shmData.data()); 0243 infoPtr->shmCounter++; 0244 infoPtr->shmDataSize = 0; 0245 shmData.unlock(); 0246 } 0247 0248 #endif // QT_NO_SHAREDMEMORY 0249 0250 #include "moc_kmemfile_p.cpp"