Qt 4.8
qfile.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 "qplatformdefs.h"
43 #include "qdebug.h"
44 #include "qfile.h"
45 #include "qfsfileengine.h"
46 #include "qtemporaryfile.h"
47 #include "qlist.h"
48 #include "qfileinfo.h"
49 #include "private/qiodevice_p.h"
50 #include "private/qfile_p.h"
51 #include "private/qsystemerror_p.h"
52 #if defined(QT_BUILD_CORE_LIB)
53 # include "qcoreapplication.h"
54 #endif
55 
56 #ifdef QT_NO_QOBJECT
57 #define tr(X) QString::fromLatin1(X)
58 #endif
59 
61 
62 static const int QFILE_WRITEBUFFER_SIZE = 16384;
63 
65 {
66 #if defined(Q_OS_DARWIN)
67  // Mac always expects UTF-8... and decomposed...
69 #elif defined(Q_OS_SYMBIAN)
70  return f.toUtf8();
71 #else
72  return f.toLocal8Bit();
73 #endif
74 }
75 
77 {
78 #if defined(Q_OS_DARWIN)
79  // Mac always gives us UTF-8 and decomposed, we want that composed...
81 #elif defined(Q_OS_SYMBIAN)
82  return QString::fromUtf8(f);
83 #else
84  return QString::fromLocal8Bit(f);
85 #endif
86 }
87 
88 //************* QFilePrivate
91 
93  : fileEngine(0), lastWasWrite(false),
94  writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
95  cachedSize(0)
96 {
97 }
98 
100 {
101  delete fileEngine;
102  fileEngine = 0;
103 }
104 
105 bool
106 QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
107 {
108 #ifdef QT_NO_FSFILEENGINE
109  Q_UNUSED(flags);
110  Q_UNUSED(fd);
111  return false;
112 #else
113  delete fileEngine;
114  fileEngine = 0;
115  QFSFileEngine *fe = new QFSFileEngine;
116  fileEngine = fe;
117  return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
118 #endif
119 }
120 
121 bool
122 QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags)
123 {
124 #ifdef QT_NO_FSFILEENGINE
125  Q_UNUSED(flags);
126  Q_UNUSED(fh);
127  return false;
128 #else
129  delete fileEngine;
130  fileEngine = 0;
131  QFSFileEngine *fe = new QFSFileEngine;
132  fileEngine = fe;
133  return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
134 #endif
135 }
136 
137 #ifdef Q_OS_SYMBIAN
138 bool QFilePrivate::openExternalFile(int flags, const RFile &f, QFile::FileHandleFlags handleFlags)
139 {
140 #ifdef QT_NO_FSFILEENGINE
141  Q_UNUSED(flags);
142  Q_UNUSED(fh);
143  return false;
144 #else
145  delete fileEngine;
146  fileEngine = 0;
147  QFSFileEngine *fe = new QFSFileEngine;
148  fileEngine = fe;
149  return fe->open(QIODevice::OpenMode(flags), f, handleFlags);
150 #endif
151 }
152 #endif
153 
154 inline bool QFilePrivate::ensureFlushed() const
155 {
156  // This function ensures that the write buffer has been flushed (const
157  // because certain const functions need to call it.
158  if (lastWasWrite) {
159  const_cast<QFilePrivate *>(this)->lastWasWrite = false;
160  if (!const_cast<QFile *>(q_func())->flush())
161  return false;
162  }
163  return true;
164 }
165 
166 void
168 {
169  error = err;
170  errorString.clear();
171 }
172 
173 void
175 {
176  error = err;
177  errorString = errStr;
178 }
179 
180 void
182 {
183  error = err;
184  errorString = qt_error_string(errNum);
185 }
186 
187 //************* QFile
188 
388 #ifdef QT3_SUPPORT
389 
397 #endif
398 
399 #ifdef QT_NO_QOBJECT
400 QFile::QFile()
401  : QIODevice(*new QFilePrivate)
402 {
403 }
404 QFile::QFile(const QString &name)
405  : QIODevice(*new QFilePrivate)
406 {
407  d_func()->fileName = name;
408 }
410  : QIODevice(dd)
411 {
412 }
413 #else
414 
418  : QIODevice(*new QFilePrivate, 0)
419 {
420 }
425  : QIODevice(*new QFilePrivate, parent)
426 {
427 }
431 QFile::QFile(const QString &name)
432  : QIODevice(*new QFilePrivate, 0)
433 {
434  Q_D(QFile);
435  d->fileName = name;
436 }
442  : QIODevice(*new QFilePrivate, parent)
443 {
444  Q_D(QFile);
445  d->fileName = name;
446 }
451  : QIODevice(dd, parent)
452 {
453 }
454 #endif
455 
460 {
461  close();
462 }
463 
471 {
473 }
474 
493 void
495 {
496  Q_D(QFile);
497  if (isOpen()) {
498  qWarning("QFile::setFileName: File (%s) is already opened",
499  qPrintable(fileName()));
500  close();
501  }
502  if(d->fileEngine) { //get a new file engine later
503  delete d->fileEngine;
504  d->fileEngine = 0;
505  }
506  d->fileName = name;
507 }
508 
529 {
530  return (*QFilePrivate::encoder)(fileName);
531 }
532 
551 QString
552 QFile::decodeName(const QByteArray &localFileName)
553 {
554  return (*QFilePrivate::decoder)(localFileName);
555 }
556 
571 void
573 {
574  if (!f)
575  f = locale_encode;
577 }
578 
605 void
607 {
608  if (!f)
609  f = locale_decode;
611 }
612 
625 bool
627 {
628  // 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
629  return (fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask
631 }
632 
638 bool
640 {
641  return QFileInfo(fileName).exists();
642 }
643 
670 QString
672 {
674 }
675 
699 QString
701 {
702  return QFileInfo(fileName).readLink();
703 }
704 
714 bool
716 {
717  Q_D(QFile);
718  if (d->fileName.isEmpty()) {
719  qWarning("QFile::remove: Empty or null file name");
720  return false;
721  }
722  unsetError();
723  close();
724  if(error() == QFile::NoError) {
725  if(fileEngine()->remove()) {
726  unsetError();
727  return true;
728  }
729  d->setError(QFile::RemoveError, d->fileEngine->errorString());
730  }
731  return false;
732 }
733 
747 bool
749 {
750  return QFile(fileName).remove();
751 }
752 
765 bool
766 QFile::rename(const QString &newName)
767 {
768  Q_D(QFile);
769  if (d->fileName.isEmpty()) {
770  qWarning("QFile::rename: Empty or null file name");
771  return false;
772  }
773  if (QFile(newName).exists()) {
774  // ### Race condition. If a file is moved in after this, it /will/ be
775  // overwritten. On Unix, the proper solution is to use hardlinks:
776  // return ::link(old, new) && ::remove(old);
777  d->setError(QFile::RenameError, tr("Destination file exists"));
778  return false;
779  }
780  unsetError();
781  close();
782  if(error() == QFile::NoError) {
783  if (fileEngine()->rename(newName)) {
784  unsetError();
785  // engine was able to handle the new name so we just reset it
786  d->fileEngine->setFileName(newName);
787  d->fileName = newName;
788  return true;
789  }
790 
791  if (isSequential()) {
792  d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy"));
793  return false;
794  }
795 
796  QFile out(newName);
797  if (open(QIODevice::ReadOnly)) {
799  bool error = false;
800  char block[4096];
801  qint64 bytes;
802  while ((bytes = read(block, sizeof(block))) > 0) {
803  if (bytes != out.write(block, bytes)) {
804  d->setError(QFile::RenameError, out.errorString());
805  error = true;
806  break;
807  }
808  }
809  if (bytes == -1) {
810  d->setError(QFile::RenameError, errorString());
811  error = true;
812  }
813  if(!error) {
814  if (!remove()) {
815  d->setError(QFile::RenameError, tr("Cannot remove source file"));
816  error = true;
817  }
818  }
819  if (error) {
820  out.remove();
821  } else {
822  d->fileEngine->setFileName(newName);
824  unsetError();
825  setFileName(newName);
826  }
827  close();
828  return !error;
829  }
830  close();
831  }
832  d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString());
833  }
834  return false;
835 }
836 
852 bool
853 QFile::rename(const QString &oldName, const QString &newName)
854 {
855  return QFile(oldName).rename(newName);
856 }
857 
876 bool
877 QFile::link(const QString &linkName)
878 {
879  Q_D(QFile);
880  if (d->fileName.isEmpty()) {
881  qWarning("QFile::link: Empty or null file name");
882  return false;
883  }
884  QFileInfo fi(linkName);
885  if(fileEngine()->link(fi.absoluteFilePath())) {
886  unsetError();
887  return true;
888  }
889  d->setError(QFile::RenameError, d->fileEngine->errorString());
890  return false;
891 }
892 
907 bool
908 QFile::link(const QString &fileName, const QString &linkName)
909 {
910  return QFile(fileName).link(linkName);
911 }
912 
925 bool
926 QFile::copy(const QString &newName)
927 {
928  Q_D(QFile);
929  if (d->fileName.isEmpty()) {
930  qWarning("QFile::copy: Empty or null file name");
931  return false;
932  }
933  if (QFile(newName).exists()) {
934  // ### Race condition. If a file is moved in after this, it /will/ be
935  // overwritten. On Unix, the proper solution is to use hardlinks:
936  // return ::link(old, new) && ::remove(old); See also rename().
937  d->setError(QFile::CopyError, tr("Destination file exists"));
938  return false;
939  }
940  unsetError();
941  close();
942  if(error() == QFile::NoError) {
943  if(fileEngine()->copy(newName)) {
944  unsetError();
945  return true;
946  } else {
947  bool error = false;
948  if(!open(QFile::ReadOnly)) {
949  error = true;
950  d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
951  } else {
952  QString fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
953 #ifdef QT_NO_TEMPORARYFILE
954  QFile out(fileTemplate.arg(QFileInfo(newName).path()));
955  if (!out.open(QIODevice::ReadWrite))
956  error = true;
957 #else
958  QTemporaryFile out(fileTemplate.arg(QFileInfo(newName).path()));
959  if (!out.open()) {
960  out.setFileTemplate(fileTemplate.arg(QDir::tempPath()));
961  if (!out.open())
962  error = true;
963  }
964 #endif
965  if (error) {
966  out.close();
967  close();
968  d->setError(QFile::CopyError, tr("Cannot open for output"));
969  } else {
970  char block[4096];
971  qint64 totalRead = 0;
972  while(!atEnd()) {
973  qint64 in = read(block, sizeof(block));
974  if (in <= 0)
975  break;
976  totalRead += in;
977  if(in != out.write(block, in)) {
978  close();
979  d->setError(QFile::CopyError, tr("Failure to write block"));
980  error = true;
981  break;
982  }
983  }
984 
985  if (totalRead != size()) {
986  // Unable to read from the source. The error string is
987  // already set from read().
988  error = true;
989  }
990  if (!error && !out.rename(newName)) {
991  error = true;
992  close();
993  d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
994  }
995 #ifdef QT_NO_TEMPORARYFILE
996  if (error)
997  out.remove();
998 #else
999  if (!error)
1000  out.setAutoRemove(false);
1001 #endif
1002  }
1003  }
1004  if(!error) {
1005  QFile::setPermissions(newName, permissions());
1006  close();
1007  unsetError();
1008  return true;
1009  }
1010  }
1011  }
1012  return false;
1013 }
1014 
1030 bool
1031 QFile::copy(const QString &fileName, const QString &newName)
1032 {
1033  return QFile(fileName).copy(newName);
1034 }
1035 
1045 {
1046  Q_D(const QFile);
1047  return d->fileEngine && d->fileEngine->isSequential();
1048 }
1049 
1064 bool QFile::open(OpenMode mode)
1065 {
1066  Q_D(QFile);
1067  if (isOpen()) {
1068  qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1069  return false;
1070  }
1071  if (mode & Append)
1072  mode |= WriteOnly;
1073 
1074  unsetError();
1075  if ((mode & (ReadOnly | WriteOnly)) == 0) {
1076  qWarning("QIODevice::open: File access not specified");
1077  return false;
1078  }
1079 
1080 #ifdef Q_OS_SYMBIAN
1081  // For symbian, the unbuffered flag is used to control write-behind cache behaviour
1082  if (fileEngine()->open(mode))
1083 #else
1084  // QIODevice provides the buffering, so there's no need to request it from the file engine.
1085  if (fileEngine()->open(mode | QIODevice::Unbuffered))
1086 #endif
1087  {
1088  QIODevice::open(mode);
1089  if (mode & Append) {
1090  //The file engine should have done this in open(),
1091  //this is a workaround for backward compatibility
1092  fileEngine()->seek(size());
1093  }
1094  return true;
1095  }
1096  QFile::FileError err = d->fileEngine->error();
1097  if(err == QFile::UnspecifiedError)
1098  err = QFile::OpenError;
1099  d->setError(err, d->fileEngine->errorString());
1100  return false;
1101 }
1102 
1151 // ### Qt5: merge this into new overload with a default parameter
1152 bool QFile::open(FILE *fh, OpenMode mode)
1153 {
1154  return open(fh, mode, DontCloseHandle);
1155 }
1156 
1203 bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
1204 {
1205  Q_D(QFile);
1206  if (isOpen()) {
1207  qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1208  return false;
1209  }
1210  if (mode & Append)
1211  mode |= WriteOnly;
1212  unsetError();
1213  if ((mode & (ReadOnly | WriteOnly)) == 0) {
1214  qWarning("QFile::open: File access not specified");
1215  return false;
1216  }
1217  if (d->openExternalFile(mode, fh, handleFlags)) {
1218  QIODevice::open(mode);
1219  if (mode & Append) {
1220  seek(size());
1221  } else {
1222  qint64 pos = (qint64)QT_FTELL(fh);
1223  if (pos != -1)
1224  seek(pos);
1225  }
1226  return true;
1227  }
1228  return false;
1229 }
1230 
1269 // ### Qt5: merge this into new overload with a default parameter
1270 bool QFile::open(int fd, OpenMode mode)
1271 {
1272  return open(fd, mode, DontCloseHandle);
1273 }
1274 
1308 bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
1309 {
1310  Q_D(QFile);
1311  if (isOpen()) {
1312  qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1313  return false;
1314  }
1315  if (mode & Append)
1316  mode |= WriteOnly;
1317  unsetError();
1318  if ((mode & (ReadOnly | WriteOnly)) == 0) {
1319  qWarning("QFile::open: File access not specified");
1320  return false;
1321  }
1322  if (d->openExternalFile(mode, fd, handleFlags)) {
1323  QIODevice::open(mode);
1324  if (mode & Append) {
1325  seek(size());
1326  } else {
1327  qint64 pos = (qint64)QT_LSEEK(fd, QT_OFF_T(0), SEEK_CUR);
1328  if (pos != -1)
1329  seek(pos);
1330  }
1331  return true;
1332  }
1333  return false;
1334 }
1335 
1336 #ifdef Q_OS_SYMBIAN
1337 
1357 bool QFile::open(const RFile &f, OpenMode mode, FileHandleFlags handleFlags)
1358 {
1359  Q_D(QFile);
1360  if (isOpen()) {
1361  qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
1362  return false;
1363  }
1364  if (mode & Append)
1365  mode |= WriteOnly;
1366  unsetError();
1367  if ((mode & (ReadOnly | WriteOnly)) == 0) {
1368  qWarning("QFile::open: File access not specified");
1369  return false;
1370  }
1371  if (d->openExternalFile(mode, f, handleFlags)) {
1372  bool ok = QIODevice::open(mode);
1373  if (ok) {
1374  if (mode & Append) {
1375  ok = seek(size());
1376  } else {
1377  qint64 pos = 0;
1378  TInt err;
1379 #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
1380  err = static_cast<const RFile64&>(f).Seek(ESeekCurrent, pos);
1381 #else
1382  TInt pos32 = 0;
1383  err = f.Seek(ESeekCurrent, pos32);
1384  pos = pos32;
1385 #endif
1386  ok = ok && (err == KErrNone);
1387  ok = ok && seek(pos);
1388  }
1389  }
1390  return ok;
1391  }
1392  return false;
1393 }
1394 #endif
1395 
1418 int
1420 {
1421  Q_D(const QFile);
1422  if (!isOpen() || !d->fileEngine)
1423  return -1;
1424 
1425  return d->fileEngine->handle();
1426 }
1427 
1461 {
1462  Q_D(QFile);
1463  if (fileEngine()
1464  && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) {
1465  unsetError();
1466  uchar *address = d->fileEngine->map(offset, size, flags);
1467  if (address == 0)
1468  d->setError(d->fileEngine->error(), d->fileEngine->errorString());
1469  return address;
1470  }
1471  return 0;
1472 }
1473 
1485 bool QFile::unmap(uchar *address)
1486 {
1487  Q_D(QFile);
1488  if (fileEngine()
1489  && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) {
1490  unsetError();
1491  bool success = d->fileEngine->unmap(address);
1492  if (!success)
1493  d->setError(d->fileEngine->error(), d->fileEngine->errorString());
1494  return success;
1495  }
1496  d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension"));
1497  return false;
1498 }
1499 
1527 bool
1529 {
1530  Q_D(QFile);
1531  if (!d->ensureFlushed())
1532  return false;
1533  fileEngine();
1534  if (isOpen() && d->fileEngine->pos() > sz)
1535  seek(sz);
1536  if(d->fileEngine->setSize(sz)) {
1537  unsetError();
1538  d->cachedSize = sz;
1539  return true;
1540  }
1541  d->cachedSize = 0;
1542  d->setError(QFile::ResizeError, d->fileEngine->errorString());
1543  return false;
1544 }
1545 
1560 bool
1562 {
1563  return QFile(fileName).resize(sz);
1564 }
1565 
1573 QFile::Permissions
1575 {
1576  QAbstractFileEngine::FileFlags perms = fileEngine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask;
1577  return QFile::Permissions((int)perms); //ewww
1578 }
1579 
1590 QFile::Permissions
1592 {
1593  return QFile(fileName).permissions();
1594 }
1595 
1604 bool
1606 {
1607  Q_D(QFile);
1608  if(fileEngine()->setPermissions(permissions)) {
1609  unsetError();
1610  return true;
1611  }
1612  d->setError(QFile::PermissionsError, d->fileEngine->errorString());
1613  return false;
1614 }
1615 
1625 bool
1627 {
1628  return QFile(fileName).setPermissions(permissions);
1629 }
1630 
1632 {
1633  qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize());
1634  if (ret > 0)
1635  buffer->free(ret);
1636  return ret;
1637 }
1638 
1644 bool
1646 {
1647  Q_D(QFile);
1648  if (!d->fileEngine) {
1649  qWarning("QFile::flush: No file engine. Is IODevice open?");
1650  return false;
1651  }
1652 
1653  if (!d->writeBuffer.isEmpty()) {
1654  qint64 size = d->writeBuffer.size();
1655  if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) {
1656  QFile::FileError err = d->fileEngine->error();
1657  if(err == QFile::UnspecifiedError)
1658  err = QFile::WriteError;
1659  d->setError(err, d->fileEngine->errorString());
1660  return false;
1661  }
1662  }
1663 
1664  if (!d->fileEngine->flush()) {
1665  QFile::FileError err = d->fileEngine->error();
1666  if(err == QFile::UnspecifiedError)
1667  err = QFile::WriteError;
1668  d->setError(err, d->fileEngine->errorString());
1669  return false;
1670  }
1671  return true;
1672 }
1673 
1679 void
1681 {
1682  Q_D(QFile);
1683  if(!isOpen())
1684  return;
1685  bool flushed = flush();
1686  QIODevice::close();
1687 
1688  // reset write buffer
1689  d->lastWasWrite = false;
1690  d->writeBuffer.clear();
1691 
1692  // keep earlier error from flush
1693  if (d->fileEngine->close() && flushed)
1694  unsetError();
1695  else if (flushed)
1696  d->setError(d->fileEngine->error(), d->fileEngine->errorString());
1697 }
1698 
1708 {
1709  Q_D(const QFile);
1710  if (!d->ensureFlushed())
1711  return 0;
1712  d->cachedSize = fileEngine()->size();
1713  return d->cachedSize;
1714 }
1715 
1721 {
1722  return QIODevice::pos();
1723 }
1724 
1735 bool QFile::atEnd() const
1736 {
1737  Q_D(const QFile);
1738 
1739  // If there's buffered data left, we're not at the end.
1740  if (!d->buffer.isEmpty())
1741  return false;
1742 
1743  if (!isOpen())
1744  return true;
1745 
1746  if (!d->ensureFlushed())
1747  return false;
1748 
1749  // If the file engine knows best, say what it says.
1750  if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
1751  // Check if the file engine supports AtEndExtension, and if it does,
1752  // check if the file engine claims to be at the end.
1753  return d->fileEngine->atEnd();
1754  }
1755 
1756  // if it looks like we are at the end, or if size is not cached,
1757  // fall through to bytesAvailable() to make sure.
1758  if (pos() < d->cachedSize)
1759  return false;
1760 
1761  // Fall back to checking how much is available (will stat files).
1762  return bytesAvailable() == 0;
1763 }
1764 
1785 {
1786  Q_D(QFile);
1787  if (!isOpen()) {
1788  qWarning("QFile::seek: IODevice is not open");
1789  return false;
1790  }
1791 
1792  if (off == d->pos && off == d->devicePos)
1793  return true; //avoid expensive flush for NOP seek to current position
1794 
1795  if (!d->ensureFlushed())
1796  return false;
1797 
1798  if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) {
1799  QFile::FileError err = d->fileEngine->error();
1800  if(err == QFile::UnspecifiedError)
1801  err = QFile::PositionError;
1802  d->setError(err, d->fileEngine->errorString());
1803  return false;
1804  }
1805  unsetError();
1806  return true;
1807 }
1808 
1813 {
1814  Q_D(QFile);
1815  if (!d->ensureFlushed())
1816  return -1;
1817 
1818  qint64 read;
1819  if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
1820  read = d->fileEngine->readLine(data, maxlen);
1821  } else {
1822  // Fall back to QIODevice's readLine implementation if the engine
1823  // cannot do it faster.
1824  read = QIODevice::readLineData(data, maxlen);
1825  }
1826 
1827  if (read < maxlen) {
1828  // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
1829  d->cachedSize = 0;
1830  }
1831 
1832  return read;
1833 }
1834 
1840 {
1841  Q_D(QFile);
1842  unsetError();
1843  if (!d->ensureFlushed())
1844  return -1;
1845 
1846  qint64 read = d->fileEngine->read(data, len);
1847  if(read < 0) {
1848  QFile::FileError err = d->fileEngine->error();
1849  if(err == QFile::UnspecifiedError)
1850  err = QFile::ReadError;
1851  d->setError(err, d->fileEngine->errorString());
1852  }
1853 
1854  if (read < len) {
1855  // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
1856  d->cachedSize = 0;
1857  }
1858 
1859  return read;
1860 }
1861 
1866 {
1867 #ifdef QT_NO_QOBJECT
1869 #else
1870 
1871  // Cutoff for code that doesn't only touch the buffer.
1872  int writeBufferSize = writeBuffer.size();
1873  if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE
1874 #ifdef Q_OS_WIN
1875  || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE)
1876 #endif
1877  ) {
1879  }
1880 
1881  if (!(openMode & QIODevice::WriteOnly)) {
1883  qWarning("QIODevice::putChar: Closed device");
1884  else
1885  qWarning("QIODevice::putChar: ReadOnly device");
1886  return false;
1887  }
1888 
1889  // Make sure the device is positioned correctly.
1890  const bool sequential = isSequential();
1891  if (pos != devicePos && !sequential && !q_func()->seek(pos))
1892  return false;
1893 
1894  lastWasWrite = true;
1895 
1896  int len = 1;
1897 #ifdef Q_OS_WIN
1898  if ((openMode & QIODevice::Text) && c == '\n') {
1899  ++len;
1900  *writeBuffer.reserve(1) = '\r';
1901  }
1902 #endif
1903 
1904  // Write to buffer.
1905  *writeBuffer.reserve(1) = c;
1906 
1907  if (!sequential) {
1908  pos += len;
1909  devicePos += len;
1910  if (!buffer.isEmpty())
1911  buffer.skip(len);
1912  }
1913 
1914  return true;
1915 #endif
1916 }
1917 
1922 qint64
1923 QFile::writeData(const char *data, qint64 len)
1924 {
1925  Q_D(QFile);
1926  unsetError();
1927  d->lastWasWrite = true;
1928  bool buffered = !(d->openMode & Unbuffered);
1929 
1930  // Flush buffered data if this read will overflow.
1931  if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) {
1932  if (!flush())
1933  return -1;
1934  }
1935 
1936  // Write directly to the engine if the block size is larger than
1937  // the write buffer size.
1938  if (!buffered || len > QFILE_WRITEBUFFER_SIZE) {
1939  qint64 ret = d->fileEngine->write(data, len);
1940  if(ret < 0) {
1941  QFile::FileError err = d->fileEngine->error();
1942  if(err == QFile::UnspecifiedError)
1943  err = QFile::WriteError;
1944  d->setError(err, d->fileEngine->errorString());
1945  }
1946  return ret;
1947  }
1948 
1949  // Write to the buffer.
1950  char *writePointer = d->writeBuffer.reserve(len);
1951  if (len == 1)
1952  *writePointer = *data;
1953  else
1954  ::memcpy(writePointer, data, len);
1955  return len;
1956 }
1957 
1966 {
1967  Q_D(const QFile);
1968  if(!d->fileEngine)
1969  d->fileEngine = QAbstractFileEngine::create(d->fileName);
1970  return d->fileEngine;
1971 }
1972 
1985 {
1986  Q_D(const QFile);
1987  return d->error;
1988 }
1989 
1995 void
1997 {
1998  Q_D(QFile);
1999  d->setError(QFile::NoError);
2000 }
2001 
double d
Definition: qnumeric_p.h:62
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const
This function should return the set of OR&#39;d flags that are true for the file engine&#39;s file...
QString qt_error_string(int errorCode)
Definition: qglobal.cpp:2600
QString fileName() const
Returns the name set by setFileName() or to the QFile constructors.
Definition: qfile.cpp:470
qint64 writeData(const char *data, qint64 len)
Reimplemented Function
Definition: qfile.cpp:1923
bool rename(const QString &newName)
Renames the file currently specified by fileName() to newName.
Definition: qfile.cpp:766
bool isSequential() const
Returns true if the file can only be manipulated sequentially; otherwise returns false.
Definition: qfile.cpp:1044
static QString fromLocal8Bit(const char *, int size=-1)
Returns a QString initialized with the first size characters of the 8-bit string str.
Definition: qstring.cpp:4245
bool openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
Definition: qfile.cpp:106
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QByteArray(* EncoderFn)(const QString &fileName)
This is a typedef for a pointer to a function with the following signature:
Definition: qfile.h:123
QFile::FileError error
Definition: qfile_p.h:85
const char * readPointer() const
Definition: qringbuffer_p.h:73
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qiodevice.cpp:590
virtual QString fileName(FileName file=DefaultName) const
Return the file engine&#39;s current file name in the format specified by file.
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
static qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer)
Definition: qfile.cpp:1631
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
#define error(msg)
int nextDataBlockSize() const
Definition: qringbuffer_p.h:69
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
The QTemporaryFile class is an I/O device that operates on temporary files.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
virtual QAbstractFileEngine * fileEngine() const
Returns the QIOEngine for this QFile object.
Definition: qfile.cpp:1965
void setError(QFile::FileError err)
Definition: qfile.cpp:167
static QString locale_decode(const QByteArray &f)
Definition: qfile.cpp:76
QString absoluteFilePath() const
Returns an absolute path including the file name.
Definition: qfileinfo.cpp:534
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool exists() const
Returns true if the file exists; otherwise returns false.
Definition: qfileinfo.cpp:675
FileFlag
The permissions and types of a file, suitable for OR&#39;ing together.
QFilePrivate()
Definition: qfile.cpp:92
bool ensureFlushed() const
Definition: qfile.cpp:154
The QString class provides a Unicode character string.
Definition: qstring.h:83
QString normalized(NormalizationForm mode) const Q_REQUIRED_RESULT
Returns the string in the given Unicode normalization mode.
Definition: qstring.cpp:6635
bool resize(qint64 sz)
Sets the file size (in bytes) sz.
Definition: qfile.cpp:1528
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_D(Class)
Definition: qglobal.h:2482
virtual qint64 readLineData(char *data, qint64 maxlen)
Reads up to maxSize characters into data and returns the number of characters read.
Definition: qiodevice.cpp:1285
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition: qfile.cpp:552
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Definition: qfile.cpp:626
QAbstractFileEngine * fileEngine
Definition: qfile_p.h:77
unsigned char uchar
Definition: qglobal.h:994
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isOpen() const
Returns true if the device is open; otherwise returns false.
Definition: qiodevice.cpp:530
qint64 readData(char *data, qint64 maxlen)
Reimplemented Function
Definition: qfile.cpp:1839
virtual bool seek(qint64 pos)
Sets the file position to the given offset.
virtual bool putCharHelper(char c)
Definition: qiodevice.cpp:1494
qint64 readLineData(char *data, qint64 maxlen)
Reimplemented Function
Definition: qfile.cpp:1812
const char * name
bool open(QIODevice::OpenMode openMode)
Reimplemented Function
bool flush()
Flushes any buffered data to the file.
Definition: qfile.cpp:1645
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
Q_CORE_EXPORT void qWarning(const char *,...)
The QAbstractFileEngine class provides an abstraction for accessing the filesystem.
static const char * data(const QByteArray &arr)
qint64 pos() const
Reimplemented Function
Definition: qfile.cpp:1720
QString(* DecoderFn)(const QByteArray &localfileName)
This is a typedef for a pointer to a function with the following signature:
Definition: qfile.h:124
~QFile()
Destroys the file object, closing it if necessary.
Definition: qfile.cpp:459
QString errorString
Definition: qiodevice_p.h:213
__int64 qint64
Definition: qglobal.h:942
static QAbstractFileEngine * create(const QString &fileName)
Creates and returns a QAbstractFileEngine suitable for processing fileName.
static QFile::EncoderFn encoder
Definition: qfile_p.h:93
QByteArray toLocal8Bit() const Q_REQUIRED_RESULT
Returns the local 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4049
int handle() const
Returns the file handle of the file.
Definition: qfile.cpp:1419
static QFile::DecoderFn decoder
Definition: qfile_p.h:94
static const int QFILE_WRITEBUFFER_SIZE
Definition: qfile.cpp:62
qint64 size() const
Returns the size of the file.
Definition: qfile.cpp:1707
static QString tempPath()
Returns the absolute path of the system&#39;s temporary directory.
Definition: qdir.cpp:1987
virtual qint64 write(const char *data, qint64 len)
Writes len bytes from data to the file.
void unsetError()
Sets the file&#39;s error to QFile::NoError.
Definition: qfile.cpp:1996
static void setEncodingFunction(EncoderFn)
Sets the function for encoding Unicode file names.
Definition: qfile.cpp:572
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
void free(int bytes)
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
bool unmap(uchar *address)
Unmaps the memory address.
Definition: qfile.cpp:1485
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
OpenMode openMode() const
Returns the mode in which the device has been opened; i.e.
Definition: qiodevice.cpp:465
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
static QByteArray locale_encode(const QString &f)
Definition: qfile.cpp:64
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
Definition: qiodevice.cpp:752
bool putCharHelper(char c)
Definition: qfile.cpp:1865
bool setPermissions(Permissions permissionSpec)
Sets the permissions for the file to the permissions specified.
Definition: qfile.cpp:1605
QFile()
Definition: qfile.cpp:417
bool copy(const QString &newName)
Copies the file currently specified by fileName() to a file called newName.
Definition: qfile.cpp:926
bool lastWasWrite
Definition: qfile_p.h:79
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
Definition: qiodevice.cpp:570
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
#define Q_OS_WIN
Definition: qglobal.h:270
Permissions permissions() const
Returns the complete OR-ed together combination of QFile::Permission for the file.
Definition: qfile.cpp:1574
static QByteArray encodeName(const QString &fileName)
By default, this function converts fileName to the local 8-bit encoding determined by the user&#39;s loca...
Definition: qfile.cpp:528
void setFileTemplate(const QString &name)
Sets the static portion of the file name to name.
QString readLink() const
Use symLinkTarget() instead.
Definition: qfileinfo.cpp:1110
MemoryMapFlags
This enum describes special options that may be used by the map() function.
Definition: qfile.h:180
FileError
This enum describes the errors that may be returned by the error() function.
Definition: qfile.h:74
FileError error() const
Returns the file error status.
Definition: qfile.cpp:1984
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
Definition: qfile.cpp:1460
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
bool atEnd() const
Returns true if the end of the file has been reached; otherwise returns false.
Definition: qfile.cpp:1735
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
#define qPrintable(string)
Definition: qglobal.h:1750
QString readLink() const
Use symLinkTarget() instead.
Definition: qfile.cpp:671
bool seek(qint64 offset)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qfile.cpp:1784
~QFilePrivate()
Definition: qfile.cpp:99
virtual qint64 size() const
Returns the size of the file.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
static void setDecodingFunction(DecoderFn)
Sets the function for decoding 8-bit file names.
Definition: qfile.cpp:606
void setFileName(const QString &name)
Sets the name of the file.
Definition: qfile.cpp:494
bool link(const QString &newName)
Creates a link named linkName that points to the file currently specified by fileName().
Definition: qfile.cpp:877
The QFSFileEngine class implements Qt&#39;s default file engine.
Definition: qfsfileengine.h:60