Qt 4.8
qfsfileengine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qfsfileengine_p.h"
44 #include "qfilesystemengine_p.h"
45 #include "qdatetime.h"
46 #include "qdiriterator.h"
47 #include "qset.h"
48 #include <QtCore/qdebug.h>
49 
50 #ifndef QT_NO_FSFILEENGINE
51 
52 #if !defined(Q_OS_WINCE)
53 #include <errno.h>
54 #endif
55 #if defined(Q_OS_UNIX)
56 #include "private/qcore_unix_p.h"
57 #endif
58 #include <stdio.h>
59 #include <stdlib.h>
60 #if defined(Q_OS_MAC)
61 # include <private/qcore_mac_p.h>
62 #endif
63 
65 
66 #ifdef Q_OS_WIN
67 # ifndef S_ISREG
68 # define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
69 # endif
70 # ifndef S_ISCHR
71 # define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
72 # endif
73 # ifndef S_ISFIFO
74 # define S_ISFIFO(x) false
75 # endif
76 # ifndef S_ISSOCK
77 # define S_ISSOCK(x) false
78 # endif
79 # ifndef INVALID_FILE_ATTRIBUTES
80 # define INVALID_FILE_ATTRIBUTES (DWORD (-1))
81 # endif
82 #endif
83 
106 //**************** QFSFileEnginePrivate
108 {
109  init();
110 }
111 
116 {
117  is_sequential = 0;
118  tried_stat = 0;
119 #if !defined(Q_OS_WINCE)
120  need_lstat = 1;
121  is_link = 0;
122 #endif
124  fd = -1;
125  fh = 0;
126 #if defined (Q_OS_SYMBIAN)
127  symbianFilePos = 0;
128 #if !defined(QT_SYMBIAN_USE_NATIVE_FILEMAP)
129  fileHandleForMaps = -1;
130 #endif
131 #endif
133  lastFlushFailed = false;
134  closeFileHandle = false;
135 #ifdef Q_OS_WIN
137  fileHandle = INVALID_HANDLE_VALUE;
138  mapHandle = NULL;
139 #ifndef Q_OS_WINCE
140  cachedFd = -1;
141 #endif
142 #endif
143 }
144 
150 {
152  d->fileEntry = QFileSystemEntry(file);
153 }
154 
159 {
160 }
161 
166  : QAbstractFileEngine(dd)
167 {
168 }
169 
174 {
176  if (d->closeFileHandle) {
177  if (d->fh) {
178  int ret;
179  do {
180  ret = fclose(d->fh);
181  } while (ret == EOF && errno == EINTR);
182  } else if (d->fd != -1) {
183  int ret;
184  do {
185  ret = QT_CLOSE(d->fd);
186  } while (ret == -1 && errno == EINTR);
187  }
188  }
189  QList<uchar*> keys = d->maps.keys();
190  for (int i = 0; i < keys.count(); ++i)
191  unmap(keys.at(i));
192 }
193 
198 {
200  d->init();
201  d->fileEntry = QFileSystemEntry(file);
202 }
203 
207 bool QFSFileEngine::open(QIODevice::OpenMode openMode)
208 {
210  if (d->fileEntry.isEmpty()) {
211  qWarning("QFSFileEngine::open: No file name specified");
212  setError(QFile::OpenError, QLatin1String("No file name specified"));
213  return false;
214  }
215 
216  // Append implies WriteOnly.
217  if (openMode & QFile::Append)
218  openMode |= QFile::WriteOnly;
219 
220  // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
221  if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
222  openMode |= QFile::Truncate;
223 
224  d->openMode = openMode;
225  d->lastFlushFailed = false;
226  d->tried_stat = 0;
227  d->fh = 0;
228  d->fd = -1;
229 
230  return d->nativeOpen(openMode);
231 }
232 
237 bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
238 {
239  return open(openMode, fh, QFile::DontCloseHandle);
240 }
241 
250 bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
251 {
253 
254  // Append implies WriteOnly.
255  if (openMode & QFile::Append)
256  openMode |= QFile::WriteOnly;
257 
258  // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
259  if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
260  openMode |= QFile::Truncate;
261 
262  d->openMode = openMode;
263  d->lastFlushFailed = false;
264  d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
265  d->fileEntry.clear();
266  d->tried_stat = 0;
267  d->fd = -1;
268 
269  return d->openFh(openMode, fh);
270 }
271 
275 bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
276 {
278  this->fh = fh;
279  fd = -1;
280 
281  // Seek to the end when in Append mode.
282  if (openMode & QIODevice::Append) {
283  int ret;
284  do {
285  ret = QT_FSEEK(fh, 0, SEEK_END);
286  } while (ret != 0 && errno == EINTR);
287 
288  if (ret != 0) {
289  q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
290  qt_error_string(int(errno)));
291 
292  this->openMode = QIODevice::NotOpen;
293  this->fh = 0;
294 
295  return false;
296  }
297  }
298 
299  return true;
300 }
301 
306 bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
307 {
308  return open(openMode, fd, QFile::DontCloseHandle);
309 }
310 
319 bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandleFlags handleFlags)
320 {
322 
323  // Append implies WriteOnly.
324  if (openMode & QFile::Append)
325  openMode |= QFile::WriteOnly;
326 
327  // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
328  if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
329  openMode |= QFile::Truncate;
330 
331  d->openMode = openMode;
332  d->lastFlushFailed = false;
333  d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
334  d->fileEntry.clear();
335  d->fh = 0;
336  d->fd = -1;
337  d->tried_stat = 0;
338 
339  return d->openFd(openMode, fd);
340 }
341 
342 
347 bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
348 {
350  this->fd = fd;
351  fh = 0;
352 
353  // Seek to the end when in Append mode.
354  if (openMode & QFile::Append) {
355  int ret;
356  do {
357  ret = QT_LSEEK(fd, 0, SEEK_END);
358  } while (ret == -1 && errno == EINTR);
359 
360  if (ret == -1) {
361  q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
362  qt_error_string(int(errno)));
363 
364  this->openMode = QIODevice::NotOpen;
365  this->fd = -1;
366 
367  return false;
368  }
369  }
370 
371  return true;
372 }
373 
378 {
380  d->openMode = QIODevice::NotOpen;
381  return d->nativeClose();
382 }
383 
388 {
390  if (fd == -1 && !fh
391 #ifdef Q_OS_SYMBIAN
392  && !symbianFile.SubSessionHandle()
393 #ifndef QT_SYMBIAN_USE_NATIVE_FILEMAP
394  && fileHandleForMaps == -1
395 #endif
396 #endif
397  )
398  return false;
399 
400  // Flush the file if it's buffered, and if the last flush didn't fail.
401  bool flushed = !fh || (!lastFlushFailed && q->flush());
402  bool closed = true;
403  tried_stat = 0;
404 
405 #if defined(Q_OS_SYMBIAN) && !defined(QT_SYMBIAN_USE_NATIVE_FILEMAP)
406  // Map handle is always owned by us so always close it
407  if (fileHandleForMaps >= 0) {
408  QT_CLOSE(fileHandleForMaps);
409  fileHandleForMaps = -1;
410  }
411 #endif
412 
413  // Close the file if we created the handle.
414  if (closeFileHandle) {
415  int ret;
416  do {
417 #ifdef Q_OS_SYMBIAN
418  if (symbianFile.SubSessionHandle()) {
419  symbianFile.Close();
420  ret = 0;
421  } else
422 #endif
423  if (fh) {
424  // Close buffered file.
425  ret = fclose(fh) != 0 ? -1 : 0;
426  } else {
427  // Close unbuffered file.
428  ret = QT_CLOSE(fd);
429  }
430  } while (ret == -1 && errno == EINTR);
431 
432  // We must reset these guys regardless; calling close again after a
433  // failed close causes crashes on some systems.
434  fh = 0;
435  fd = -1;
436  closed = (ret == 0);
437  }
438 
439  // Report errors.
440  if (!flushed || !closed) {
441  if (flushed) {
442  // If not flushed, we want the flush error to fall through.
444  }
445  return false;
446  }
447 
448  return true;
449 }
450 
455 {
457  if ((d->openMode & QIODevice::WriteOnly) == 0) {
458  // Nothing in the write buffers, so flush succeeds in doing
459  // nothing.
460  return true;
461  }
462  return d->nativeFlush();
463 }
464 
469 {
471 
472  // Never try to flush again if the last flush failed. Otherwise you can
473  // get crashes on some systems (AIX).
474  if (lastFlushFailed)
475  return false;
476 
477  int ret = fflush(fh);
478 
479  lastFlushFailed = (ret != 0);
480  lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
481 
482  if (ret != 0) {
483  q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
485  return false;
486  }
487  return true;
488 }
489 
494 {
495  Q_D(const QFSFileEngine);
496  return d->nativeSize();
497 }
498 
499 #ifndef Q_OS_WIN
500 
503 qint64 QFSFileEnginePrivate::sizeFdFh() const
504 {
505  Q_Q(const QFSFileEngine);
506  const_cast<QFSFileEngine *>(q)->flush();
507 
508  tried_stat = 0;
509  metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
511  return 0;
512  return metaData.size();
513 }
514 #endif
515 
520 {
521  Q_D(const QFSFileEngine);
522  return d->nativePos();
523 }
524 
529 {
530  if (fh)
531  return qint64(QT_FTELL(fh));
532  return QT_LSEEK(fd, 0, SEEK_CUR);
533 }
534 
539 {
541  return d->nativeSeek(pos);
542 }
543 
548 {
550 
551  // On Windows' stdlib implementation, the results of calling fread and
552  // fwrite are undefined if not called either in sequence, or if preceded
553  // with a call to fflush().
554  if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
555  return false;
556 
557  if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
558  return false;
559 
560  if (fh) {
561  // Buffered stdlib mode.
562  int ret;
563  do {
564  ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
565  } while (ret != 0 && errno == EINTR);
566 
567  if (ret != 0) {
568  q->setError(QFile::ReadError, qt_error_string(int(errno)));
569  return false;
570  }
571  } else {
572  // Unbuffered stdio mode.
573  if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
574  qWarning() << "QFile::at: Cannot set file position" << pos;
576  return false;
577  }
578  }
579  return true;
580 }
581 
586 {
587  Q_D(const QFSFileEngine);
588  return d->nativeHandle();
589 }
590 
595 {
597 
598  // On Windows' stdlib implementation, the results of calling fread and
599  // fwrite are undefined if not called either in sequence, or if preceded
600  // with a call to fflush().
601  if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
602  flush();
603  d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
604  }
605 
606  return d->nativeRead(data, maxlen);
607 }
608 
613 {
615 
616  if (len < 0 || len != qint64(size_t(len))) {
617  q->setError(QFile::ReadError, qt_error_string(EINVAL));
618  return -1;
619  }
620 
621  qint64 readBytes = 0;
622  bool eof = false;
623 
624  if (fh) {
625  // Buffered stdlib mode.
626 
627  size_t result;
628  bool retry = true;
629  do {
630  result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
631  eof = feof(fh);
632  if (retry && eof && result == 0) {
633  // On Mac OS, this is needed, e.g., if a file was written to
634  // through another stream since our last read. See test
635  // tst_QFile::appendAndRead
636  QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
637  retry = false;
638  continue;
639  }
640  readBytes += result;
641  } while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
642 
643  } else if (fd != -1) {
644  // Unbuffered stdio mode.
645 
646 #ifdef Q_OS_WIN
647  int result;
648 #else
649  ssize_t result;
650 #endif
651  do {
652  result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
653  } while ((result == -1 && errno == EINTR)
654  || (result > 0 && (readBytes += result) < len));
655 
656  eof = !(result == -1);
657  }
658 
659  if (!eof && readBytes == 0) {
660  readBytes = -1;
661  q->setError(QFile::ReadError, qt_error_string(errno));
662  }
663 
664  return readBytes;
665 }
666 
671 {
673 
674  // On Windows' stdlib implementation, the results of calling fread and
675  // fwrite are undefined if not called either in sequence, or if preceded
676  // with a call to fflush().
677  if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
678  flush();
679  d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
680  }
681 
682  return d->nativeReadLine(data, maxlen);
683 }
684 
689 {
691  if (!fh)
692  return q->QAbstractFileEngine::readLine(data, maxlen);
693 
694  QT_OFF_T oldPos = 0;
695 #ifdef Q_OS_WIN
696  bool seq = q->isSequential();
697  if (!seq)
698 #endif
699  oldPos = QT_FTELL(fh);
700 
701  // QIODevice::readLine() passes maxlen - 1 to QFile::readLineData()
702  // because it has made space for the '\0' at the end of data. But fgets
703  // does the same, so we'd get two '\0' at the end - passing maxlen + 1
704  // solves this.
705  if (!fgets(data, int(maxlen + 1), fh)) {
706  if (!feof(fh))
707  q->setError(QFile::ReadError, qt_error_string(int(errno)));
708  return -1; // error
709  }
710 
711 #ifdef Q_OS_WIN
712  if (seq)
713  return qstrlen(data);
714 #endif
715 
716  qint64 lineLength = QT_FTELL(fh) - oldPos;
717  return lineLength > 0 ? lineLength : qstrlen(data);
718 }
719 
724 {
726 
727  // On Windows' stdlib implementation, the results of calling fread and
728  // fwrite are undefined if not called either in sequence, or if preceded
729  // with a call to fflush().
730  if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
731  flush();
732  d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
733  }
734 
735  return d->nativeWrite(data, len);
736 }
737 
742 {
744 
745  if (len < 0 || len != qint64(size_t(len))) {
746  q->setError(QFile::WriteError, qt_error_string(EINVAL));
747  return -1;
748  }
749 
750  qint64 writtenBytes = 0;
751 
752  if (fh) {
753  // Buffered stdlib mode.
754 
755  size_t result;
756  do {
757  result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
758  writtenBytes += result;
759  } while (result == 0 ? errno == EINTR : writtenBytes < len);
760 
761  } else if (fd != -1) {
762  // Unbuffered stdio mode.
763 
764 #ifdef Q_OS_WIN
765  int result;
766 #else
767  ssize_t result;
768 #endif
769  do {
770  result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
771  } while ((result == -1 && errno == EINTR)
772  || (result > 0 && (writtenBytes += result) < len));
773  }
774 
775  if (len && writtenBytes == 0) {
776  writtenBytes = -1;
778  }
779 
780  return writtenBytes;
781 }
782 
783 #ifndef QT_NO_FILESYSTEMITERATOR
784 
788 {
789  return new QFSFileEngineIterator(filters, filterNames);
790 }
791 
796 {
797  return 0;
798 }
799 #endif
800 
804 QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
805 {
806  return QAbstractFileEngine::entryList(filters, filterNames);
807 }
808 
813 {
814  Q_D(const QFSFileEngine);
815  if (d->is_sequential == 0)
816  d->is_sequential = d->nativeIsSequential() ? 1 : 2;
817  return d->is_sequential == 1;
818 }
819 
823 #ifdef Q_OS_UNIX
824 bool QFSFileEnginePrivate::isSequentialFdFh() const
825 {
827  return metaData.isSequential();
828  return true;
829 }
830 #endif
831 
836 {
838  if (extension == AtEndExtension && d->fh && isSequential())
839  return feof(d->fh);
840 
841  if (extension == MapExtension) {
842  const MapExtensionOption *options = (MapExtensionOption*)(option);
843  MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
844  returnValue->address = d->map(options->offset, options->size, options->flags);
845  return (returnValue->address != 0);
846  }
847  if (extension == UnMapExtension) {
848  UnMapExtensionOption *options = (UnMapExtensionOption*)option;
849  return d->unmap(options->address);
850  }
851 
852  return false;
853 }
854 
859 {
860  Q_D(const QFSFileEngine);
861  if (extension == AtEndExtension && d->fh && isSequential())
862  return true;
863  if (extension == FastReadLineExtension && d->fh)
864  return true;
865  if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
866  return true;
867  if (extension == UnMapExtension || extension == MapExtension)
868  return true;
869  return false;
870 }
871 
1020 
1021 #endif // QT_NO_FSFILEENGINE
void setError(QFile::FileError error, const QString &str)
Sets the error type to error, and the error string to errorString.
double d
Definition: qnumeric_p.h:62
QString qt_error_string(int errorCode)
Definition: qglobal.cpp:2600
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
LastIOCommand lastIOCommand
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const
Requests that a list of all the files matching the filters list based on the filterNames in the file ...
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
qint64 writeFdFh(const char *data, qint64 len)
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_D(Class)
Definition: qglobal.h:2482
#define INVALID_FILE_ATTRIBUTES
QStringList keys
bool isSequential() const
Reimplemented Function
#define QT_READ
Definition: qcore_unix_p.h:280
void setFileName(const QString &file)
Reimplemented Function
QIODevice::OpenMode openMode
bool supportsExtension(Extension extension) const
Reimplemented Function
provides an extended output argument to QAbstractFileEngine&#39;s extension support.
#define Q_Q(Class)
Definition: qglobal.h:2483
bool flush()
Reimplemented Function
QFSFileEngine()
Constructs a QFSFileEngine.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const
Extension
This enum describes the types of extensions that the file engine can support.
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
bool open(QIODevice::OpenMode openMode)
Reimplemented Function
provides an extended input argument to QAbstractFileEngine&#39;s extension support.
Q_CORE_EXPORT void qWarning(const char *,...)
The QAbstractFileEngine class provides an abstraction for accessing the filesystem.
bool seek(qint64)
Reimplemented Function
static const char * data(const QByteArray &arr)
bool openFd(QIODevice::OpenMode flags, int fd)
Opens the file descriptor fd to the file engine, using the open mode flags.
__int64 qint64
Definition: qglobal.h:942
qint64 pos() const
Reimplemented Function
bool unmap(uchar *ptr)
Unmaps the memory address.
Iterator * endEntryList()
Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames)
qint64 size() const
Reimplemented Function
qint64 readLine(char *data, qint64 maxlen)
Reimplemented Function
qint64 read(char *data, qint64 maxlen)
Reimplemented Function
static const char *const filters[3]
uint qstrlen(const char *str)
Definition: qbytearray.h:79
qint64 write(const char *data, qint64 len)
Reimplemented Function
int handle() const
Reimplemented Function
qint64 posFdFh() const
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines...
qint64 readLineFdFh(char *data, qint64 maxlen)
~QFSFileEngine()
Destructs the QFSFileEngine.
bool openFh(QIODevice::OpenMode flags, FILE *fh)
Opens the file handle fh using the open mode flags.
#define QT_WRITE
Definition: qcore_unix_p.h:289
bool extension(Extension extension, const ExtensionOption *option=0, ExtensionReturn *output=0)
Reimplemented Function
bool close()
Reimplemented Function
int errno
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
qint64 readFdFh(char *data, qint64 maxlen)
The QFSFileEngine class implements Qt&#39;s default file engine.
Definition: qfsfileengine.h:60
#define QT_CLOSE
Definition: qcore_unix_p.h:304