Advertisement
Guest User

Untitled

a guest
Oct 3rd, 2017
437
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 51.60 KB | None | 0 0
  1. From 6123a6e8bafbbec3bbce8836540b81b5dc7f751d Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  3. Date: Fri, 5 Aug 2011 10:35:55 +0200
  4. Subject: [PATCH 01/11] Encapsulate pointer manipulations to
  5.  createFileTemplate function
  6.  
  7. , where we actually control how we use the pointers. Reduce some code
  8. duplication in #ifdefs.
  9. ---
  10. src/corelib/io/qtemporaryfile.cpp |   33 ++++++++++++++++++---------------
  11.  1 files changed, 18 insertions(+), 15 deletions(-)
  12.  
  13. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  14. index d457601..9228f94 100644
  15. --- a/src/corelib/io/qtemporaryfile.cpp
  16. +++ b/src/corelib/io/qtemporaryfile.cpp
  17. @@ -96,18 +96,22 @@ QT_BEGIN_NAMESPACE
  18.      \internal
  19.  
  20.      Generates a unique file path and returns a native handle to the open file.
  21. -    \a path is used as a template when generating unique paths,
  22. -    \a placeholderStart and \a placeholderEnd delimit the sub-string that will
  23. -    be randomized.
  24. +    \a path is used as a template when generating unique paths, \a pos
  25. +    identifies the position of the first character that will be replaced in the
  26. +    template and \a length the number of characters that may be substituted.
  27.  
  28.      Returns an open handle to the newly created file if successful, an invalid
  29.      handle otherwise. In both cases, the string in \a path will be changed and
  30.      contain the generated path name.
  31.  */
  32. -static int createFileFromTemplate(char *const path,
  33. -        char *const placeholderStart, char *const placeholderEnd)
  34. +static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  35.  {
  36. -    Q_ASSERT(placeholderEnd > placeholderStart);
  37. +    Q_ASSERT(length != 0);
  38. +    Q_ASSERT(pos < size_t(path.length()));
  39. +    Q_ASSERT(length < size_t(path.length()) - pos);
  40. +
  41. +    char *const placeholderStart = path.data() + pos;
  42. +    char *const placeholderEnd = placeholderStart + length;
  43.  
  44.      // Initialize placeholder with random chars + PID.
  45.      {
  46. @@ -134,14 +138,16 @@ static int createFileFromTemplate(char *const path,
  47.          // Atomically create file and obtain handle
  48.  #ifndef Q_OS_WIN
  49.          {
  50. -            int fd = QT_OPEN(path, QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE, 0600);
  51. +            int fd = QT_OPEN(path.constData(),
  52. +                    QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
  53. +                    0600);
  54.              if (fd != -1)
  55.                  return fd;
  56.              if (errno != EEXIST)
  57.                  return -1;
  58.          }
  59.  #else
  60. -        if (!QFileInfo(QString::fromLocal8Bit(path)).exists())
  61. +        if (!QFileInfo(QString::fromLocal8Bit(path.constData(), path.length())).exists())
  62.              return 1;
  63.  #endif
  64.  
  65. @@ -295,10 +301,9 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  66.      else
  67.          filename.insert(phPos + phLength, suffix.toLocal8Bit());
  68.  
  69. -    char *path = filename.data();
  70. +    int fd = createFileFromTemplate(filename, phPos, phLength);
  71.  
  72.  #ifndef Q_OS_WIN
  73. -    int fd = createFileFromTemplate(path, path + phPos, path + phPos + phLength);
  74.      if (fd != -1) {
  75.          // First open the fd as an external file descriptor to
  76.          // initialize the engine properly.
  77. @@ -308,7 +313,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  78.              d->closeFileHandle = true;
  79.  
  80.              // Restore the file names (open() resets them).
  81. -            d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length())); //note that filename is NOT a native path
  82. +            d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length())); //note that filename is NOT a native path
  83.              filePathIsTemplate = false;
  84.              return true;
  85.          }
  86. @@ -318,13 +323,11 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  87.      setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno));
  88.      return false;
  89.  #else
  90. -    if (createFileFromTemplate(path, path + phPos, path + phPos + phLength) == -1) {
  91. +    if (fd == -1)
  92.          return false;
  93. -    }
  94.  
  95.      QString template_ = d->fileEntry.filePath();
  96. -    d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length()));
  97. -
  98. +    d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length()));
  99.      if (QFSFileEngine::open(openMode)) {
  100.          filePathIsTemplate = false;
  101.          return true;
  102. --
  103. 1.7.5.2
  104.  
  105.  
  106. From c45ba032cba21c4e2fc46c2a0a2e8ee13467dd11 Mon Sep 17 00:00:00 2001
  107. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  108. Date: Fri, 5 Aug 2011 10:39:53 +0200
  109. Subject: [PATCH 02/11] Make Symbian follow Windows code in temporary path
  110.  generation
  111.  
  112. On the one hand, we stop using OpenC here. On the other, we no longer
  113. use an atomic create and obtain file handle API -- just as we don't on
  114. Windows yet.
  115.  
  116. This is a stepping stone to removing back and forth conversions of path
  117. names when generating unique names and also towards the use of native
  118. APIs for creating and obtaining a file handle atomically.
  119.  
  120. Reviewed-by: Gareth Stockwell
  121. Reviewed-by: Shane Kearns
  122. ---
  123. src/corelib/io/qtemporaryfile.cpp |   13 +++++--------
  124.  1 files changed, 5 insertions(+), 8 deletions(-)
  125.  
  126. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  127. index 9228f94..497faad 100644
  128. --- a/src/corelib/io/qtemporaryfile.cpp
  129. +++ b/src/corelib/io/qtemporaryfile.cpp
  130. @@ -49,12 +49,9 @@
  131.  #include "private/qabstractfileengine_p.h"
  132.  #include "private/qfsfileengine_p.h"
  133.  
  134. -#if !defined(Q_OS_WINCE)
  135. -#  include <errno.h>
  136. -#endif
  137. -
  138. -#if defined(Q_OS_UNIX)
  139. -# include "private/qcore_unix_p.h"      // overrides QT_OPEN
  140. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  141. +#include "private/qcore_unix_p.h"       // overrides QT_OPEN
  142. +#include <errno.h>
  143.  #endif
  144.  
  145.  #if defined(QT_BUILD_CORE_LIB)
  146. @@ -136,7 +133,7 @@ static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  147.  
  148.      for (;;) {
  149.          // Atomically create file and obtain handle
  150. -#ifndef Q_OS_WIN
  151. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  152.          {
  153.              int fd = QT_OPEN(path.constData(),
  154.                      QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
  155. @@ -303,7 +300,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  156.  
  157.      int fd = createFileFromTemplate(filename, phPos, phLength);
  158.  
  159. -#ifndef Q_OS_WIN
  160. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  161.      if (fd != -1) {
  162.          // First open the fd as an external file descriptor to
  163.          // initialize the engine properly.
  164. --
  165. 1.7.5.2
  166.  
  167.  
  168. From d15ecfafc54e0a054ab328e5ee2b2ccc858e3bca Mon Sep 17 00:00:00 2001
  169. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  170. Date: Fri, 5 Aug 2011 10:57:19 +0200
  171. Subject: [PATCH 03/11] Use QStringBuilder when copying template for
  172.  modification
  173.  
  174. This avoids modifying the original string in the case where a
  175. placeholder marker is not found. By marking the variable const we
  176. further avoid checks on the reference count and detaches, also allowing
  177. us to safely reuse it later in the function.
  178.  
  179. The new approach also fixes an issue where suffix wasn't empty, but the
  180. toLocal8Bit conversion would be. This resulted in a buffer overflow
  181. inside createFileFromTemplate.
  182.  
  183. Reviewed-by: Shane Kearns
  184. ---
  185. src/corelib/io/qtemporaryfile.cpp |   62 ++++++++++++++++++++++++++++---------
  186.  1 files changed, 47 insertions(+), 15 deletions(-)
  187.  
  188. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  189. index 497faad..b079d3e 100644
  190. --- a/src/corelib/io/qtemporaryfile.cpp
  191. +++ b/src/corelib/io/qtemporaryfile.cpp
  192. @@ -45,6 +45,7 @@
  193.  
  194.  #include "qplatformdefs.h"
  195.  #include "qabstractfileengine.h"
  196. +#include "qstringbuilder.h"
  197.  #include "private/qfile_p.h"
  198.  #include "private/qabstractfileengine_p.h"
  199.  #include "private/qfsfileengine_p.h"
  200. @@ -60,6 +61,38 @@
  201.  
  202.  QT_BEGIN_NAMESPACE
  203.  
  204. +struct Placeholder
  205. +{
  206. +    Placeholder(int size)
  207. +        : size_(size)
  208. +    {
  209. +    }
  210. +
  211. +    int size() const
  212. +    {
  213. +        return size_;
  214. +    }
  215. +
  216. +private:
  217. +    int size_;
  218. +};
  219. +
  220. +template <>
  221. +struct QConcatenable<Placeholder>
  222. +{
  223. +    typedef Placeholder type;
  224. +    typedef QByteArray ConvertTo;
  225. +    enum { ExactSize = true };
  226. +    static int size(const Placeholder &p) { return p.size(); }
  227. +
  228. +    template <class CharT>
  229. +    static inline void appendTo(const Placeholder &p, CharT *&out)
  230. +    {
  231. +        // Uninitialized
  232. +        out += p.size();
  233. +    }
  234. +};
  235. +
  236.  /*
  237.   * Copyright (c) 1987, 1993
  238.   * The Regents of the University of California.  All rights reserved.
  239. @@ -258,7 +291,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  240.      if (!filePathIsTemplate)
  241.          return QFSFileEngine::open(openMode);
  242.  
  243. -    QString qfilename = d->fileEntry.filePath();
  244. +    const QString qfilename = d->fileEntry.filePath();
  245.  
  246.      // Find placeholder string.
  247.      uint phPos = qfilename.length();
  248. @@ -281,22 +314,22 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  249.          phLength = 0;
  250.      }
  251.  
  252. -    QStringRef prefix, suffix;
  253. +    QByteArray filename;
  254. +
  255.      if (phLength < 6) {
  256. -        qfilename += QLatin1Char('.');
  257. -        prefix = QStringRef(&qfilename);
  258. +        filename = qfilename.toLocal8Bit();
  259. +
  260. +        phPos = filename.length() + 1; // Account for added dot in prefix
  261.          phLength = 6;
  262. +        filename = filename % '.' % Placeholder(phLength);
  263.      } else {
  264. -        prefix = qfilename.leftRef(phPos);
  265. -        suffix = qfilename.midRef(phPos + phLength);
  266. -    }
  267. +        QByteArray prefix, suffix;
  268. +        prefix = qfilename.leftRef(phPos).toLocal8Bit();
  269. +        suffix = qfilename.midRef(phPos + phLength).toLocal8Bit();
  270.  
  271. -    QByteArray filename = prefix.toLocal8Bit();
  272. -    phPos = filename.length();
  273. -    if (suffix.isEmpty())
  274. -        filename.resize(phPos + phLength);
  275. -    else
  276. -        filename.insert(phPos + phLength, suffix.toLocal8Bit());
  277. +        phPos = prefix.length();
  278. +        filename = prefix % Placeholder(phLength) % suffix;
  279. +    }
  280.  
  281.      int fd = createFileFromTemplate(filename, phPos, phLength);
  282.  
  283. @@ -323,14 +356,13 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  284.      if (fd == -1)
  285.          return false;
  286.  
  287. -    QString template_ = d->fileEntry.filePath();
  288.      d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length()));
  289.      if (QFSFileEngine::open(openMode)) {
  290.          filePathIsTemplate = false;
  291.          return true;
  292.      }
  293.  
  294. -    d->fileEntry = QFileSystemEntry(template_, QFileSystemEntry::FromInternalPath());
  295. +    d->fileEntry = QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath());
  296.      return false;
  297.  #endif
  298.  }
  299. --
  300. 1.7.5.2
  301.  
  302.  
  303. From 2df98e039e8ffb4858df474e65ef9b250e5b8708 Mon Sep 17 00:00:00 2001
  304. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  305. Date: Fri, 5 Aug 2011 10:58:08 +0200
  306. Subject: [PATCH 04/11] Minimize encoding conversions when generating unique
  307.  file name
  308.  
  309. With minor adjustments, createFileFromTemplate is made to work directly
  310. on (UTF-16) QString data, which is already in the native encoding for
  311. Windows and Symbian. This is possible because the function only fills
  312. out the placeholder sub-string, without touching adjacent characters.
  313.  
  314. This eliminates unnecessary conversions on those platforms.
  315.  
  316. Reviewed-by: Gareth Stockwell
  317. Reviewed-by: Shane Kearns
  318. ---
  319. src/corelib/io/qtemporaryfile.cpp |   69 +++++++++++++++++++++++++++++--------
  320.  1 files changed, 54 insertions(+), 15 deletions(-)
  321.  
  322. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  323. index b079d3e..e4c53aa 100644
  324. --- a/src/corelib/io/qtemporaryfile.cpp
  325. +++ b/src/corelib/io/qtemporaryfile.cpp
  326. @@ -61,6 +61,33 @@
  327.  
  328.  QT_BEGIN_NAMESPACE
  329.  
  330. +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
  331. +typedef ushort Char;
  332. +
  333. +static inline Char Latin1Char(char ch)
  334. +{
  335. +    return ushort(uchar(ch));
  336. +}
  337. +
  338. +template <>
  339. +struct QConcatenable<Char>
  340. +{
  341. +    typedef Char type;
  342. +    typedef QString ConvertTo;
  343. +    enum { ExactSize = true };
  344. +    static int size(const Char &) { return 1; }
  345. +
  346. +    static inline void appendTo(const Char &u16, QChar *&out)
  347. +    {
  348. +        *out++ = QChar(u16);
  349. +    }
  350. +};
  351. +
  352. +#else // POSIX
  353. +typedef char Char;
  354. +typedef char Latin1Char;
  355. +#endif
  356. +
  357.  struct Placeholder
  358.  {
  359.      Placeholder(int size)
  360. @@ -134,23 +161,24 @@ struct QConcatenable<Placeholder>
  361.      handle otherwise. In both cases, the string in \a path will be changed and
  362.      contain the generated path name.
  363.  */
  364. -static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  365. +static int createFileFromTemplate(QFileSystemEntry::NativePath &path,
  366. +        size_t pos, size_t length)
  367.  {
  368.      Q_ASSERT(length != 0);
  369.      Q_ASSERT(pos < size_t(path.length()));
  370.      Q_ASSERT(length < size_t(path.length()) - pos);
  371.  
  372. -    char *const placeholderStart = path.data() + pos;
  373. -    char *const placeholderEnd = placeholderStart + length;
  374. +    Char *const placeholderStart = (Char *)path.data() + pos;
  375. +    Char *const placeholderEnd = placeholderStart + length;
  376.  
  377.      // Initialize placeholder with random chars + PID.
  378.      {
  379. -        char *rIter = placeholderEnd;
  380. +        Char *rIter = placeholderEnd;
  381.  
  382.  #if defined(QT_BUILD_CORE_LIB)
  383.          quint64 pid = quint64(QCoreApplication::applicationPid());
  384.          do {
  385. -            *--rIter = (pid % 10) + '0';
  386. +            *--rIter = Latin1Char((pid % 10) + '0');
  387.              pid /= 10;
  388.          } while (rIter != placeholderStart && pid != 0);
  389.  #endif
  390. @@ -158,9 +186,9 @@ static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  391.          while (rIter != placeholderStart) {
  392.              char ch = char((qrand() & 0xffff) % (26 + 26));
  393.              if (ch < 26)
  394. -                *--rIter = ch + 'A';
  395. +                *--rIter = Latin1Char(ch + 'A');
  396.              else
  397. -                *--rIter = ch - 26 + 'a';
  398. +                *--rIter = Latin1Char(ch - 26 + 'a');
  399.          }
  400.      }
  401.  
  402. @@ -177,18 +205,18 @@ static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  403.                  return -1;
  404.          }
  405.  #else
  406. -        if (!QFileInfo(QString::fromLocal8Bit(path.constData(), path.length())).exists())
  407. +        if (!QFileInfo(path).exists())
  408.              return 1;
  409.  #endif
  410.  
  411.          /* tricky little algorwwithm for backward compatibility */
  412. -        for (char *iter = placeholderStart;;) {
  413. +        for (Char *iter = placeholderStart;;) {
  414.              // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
  415.              // String progression: "ZZaiC" => "aabiC"
  416. -            switch (*iter) {
  417. +            switch (char(*iter)) {
  418.                  case 'Z':
  419.                      // Rollover, advance next character
  420. -                    *iter = 'a';
  421. +                    *iter = Latin1Char('a');
  422.                      if (++iter == placeholderEnd)
  423.                          return -1;
  424.  
  425. @@ -196,12 +224,12 @@ static int createFileFromTemplate(QByteArray &path, size_t pos, size_t length)
  426.  
  427.                  case '0': case '1': case '2': case '3': case '4':
  428.                  case '5': case '6': case '7': case '8': case '9':
  429. -                    *iter = 'a';
  430. +                    *iter = Latin1Char('a');
  431.                      break;
  432.  
  433.                  case 'z':
  434.                      // increment 'z' to 'A'
  435. -                    *iter = 'A';
  436. +                    *iter = Latin1Char('A');
  437.                      break;
  438.  
  439.                  default:
  440. @@ -314,8 +342,9 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  441.          phLength = 0;
  442.      }
  443.  
  444. -    QByteArray filename;
  445. +    QFileSystemEntry::NativePath filename;
  446.  
  447. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  448.      if (phLength < 6) {
  449.          filename = qfilename.toLocal8Bit();
  450.  
  451. @@ -330,6 +359,16 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  452.          phPos = prefix.length();
  453.          filename = prefix % Placeholder(phLength) % suffix;
  454.      }
  455. +#else
  456. +    if (phLength < 6) {
  457. +        phPos = qfilename.length() + 1; // Account for added dot in prefix
  458. +        phLength = 6;
  459. +        filename = qfilename % Latin1Char('.') % Placeholder(phLength);
  460. +    } else
  461. +        filename = qfilename;
  462. +
  463. +    // No native separators, not a "native path"
  464. +#endif
  465.  
  466.      int fd = createFileFromTemplate(filename, phPos, phLength);
  467.  
  468. @@ -356,7 +395,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  469.      if (fd == -1)
  470.          return false;
  471.  
  472. -    d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length()));
  473. +    d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromInternalPath());
  474.      if (QFSFileEngine::open(openMode)) {
  475.          filePathIsTemplate = false;
  476.          return true;
  477. --
  478. 1.7.5.2
  479.  
  480.  
  481. From 7e73761bf45350a49b82db5f7f2514ff440be3c2 Mon Sep 17 00:00:00 2001
  482. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  483. Date: Fri, 5 Aug 2011 10:45:08 +0200
  484. Subject: [PATCH 05/11] Atomic implementation of create file and obtain handle
  485.  for Win/Symbian
  486.  
  487. Besides generating a unique name, createFileFromTemplate now also
  488. acquires a file handle on all platforms. The file engine's native handle
  489. is passed by reference and modified in place.
  490.  
  491. This fixes a long standing security issue on Windows.
  492.  
  493. On Windows and Symbian platforms we directly use the "native" file path
  494. when processing the template and generating the unique name. Since the
  495. native encoding is known, conversions at this point are safe.
  496.  
  497. Errors other than "file exists" are propagated to Q(Temporary)File,
  498. and result in a failure in open(). The changes also unify error handling
  499. and should give consistent behaviour across all platforms.
  500.  
  501. Worthy of note, there's a change in behaviour on Windows and Symbian:
  502. fileNames returned by QTemporaryFile on Windows and Symbian are always
  503. absolute after open has been called. This has to do with how
  504. QFileSystemEntry::nativeFilePath works on these platforms. (Test was
  505. updated to reflect change in behaviour.)
  506.  
  507. Reviewed-by: Gareth Stockwell
  508. Reviewed-by: Shane Kearns
  509. ---
  510. src/corelib/io/qtemporaryfile.cpp                |  151 +++++++++++++++-------
  511.  tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp |   31 +++--
  512.  2 files changed, 122 insertions(+), 60 deletions(-)
  513.  
  514. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  515. index e4c53aa..cd6ab40 100644
  516. --- a/src/corelib/io/qtemporaryfile.cpp
  517. +++ b/src/corelib/io/qtemporaryfile.cpp
  518. @@ -49,6 +49,11 @@
  519.  #include "private/qfile_p.h"
  520.  #include "private/qabstractfileengine_p.h"
  521.  #include "private/qfsfileengine_p.h"
  522. +#include "private/qsystemerror_p.h"
  523. +
  524. +#if defined(Q_OS_SYMBIAN)
  525. +#include "private/qcore_symbian_p.h"
  526. +#endif
  527.  
  528.  #if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  529.  #include "private/qcore_unix_p.h"       // overrides QT_OPEN
  530. @@ -83,9 +88,20 @@ struct QConcatenable<Char>
  531.      }
  532.  };
  533.  
  534. +# ifdef Q_OS_WIN
  535. +typedef HANDLE NativeFileHandle;
  536. +# else // Q_OS_SYMBIAN
  537. +#  ifdef  SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
  538. +typedef RFile64 NativeFileHandle;
  539. +#  else
  540. +typedef RFile NativeFileHandle;
  541. +#  endif
  542. +# endif
  543. +
  544.  #else // POSIX
  545.  typedef char Char;
  546.  typedef char Latin1Char;
  547. +typedef int NativeFileHandle;
  548.  #endif
  549.  
  550.  struct Placeholder
  551. @@ -161,8 +177,9 @@ struct QConcatenable<Placeholder>
  552.      handle otherwise. In both cases, the string in \a path will be changed and
  553.      contain the generated path name.
  554.  */
  555. -static int createFileFromTemplate(QFileSystemEntry::NativePath &path,
  556. -        size_t pos, size_t length)
  557. +static bool createFileFromTemplate(NativeFileHandle &file,
  558. +        QFileSystemEntry::NativePath &path, size_t pos, size_t length,
  559. +        QSystemError &error)
  560.  {
  561.      Q_ASSERT(length != 0);
  562.      Q_ASSERT(pos < size_t(path.length()));
  563. @@ -192,21 +209,50 @@ static int createFileFromTemplate(QFileSystemEntry::NativePath &path,
  564.          }
  565.      }
  566.  
  567. +#ifdef Q_OS_SYMBIAN
  568. +    RFs& fs = qt_s60GetRFs();
  569. +#endif
  570. +
  571.      for (;;) {
  572.          // Atomically create file and obtain handle
  573. -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  574. -        {
  575. -            int fd = QT_OPEN(path.constData(),
  576. -                    QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
  577. -                    0600);
  578. -            if (fd != -1)
  579. -                return fd;
  580. -            if (errno != EEXIST)
  581. -                return -1;
  582. +#if defined(Q_OS_WIN)
  583. +        file = CreateFile((const wchar_t *)path.constData(),
  584. +                GENERIC_READ | GENERIC_WRITE,
  585. +                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
  586. +                FILE_ATTRIBUTE_NORMAL, NULL);
  587. +
  588. +        if (file != INVALID_HANDLE_VALUE)
  589. +            return true;
  590. +
  591. +        DWORD err = GetLastError();
  592. +        if (err != ERROR_FILE_EXISTS) {
  593. +            error = QSystemError(err, QSystemError::NativeError);
  594. +            return false;
  595. +        }
  596. +#elif defined(Q_OS_SYMBIAN)
  597. +        TInt err = file.Create(fs, qt_QString2TPtrC(path),
  598. +                EFileRead | EFileWrite | EFileShareReadersOrWriters);
  599. +
  600. +        if (err == KErrNone)
  601. +            return true;
  602. +
  603. +        if (err != KErrAlreadyExists) {
  604. +            error = QSystemError(err, QSystemError::NativeError);
  605. +            return false;
  606. +        }
  607. +#else // POSIX
  608. +        file = QT_OPEN(path.constData(),
  609. +                QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
  610. +                0600);
  611. +
  612. +        if (file != -1)
  613. +            return true;
  614. +
  615. +        int err = errno;
  616. +        if (err != EEXIST) {
  617. +            error = QSystemError(err, QSystemError::NativeError);
  618. +            return false;
  619.          }
  620. -#else
  621. -        if (!QFileInfo(path).exists())
  622. -            return 1;
  623.  #endif
  624.  
  625.          /* tricky little algorwwithm for backward compatibility */
  626. @@ -217,8 +263,11 @@ static int createFileFromTemplate(QFileSystemEntry::NativePath &path,
  627.                  case 'Z':
  628.                      // Rollover, advance next character
  629.                      *iter = Latin1Char('a');
  630. -                    if (++iter == placeholderEnd)
  631. -                        return -1;
  632. +                    if (++iter == placeholderEnd) {
  633. +                        // Out of alternatives. Return file exists error, previously set.
  634. +                        error = QSystemError(err, QSystemError::NativeError);
  635. +                        return false;
  636. +                    }
  637.  
  638.                      continue;
  639.  
  640. @@ -319,7 +368,14 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  641.      if (!filePathIsTemplate)
  642.          return QFSFileEngine::open(openMode);
  643.  
  644. -    const QString qfilename = d->fileEntry.filePath();
  645. +    const QString qfilename =
  646. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  647. +        // Since the native encoding is out of our control, we need to process
  648. +        // the path as UTF-16 before doing any conversions
  649. +        d->fileEntry.filePath();
  650. +#else
  651. +        d->fileEntry.nativeFilePath();
  652. +#endif
  653.  
  654.      // Find placeholder string.
  655.      uint phPos = qfilename.length();
  656. @@ -333,8 +389,14 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  657.              continue;
  658.          }
  659.  
  660. -        if (qfilename[phPos] == QLatin1Char('/')
  661. -                || phLength >= 6) {
  662. +        if (phLength >= 6
  663. +                || qfilename[phPos] ==
  664. +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  665. +                    QLatin1Char('/')
  666. +#else
  667. +                    QLatin1Char('\\')
  668. +#endif
  669. +                ) {
  670.              ++phPos;
  671.              break;
  672.          }
  673. @@ -366,44 +428,35 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  674.          filename = qfilename % Latin1Char('.') % Placeholder(phLength);
  675.      } else
  676.          filename = qfilename;
  677. -
  678. -    // No native separators, not a "native path"
  679.  #endif
  680.  
  681. -    int fd = createFileFromTemplate(filename, phPos, phLength);
  682. +    QSystemError error;
  683. +#if defined(Q_OS_WIN)
  684. +    NativeFileHandle &file = d->fileHandle;
  685. +#elif defined(Q_OS_SYMBIAN)
  686. +    NativeFileHandle &file = d->symbianFile;
  687. +#else // POSIX
  688. +    NativeFileHandle &file = d->fd;
  689. +#endif
  690.  
  691. -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  692. -    if (fd != -1) {
  693. -        // First open the fd as an external file descriptor to
  694. -        // initialize the engine properly.
  695. -        if (QFSFileEngine::open(openMode, fd)) {
  696. +    if (!createFileFromTemplate(file, filename, phPos, phLength, error)) {
  697. +        setError(QFile::OpenError, error.toString());
  698. +        return false;
  699. +    }
  700.  
  701. -            // Allow the engine to close the handle even if it's "external".
  702. -            d->closeFileHandle = true;
  703. +    d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath());
  704.  
  705. -            // Restore the file names (open() resets them).
  706. -            d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename.constData(), filename.length())); //note that filename is NOT a native path
  707. -            filePathIsTemplate = false;
  708. -            return true;
  709. -        }
  710. +#if !defined(Q_OS_WIN)
  711. +    d->closeFileHandle = true;
  712. +#endif
  713.  
  714. -        QT_CLOSE(fd);
  715. -    }
  716. -    setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno));
  717. -    return false;
  718. -#else
  719. -    if (fd == -1)
  720. -        return false;
  721. +    filePathIsTemplate = false;
  722.  
  723. -    d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromInternalPath());
  724. -    if (QFSFileEngine::open(openMode)) {
  725. -        filePathIsTemplate = false;
  726. -        return true;
  727. -    }
  728. +    d->openMode = openMode;
  729. +    d->lastFlushFailed = false;
  730. +    d->tried_stat = 0;
  731.  
  732. -    d->fileEntry = QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath());
  733. -    return false;
  734. -#endif
  735. +    return true;
  736.  }
  737.  
  738.  bool QTemporaryFileEngine::remove()
  739. diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  740. index 2edb93a..05fee95 100644
  741. --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  742. +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  743. @@ -201,11 +201,12 @@ void tst_QTemporaryFile::fileTemplate()
  744.  
  745.      QCOMPARE(file.open(), true);
  746.  
  747. +    QString fileName = QFileInfo(file).fileName();
  748.      if (prefix.length())
  749. -        QCOMPARE(file.fileName().left(prefix.length()), prefix);
  750. +        QCOMPARE(fileName.left(prefix.length()), prefix);
  751.  
  752.      if (suffix.length())
  753. -        QCOMPARE(file.fileName().right(suffix.length()), suffix);
  754. +        QCOMPARE(fileName.right(suffix.length()), suffix);
  755.  }
  756.  
  757.  
  758. @@ -701,20 +702,28 @@ void tst_QTemporaryFile::QTBUG_4796()
  759.                  << file5.fileName()
  760.                  << file6.fileName();
  761.  
  762. -            QVERIFY(file1.fileName().startsWith(fileTemplate1 + QLatin1Char('.')));
  763. -            QVERIFY(file2.fileName().startsWith(fileTemplate2 + QLatin1Char('.')));
  764. -            QVERIFY(file5.fileName().startsWith("test-XXXXXX/" + fileTemplate1 + QLatin1Char('.')));
  765. -            QVERIFY(file6.fileName().startsWith("test-XXXXXX/" + prefix));
  766. +            QDir currentDir;
  767. +            QString fileName1 = currentDir.relativeFilePath(file1.fileName());
  768. +            QString fileName2 = currentDir.relativeFilePath(file2.fileName());
  769. +            QString fileName3 = currentDir.relativeFilePath(file3.fileName());
  770. +            QString fileName4 = currentDir.relativeFilePath(file4.fileName());
  771. +            QString fileName5 = currentDir.relativeFilePath(file5.fileName());
  772. +            QString fileName6 = currentDir.relativeFilePath(file6.fileName());
  773. +
  774. +            QVERIFY(fileName1.startsWith(fileTemplate1 + QLatin1Char('.')));
  775. +            QVERIFY(fileName2.startsWith(fileTemplate2 + QLatin1Char('.')));
  776. +            QVERIFY(fileName5.startsWith("test-XXXXXX/" + fileTemplate1 + QLatin1Char('.')));
  777. +            QVERIFY(fileName6.startsWith("test-XXXXXX/" + prefix));
  778.  
  779.              if (!prefix.isEmpty()) {
  780. -                QVERIFY(file3.fileName().startsWith(prefix));
  781. -                QVERIFY(file4.fileName().startsWith(prefix));
  782. +                QVERIFY(fileName3.startsWith(prefix));
  783. +                QVERIFY(fileName4.startsWith(prefix));
  784.              }
  785.  
  786.              if (!suffix.isEmpty()) {
  787. -                QVERIFY(file3.fileName().endsWith(suffix));
  788. -                QVERIFY(file4.fileName().endsWith(suffix));
  789. -                QVERIFY(file6.fileName().endsWith(suffix));
  790. +                QVERIFY(fileName3.endsWith(suffix));
  791. +                QVERIFY(fileName4.endsWith(suffix));
  792. +                QVERIFY(fileName6.endsWith(suffix));
  793.              }
  794.          }
  795.      }
  796. --
  797. 1.7.5.2
  798.  
  799.  
  800. From c910587cc28943f3c24a4baa34e8f77352fbce76 Mon Sep 17 00:00:00 2001
  801. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  802. Date: Tue, 16 Aug 2011 16:02:47 +0200
  803. Subject: [PATCH 06/11] Add output on test failure
  804.  
  805. ---
  806. tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp |   43 +++++++++++++---------
  807.  1 files changed, 26 insertions(+), 17 deletions(-)
  808.  
  809. diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  810. index 05fee95..2db5c60 100644
  811. --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  812. +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  813. @@ -412,11 +412,11 @@ void tst_QTemporaryFile::rename()
  814.      {
  815.          QTemporaryFile file(dir.filePath("temporary-file.XXXXXX"));
  816.  
  817. -        QVERIFY(file.open());
  818. +        QVERIFY2(file.open(), qPrintable(file.errorString()));
  819.          tempname = file.fileName();
  820.          QVERIFY(dir.exists(tempname));
  821.  
  822. -        QVERIFY(file.rename("temporary-file.txt"));
  823. +        QVERIFY2(file.rename("temporary-file.txt"), qPrintable(file.errorString()));
  824.          QVERIFY(!dir.exists(tempname));
  825.          QVERIFY(dir.exists("temporary-file.txt"));
  826.          QCOMPARE(file.fileName(), QString("temporary-file.txt"));
  827. @@ -679,12 +679,21 @@ void tst_QTemporaryFile::QTBUG_4796()
  828.          QTemporaryFile file5("test-XXXXXX/" + fileTemplate1);
  829.          QTemporaryFile file6("test-XXXXXX/" + fileTemplate3);
  830.  
  831. -        QCOMPARE(file1.open(), openResult);
  832. -        QCOMPARE(file2.open(), openResult);
  833. -        QCOMPARE(file3.open(), openResult);
  834. -        QCOMPARE(file4.open(), openResult);
  835. -        QCOMPARE(file5.open(), openResult);
  836. -        QCOMPARE(file6.open(), openResult);
  837. +        if (openResult) {
  838. +            QVERIFY2(file1.open(), qPrintable(file1.errorString()));
  839. +            QVERIFY2(file2.open(), qPrintable(file2.errorString()));
  840. +            QVERIFY2(file3.open(), qPrintable(file3.errorString()));
  841. +            QVERIFY2(file4.open(), qPrintable(file4.errorString()));
  842. +            QVERIFY2(file5.open(), qPrintable(file5.errorString()));
  843. +            QVERIFY2(file6.open(), qPrintable(file6.errorString()));
  844. +        } else {
  845. +            QVERIFY(!file1.open());
  846. +            QVERIFY(!file2.open());
  847. +            QVERIFY(!file3.open());
  848. +            QVERIFY(!file4.open());
  849. +            QVERIFY(!file5.open());
  850. +            QVERIFY(!file6.open());
  851. +        }
  852.  
  853.          QCOMPARE(file1.exists(), openResult);
  854.          QCOMPARE(file2.exists(), openResult);
  855. @@ -710,20 +719,20 @@ void tst_QTemporaryFile::QTBUG_4796()
  856.              QString fileName5 = currentDir.relativeFilePath(file5.fileName());
  857.              QString fileName6 = currentDir.relativeFilePath(file6.fileName());
  858.  
  859. -            QVERIFY(fileName1.startsWith(fileTemplate1 + QLatin1Char('.')));
  860. -            QVERIFY(fileName2.startsWith(fileTemplate2 + QLatin1Char('.')));
  861. -            QVERIFY(fileName5.startsWith("test-XXXXXX/" + fileTemplate1 + QLatin1Char('.')));
  862. -            QVERIFY(fileName6.startsWith("test-XXXXXX/" + prefix));
  863. +            QVERIFY2(fileName1.startsWith(fileTemplate1 + QLatin1Char('.')), qPrintable(file1.fileName()));
  864. +            QVERIFY2(fileName2.startsWith(fileTemplate2 + QLatin1Char('.')), qPrintable(file2.fileName()));
  865. +            QVERIFY2(fileName5.startsWith("test-XXXXXX/" + fileTemplate1 + QLatin1Char('.')), qPrintable(file5.fileName()));
  866. +            QVERIFY2(fileName6.startsWith("test-XXXXXX/" + prefix), qPrintable(file6.fileName()));
  867.  
  868.              if (!prefix.isEmpty()) {
  869. -                QVERIFY(fileName3.startsWith(prefix));
  870. -                QVERIFY(fileName4.startsWith(prefix));
  871. +                QVERIFY2(fileName3.startsWith(prefix), qPrintable(file3.fileName()));
  872. +                QVERIFY2(fileName4.startsWith(prefix), qPrintable(file4.fileName()));
  873.              }
  874.  
  875.              if (!suffix.isEmpty()) {
  876. -                QVERIFY(fileName3.endsWith(suffix));
  877. -                QVERIFY(fileName4.endsWith(suffix));
  878. -                QVERIFY(fileName6.endsWith(suffix));
  879. +                QVERIFY2(fileName3.endsWith(suffix), qPrintable(file3.fileName()));
  880. +                QVERIFY2(fileName4.endsWith(suffix), qPrintable(file4.fileName()));
  881. +                QVERIFY2(fileName6.endsWith(suffix), qPrintable(file6.fileName()));
  882.              }
  883.          }
  884.      }
  885. --
  886. 1.7.5.2
  887.  
  888.  
  889. From 1ee92ef77eeb4fd1a4b76faf4e1a1c3bd32dc6b4 Mon Sep 17 00:00:00 2001
  890. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  891. Date: Fri, 5 Aug 2011 10:47:01 +0200
  892. Subject: [PATCH 07/11] Cleanup #includes
  893.  
  894. These are already required and included by qfsfileengine_p.h.
  895. ---
  896. src/corelib/io/qtemporaryfile.cpp |    2 --
  897.  1 files changed, 0 insertions(+), 2 deletions(-)
  898.  
  899. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  900. index cd6ab40..9f7cde2 100644
  901. --- a/src/corelib/io/qtemporaryfile.cpp
  902. +++ b/src/corelib/io/qtemporaryfile.cpp
  903. @@ -44,10 +44,8 @@
  904.  #ifndef QT_NO_TEMPORARYFILE
  905.  
  906.  #include "qplatformdefs.h"
  907. -#include "qabstractfileengine.h"
  908.  #include "qstringbuilder.h"
  909.  #include "private/qfile_p.h"
  910. -#include "private/qabstractfileengine_p.h"
  911.  #include "private/qfsfileengine_p.h"
  912.  #include "private/qsystemerror_p.h"
  913.  
  914. --
  915. 1.7.5.2
  916.  
  917.  
  918. From 3e7fa05d47ffd5a0012b5a512956e6ce386e2fc5 Mon Sep 17 00:00:00 2001
  919. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  920. Date: Fri, 5 Aug 2011 10:49:44 +0200
  921. Subject: [PATCH 08/11] Use "native paths" on POSIX platforms as well
  922.  
  923. And don't rely solely on "local8Bit" conversions.
  924.  
  925. QFile defines an API for overriding how encoding conversions are done
  926. for filenames. In generating unique names, QTemporaryFile ignored that
  927. API and hardcoded the use of local 8-bit, implicitly assuming that that
  928. was appropriate.
  929.  
  930. With this change, we switch that assumption to one where user supplied
  931. encoding function keeps the byte value of 'X' and '/', also assuming
  932. that encoded 'X' takes up a single-byte (i.e., the byte sequence for
  933. "XXXXXX" remains unchanged).
  934.  
  935. There was also, and there still is an assumption in name generation that
  936. byte values for ASCII alpha-numeric characters are valid in the "native"
  937. encoding.
  938.  
  939. In practice this change is compatible with UTF-8, Latin-1 and other
  940. ISO/IEC 8859 encodings. At any rate, it's very likely that only UTF-8 is
  941. relevant here.
  942.  
  943. Reviewed-by: Denis Dzyubenko
  944. ---
  945. src/corelib/io/qtemporaryfile.cpp |   30 +++---------------------------
  946.  1 files changed, 3 insertions(+), 27 deletions(-)
  947.  
  948. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  949. index 9f7cde2..ac5deac 100644
  950. --- a/src/corelib/io/qtemporaryfile.cpp
  951. +++ b/src/corelib/io/qtemporaryfile.cpp
  952. @@ -366,14 +366,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  953.      if (!filePathIsTemplate)
  954.          return QFSFileEngine::open(openMode);
  955.  
  956. -    const QString qfilename =
  957. -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  958. -        // Since the native encoding is out of our control, we need to process
  959. -        // the path as UTF-16 before doing any conversions
  960. -        d->fileEntry.filePath();
  961. -#else
  962. -        d->fileEntry.nativeFilePath();
  963. -#endif
  964. +    const QFileSystemEntry::NativePath qfilename = d->fileEntry.nativeFilePath();
  965.  
  966.      // Find placeholder string.
  967.      uint phPos = qfilename.length();
  968. @@ -382,7 +375,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  969.      while (phPos != 0) {
  970.          --phPos;
  971.  
  972. -        if (qfilename[phPos] == QLatin1Char('X')) {
  973. +        if (qfilename[phPos] == Latin1Char('X')) {
  974.              ++phLength;
  975.              continue;
  976.          }
  977. @@ -390,7 +383,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  978.          if (phLength >= 6
  979.                  || qfilename[phPos] ==
  980.  #if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  981. -                    QLatin1Char('/')
  982. +                    '/'
  983.  #else
  984.                      QLatin1Char('\\')
  985.  #endif
  986. @@ -404,29 +397,12 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  987.  
  988.      QFileSystemEntry::NativePath filename;
  989.  
  990. -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  991. -    if (phLength < 6) {
  992. -        filename = qfilename.toLocal8Bit();
  993. -
  994. -        phPos = filename.length() + 1; // Account for added dot in prefix
  995. -        phLength = 6;
  996. -        filename = filename % '.' % Placeholder(phLength);
  997. -    } else {
  998. -        QByteArray prefix, suffix;
  999. -        prefix = qfilename.leftRef(phPos).toLocal8Bit();
  1000. -        suffix = qfilename.midRef(phPos + phLength).toLocal8Bit();
  1001. -
  1002. -        phPos = prefix.length();
  1003. -        filename = prefix % Placeholder(phLength) % suffix;
  1004. -    }
  1005. -#else
  1006.      if (phLength < 6) {
  1007.          phPos = qfilename.length() + 1; // Account for added dot in prefix
  1008.          phLength = 6;
  1009.          filename = qfilename % Latin1Char('.') % Placeholder(phLength);
  1010.      } else
  1011.          filename = qfilename;
  1012. -#endif
  1013.  
  1014.      QSystemError error;
  1015.  #if defined(Q_OS_WIN)
  1016. --
  1017. 1.7.5.2
  1018.  
  1019.  
  1020. From d0be3224db3b9b59e4df17eddee7eed38e4460c5 Mon Sep 17 00:00:00 2001
  1021. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  1022. Date: Tue, 16 Aug 2011 17:53:41 +0200
  1023. Subject: [PATCH 09/11] Fix QTemporaryFile regressions and new found issues
  1024.  
  1025. With this change, the file template is always processed in original
  1026. QString format. Trying to generate native paths before adding a missing
  1027. placeholder mask could change the meaning of templates, such as "." and
  1028. "..", which are now tested to mean "..XXXXXX" and "...XXXXXX",
  1029. respectively.
  1030.  
  1031. After ensuring the template includes a placeholder mask, the path is
  1032. converted to a native *absolute* file path and the mask is sought for
  1033. again. On Windows, native paths were already absolute. On Symbian, we'd
  1034. need at least a clean path, as "." and ",," are not natively understood.
  1035.  
  1036. There is a requirement that the placeholder mask /XXXXXX+/ makes it
  1037. through this conversion unaltered, which relaxes prior requirements on
  1038. *nix platforms. On Windows and Symbian the conversion is under Qt's
  1039. control and not user-configurable.
  1040.  
  1041. Reviewed-by: Shane Kearns
  1042. ---
  1043. src/corelib/io/qtemporaryfile.cpp                |   84 +++++++++-------------
  1044.  tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp |    2 +
  1045.  2 files changed, 36 insertions(+), 50 deletions(-)
  1046.  
  1047. diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
  1048. index ac5deac..375d07f 100644
  1049. --- a/src/corelib/io/qtemporaryfile.cpp
  1050. +++ b/src/corelib/io/qtemporaryfile.cpp
  1051. @@ -44,10 +44,10 @@
  1052.  #ifndef QT_NO_TEMPORARYFILE
  1053.  
  1054.  #include "qplatformdefs.h"
  1055. -#include "qstringbuilder.h"
  1056.  #include "private/qfile_p.h"
  1057.  #include "private/qfsfileengine_p.h"
  1058.  #include "private/qsystemerror_p.h"
  1059. +#include "private/qfilesystemengine_p.h"
  1060.  
  1061.  #if defined(Q_OS_SYMBIAN)
  1062.  #include "private/qcore_symbian_p.h"
  1063. @@ -102,38 +102,6 @@ typedef char Latin1Char;
  1064.  typedef int NativeFileHandle;
  1065.  #endif
  1066.  
  1067. -struct Placeholder
  1068. -{
  1069. -    Placeholder(int size)
  1070. -        : size_(size)
  1071. -    {
  1072. -    }
  1073. -
  1074. -    int size() const
  1075. -    {
  1076. -        return size_;
  1077. -    }
  1078. -
  1079. -private:
  1080. -    int size_;
  1081. -};
  1082. -
  1083. -template <>
  1084. -struct QConcatenable<Placeholder>
  1085. -{
  1086. -    typedef Placeholder type;
  1087. -    typedef QByteArray ConvertTo;
  1088. -    enum { ExactSize = true };
  1089. -    static int size(const Placeholder &p) { return p.size(); }
  1090. -
  1091. -    template <class CharT>
  1092. -    static inline void appendTo(const Placeholder &p, CharT *&out)
  1093. -    {
  1094. -        // Uninitialized
  1095. -        out += p.size();
  1096. -    }
  1097. -};
  1098. -
  1099.  /*
  1100.   * Copyright (c) 1987, 1993
  1101.   * The Regents of the University of California.  All rights reserved.
  1102. @@ -366,43 +334,59 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
  1103.      if (!filePathIsTemplate)
  1104.          return QFSFileEngine::open(openMode);
  1105.  
  1106. -    const QFileSystemEntry::NativePath qfilename = d->fileEntry.nativeFilePath();
  1107. +    QString qfilename = d->fileEntry.filePath();
  1108.  
  1109. -    // Find placeholder string.
  1110. +    // Ensure there is a placeholder mask
  1111.      uint phPos = qfilename.length();
  1112.      uint phLength = 0;
  1113.  
  1114.      while (phPos != 0) {
  1115.          --phPos;
  1116.  
  1117. -        if (qfilename[phPos] == Latin1Char('X')) {
  1118. +        if (qfilename[phPos] == QLatin1Char('X')) {
  1119.              ++phLength;
  1120.              continue;
  1121.          }
  1122.  
  1123.          if (phLength >= 6
  1124. -                || qfilename[phPos] ==
  1125. -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
  1126. -                    '/'
  1127. -#else
  1128. -                    QLatin1Char('\\')
  1129. -#endif
  1130. -                ) {
  1131. +                || qfilename[phPos] == QLatin1Char('/')) {
  1132.              ++phPos;
  1133.              break;
  1134.          }
  1135.  
  1136. +        // start over
  1137.          phLength = 0;
  1138.      }
  1139.  
  1140. -    QFileSystemEntry::NativePath filename;
  1141. +    if (phLength < 6)
  1142. +        qfilename.append(QLatin1String(".XXXXXX"));
  1143. +
  1144. +    // "Nativify" :-)
  1145. +    QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
  1146. +            QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
  1147. +        .nativeFilePath();
  1148. +
  1149. +    // Find mask in native path
  1150. +    phPos = filename.length();
  1151. +    phLength = 0;
  1152. +    while (phPos != 0) {
  1153. +        --phPos;
  1154. +
  1155. +        if (filename[phPos] == Latin1Char('X')) {
  1156. +            ++phLength;
  1157. +            continue;
  1158. +        }
  1159. +
  1160. +        if (phLength >= 6) {
  1161. +            ++phPos;
  1162. +            break;
  1163. +        }
  1164. +
  1165. +        // start over
  1166. +        phLength = 0;
  1167. +    }
  1168.  
  1169. -    if (phLength < 6) {
  1170. -        phPos = qfilename.length() + 1; // Account for added dot in prefix
  1171. -        phLength = 6;
  1172. -        filename = qfilename % Latin1Char('.') % Placeholder(phLength);
  1173. -    } else
  1174. -        filename = qfilename;
  1175. +    Q_ASSERT(phLength >= 6);
  1176.  
  1177.      QSystemError error;
  1178.  #if defined(Q_OS_WIN)
  1179. diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1180. index 2db5c60..18b9337 100644
  1181. --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1182. +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1183. @@ -632,6 +632,8 @@ void tst_QTemporaryFile::QTBUG_4796_data()
  1184.      QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8");
  1185.  
  1186.      QTest::newRow("<empty>") << QString() << QString() << true;
  1187. +    QTest::newRow(".") << QString(".") << QString() << true;
  1188. +    QTest::newRow("..") << QString("..") << QString() << true;
  1189.      QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true;
  1190.      QTest::newRow("XXXXXXbla") << QString() << QString("bla") << true;
  1191.      QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false;
  1192. --
  1193. 1.7.5.2
  1194.  
  1195.  
  1196. From 72befe44016f283a95aca9faf276e802633e5a76 Mon Sep 17 00:00:00 2001
  1197. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  1198. Date: Wed, 17 Aug 2011 14:38:27 +0200
  1199. Subject: [PATCH 10/11] Cleanup code: removing empty stubs
  1200.  
  1201. ---
  1202. tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp |   29 ----------------------
  1203.  1 files changed, 0 insertions(+), 29 deletions(-)
  1204.  
  1205. diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1206. index 18b9337..11b2bb3 100644
  1207. --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1208. +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1209. @@ -69,13 +69,7 @@
  1210.  class tst_QTemporaryFile : public QObject
  1211.  {
  1212.      Q_OBJECT
  1213. -public:
  1214. -    tst_QTemporaryFile();
  1215. -    virtual ~tst_QTemporaryFile();
  1216.  public slots:
  1217. -    void init();
  1218. -    void cleanup();
  1219. -
  1220.      void initTestCase();
  1221.      void cleanupTestCase();
  1222.  
  1223. @@ -103,8 +97,6 @@ private slots:
  1224.  
  1225.      void QTBUG_4796_data();
  1226.      void QTBUG_4796();
  1227. -
  1228. -public:
  1229.  };
  1230.  
  1231.  void tst_QTemporaryFile::initTestCase()
  1232. @@ -139,27 +131,6 @@ void tst_QTemporaryFile::getSetCheck()
  1233.      QCOMPARE(true, obj1.autoRemove());
  1234.  }
  1235.  
  1236. -tst_QTemporaryFile::tst_QTemporaryFile()
  1237. -{
  1238. -}
  1239. -
  1240. -tst_QTemporaryFile::~tst_QTemporaryFile()
  1241. -{
  1242. -
  1243. -}
  1244. -
  1245. -void tst_QTemporaryFile::init()
  1246. -{
  1247. -// TODO: Add initialization code here.
  1248. -// This will be executed immediately before each test is run.
  1249. -}
  1250. -
  1251. -void tst_QTemporaryFile::cleanup()
  1252. -{
  1253. -// TODO: Add cleanup code here.
  1254. -// This will be executed immediately after each test is run.
  1255. -}
  1256. -
  1257.  void tst_QTemporaryFile::fileTemplate_data()
  1258.  {
  1259.      QTest::addColumn<QString>("constructorTemplate");
  1260. --
  1261. 1.7.5.2
  1262.  
  1263.  
  1264. From efa0c44e9fb2a0c25329eaf8b1582f93f2da5efd Mon Sep 17 00:00:00 2001
  1265. From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= <joao.abecasis@nokia.com>
  1266. Date: Wed, 17 Aug 2011 14:43:18 +0200
  1267. Subject: [PATCH 11/11] Merged fileTemplate test with QTBUG_4796
  1268.  
  1269. The latter was more thorough, but didn't test setting the file template
  1270. after construction, while the former included some prefix/suffix
  1271. combinations that weren't specifically tested in the latter.
  1272.  
  1273. Reviewed-by: ?
  1274. ---
  1275. tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp |  116 +++++++++-------------
  1276.  1 files changed, 48 insertions(+), 68 deletions(-)
  1277.  
  1278. diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1279. index 11b2bb3..c9d4ba4 100644
  1280. --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1281. +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp
  1282. @@ -94,20 +94,17 @@ private slots:
  1283.      void resetTemplateAfterError();
  1284.      void setTemplateAfterOpen();
  1285.      void autoRemoveAfterFailedRename();
  1286. -
  1287. -    void QTBUG_4796_data();
  1288. -    void QTBUG_4796();
  1289.  };
  1290.  
  1291.  void tst_QTemporaryFile::initTestCase()
  1292.  {
  1293. -    // For QTBUG_4796
  1294. +    // For fileTemplate tests
  1295.      QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX"));
  1296.  }
  1297.  
  1298.  void tst_QTemporaryFile::cleanupTestCase()
  1299.  {
  1300. -    // From QTBUG_4796
  1301. +    // From fileTemplate tests
  1302.      QVERIFY(QDir().rmdir("test-XXXXXX"));
  1303.  }
  1304.  
  1305. @@ -131,56 +128,6 @@ void tst_QTemporaryFile::getSetCheck()
  1306.      QCOMPARE(true, obj1.autoRemove());
  1307.  }
  1308.  
  1309. -void tst_QTemporaryFile::fileTemplate_data()
  1310. -{
  1311. -    QTest::addColumn<QString>("constructorTemplate");
  1312. -    QTest::addColumn<QString>("prefix");
  1313. -    QTest::addColumn<QString>("suffix");
  1314. -    QTest::addColumn<QString>("fileTemplate");
  1315. -
  1316. -    QTest::newRow("constructor default") << "" << "." << "" << "";
  1317. -    QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "qt_" << "xxx" << "";
  1318. -    QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "qt_" << "xXx" << "";
  1319. -    QTest::newRow("constructor with no sufix") << "qt_XXXXXX" << "qt_" << "" << "";
  1320. -    QTest::newRow("constructor with >6 X's and xxx suffix") << "qt_XXXXXXXXXXxxx" << "qt_" << "xxx" << "";
  1321. -    QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "qt_" << "" << "";
  1322. -
  1323. -    QTest::newRow("constructor with XXXX suffix") << "qt_XXXXXX_XXXX" << "qt_" << "_XXXX" << "";
  1324. -    QTest::newRow("constructor with XXXXX suffix") << "qt_XXXXXX_XXXXX" << "qt_" << "_XXXXX" << "";
  1325. -    QTest::newRow("constructor with XXXX prefix") << "qt_XXXX" << "qt_XXXX." << "" << "";
  1326. -    QTest::newRow("constructor with XXXXX prefix") << "qt_XXXXX" << "qt_XXXXX." << "" << "";
  1327. -    QTest::newRow("constructor with XXXX  prefix and suffix") << "qt_XXXX_XXXXXX_XXXX" << "qt_XXXX_" << "_XXXX" << "";
  1328. -    QTest::newRow("constructor with XXXXX prefix and suffix") << "qt_XXXXX_XXXXXX_XXXXX" << "qt_XXXXX_" << "_XXXXX" << "";
  1329. -
  1330. -    QTest::newRow("set template, no suffix") << "" << "foo" << "" << "foo";
  1331. -    QTest::newRow("set template, with lowercase XXXXXX") << "" << "qt_" << "xxxxxx" << "qt_XXXXXXxxxxxx";
  1332. -    QTest::newRow("set template, with xxx") << "" << "qt_" << ".xxx" << "qt_XXXXXX.xxx";
  1333. -    QTest::newRow("set template, with >6 X's") << "" << "qt_" << ".xxx" << "qt_XXXXXXXXXXXXXX.xxx";
  1334. -    QTest::newRow("set template, with >6 X's, no suffix") << "" << "qt_" << "" << "qt_XXXXXXXXXXXXXX";
  1335. -}
  1336. -
  1337. -void tst_QTemporaryFile::fileTemplate()
  1338. -{
  1339. -    QFETCH(QString, constructorTemplate);
  1340. -    QFETCH(QString, prefix);
  1341. -    QFETCH(QString, suffix);
  1342. -    QFETCH(QString, fileTemplate);
  1343. -
  1344. -    QTemporaryFile file(constructorTemplate);
  1345. -    if (!fileTemplate.isEmpty())
  1346. -        file.setFileTemplate(fileTemplate);
  1347. -
  1348. -    QCOMPARE(file.open(), true);
  1349. -
  1350. -    QString fileName = QFileInfo(file).fileName();
  1351. -    if (prefix.length())
  1352. -        QCOMPARE(fileName.left(prefix.length()), prefix);
  1353. -
  1354. -    if (suffix.length())
  1355. -        QCOMPARE(fileName.right(suffix.length()), suffix);
  1356. -}
  1357. -
  1358. -
  1359.  /*
  1360.      This tests whether the temporary file really gets placed in QDir::tempPath
  1361.  */
  1362. @@ -594,7 +541,7 @@ void tst_QTemporaryFile::autoRemoveAfterFailedRename()
  1363.      cleaner.reset();
  1364.  }
  1365.  
  1366. -void tst_QTemporaryFile::QTBUG_4796_data()
  1367. +void tst_QTemporaryFile::fileTemplate_data()
  1368.  {
  1369.      QTest::addColumn<QString>("prefix");
  1370.      QTest::addColumn<QString>("suffix");
  1371. @@ -603,17 +550,33 @@ void tst_QTemporaryFile::QTBUG_4796_data()
  1372.      QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8");
  1373.  
  1374.      QTest::newRow("<empty>") << QString() << QString() << true;
  1375. +
  1376.      QTest::newRow(".") << QString(".") << QString() << true;
  1377.      QTest::newRow("..") << QString("..") << QString() << true;
  1378. +
  1379. +    QTest::newRow("foo") << QString("foo") << QString() << true;
  1380. +    QTest::newRow("qt_ ... xxxxxx") << QString("qt_") << QString("xxxxxx") << true;
  1381. +    QTest::newRow("qt_ ... xxx") << QString("qt_") << QString("xxx") << true;
  1382. +    QTest::newRow("qt_ ... xXx") << QString("qt_") << QString("xXx") << true;
  1383. +    QTest::newRow("qt_ ...") << QString("qt_") << QString() << true;
  1384. +    QTest::newRow("qt_ ... _XXXX") << QString("qt_") << QString("_XXXX") << true;
  1385. +    QTest::newRow("qt_ ... _XXXXX") << QString("qt_") << QString("_XXXXX") << true;
  1386. +    QTest::newRow("qt_XXXX_ ...") << QString("qt_XXXX_") << QString() << true;
  1387. +    QTest::newRow("qt_XXXXX_ ...") << QString("qt_XXXXX_") << QString() << true;
  1388. +    QTest::newRow("qt_XXXX_ ... _XXXX") << QString("qt_XXXX_") << QString("_XXXX") << true;
  1389. +    QTest::newRow("qt_XXXXX_ ... _XXXXX") << QString("qt_XXXXX_") << QString("_XXXXX") << true;
  1390. +
  1391.      QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true;
  1392.      QTest::newRow("XXXXXXbla") << QString() << QString("bla") << true;
  1393. +
  1394.      QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false;
  1395. +
  1396.      QTest::newRow("XXXXXX<unicode>") << QString() << unicode << true;
  1397.      QTest::newRow("<unicode>XXXXXX") << unicode << QString() << true;
  1398.      QTest::newRow("<unicode>XXXXXX<unicode>") << unicode << unicode << true;
  1399.  }
  1400.  
  1401. -void tst_QTemporaryFile::QTBUG_4796()
  1402. +void tst_QTemporaryFile::fileTemplate()
  1403.  {
  1404.      QVERIFY(QDir("test-XXXXXX").exists());
  1405.  
  1406. @@ -639,18 +602,40 @@ void tst_QTemporaryFile::QTBUG_4796()
  1407.      QFETCH(QString, suffix);
  1408.      QFETCH(bool, openResult);
  1409.  
  1410. +    enum IterationType {
  1411. +        UseConstructor,
  1412. +        UseSetFileTemplate,
  1413. +        Done
  1414. +    };
  1415. +
  1416. +    for (IterationType setFileTemplate = UseConstructor; setFileTemplate != Done;
  1417. +            setFileTemplate = IterationType(int(setFileTemplate) + 1))
  1418.      {
  1419. +        Q_FOREACH(QString const &tempName, cleaner.tempNames)
  1420. +            QVERIFY( !QFile::exists(tempName) );
  1421. +
  1422. +        cleaner.reset();
  1423. +
  1424.          QString fileTemplate1 = prefix + QString("XX") + suffix;
  1425.          QString fileTemplate2 = prefix + QString("XXXX") + suffix;
  1426.          QString fileTemplate3 = prefix + QString("XXXXXX") + suffix;
  1427.          QString fileTemplate4 = prefix + QString("XXXXXXXX") + suffix;
  1428.  
  1429. -        QTemporaryFile file1(fileTemplate1);
  1430. -        QTemporaryFile file2(fileTemplate2);
  1431. -        QTemporaryFile file3(fileTemplate3);
  1432. -        QTemporaryFile file4(fileTemplate4);
  1433. -        QTemporaryFile file5("test-XXXXXX/" + fileTemplate1);
  1434. -        QTemporaryFile file6("test-XXXXXX/" + fileTemplate3);
  1435. +        QTemporaryFile file1(setFileTemplate ? QString() : fileTemplate1);
  1436. +        QTemporaryFile file2(setFileTemplate ? QString() : fileTemplate2);
  1437. +        QTemporaryFile file3(setFileTemplate ? QString() : fileTemplate3);
  1438. +        QTemporaryFile file4(setFileTemplate ? QString() : fileTemplate4);
  1439. +        QTemporaryFile file5(setFileTemplate ? QString() : "test-XXXXXX/" + fileTemplate1);
  1440. +        QTemporaryFile file6(setFileTemplate ? QString() : "test-XXXXXX/" + fileTemplate3);
  1441. +
  1442. +        if (setFileTemplate) {
  1443. +            file1.setFileTemplate(fileTemplate1);
  1444. +            file2.setFileTemplate(fileTemplate2);
  1445. +            file3.setFileTemplate(fileTemplate3);
  1446. +            file4.setFileTemplate(fileTemplate4);
  1447. +            file5.setFileTemplate("test-XXXXXX/" + fileTemplate1);
  1448. +            file6.setFileTemplate("test-XXXXXX/" + fileTemplate3);
  1449. +        }
  1450.  
  1451.          if (openResult) {
  1452.              QVERIFY2(file1.open(), qPrintable(file1.errorString()));
  1453. @@ -709,11 +694,6 @@ void tst_QTemporaryFile::QTBUG_4796()
  1454.              }
  1455.          }
  1456.      }
  1457. -
  1458. -    Q_FOREACH(QString const &tempName, cleaner.tempNames)
  1459. -        QVERIFY( !QFile::exists(tempName) );
  1460. -
  1461. -    cleaner.reset();
  1462.  }
  1463.  
  1464.  QTEST_MAIN(tst_QTemporaryFile)
  1465. --
  1466. 1.7.5.2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement