• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • sycoca
kmemfile.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3  Copyright (C) 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kmemfile.h"
22 
23 #ifndef QT_NO_SHAREDMEMORY
24 
25 #include <QtCore/QSharedMemory>
26 #include <QtCore/QCryptographicHash>
27 #include <QtCore/QFile>
28 #include <QtCore/QDir>
29 
30 #include "klocalizedstring.h"
31 
32 class KMemFile::Private
33 {
34 public:
35  struct sharedInfoData {
36  int shmCounter;
37  qint64 shmDataSize;
38 
39  sharedInfoData() {
40  memset ( this, 0, sizeof ( *this ) );
41  }
42  };
43  Private ( KMemFile *_parent ) : readWritePos ( 0 ), shmDataSize ( 0 ), parent ( _parent ) {}
44 
45  QString getShmKey ( int iCounter = -1 );
46  static QString getShmKey ( const QString &filename, int iCounter = -1 );
47  bool loadContentsFromFile();
48  void close();
49 
50  QString filename;
51  QSharedMemory shmInfo;
52  QSharedMemory shmData;
53  qint64 readWritePos;
54  qint64 shmDataSize;
55 
56  KMemFile *parent;
57 };
58 
59 QString KMemFile::Private::getShmKey ( int iCounter )
60 {
61  return getShmKey ( filename, iCounter );
62 }
63 
64 QString KMemFile::Private::getShmKey ( const QString &filename, int iCounter )
65 {
66  QByteArray tmp = QString ( QDir ( filename ).canonicalPath() + QString::number ( iCounter ) ).toUtf8();
67  return QString::fromLatin1 ( QCryptographicHash::hash ( tmp, QCryptographicHash::Sha1 ) );
68 }
69 
70 bool KMemFile::Private::loadContentsFromFile()
71 {
72  QFile f ( filename );
73  if ( !f.exists() ) {
74  close();
75  parent->setErrorString ( i18n ( "File %1 does not exist" , filename ) );
76  return false;
77  }
78  if ( !f.open ( QIODevice::ReadOnly ) ) {
79  close();
80  parent->setErrorString ( i18n ( "Cannot open %1 for reading" , filename ) );
81  return false;
82  }
83 
84  sharedInfoData *infoPtr = static_cast<sharedInfoData*> ( shmInfo.data() );
85 
86  infoPtr->shmDataSize = f.size();
87  shmData.setKey ( getShmKey ( infoPtr->shmCounter ) );
88  if ( !shmData.create ( infoPtr->shmDataSize ) ) {
89  close();
90  parent->setErrorString ( i18n ( "Cannot create memory segment for file %1" , filename ) );
91  return false;
92  }
93  shmData.lock();
94  qint64 size = 0;
95  qint64 bytesRead;
96  char *data = static_cast<char*> ( shmData.data() );
97  bytesRead = f.read ( data, infoPtr->shmDataSize );
98  if ( bytesRead != infoPtr->shmDataSize ) {
99  close();
100  parent->setErrorString ( i18n ( "Could not read data from %1 into shm" , filename ) );
101  return false;
102  }
103  shmDataSize = size;
104  shmData.unlock();
105  return true;
106 }
107 
108 void KMemFile::Private::close()
109 {
110  shmData.unlock();
111  shmData.detach();
112  shmInfo.unlock();
113  shmInfo.detach();
114  readWritePos = 0;
115  shmDataSize = 0;
116 }
117 
118 KMemFile::KMemFile ( const QString &filename, QObject *parent )
119  : QIODevice ( parent ), d ( new Private ( this ) )
120 {
121  d->filename = filename;
122 }
123 
124 KMemFile::~KMemFile()
125 {
126  close();
127  delete d;
128 }
129 
130 void KMemFile::close ()
131 {
132  QIODevice::close();
133  if ( !isOpen() )
134  return;
135  d->close();
136 }
137 
138 bool KMemFile::isSequential () const
139 {
140  return false;
141 }
142 
143 bool KMemFile::open ( OpenMode mode )
144 {
145  if ( isOpen() ) {
146  QIODevice::open ( mode );
147  return false;
148  }
149 
150  if ( mode != QIODevice::ReadOnly ) {
151  setErrorString ( i18n ( "Only 'ReadOnly' allowed" ) );
152  return false;
153  }
154 
155  if ( !QFile::exists ( d->filename ) ) {
156  setErrorString ( i18n ( "File %1 does not exist" , d->filename ) );
157  return false;
158  }
159 
160  QSharedMemory lock ( QDir ( d->filename ).canonicalPath() );
161  lock.lock();
162 
163  Private::sharedInfoData *infoPtr;
164  d->shmInfo.setKey ( d->getShmKey() );
165  // see if it's already in memory
166  if ( !d->shmInfo.attach ( QSharedMemory::ReadWrite ) ) {
167  if ( !d->shmInfo.create ( sizeof ( Private::sharedInfoData ) ) ) {
168  lock.unlock();
169  setErrorString ( i18n ( "Cannot create memory segment for file %1" , d->filename ) );
170  return false;
171  }
172  d->shmInfo.lock();
173  // no -> create it
174  infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
175  memset ( infoPtr, 0, sizeof ( Private::sharedInfoData ) );
176  infoPtr->shmCounter = 1;
177  if ( !d->loadContentsFromFile() ) {
178  d->shmInfo.unlock();
179  d->shmInfo.detach();
180  lock.unlock();
181  return false;
182  }
183  } else {
184  d->shmInfo.lock();
185  infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
186  d->shmData.setKey ( d->getShmKey ( infoPtr->shmCounter ) );
187  if ( !d->shmData.attach ( QSharedMemory::ReadOnly ) ) {
188  if ( !d->loadContentsFromFile() ) {
189  d->shmInfo.unlock();
190  d->shmInfo.detach();
191  lock.unlock();
192  return false;
193  }
194  }
195  }
196  d->shmDataSize = infoPtr->shmDataSize;
197  d->shmInfo.unlock();
198  lock.unlock();
199 
200  setOpenMode ( mode );
201  return true;
202 }
203 
204 bool KMemFile::seek ( qint64 pos )
205 {
206  if ( d->shmDataSize < pos ) {
207  setErrorString ( i18n ( "Cannot seek past eof" ) );
208  return false;
209  }
210  d->readWritePos = pos;
211  QIODevice::seek ( pos );
212  return true;
213 }
214 
215 qint64 KMemFile::size () const
216 {
217  return d->shmDataSize;
218 }
219 
220 qint64 KMemFile::readData ( char * data, qint64 maxSize )
221 {
222  if ( ( openMode() & QIODevice::ReadOnly ) == 0 )
223  return -1;
224 
225  qint64 maxRead = size() - d->readWritePos;
226  qint64 bytesToRead = qMin ( maxRead, maxSize );
227  const char *src = static_cast<const char*> ( d->shmData.data() );
228  memcpy ( data, &src[d->readWritePos], bytesToRead );
229  d->readWritePos += bytesToRead;
230  return bytesToRead;
231 }
232 
233 qint64 KMemFile::writeData ( const char *, qint64 )
234 {
235  return -1;
236 }
237 
238 void KMemFile::fileContentsChanged ( const QString &filename )
239 {
240  QSharedMemory lock ( QDir ( filename ).canonicalPath() );
241  lock.lock();
242 
243  QSharedMemory shmData ( Private::getShmKey ( filename ) );
244  if ( !shmData.attach() )
245  return;
246  shmData.lock();
247  Private::sharedInfoData *infoPtr = static_cast<Private::sharedInfoData*> ( shmData.data() );
248  infoPtr->shmCounter++;
249  infoPtr->shmDataSize = 0;
250  shmData.unlock();
251 }
252 
253 #endif //QT_NO_SHAREDMEMORY
QIODevice
i18n
QString i18n(const char *text)
Returns a localized version of a string.
Definition: klocalizedstring.h:630
qint64
KMemFile::readData
virtual qint64 readData(char *data, qint64 maxSize)
Definition: kmemfile.cpp:220
QIODevice::seek
virtual bool seek(qint64 pos)
QByteArray
QSharedMemory::attach
bool attach(AccessMode mode)
QSharedMemory::lock
bool lock()
KMemFile::Private
friend class Private
Definition: kmemfile.h:93
QFile::exists
bool exists() const
QIODevice::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QIODevice::close
virtual void close()
QFile
QIODevice::pos
virtual qint64 pos() const
KMemFile::isSequential
virtual bool isSequential() const
As KMemFile is a random access device, it returns false.
Definition: kmemfile.cpp:138
QString::number
QString number(int n, int base)
KMemFile::seek
virtual bool seek(qint64 pos)
Sets the current read/write position to pos.
Definition: kmemfile.cpp:204
QObject
kmemfile.h
KMemFile::fileContentsChanged
static void fileContentsChanged(const QString &filename)
This static function updates the internal information about the file loaded into shared memory...
Definition: kmemfile.cpp:238
QIODevice::isOpen
bool isOpen() const
QString
KMemFile
Definition: kmemfile.h:39
QIODevice::openMode
OpenMode openMode() const
QDir
KMemFile::~KMemFile
virtual ~KMemFile()
dtor
Definition: kmemfile.cpp:124
QSharedMemory::data
void * data()
KMemFile::writeData
virtual qint64 writeData(const char *data, qint64 maxSize)
Definition: kmemfile.cpp:233
klocalizedstring.h
QSharedMemory::unlock
bool unlock()
KMemFile::size
virtual qint64 size() const
Returns the size of the file.
Definition: kmemfile.cpp:215
QCryptographicHash::hash
QByteArray hash(const QByteArray &data, Algorithm method)
KMemFile::open
virtual bool open(OpenMode mode)
Definition: kmemfile.cpp:143
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QDir::canonicalPath
QString canonicalPath() const
QIODevice::setErrorString
void setErrorString(const QString &str)
QSharedMemory
KMemFile::KMemFile
KMemFile(const QString &filename, QObject *parent=0)
ctor
Definition: kmemfile.cpp:118
QIODevice::setOpenMode
void setOpenMode(QFlags< QIODevice::OpenModeFlag > openMode)
QObject::parent
QObject * parent() const
KMemFile::close
virtual void close()
closes the KMemFile
Definition: kmemfile.cpp:130
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal