Backporting QlockFile. Successful build on Windows.
--HG-- branch : develop
This commit is contained in:
parent
94e2fe8c5a
commit
93eb3d692c
|
@ -430,6 +430,9 @@ DEPENDPATH += $$PWD/../libs/vlayout
|
|||
win32:!win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/vlayout.lib
|
||||
else:unix|win32-g++: PRE_TARGETDEPS += $$OUT_PWD/../libs/vlayout/$${DESTDIR}/libvlayout.a
|
||||
|
||||
# For build qt backport code
|
||||
win32: LIBS+= libole32 libuuid
|
||||
|
||||
|
||||
# Strip after you link all libaries.
|
||||
CONFIG(release, debug|release){
|
||||
|
|
1251
src/app/core/backport/qabstractfileengine.cpp
Normal file
1251
src/app/core/backport/qabstractfileengine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
251
src/app/core/backport/qabstractfileengine_p.h
Normal file
251
src/app/core/backport/qabstractfileengine_p.h
Normal file
|
@ -0,0 +1,251 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QABSTRACTFILEENGINE_P_H
|
||||
#define QABSTRACTFILEENGINE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifdef open
|
||||
#error qabstractfileengine_p.h must be included before any header file that defines open
|
||||
#endif
|
||||
|
||||
class QVariant;
|
||||
class QAbstractFileEngineIterator;
|
||||
class QAbstractFileEnginePrivate;
|
||||
|
||||
class QAbstractFileEngine
|
||||
{
|
||||
public:
|
||||
enum FileFlag {
|
||||
//perms (overlaps the QFile::Permission)
|
||||
ReadOwnerPerm = 0x4000, WriteOwnerPerm = 0x2000, ExeOwnerPerm = 0x1000,
|
||||
ReadUserPerm = 0x0400, WriteUserPerm = 0x0200, ExeUserPerm = 0x0100,
|
||||
ReadGroupPerm = 0x0040, WriteGroupPerm = 0x0020, ExeGroupPerm = 0x0010,
|
||||
ReadOtherPerm = 0x0004, WriteOtherPerm = 0x0002, ExeOtherPerm = 0x0001,
|
||||
|
||||
//types
|
||||
LinkType = 0x10000,
|
||||
FileType = 0x20000,
|
||||
DirectoryType = 0x40000,
|
||||
BundleType = 0x80000,
|
||||
|
||||
//flags
|
||||
HiddenFlag = 0x0100000,
|
||||
LocalDiskFlag = 0x0200000,
|
||||
ExistsFlag = 0x0400000,
|
||||
RootFlag = 0x0800000,
|
||||
Refresh = 0x1000000,
|
||||
|
||||
//masks
|
||||
PermsMask = 0x0000FFFF,
|
||||
TypesMask = 0x000F0000,
|
||||
FlagsMask = 0x0FF00000,
|
||||
FileInfoAll = FlagsMask | PermsMask | TypesMask
|
||||
};
|
||||
Q_DECLARE_FLAGS(FileFlags, FileFlag)
|
||||
|
||||
enum FileName {
|
||||
DefaultName,
|
||||
BaseName,
|
||||
PathName,
|
||||
AbsoluteName,
|
||||
AbsolutePathName,
|
||||
LinkName,
|
||||
CanonicalName,
|
||||
CanonicalPathName,
|
||||
BundleName,
|
||||
NFileNames = 9
|
||||
};
|
||||
enum FileOwner {
|
||||
OwnerUser,
|
||||
OwnerGroup
|
||||
};
|
||||
enum FileTime {
|
||||
CreationTime,
|
||||
ModificationTime,
|
||||
AccessTime
|
||||
};
|
||||
|
||||
virtual ~QAbstractFileEngine();
|
||||
|
||||
virtual bool open(QIODevice::OpenMode openMode);
|
||||
virtual bool close();
|
||||
virtual bool flush();
|
||||
virtual bool syncToDisk();
|
||||
virtual qint64 size() const;
|
||||
virtual qint64 pos() const;
|
||||
virtual bool seek(qint64 pos);
|
||||
virtual bool isSequential() const;
|
||||
virtual bool remove();
|
||||
virtual bool copy(const QString &newName);
|
||||
virtual bool rename(const QString &newName);
|
||||
virtual bool renameOverwrite(const QString &newName);
|
||||
virtual bool link(const QString &newName);
|
||||
virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||
virtual bool setSize(qint64 size);
|
||||
virtual bool caseSensitive() const;
|
||||
virtual bool isRelativePath() const;
|
||||
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const;
|
||||
virtual bool setPermissions(uint perms);
|
||||
virtual QString fileName(FileName file=DefaultName) const;
|
||||
virtual uint ownerId(FileOwner) const;
|
||||
virtual QString owner(FileOwner) const;
|
||||
virtual QDateTime fileTime(FileTime time) const;
|
||||
virtual void setFileName(const QString &file);
|
||||
virtual int handle() const;
|
||||
bool atEnd() const;
|
||||
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
|
||||
bool unmap(uchar *ptr);
|
||||
|
||||
typedef QAbstractFileEngineIterator Iterator;
|
||||
virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||
virtual Iterator *endEntryList();
|
||||
|
||||
virtual qint64 read(char *data, qint64 maxlen);
|
||||
virtual qint64 readLine(char *data, qint64 maxlen);
|
||||
virtual qint64 write(const char *data, qint64 len);
|
||||
|
||||
QFile::FileError error() const;
|
||||
QString errorString() const;
|
||||
|
||||
enum Extension {
|
||||
AtEndExtension,
|
||||
FastReadLineExtension,
|
||||
MapExtension,
|
||||
UnMapExtension
|
||||
};
|
||||
class ExtensionOption
|
||||
{};
|
||||
class ExtensionReturn
|
||||
{};
|
||||
|
||||
class MapExtensionOption : public ExtensionOption {
|
||||
public:
|
||||
qint64 offset;
|
||||
qint64 size;
|
||||
QFile::MemoryMapFlags flags;
|
||||
};
|
||||
class MapExtensionReturn : public ExtensionReturn {
|
||||
public:
|
||||
uchar *address;
|
||||
};
|
||||
|
||||
class UnMapExtensionOption : public ExtensionOption {
|
||||
public:
|
||||
uchar *address;
|
||||
};
|
||||
|
||||
virtual bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||
virtual bool supportsExtension(Extension extension) const;
|
||||
|
||||
// Factory
|
||||
static QAbstractFileEngine *create(const QString &fileName);
|
||||
|
||||
protected:
|
||||
void setError(QFile::FileError error, const QString &str);
|
||||
|
||||
QAbstractFileEngine();
|
||||
QAbstractFileEngine(QAbstractFileEnginePrivate &);
|
||||
|
||||
QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QAbstractFileEngine)
|
||||
Q_DISABLE_COPY(QAbstractFileEngine)
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFileEngine::FileFlags)
|
||||
|
||||
class QAbstractFileEngineHandler
|
||||
{
|
||||
public:
|
||||
QAbstractFileEngineHandler();
|
||||
virtual ~QAbstractFileEngineHandler();
|
||||
virtual QAbstractFileEngine *create(const QString &fileName) const = 0;
|
||||
};
|
||||
|
||||
class QAbstractFileEngineIteratorPrivate;
|
||||
class QAbstractFileEngineIterator
|
||||
{
|
||||
public:
|
||||
QAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters);
|
||||
virtual ~QAbstractFileEngineIterator();
|
||||
|
||||
virtual QString next() = 0;
|
||||
virtual bool hasNext() const = 0;
|
||||
|
||||
QString path() const;
|
||||
QStringList nameFilters() const;
|
||||
QDir::Filters filters() const;
|
||||
|
||||
virtual QString currentFileName() const = 0;
|
||||
virtual QFileInfo currentFileInfo() const;
|
||||
QString currentFilePath() const;
|
||||
|
||||
protected:
|
||||
enum EntryInfoType {
|
||||
};
|
||||
virtual QVariant entryInfo(EntryInfoType type) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QAbstractFileEngineIterator)
|
||||
friend class QDirIterator;
|
||||
friend class QDirIteratorPrivate;
|
||||
void setPath(const QString &path);
|
||||
QScopedPointer<QAbstractFileEngineIteratorPrivate> d;
|
||||
};
|
||||
|
||||
class QAbstractFileEnginePrivate
|
||||
{
|
||||
public:
|
||||
inline QAbstractFileEnginePrivate()
|
||||
: fileError(QFile::UnspecifiedError)
|
||||
{
|
||||
}
|
||||
inline virtual ~QAbstractFileEnginePrivate() { }
|
||||
|
||||
QFile::FileError fileError;
|
||||
QString errorString;
|
||||
|
||||
QAbstractFileEngine *q_ptr;
|
||||
Q_DECLARE_PUBLIC(QAbstractFileEngine)
|
||||
};
|
||||
|
||||
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path);
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QABSTRACTFILEENGINE_P_H
|
61
src/app/core/backport/qcore_mac.cpp
Normal file
61
src/app/core/backport/qcore_mac.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcore_mac_p.h"
|
||||
#include <new>
|
||||
#include <QVarLengthArray>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
QString QCFString::toQString(CFStringRef str)
|
||||
{
|
||||
if(!str)
|
||||
return QString();
|
||||
CFIndex length = CFStringGetLength(str);
|
||||
const UniChar *chars = CFStringGetCharactersPtr(str);
|
||||
if (chars)
|
||||
return QString(reinterpret_cast<const QChar *>(chars), length);
|
||||
|
||||
QVarLengthArray<UniChar> buffer(length);
|
||||
CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
|
||||
return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
|
||||
}
|
||||
|
||||
QCFString::operator QString() const
|
||||
{
|
||||
if (string.isEmpty() && type)
|
||||
const_cast<QCFString*>(this)->string = toQString(type);
|
||||
return string;
|
||||
}
|
||||
|
||||
CFStringRef QCFString::toCFStringRef(const QString &string)
|
||||
{
|
||||
return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
|
||||
string.length());
|
||||
}
|
||||
|
||||
QCFString::operator CFStringRef() const
|
||||
{
|
||||
if (!type)
|
||||
const_cast<QCFString*>(this)->type = toCFStringRef(string);
|
||||
return type;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
131
src/app/core/backport/qcore_mac_p.h
Normal file
131
src/app/core/backport/qcore_mac_p.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QCORE_MAC_P_H
|
||||
#define QCORE_MAC_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of other Qt classes. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef __IMAGECAPTURE__
|
||||
# define __IMAGECAPTURE__
|
||||
#endif
|
||||
|
||||
#if defined(QT_BOOTSTRAPPED)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#else
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_MACX
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#include <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#include <QString>
|
||||
|
||||
#if defined( __OBJC__) && defined(QT_NAMESPACE)
|
||||
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
|
||||
#else
|
||||
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Helper class that automates refernce counting for CFtypes.
|
||||
After constructing the QCFType object, it can be copied like a
|
||||
value-based type.
|
||||
|
||||
Note that you must own the object you are wrapping.
|
||||
This is typically the case if you get the object from a Core
|
||||
Foundation function with the word "Create" or "Copy" in it. If
|
||||
you got the object from a "Get" function, either retain it or use
|
||||
constructFromGet(). One exception to this rule is the
|
||||
HIThemeGet*Shape functions, which in reality are "Copy" functions.
|
||||
*/
|
||||
template <typename T>
|
||||
class QCFType
|
||||
{
|
||||
public:
|
||||
inline QCFType(const T &t = 0) : type(t) {}
|
||||
inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
|
||||
inline ~QCFType() { if (type) CFRelease(type); }
|
||||
inline operator T() { return type; }
|
||||
inline QCFType operator =(const QCFType &helper)
|
||||
{
|
||||
if (helper.type)
|
||||
CFRetain(helper.type);
|
||||
CFTypeRef type2 = type;
|
||||
type = helper.type;
|
||||
if (type2)
|
||||
CFRelease(type2);
|
||||
return *this;
|
||||
}
|
||||
inline T *operator&() { return &type; }
|
||||
template <typename X> X as() const { return reinterpret_cast<X>(type); }
|
||||
static QCFType constructFromGet(const T &t)
|
||||
{
|
||||
CFRetain(t);
|
||||
return QCFType<T>(t);
|
||||
}
|
||||
protected:
|
||||
T type;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
|
||||
{
|
||||
public:
|
||||
inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
|
||||
inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
|
||||
inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
|
||||
operator QString() const;
|
||||
operator CFStringRef() const;
|
||||
static QString toQString(CFStringRef cfstr);
|
||||
static CFStringRef toCFStringRef(const QString &str);
|
||||
#ifdef __OBJC__
|
||||
static QString toQString(const NSString *nsstr);
|
||||
static NSString *toNSString(const QString &string);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString string;
|
||||
};
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
QSysInfo::MacVersion qt_ios_version();
|
||||
#endif
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QCORE_MAC_P_H
|
109
src/app/core/backport/qcore_unix.cpp
Normal file
109
src/app/core/backport/qcore_unix.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcore_unix_p.h"
|
||||
#include "qelapsedtimer.h"
|
||||
|
||||
#ifdef Q_OS_NACL
|
||||
#elif !defined (Q_OS_VXWORKS)
|
||||
# if !defined(Q_OS_HPUX) || defined(__ia64)
|
||||
# include <sys/select.h>
|
||||
# endif
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include <selectLib.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
static inline bool time_update(struct timespec *tv, const struct timespec &start,
|
||||
const struct timespec &timeout)
|
||||
{
|
||||
// clock source is (hopefully) monotonic, so we can recalculate how much timeout is left;
|
||||
// if it isn't monotonic, we'll simply hope that it hasn't jumped, because we have no alternative
|
||||
struct timespec now = qt_gettime();
|
||||
*tv = timeout + start - now;
|
||||
return tv->tv_sec >= 0;
|
||||
}
|
||||
|
||||
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
|
||||
const struct timespec *orig_timeout)
|
||||
{
|
||||
if (!orig_timeout) {
|
||||
// no timeout -> block forever
|
||||
int ret;
|
||||
EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
|
||||
return ret;
|
||||
}
|
||||
|
||||
timespec start = qt_gettime();
|
||||
timespec timeout = *orig_timeout;
|
||||
|
||||
// loop and recalculate the timeout as needed
|
||||
int ret;
|
||||
forever {
|
||||
#ifndef Q_OS_QNX
|
||||
ret = ::pselect(nfds, fdread, fdwrite, fdexcept, &timeout, 0);
|
||||
#else
|
||||
timeval timeoutVal;
|
||||
timeoutVal.tv_sec = timeout.tv_sec;
|
||||
timeoutVal.tv_usec = timeout.tv_nsec / 1000;
|
||||
ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeoutVal);
|
||||
#endif
|
||||
if (ret != -1 || errno != EINTR)
|
||||
return ret;
|
||||
|
||||
// recalculate the timeout
|
||||
if (!time_update(&timeout, start, *orig_timeout)) {
|
||||
// timeout during update
|
||||
// or clock reset, fake timeout error
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
335
src/app/core/backport/qcore_unix_p.h
Normal file
335
src/app/core/backport/qcore_unix_p.h
Normal file
|
@ -0,0 +1,335 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QCORE_UNIX_P_H
|
||||
#define QCORE_UNIX_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of Qt code on Unix. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qatomic.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef Q_OS_UNIX
|
||||
# error "qcore_unix_p.h included on a non-Unix system"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(Q_OS_VXWORKS)
|
||||
# include <ioLib.h>
|
||||
#endif
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
#if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
|
||||
# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
|
||||
|
||||
namespace QtLibcSupplement {
|
||||
inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
|
||||
{ errno = ENOSYS; return -1; }
|
||||
inline int dup3(int, int, int)
|
||||
{ errno = ENOSYS; return -1; }
|
||||
inline int pipe2(int [], int )
|
||||
{ errno = ENOSYS; return -1; }
|
||||
}
|
||||
|
||||
using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
|
||||
|
||||
#else
|
||||
# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#define EINTR_LOOP(var, cmd) \
|
||||
do { \
|
||||
var = cmd; \
|
||||
} while (var == -1 && errno == EINTR)
|
||||
|
||||
|
||||
|
||||
// Internal operator functions for timespecs
|
||||
inline timespec &normalizedTimespec(timespec &t)
|
||||
{
|
||||
while (t.tv_nsec >= 1000000000) {
|
||||
++t.tv_sec;
|
||||
t.tv_nsec -= 1000000000;
|
||||
}
|
||||
while (t.tv_nsec < 0) {
|
||||
--t.tv_sec;
|
||||
t.tv_nsec += 1000000000;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
inline bool operator<(const timespec &t1, const timespec &t2)
|
||||
{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec); }
|
||||
inline bool operator==(const timespec &t1, const timespec &t2)
|
||||
{ return t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec; }
|
||||
inline timespec &operator+=(timespec &t1, const timespec &t2)
|
||||
{
|
||||
t1.tv_sec += t2.tv_sec;
|
||||
t1.tv_nsec += t2.tv_nsec;
|
||||
return normalizedTimespec(t1);
|
||||
}
|
||||
inline timespec operator+(const timespec &t1, const timespec &t2)
|
||||
{
|
||||
timespec tmp;
|
||||
tmp.tv_sec = t1.tv_sec + t2.tv_sec;
|
||||
tmp.tv_nsec = t1.tv_nsec + t2.tv_nsec;
|
||||
return normalizedTimespec(tmp);
|
||||
}
|
||||
inline timespec operator-(const timespec &t1, const timespec &t2)
|
||||
{
|
||||
timespec tmp;
|
||||
tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
|
||||
tmp.tv_nsec = t1.tv_nsec - (t2.tv_nsec + 1000000000);
|
||||
return normalizedTimespec(tmp);
|
||||
}
|
||||
inline timespec operator*(const timespec &t1, int mul)
|
||||
{
|
||||
timespec tmp;
|
||||
tmp.tv_sec = t1.tv_sec * mul;
|
||||
tmp.tv_nsec = t1.tv_nsec * mul;
|
||||
return normalizedTimespec(tmp);
|
||||
}
|
||||
|
||||
inline void qt_ignore_sigpipe()
|
||||
{
|
||||
// Set to ignore SIGPIPE once only.
|
||||
static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
if (!atom.load()) {
|
||||
// More than one thread could turn off SIGPIPE at the same time
|
||||
// But that's acceptable because they all would be doing the same
|
||||
// action
|
||||
struct sigaction noaction;
|
||||
memset(&noaction, 0, sizeof(noaction));
|
||||
noaction.sa_handler = SIG_IGN;
|
||||
::sigaction(SIGPIPE, &noaction, 0);
|
||||
atom.store(1);
|
||||
}
|
||||
}
|
||||
|
||||
// don't call QT_OPEN or ::open
|
||||
// call qt_safe_open
|
||||
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
|
||||
{
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
int fd;
|
||||
EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
|
||||
|
||||
// unknown flags are ignored, so we have no way of verifying if
|
||||
// O_CLOEXEC was accepted
|
||||
if (fd != -1)
|
||||
::fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
return fd;
|
||||
}
|
||||
#undef QT_OPEN
|
||||
#define QT_OPEN qt_safe_open
|
||||
|
||||
#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
|
||||
// don't call ::pipe
|
||||
// call qt_safe_pipe
|
||||
static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
|
||||
{
|
||||
#ifdef O_CLOEXEC
|
||||
Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0);
|
||||
#else
|
||||
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
|
||||
#endif
|
||||
|
||||
int ret;
|
||||
#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
|
||||
// use pipe2
|
||||
flags |= O_CLOEXEC;
|
||||
ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
|
||||
if (ret == 0 || errno != ENOSYS)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
ret = ::pipe(pipefd);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
|
||||
::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
// set non-block too?
|
||||
if (flags & O_NONBLOCK) {
|
||||
::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
|
||||
::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // Q_OS_VXWORKS
|
||||
|
||||
// don't call dup or fcntl(F_DUPFD)
|
||||
static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
|
||||
{
|
||||
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
|
||||
|
||||
int ret;
|
||||
#ifdef F_DUPFD_CLOEXEC
|
||||
// use this fcntl
|
||||
if (flags & FD_CLOEXEC) {
|
||||
ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
|
||||
if (ret != -1 || errno != EINVAL)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// use F_DUPFD
|
||||
ret = ::fcntl(oldfd, F_DUPFD, atleast);
|
||||
|
||||
if (flags && ret != -1)
|
||||
::fcntl(ret, F_SETFD, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// don't call dup2
|
||||
// call qt_safe_dup2
|
||||
static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
|
||||
{
|
||||
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
|
||||
|
||||
int ret;
|
||||
#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
|
||||
// use dup3
|
||||
if (flags & FD_CLOEXEC) {
|
||||
EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
|
||||
if (ret == 0 || errno != ENOSYS)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
EINTR_LOOP(ret, ::dup2(oldfd, newfd));
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
if (flags)
|
||||
::fcntl(newfd, F_SETFD, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
|
||||
{
|
||||
qint64 ret = 0;
|
||||
EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
|
||||
return ret;
|
||||
}
|
||||
#undef QT_READ
|
||||
#define QT_READ qt_safe_read
|
||||
|
||||
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
|
||||
{
|
||||
qint64 ret = 0;
|
||||
EINTR_LOOP(ret, QT_WRITE(fd, data, len));
|
||||
return ret;
|
||||
}
|
||||
#undef QT_WRITE
|
||||
#define QT_WRITE qt_safe_write
|
||||
|
||||
static inline qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
|
||||
{
|
||||
qt_ignore_sigpipe();
|
||||
return qt_safe_write(fd, data, len);
|
||||
}
|
||||
|
||||
static inline int qt_safe_close(int fd)
|
||||
{
|
||||
int ret;
|
||||
EINTR_LOOP(ret, QT_CLOSE(fd));
|
||||
return ret;
|
||||
}
|
||||
#undef QT_CLOSE
|
||||
#define QT_CLOSE qt_safe_close
|
||||
|
||||
// - VxWorks doesn't have processes
|
||||
#if !defined(Q_OS_VXWORKS)
|
||||
static inline int qt_safe_execve(const char *filename, char *const argv[],
|
||||
char *const envp[])
|
||||
{
|
||||
int ret;
|
||||
EINTR_LOOP(ret, ::execve(filename, argv, envp));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int qt_safe_execv(const char *path, char *const argv[])
|
||||
{
|
||||
int ret;
|
||||
EINTR_LOOP(ret, ::execv(path, argv));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int qt_safe_execvp(const char *file, char *const argv[])
|
||||
{
|
||||
int ret;
|
||||
EINTR_LOOP(ret, ::execvp(file, argv));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
|
||||
{
|
||||
int ret;
|
||||
EINTR_LOOP(ret, ::waitpid(pid, status, options));
|
||||
return ret;
|
||||
}
|
||||
#endif // Q_OS_VXWORKS
|
||||
|
||||
#if !defined(_POSIX_MONOTONIC_CLOCK)
|
||||
# define _POSIX_MONOTONIC_CLOCK -1
|
||||
#endif
|
||||
|
||||
// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
|
||||
timespec qt_gettime() Q_DECL_NOTHROW;
|
||||
void qt_nanosleep(timespec amount);
|
||||
|
||||
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timespec *tv);
|
||||
|
||||
// according to X/OPEN we have to define semun ourselves
|
||||
// we use prefix as on some systems sem.h will have it
|
||||
struct semid_ds;
|
||||
union qt_semun {
|
||||
int val; /* value for SETVAL */
|
||||
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
|
||||
unsigned short *array; /* array for GETALL, SETALL */
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif
|
164
src/app/core/backport/qfileinfo_p.h
Normal file
164
src/app/core/backport/qfileinfo_p.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFILEINFO_P_H
|
||||
#define QFILEINFO_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include "qatomic.h"
|
||||
#include <QSharedData>
|
||||
#include "qfilesystemengine_p.h"
|
||||
#include <QVector>
|
||||
|
||||
#include "qabstractfileengine_p.h"
|
||||
#include "qfilesystementry_p.h"
|
||||
#include "qfilesystemmetadata_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QFileInfoPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
|
||||
CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
|
||||
CachedSize =0x08, CachedPerms=0x80 };
|
||||
|
||||
inline QFileInfoPrivate()
|
||||
: QSharedData(), fileEngine(0),
|
||||
cachedFlags(0),
|
||||
isDefaultConstructed(true),
|
||||
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||
{}
|
||||
inline QFileInfoPrivate(const QFileInfoPrivate ©)
|
||||
: QSharedData(copy),
|
||||
fileEntry(copy.fileEntry),
|
||||
metaData(copy.metaData),
|
||||
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||
cachedFlags(0),
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
isDefaultConstructed(false),
|
||||
#else
|
||||
isDefaultConstructed(!fileEngine),
|
||||
#endif
|
||||
cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0)
|
||||
{}
|
||||
inline QFileInfoPrivate(const QString &file)
|
||||
: fileEntry(QDir::fromNativeSeparators(file)),
|
||||
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||
cachedFlags(0),
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
isDefaultConstructed(false),
|
||||
#else
|
||||
isDefaultConstructed(!fileEngine),
|
||||
#endif
|
||||
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data)
|
||||
: QSharedData(),
|
||||
fileEntry(file),
|
||||
metaData(data),
|
||||
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
|
||||
cachedFlags(0),
|
||||
isDefaultConstructed(false),
|
||||
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||
{
|
||||
//If the file engine is not null, this maybe a "mount point" for a custom file engine
|
||||
//in which case we can't trust the metadata
|
||||
if (fileEngine)
|
||||
metaData = QFileSystemMetaData();
|
||||
}
|
||||
|
||||
inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, QAbstractFileEngine *engine)
|
||||
: fileEntry(file),
|
||||
metaData(data),
|
||||
fileEngine(engine),
|
||||
cachedFlags(0),
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
isDefaultConstructed(false),
|
||||
#else
|
||||
isDefaultConstructed(!fileEngine),
|
||||
#endif
|
||||
cache_enabled(true), fileFlags(0), fileSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void clearFlags() const {
|
||||
fileFlags = 0;
|
||||
cachedFlags = 0;
|
||||
if (fileEngine)
|
||||
(void)fileEngine->fileFlags(QAbstractFileEngine::Refresh);
|
||||
}
|
||||
inline void clear() {
|
||||
metaData.clear();
|
||||
clearFlags();
|
||||
for (int i = QAbstractFileEngine::NFileNames - 1 ; i >= 0 ; --i)
|
||||
fileNames[i].clear();
|
||||
fileOwners[1].clear();
|
||||
fileOwners[0].clear();
|
||||
}
|
||||
|
||||
uint getFileFlags(QAbstractFileEngine::FileFlags) const;
|
||||
QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
|
||||
QString getFileName(QAbstractFileEngine::FileName) const;
|
||||
QString getFileOwner(QAbstractFileEngine::FileOwner own) const;
|
||||
|
||||
QFileSystemEntry fileEntry;
|
||||
mutable QFileSystemMetaData metaData;
|
||||
|
||||
QScopedPointer<QAbstractFileEngine> const fileEngine;
|
||||
|
||||
mutable QString fileNames[QAbstractFileEngine::NFileNames];
|
||||
mutable QString fileOwners[2];
|
||||
|
||||
mutable uint cachedFlags : 30;
|
||||
bool const isDefaultConstructed : 1; // QFileInfo is a default constructed instance
|
||||
bool cache_enabled : 1;
|
||||
mutable uint fileFlags;
|
||||
mutable qint64 fileSize;
|
||||
// ### Qt6: FIXME: This vector is essentially a plain array
|
||||
// mutable QDateTime fileTimes[3], but the array is slower
|
||||
// to initialize than the QVector as QDateTime has a pimpl.
|
||||
// In Qt 6, QDateTime should inline its data members,
|
||||
// and this here can be an array again.
|
||||
mutable QVector<QDateTime> fileTimes;
|
||||
inline bool getCachedFlag(uint c) const
|
||||
{ return cache_enabled ? (cachedFlags & c) : 0; }
|
||||
inline void setCachedFlag(uint c) const
|
||||
{ if (cache_enabled) cachedFlags |= c; }
|
||||
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QFILEINFO_P_H
|
403
src/app/core/backport/qfilesystemengine.cpp
Normal file
403
src/app/core/backport/qfilesystemengine.cpp
Normal file
|
@ -0,0 +1,403 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qfilesystemengine_p.h"
|
||||
#include <QDir>
|
||||
#include <QSet>
|
||||
#include <QStringBuilder>
|
||||
#include "qabstractfileengine_p.h"
|
||||
#ifdef QT_BUILD_CORE_LIB
|
||||
#include "qresource_p.h"
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns the canonicalized form of \a path (i.e., with all symlinks
|
||||
resolved, and all redundant path elements removed.
|
||||
*/
|
||||
QString QFileSystemEngine::slowCanonicalized(const QString &path)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return path;
|
||||
|
||||
QFileInfo fi;
|
||||
const QChar slash(QLatin1Char('/'));
|
||||
QString tmpPath = path;
|
||||
int separatorPos = 0;
|
||||
QSet<QString> nonSymlinks;
|
||||
QSet<QString> known;
|
||||
|
||||
known.insert(path);
|
||||
do {
|
||||
#ifdef Q_OS_WIN
|
||||
if (separatorPos == 0) {
|
||||
if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) {
|
||||
// UNC, skip past the first two elements
|
||||
separatorPos = tmpPath.indexOf(slash, 2);
|
||||
} else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) {
|
||||
// volume root, skip since it can not be a symlink
|
||||
separatorPos = 2;
|
||||
}
|
||||
}
|
||||
if (separatorPos != -1)
|
||||
#endif
|
||||
separatorPos = tmpPath.indexOf(slash, separatorPos + 1);
|
||||
QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos);
|
||||
if (!nonSymlinks.contains(prefix)) {
|
||||
fi.setFile(prefix);
|
||||
if (fi.isSymLink()) {
|
||||
QString target = fi.symLinkTarget();
|
||||
if(QFileInfo(target).isRelative())
|
||||
target = fi.absolutePath() + slash + target;
|
||||
if (separatorPos != -1) {
|
||||
if (fi.isDir() && !target.endsWith(slash))
|
||||
target.append(slash);
|
||||
target.append(tmpPath.mid(separatorPos));
|
||||
}
|
||||
tmpPath = QDir::cleanPath(target);
|
||||
separatorPos = 0;
|
||||
|
||||
if (known.contains(tmpPath))
|
||||
return QString();
|
||||
known.insert(tmpPath);
|
||||
} else {
|
||||
nonSymlinks.insert(prefix);
|
||||
}
|
||||
}
|
||||
} while (separatorPos != -1);
|
||||
|
||||
return QDir::cleanPath(tmpPath);
|
||||
}
|
||||
|
||||
static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry)
|
||||
{
|
||||
if (resolvingEntry) {
|
||||
if (!QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute)
|
||||
|| !data.exists()) {
|
||||
data.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry)
|
||||
{
|
||||
if (resolvingEntry) {
|
||||
if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
|
||||
delete engine;
|
||||
engine = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||
QAbstractFileEngine *&engine, bool resolvingEntry = false)
|
||||
{
|
||||
QString const &filePath = entry.filePath();
|
||||
if ((engine = qt_custom_file_engine_handler_create(filePath)))
|
||||
return _q_checkEntry(engine, resolvingEntry);
|
||||
|
||||
#if defined(QT_BUILD_CORE_LIB)
|
||||
for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
|
||||
QChar const ch = filePath[prefixSeparator];
|
||||
if (ch == QLatin1Char('/'))
|
||||
break;
|
||||
|
||||
if (ch == QLatin1Char(':')) {
|
||||
if (prefixSeparator == 0) {
|
||||
engine = new QResourceFileEngine(filePath);
|
||||
return _q_checkEntry(engine, resolvingEntry);
|
||||
}
|
||||
|
||||
if (prefixSeparator == 1)
|
||||
break;
|
||||
|
||||
const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator));
|
||||
for (int i = 0; i < paths.count(); i++) {
|
||||
entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1)));
|
||||
// Recurse!
|
||||
if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true))
|
||||
return true;
|
||||
}
|
||||
|
||||
// entry may have been clobbered at this point.
|
||||
return false;
|
||||
}
|
||||
|
||||
// There's no need to fully validate the prefix here. Consulting the
|
||||
// unicode tables could be expensive and validation is already
|
||||
// performed in QDir::setSearchPaths.
|
||||
//
|
||||
// if (!ch.isLetterOrNumber())
|
||||
// break;
|
||||
}
|
||||
#endif // defined(QT_BUILD_CORE_LIB)
|
||||
|
||||
return _q_checkEntry(entry, data, resolvingEntry);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Resolves the \a entry (see QDir::searchPaths) and returns an engine for
|
||||
it, but never a QFSFileEngine.
|
||||
|
||||
Returns a file engine that can be used to access the entry. Returns 0 if
|
||||
QFileSystemEngine API should be used to query and interact with the file
|
||||
system object.
|
||||
*/
|
||||
QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
|
||||
QFileSystemEntry &entry, QFileSystemMetaData &data) {
|
||||
QFileSystemEntry copy = entry;
|
||||
QAbstractFileEngine *engine = 0;
|
||||
|
||||
if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
|
||||
// Reset entry to resolved copy.
|
||||
entry = copy;
|
||||
else
|
||||
data.clear();
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
//these unix functions are in this file, because they are shared by symbian port
|
||||
//for open C file handles.
|
||||
#ifdef Q_OS_UNIX
|
||||
//static
|
||||
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
|
||||
{
|
||||
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
|
||||
|
||||
QT_STATBUF statBuffer;
|
||||
if (QT_FSTAT(fd, &statBuffer) == 0) {
|
||||
data.fillFromStatBuf(statBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_QNX)
|
||||
static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32)
|
||||
{
|
||||
statBuf64->st_mode = statBuf32.st_mode;
|
||||
statBuf64->st_size = statBuf32.st_size;
|
||||
statBuf64->st_ctime = statBuf32.st_ctime;
|
||||
statBuf64->st_mtime = statBuf32.st_mtime;
|
||||
statBuf64->st_atime = statBuf32.st_atime;
|
||||
statBuf64->st_uid = statBuf32.st_uid;
|
||||
statBuf64->st_gid = statBuf32.st_gid;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
|
||||
{
|
||||
// Permissions
|
||||
if (statBuffer.st_mode & S_IRUSR)
|
||||
entryFlags |= QFileSystemMetaData::OwnerReadPermission;
|
||||
if (statBuffer.st_mode & S_IWUSR)
|
||||
entryFlags |= QFileSystemMetaData::OwnerWritePermission;
|
||||
if (statBuffer.st_mode & S_IXUSR)
|
||||
entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
|
||||
|
||||
if (statBuffer.st_mode & S_IRGRP)
|
||||
entryFlags |= QFileSystemMetaData::GroupReadPermission;
|
||||
if (statBuffer.st_mode & S_IWGRP)
|
||||
entryFlags |= QFileSystemMetaData::GroupWritePermission;
|
||||
if (statBuffer.st_mode & S_IXGRP)
|
||||
entryFlags |= QFileSystemMetaData::GroupExecutePermission;
|
||||
|
||||
if (statBuffer.st_mode & S_IROTH)
|
||||
entryFlags |= QFileSystemMetaData::OtherReadPermission;
|
||||
if (statBuffer.st_mode & S_IWOTH)
|
||||
entryFlags |= QFileSystemMetaData::OtherWritePermission;
|
||||
if (statBuffer.st_mode & S_IXOTH)
|
||||
entryFlags |= QFileSystemMetaData::OtherExecutePermission;
|
||||
|
||||
// Type
|
||||
if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
|
||||
entryFlags |= QFileSystemMetaData::FileType;
|
||||
else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
|
||||
entryFlags |= QFileSystemMetaData::DirectoryType;
|
||||
else
|
||||
entryFlags |= QFileSystemMetaData::SequentialType;
|
||||
|
||||
// Attributes
|
||||
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||
size_ = statBuffer.st_size;
|
||||
#if defined(Q_OS_MACX)
|
||||
if (statBuffer.st_flags & UF_HIDDEN) {
|
||||
entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||
knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Times
|
||||
creationTime_ = statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime;
|
||||
modificationTime_ = statBuffer.st_mtime;
|
||||
accessTime_ = statBuffer.st_atime;
|
||||
userId_ = statBuffer.st_uid;
|
||||
groupId_ = statBuffer.st_gid;
|
||||
}
|
||||
|
||||
void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
|
||||
{
|
||||
#if defined(Q_OS_QNX)
|
||||
knownFlagsMask = 0;
|
||||
entryFlags = 0;
|
||||
for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry);
|
||||
extra = _DEXTRA_NEXT(extra)) {
|
||||
if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
|
||||
|
||||
const struct dirent_extra_stat * const extra_stat =
|
||||
reinterpret_cast<struct dirent_extra_stat *>(extra);
|
||||
|
||||
// Remember whether this was a link or not, this saves an lstat() call later.
|
||||
if (extra->d_type == _DTYPE_LSTAT) {
|
||||
knownFlagsMask |= QFileSystemMetaData::LinkType;
|
||||
if (S_ISLNK(extra_stat->d_stat.st_mode))
|
||||
entryFlags |= QFileSystemMetaData::LinkType;
|
||||
}
|
||||
|
||||
// For symlinks, the extra type _DTYPE_LSTAT doesn't work for filling out the meta data,
|
||||
// as we need the stat() information there, not the lstat() information.
|
||||
// In this case, don't use the extra information.
|
||||
// Unfortunately, readdir() never seems to return extra info of type _DTYPE_STAT, so for
|
||||
// symlinks, we always incur the cost of an extra stat() call later.
|
||||
if (S_ISLNK(extra_stat->d_stat.st_mode) && extra->d_type == _DTYPE_LSTAT)
|
||||
continue;
|
||||
|
||||
#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
|
||||
// Even with large file support, d_stat is always of type struct stat, not struct stat64,
|
||||
// so it needs to be converted
|
||||
struct stat64 statBuf;
|
||||
fillStat64fromStat32(&statBuf, extra_stat->d_stat);
|
||||
fillFromStatBuf(statBuf);
|
||||
#else
|
||||
fillFromStatBuf(extra_stat->d_stat);
|
||||
#endif
|
||||
knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
|
||||
if (!S_ISLNK(extra_stat->d_stat.st_mode)) {
|
||||
knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||
entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
|
||||
// BSD4 includes Mac OS X
|
||||
|
||||
// ### This will clear all entry flags and knownFlagsMask
|
||||
switch (entry.d_type)
|
||||
{
|
||||
case DT_DIR:
|
||||
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||
| QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::SequentialType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
entryFlags = QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
break;
|
||||
|
||||
case DT_BLK:
|
||||
case DT_CHR:
|
||||
case DT_FIFO:
|
||||
case DT_SOCK:
|
||||
// ### System attribute
|
||||
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||
| QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::BundleType
|
||||
| QFileSystemMetaData::AliasType
|
||||
| QFileSystemMetaData::SequentialType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
entryFlags = QFileSystemMetaData::SequentialType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
break;
|
||||
|
||||
case DT_LNK:
|
||||
knownFlagsMask = QFileSystemMetaData::LinkType;
|
||||
entryFlags = QFileSystemMetaData::LinkType;
|
||||
break;
|
||||
|
||||
case DT_REG:
|
||||
knownFlagsMask = QFileSystemMetaData::LinkType
|
||||
| QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::BundleType
|
||||
| QFileSystemMetaData::SequentialType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
entryFlags = QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
break;
|
||||
|
||||
case DT_UNKNOWN:
|
||||
default:
|
||||
clear();
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(entry)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
Q_UNUSED(metaData);
|
||||
return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerUser);
|
||||
#else //(Q_OS_UNIX)
|
||||
if (!metaData.hasFlags(QFileSystemMetaData::UserId))
|
||||
QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::UserId);
|
||||
return resolveUserName(metaData.userId());
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
Q_UNUSED(metaData);
|
||||
return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerGroup);
|
||||
#else //(Q_OS_UNIX)
|
||||
if (!metaData.hasFlags(QFileSystemMetaData::GroupId))
|
||||
QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::GroupId);
|
||||
return resolveGroupName(metaData.groupId());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
120
src/app/core/backport/qfilesystemengine_p.h
Normal file
120
src/app/core/backport/qfilesystemengine_p.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFILESYSTEMENGINE_P_H
|
||||
#define QFILESYSTEMENGINE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QFile>
|
||||
#include "qfilesystementry_p.h"
|
||||
#include "qfilesystemmetadata_p.h"
|
||||
#include "qsystemerror_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QFileSystemEngine
|
||||
{
|
||||
public:
|
||||
static bool isCaseSensitive()
|
||||
{
|
||||
#ifndef Q_OS_WIN
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data);
|
||||
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||
static QFileSystemEntry absoluteName(const QFileSystemEntry &entry);
|
||||
static QByteArray id(const QFileSystemEntry &entry);
|
||||
static QString resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||
static QString resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &data);
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
static QString resolveUserName(uint userId);
|
||||
static QString resolveGroupName(uint groupId);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
static QString bundleName(const QFileSystemEntry &entry);
|
||||
#else
|
||||
static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
|
||||
#endif
|
||||
|
||||
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
#if defined(Q_OS_UNIX)
|
||||
static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
static bool uncListSharesOnServer(const QString &server, QStringList *list); //Used also by QFSFileEngineIterator::hasNext()
|
||||
static bool fillMetaData(int fd, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
static bool fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
|
||||
static QString nativeAbsoluteFilePath(const QString &path);
|
||||
#endif
|
||||
//homePath, rootPath and tempPath shall return clean paths
|
||||
static QString homePath();
|
||||
static QString rootPath();
|
||||
static QString tempPath();
|
||||
|
||||
static bool createDirectory(const QFileSystemEntry &entry, bool createParents);
|
||||
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents);
|
||||
|
||||
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||
|
||||
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
|
||||
|
||||
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
|
||||
QFileSystemMetaData *data = 0);
|
||||
|
||||
static bool setCurrentPath(const QFileSystemEntry &entry);
|
||||
static QFileSystemEntry currentPath();
|
||||
|
||||
static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
|
||||
QFileSystemMetaData &data);
|
||||
private:
|
||||
static QString slowCanonicalized(const QString &path);
|
||||
#if defined(Q_OS_WIN)
|
||||
static void clearWinStatData(QFileSystemMetaData &data);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // include guard
|
756
src/app/core/backport/qfilesystemengine_unix.cpp
Normal file
756
src/app/core/backport/qfilesystemengine_unix.cpp
Normal file
|
@ -0,0 +1,756 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>>
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qfilesystemengine_p.h"
|
||||
#include <QFile>
|
||||
|
||||
#include <QVarLengthArray>
|
||||
|
||||
#include <stdlib.h> // for realpath()
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
# include "qcore_mac_p.h"
|
||||
# include <CoreFoundation/CFBundle.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
static inline bool _q_isMacHidden(const char *nativePath)
|
||||
{
|
||||
OSErr err;
|
||||
|
||||
FSRef fsRef;
|
||||
err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath),
|
||||
kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
|
||||
if (err != noErr)
|
||||
return false;
|
||||
|
||||
FSCatalogInfo catInfo;
|
||||
err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL);
|
||||
if (err != noErr)
|
||||
return false;
|
||||
|
||||
FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
|
||||
return (fileInfo->finderFlags & kIsInvisible);
|
||||
}
|
||||
|
||||
static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
|
||||
{
|
||||
if (!data.isDirectory())
|
||||
return false;
|
||||
|
||||
QFileInfo info(entry.filePath());
|
||||
QString suffix = info.suffix();
|
||||
|
||||
// First step: is the extenstion known ?
|
||||
if (suffix == QLatin1String("app")
|
||||
|| suffix == QLatin1String("debug")
|
||||
|| suffix == QLatin1String("profile")
|
||||
|| suffix == QLatin1String("bundle")
|
||||
|| suffix == QLatin1String("pkg")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Second step: check if an application knows the package type
|
||||
const QByteArray &native = entry.nativeFilePath();
|
||||
const char *nativeFilePath = native.constData();
|
||||
int nativeFilePathLength = native.size();
|
||||
|
||||
QCFType<CFStringRef> path = CFStringCreateWithBytes(0,
|
||||
reinterpret_cast<const UInt8*>(nativeFilePath),
|
||||
nativeFilePathLength,
|
||||
kCFStringEncodingUTF8,
|
||||
false);
|
||||
|
||||
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true);
|
||||
|
||||
UInt32 type, creator;
|
||||
// Well created packages have the PkgInfo file
|
||||
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
|
||||
return true;
|
||||
|
||||
// Find if an application other than Finder claims to know how to handle the package
|
||||
if (suffix.length() > 0) {
|
||||
QCFType<CFURLRef> application;
|
||||
LSGetApplicationForURL(url,
|
||||
kLSRolesEditor|kLSRolesViewer|kLSRolesViewer,
|
||||
NULL,
|
||||
&application);
|
||||
|
||||
if (application) {
|
||||
CFStringRef path = CFURLGetString(application);
|
||||
QString applicationPath = QCFString::toQString(path);
|
||||
if (applicationPath != QLatin1String("file://localhost/System/Library/CoreServices/Finder.app/"))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Third step: check if the directory has the package bit set
|
||||
FSRef packageRef;
|
||||
FSPathMakeRef((UInt8 *)nativeFilePath, &packageRef, NULL);
|
||||
|
||||
FSCatalogInfo catalogInfo;
|
||||
FSGetCatalogInfo(&packageRef,
|
||||
kFSCatInfoFinderInfo,
|
||||
&catalogInfo,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
FolderInfo *folderInfo = reinterpret_cast<FolderInfo *>(catalogInfo.finderInfo);
|
||||
return folderInfo->finderFlags & kHasBundle;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline bool _q_isMacHidden(const char *nativePath)
|
||||
{
|
||||
Q_UNUSED(nativePath);
|
||||
// no-op
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//static
|
||||
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
|
||||
{
|
||||
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||
#define PATH_CHUNK_SIZE 256
|
||||
char *s = 0;
|
||||
int len = -1;
|
||||
int size = PATH_CHUNK_SIZE;
|
||||
|
||||
while (1) {
|
||||
s = (char *) ::realloc(s, size);
|
||||
Q_CHECK_PTR(s);
|
||||
len = ::readlink(link.nativeFilePath().constData(), s, size);
|
||||
if (len < 0) {
|
||||
::free(s);
|
||||
break;
|
||||
}
|
||||
if (len < size) {
|
||||
break;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
#else
|
||||
char s[PATH_MAX+1];
|
||||
int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX);
|
||||
#endif
|
||||
if (len > 0) {
|
||||
QString ret;
|
||||
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
||||
fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
|
||||
if (data.isDirectory() && s[0] != '/') {
|
||||
QDir parent(link.filePath());
|
||||
parent.cdUp();
|
||||
ret = parent.path();
|
||||
if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
|
||||
ret += QLatin1Char('/');
|
||||
}
|
||||
s[len] = '\0';
|
||||
ret += QFile::decodeName(QByteArray(s));
|
||||
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||
::free(s);
|
||||
#endif
|
||||
|
||||
if (!ret.startsWith(QLatin1Char('/'))) {
|
||||
if (link.filePath().startsWith(QLatin1Char('/'))) {
|
||||
ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/')))
|
||||
+ QLatin1Char('/'));
|
||||
} else {
|
||||
ret.prepend(QDir::currentPath() + QLatin1Char('/'));
|
||||
}
|
||||
}
|
||||
ret = QDir::cleanPath(ret);
|
||||
if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
|
||||
ret.chop(1);
|
||||
return QFileSystemEntry(ret);
|
||||
}
|
||||
#if defined(Q_OS_MACX)
|
||||
{
|
||||
FSRef fref;
|
||||
if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) {
|
||||
// TODO get the meta data info from the QFileSystemMetaData object
|
||||
Boolean isAlias, isFolder;
|
||||
if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) {
|
||||
AliasHandle alias;
|
||||
if (FSNewAlias(0, &fref, &alias) == noErr && alias) {
|
||||
QCFString cfstr;
|
||||
if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr)
|
||||
return QFileSystemEntry(QCFString::toQString(cfstr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return QFileSystemEntry();
|
||||
}
|
||||
|
||||
//static
|
||||
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
|
||||
{
|
||||
if (entry.isEmpty() || entry.isRoot())
|
||||
return entry;
|
||||
|
||||
#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && _POSIX_VERSION < 200809L
|
||||
// realpath(X,0) is not supported
|
||||
Q_UNUSED(data);
|
||||
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
|
||||
#else
|
||||
char *ret = 0;
|
||||
# if defined(Q_OS_MACX)
|
||||
// When using -mmacosx-version-min=10.4, we get the legacy realpath implementation,
|
||||
// which does not work properly with the realpath(X,0) form. See QTBUG-28282.
|
||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
|
||||
ret = (char*)malloc(PATH_MAX + 1);
|
||||
if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
||||
const int savedErrno = errno; // errno is checked below, and free() might change it
|
||||
free(ret);
|
||||
errno = savedErrno;
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
// on 10.5 we can use FSRef to resolve the file path.
|
||||
QString path = QDir::cleanPath(entry.filePath());
|
||||
FSRef fsref;
|
||||
if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) {
|
||||
CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref);
|
||||
CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle);
|
||||
QString ret = QCFString::toQString(canonicalPath);
|
||||
CFRelease(canonicalPath);
|
||||
CFRelease(urlref);
|
||||
return QFileSystemEntry(ret);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# if _POSIX_VERSION >= 200801L
|
||||
ret = realpath(entry.nativeFilePath().constData(), (char*)0);
|
||||
# else
|
||||
ret = (char*)malloc(PATH_MAX + 1);
|
||||
if (realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
|
||||
const int savedErrno = errno; // errno is checked below, and free() might change it
|
||||
free(ret);
|
||||
errno = savedErrno;
|
||||
ret = 0;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
if (ret) {
|
||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||
QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret));
|
||||
free(ret);
|
||||
return QFileSystemEntry(canonicalPath);
|
||||
} else if (errno == ENOENT) { // file doesn't exist
|
||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||
data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute);
|
||||
return QFileSystemEntry();
|
||||
}
|
||||
return entry;
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
|
||||
{
|
||||
if (entry.isAbsolute() && entry.isClean())
|
||||
return entry;
|
||||
|
||||
QByteArray orig = entry.nativeFilePath();
|
||||
QByteArray result;
|
||||
if (orig.isEmpty() || !orig.startsWith('/')) {
|
||||
QFileSystemEntry cur(currentPath());
|
||||
result = cur.nativeFilePath();
|
||||
}
|
||||
if (!orig.isEmpty() && !(orig.length() == 1 && orig[0] == '.')) {
|
||||
if (!result.isEmpty() && !result.endsWith('/'))
|
||||
result.append('/');
|
||||
result.append(orig);
|
||||
}
|
||||
|
||||
if (result.length() == 1 && result[0] == '/')
|
||||
return QFileSystemEntry(result, QFileSystemEntry::FromNativePath());
|
||||
const bool isDir = result.endsWith('/');
|
||||
|
||||
/* as long as QDir::cleanPath() operates on a QString we have to convert to a string here.
|
||||
* ideally we never convert to a string since that loses information. Please fix after
|
||||
* we get a QByteArray version of QDir::cleanPath()
|
||||
*/
|
||||
QFileSystemEntry resultingEntry(result, QFileSystemEntry::FromNativePath());
|
||||
QString stringVersion = QDir::cleanPath(resultingEntry.filePath());
|
||||
if (isDir)
|
||||
stringVersion.append(QLatin1Char('/'));
|
||||
return QFileSystemEntry(stringVersion);
|
||||
}
|
||||
|
||||
//static
|
||||
QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
||||
{
|
||||
struct stat statResult;
|
||||
if (stat(entry.nativeFilePath().constData(), &statResult)) {
|
||||
qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData());
|
||||
return QByteArray();
|
||||
}
|
||||
QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16);
|
||||
result += ':';
|
||||
result += QByteArray::number(quint64(statResult.st_ino));
|
||||
return result;
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::resolveUserName(uint userId)
|
||||
{
|
||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (size_max == -1)
|
||||
size_max = 1024;
|
||||
QVarLengthArray<char, 1024> buf(size_max);
|
||||
#endif
|
||||
|
||||
struct passwd *pw = 0;
|
||||
#if !defined(Q_OS_INTEGRITY)
|
||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
|
||||
struct passwd entry;
|
||||
getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw);
|
||||
#else
|
||||
pw = getpwuid(userId);
|
||||
#endif
|
||||
#endif
|
||||
if (pw)
|
||||
return QFile::decodeName(QByteArray(pw->pw_name));
|
||||
return QString();
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::resolveGroupName(uint groupId)
|
||||
{
|
||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
|
||||
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (size_max == -1)
|
||||
size_max = 1024;
|
||||
QVarLengthArray<char, 1024> buf(size_max);
|
||||
#endif
|
||||
|
||||
struct group *gr = 0;
|
||||
#if !defined(Q_OS_INTEGRITY)
|
||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
|
||||
size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
if (size_max == -1)
|
||||
size_max = 1024;
|
||||
buf.resize(size_max);
|
||||
struct group entry;
|
||||
// Some large systems have more members than the POSIX max size
|
||||
// Loop over by doubling the buffer size (upper limit 250k)
|
||||
for (unsigned size = size_max; size < 256000; size += size)
|
||||
{
|
||||
buf.resize(size);
|
||||
// ERANGE indicates that the buffer was too small
|
||||
if (!getgrgid_r(groupId, &entry, buf.data(), buf.size(), &gr)
|
||||
|| errno != ERANGE)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
gr = getgrgid(groupId);
|
||||
#endif
|
||||
#endif
|
||||
if (gr)
|
||||
return QFile::decodeName(QByteArray(gr->gr_name));
|
||||
return QString();
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
//static
|
||||
QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
|
||||
{
|
||||
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(entry.filePath()),
|
||||
kCFURLPOSIXPathStyle, true);
|
||||
if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(url)) {
|
||||
if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
|
||||
if (CFGetTypeID(name) == CFStringGetTypeID())
|
||||
return QCFString::toQString((CFStringRef)name);
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
#endif
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what)
|
||||
{
|
||||
#if defined(Q_OS_MACX)
|
||||
if (what & QFileSystemMetaData::BundleType) {
|
||||
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
|
||||
what |= QFileSystemMetaData::DirectoryType;
|
||||
}
|
||||
if (what & QFileSystemMetaData::HiddenAttribute) {
|
||||
// Mac OS >= 10.5: st_flags & UF_HIDDEN
|
||||
what |= QFileSystemMetaData::PosixStatFlags;
|
||||
}
|
||||
#endif // defined(Q_OS_MACX)
|
||||
|
||||
if (what & QFileSystemMetaData::PosixStatFlags)
|
||||
what |= QFileSystemMetaData::PosixStatFlags;
|
||||
|
||||
if (what & QFileSystemMetaData::ExistsAttribute) {
|
||||
// FIXME: Would other queries being performed provide this bit?
|
||||
what |= QFileSystemMetaData::PosixStatFlags;
|
||||
}
|
||||
|
||||
data.entryFlags &= ~what;
|
||||
|
||||
const char * nativeFilePath;
|
||||
int nativeFilePathLength;
|
||||
{
|
||||
const QByteArray &path = entry.nativeFilePath();
|
||||
nativeFilePath = path.constData();
|
||||
nativeFilePathLength = path.size();
|
||||
Q_UNUSED(nativeFilePathLength);
|
||||
}
|
||||
|
||||
bool entryExists = true; // innocent until proven otherwise
|
||||
|
||||
QT_STATBUF statBuffer;
|
||||
bool statBufferValid = false;
|
||||
if (what & QFileSystemMetaData::LinkType) {
|
||||
if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
|
||||
if (S_ISLNK(statBuffer.st_mode)) {
|
||||
data.entryFlags |= QFileSystemMetaData::LinkType;
|
||||
} else {
|
||||
statBufferValid = true;
|
||||
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||
}
|
||||
} else {
|
||||
entryExists = false;
|
||||
}
|
||||
|
||||
data.knownFlagsMask |= QFileSystemMetaData::LinkType;
|
||||
}
|
||||
|
||||
if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
|
||||
if (entryExists && !statBufferValid)
|
||||
statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
|
||||
|
||||
if (statBufferValid)
|
||||
data.fillFromStatBuf(statBuffer);
|
||||
else {
|
||||
entryExists = false;
|
||||
data.creationTime_ = 0;
|
||||
data.modificationTime_ = 0;
|
||||
data.accessTime_ = 0;
|
||||
data.size_ = 0;
|
||||
data.userId_ = (uint) -2;
|
||||
data.groupId_ = (uint) -2;
|
||||
}
|
||||
|
||||
// reset the mask
|
||||
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
if (what & QFileSystemMetaData::AliasType)
|
||||
{
|
||||
if (entryExists) {
|
||||
FSRef fref;
|
||||
if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) {
|
||||
Boolean isAlias, isFolder;
|
||||
if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) {
|
||||
if (isAlias)
|
||||
data.entryFlags |= QFileSystemMetaData::AliasType;
|
||||
}
|
||||
}
|
||||
}
|
||||
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (what & QFileSystemMetaData::UserPermissions) {
|
||||
// calculate user permissions
|
||||
|
||||
if (entryExists) {
|
||||
if (what & QFileSystemMetaData::UserReadPermission) {
|
||||
if (QT_ACCESS(nativeFilePath, R_OK) == 0)
|
||||
data.entryFlags |= QFileSystemMetaData::UserReadPermission;
|
||||
}
|
||||
if (what & QFileSystemMetaData::UserWritePermission) {
|
||||
if (QT_ACCESS(nativeFilePath, W_OK) == 0)
|
||||
data.entryFlags |= QFileSystemMetaData::UserWritePermission;
|
||||
}
|
||||
if (what & QFileSystemMetaData::UserExecutePermission) {
|
||||
if (QT_ACCESS(nativeFilePath, X_OK) == 0)
|
||||
data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
|
||||
}
|
||||
}
|
||||
data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions);
|
||||
}
|
||||
|
||||
if (what & QFileSystemMetaData::HiddenAttribute
|
||||
&& !data.isHidden()) {
|
||||
QString fileName = entry.fileName();
|
||||
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
||||
|| (entryExists && _q_isMacHidden(nativeFilePath)))
|
||||
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
if (what & QFileSystemMetaData::BundleType) {
|
||||
if (entryExists && isPackage(data, entry))
|
||||
data.entryFlags |= QFileSystemMetaData::BundleType;
|
||||
|
||||
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
||||
}
|
||||
#endif
|
||||
if (!entryExists) {
|
||||
data.clearFlags(what);
|
||||
return false;
|
||||
}
|
||||
return data.hasFlags(what);
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents)
|
||||
{
|
||||
QString dirName = entry.filePath();
|
||||
if (createParents) {
|
||||
dirName = QDir::cleanPath(dirName);
|
||||
for (int oldslash = -1, slash=0; slash != -1; oldslash = slash) {
|
||||
slash = dirName.indexOf(QDir::separator(), oldslash+1);
|
||||
if (slash == -1) {
|
||||
if (oldslash == dirName.length())
|
||||
break;
|
||||
slash = dirName.length();
|
||||
}
|
||||
if (slash) {
|
||||
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
|
||||
if (QT_MKDIR(chunk.constData(), 0777) != 0) {
|
||||
if (errno == EEXIST
|
||||
#if defined(Q_OS_QNX)
|
||||
// On QNX the QNet (VFS paths of other hosts mounted under a directory
|
||||
// such as /net) mountpoint returns ENOENT, despite existing. stat()
|
||||
// on the QNet mountpoint returns successfully and reports S_IFDIR.
|
||||
|| errno == ENOENT
|
||||
#endif
|
||||
) {
|
||||
QT_STATBUF st;
|
||||
if (QT_STAT(chunk.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s
|
||||
if (dirName.endsWith(QLatin1Char('/')))
|
||||
dirName.chop(1);
|
||||
#endif
|
||||
return (QT_MKDIR(QFile::encodeName(dirName).constData(), 0777) == 0);
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
|
||||
{
|
||||
if (removeEmptyParents) {
|
||||
QString dirName = QDir::cleanPath(entry.filePath());
|
||||
for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
|
||||
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
|
||||
QT_STATBUF st;
|
||||
if (QT_STAT(chunk.constData(), &st) != -1) {
|
||||
if ((st.st_mode & S_IFMT) != S_IFDIR)
|
||||
return false;
|
||||
if (::rmdir(chunk.constData()) != 0)
|
||||
return oldslash != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return rmdir(QFile::encodeName(entry.filePath()).constData()) == 0;
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||
{
|
||||
if (::symlink(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
|
||||
return true;
|
||||
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||
{
|
||||
Q_UNUSED(source);
|
||||
Q_UNUSED(target);
|
||||
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||
{
|
||||
if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
|
||||
return true;
|
||||
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
|
||||
{
|
||||
if (unlink(entry.nativeFilePath().constData()) == 0)
|
||||
return true;
|
||||
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
if (permissions & QFile::ReadOwner)
|
||||
mode |= S_IRUSR;
|
||||
if (permissions & QFile::WriteOwner)
|
||||
mode |= S_IWUSR;
|
||||
if (permissions & QFile::ExeOwner)
|
||||
mode |= S_IXUSR;
|
||||
if (permissions & QFile::ReadUser)
|
||||
mode |= S_IRUSR;
|
||||
if (permissions & QFile::WriteUser)
|
||||
mode |= S_IWUSR;
|
||||
if (permissions & QFile::ExeUser)
|
||||
mode |= S_IXUSR;
|
||||
if (permissions & QFile::ReadGroup)
|
||||
mode |= S_IRGRP;
|
||||
if (permissions & QFile::WriteGroup)
|
||||
mode |= S_IWGRP;
|
||||
if (permissions & QFile::ExeGroup)
|
||||
mode |= S_IXGRP;
|
||||
if (permissions & QFile::ReadOther)
|
||||
mode |= S_IROTH;
|
||||
if (permissions & QFile::WriteOther)
|
||||
mode |= S_IWOTH;
|
||||
if (permissions & QFile::ExeOther)
|
||||
mode |= S_IXOTH;
|
||||
|
||||
bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;
|
||||
if (success && data) {
|
||||
data->entryFlags &= ~QFileSystemMetaData::Permissions;
|
||||
data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
|
||||
data->knownFlagsMask |= QFileSystemMetaData::Permissions;
|
||||
}
|
||||
if (!success)
|
||||
error = QSystemError(errno, QSystemError::StandardLibraryError);
|
||||
return success;
|
||||
}
|
||||
|
||||
QString QFileSystemEngine::homePath()
|
||||
{
|
||||
QString home = QFile::decodeName(qgetenv("HOME"));
|
||||
if (home.isEmpty())
|
||||
home = rootPath();
|
||||
return QDir::cleanPath(home);
|
||||
}
|
||||
|
||||
QString QFileSystemEngine::rootPath()
|
||||
{
|
||||
return QLatin1String("/");
|
||||
}
|
||||
|
||||
QString QFileSystemEngine::tempPath()
|
||||
{
|
||||
#ifdef QT_UNIX_TEMP_PATH_OVERRIDE
|
||||
return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE);
|
||||
#elif defined(Q_OS_BLACKBERRY)
|
||||
QString temp = QFile::decodeName(qgetenv("TEMP"));
|
||||
if (temp.isEmpty())
|
||||
temp = QFile::decodeName(qgetenv("TMPDIR"));
|
||||
|
||||
if (temp.isEmpty()) {
|
||||
qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /tmp.");
|
||||
temp = QLatin1String("/tmp/");
|
||||
}
|
||||
return QDir::cleanPath(temp);
|
||||
#else
|
||||
QString temp = QFile::decodeName(qgetenv("TMPDIR"));
|
||||
if (temp.isEmpty())
|
||||
temp = QLatin1String("/tmp/");
|
||||
return QDir::cleanPath(temp);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path)
|
||||
{
|
||||
int r;
|
||||
r = QT_CHDIR(path.nativeFilePath().constData());
|
||||
return r >= 0;
|
||||
}
|
||||
|
||||
QFileSystemEntry QFileSystemEngine::currentPath()
|
||||
{
|
||||
QFileSystemEntry result;
|
||||
QT_STATBUF st;
|
||||
if (QT_STAT(".", &st) == 0) {
|
||||
#if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||
char *currentName = ::get_current_dir_name();
|
||||
if (currentName) {
|
||||
result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
|
||||
::free(currentName);
|
||||
}
|
||||
#else
|
||||
char currentName[PATH_MAX+1];
|
||||
if (::getcwd(currentName, PATH_MAX)) {
|
||||
#if defined(Q_OS_VXWORKS) && defined(VXWORKS_VXSIM)
|
||||
QByteArray dir(currentName);
|
||||
if (dir.indexOf(':') < dir.indexOf('/'))
|
||||
dir.remove(0, dir.indexOf(':')+1);
|
||||
|
||||
qstrncpy(currentName, dir.constData(), PATH_MAX);
|
||||
#endif
|
||||
result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath());
|
||||
}
|
||||
# if defined(QT_DEBUG)
|
||||
if (result.isEmpty())
|
||||
qWarning("QFileSystemEngine::currentPath: getcwd() failed");
|
||||
# endif
|
||||
#endif
|
||||
} else {
|
||||
# if defined(QT_DEBUG)
|
||||
qWarning("QFileSystemEngine::currentPath: stat(\".\") failed");
|
||||
# endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
1324
src/app/core/backport/qfilesystemengine_win.cpp
Normal file
1324
src/app/core/backport/qfilesystemengine_win.cpp
Normal file
File diff suppressed because it is too large
Load Diff
388
src/app/core/backport/qfilesystementry.cpp
Normal file
388
src/app/core/backport/qfilesystementry.cpp
Normal file
|
@ -0,0 +1,388 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qfilesystementry_p.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include "qfsfileengine_p.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QStringBuilder>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static bool isUncRoot(const QString &server)
|
||||
{
|
||||
QString localPath = QDir::toNativeSeparators(server);
|
||||
if (!localPath.startsWith(QLatin1String("\\\\")))
|
||||
return false;
|
||||
|
||||
int idx = localPath.indexOf(QLatin1Char('\\'), 2);
|
||||
if (idx == -1 || idx + 1 == localPath.length())
|
||||
return true;
|
||||
|
||||
localPath = localPath.right(localPath.length() - idx - 1).trimmed();
|
||||
return localPath.isEmpty();
|
||||
}
|
||||
|
||||
static inline QString fixIfRelativeUncPath(const QString &path)
|
||||
{
|
||||
QString currentPath = QDir::currentPath();
|
||||
if (currentPath.startsWith(QLatin1String("//")))
|
||||
return currentPath % QChar(QLatin1Char('/')) % path;
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
QFileSystemEntry::QFileSystemEntry()
|
||||
: m_lastSeparator(-1),
|
||||
m_firstDotInFileName(-1),
|
||||
m_lastDotInFileName(-1)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Use this constructor when the path is supplied by user code, as it may contain a mix
|
||||
of '/' and the native separator.
|
||||
*/
|
||||
QFileSystemEntry::QFileSystemEntry(const QString &filePath)
|
||||
: m_filePath(QDir::fromNativeSeparators(filePath)),
|
||||
m_lastSeparator(-2),
|
||||
m_firstDotInFileName(-2),
|
||||
m_lastDotInFileName(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Use this constructor when the path is guaranteed to be in internal format, i.e. all
|
||||
directory separators are '/' and not the native separator.
|
||||
*/
|
||||
QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */)
|
||||
: m_filePath(filePath),
|
||||
m_lastSeparator(-2),
|
||||
m_firstDotInFileName(-2),
|
||||
m_lastDotInFileName(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Use this constructor when the path comes from a native API
|
||||
*/
|
||||
QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */)
|
||||
: m_nativeFilePath(nativeFilePath),
|
||||
m_lastSeparator(-2),
|
||||
m_firstDotInFileName(-2),
|
||||
m_lastDotInFileName(0)
|
||||
{
|
||||
}
|
||||
|
||||
QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath)
|
||||
: m_filePath(QDir::fromNativeSeparators(filePath)),
|
||||
m_nativeFilePath(nativeFilePath),
|
||||
m_lastSeparator(-2),
|
||||
m_firstDotInFileName(-2),
|
||||
m_lastDotInFileName(0)
|
||||
{
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::filePath() const
|
||||
{
|
||||
resolveFilePath();
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const
|
||||
{
|
||||
resolveNativeFilePath();
|
||||
return m_nativeFilePath;
|
||||
}
|
||||
|
||||
void QFileSystemEntry::resolveFilePath() const
|
||||
{
|
||||
if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
|
||||
#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
|
||||
m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
|
||||
#ifdef Q_OS_WIN
|
||||
if (m_filePath.startsWith(QLatin1String("//?/UNC/")))
|
||||
m_filePath = m_filePath.remove(2,6);
|
||||
if (m_filePath.startsWith(QLatin1String("//?/")))
|
||||
m_filePath = m_filePath.remove(0,4);
|
||||
#endif
|
||||
#else
|
||||
m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void QFileSystemEntry::resolveNativeFilePath() const
|
||||
{
|
||||
if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) {
|
||||
#ifdef Q_OS_WIN
|
||||
QString filePath = m_filePath;
|
||||
if (isRelative())
|
||||
filePath = fixIfRelativeUncPath(m_filePath);
|
||||
m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath));
|
||||
#elif defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
|
||||
m_nativeFilePath = QDir::toNativeSeparators(m_filePath);
|
||||
#else
|
||||
m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::fileName() const
|
||||
{
|
||||
findLastSeparator();
|
||||
#if defined(Q_OS_WIN)
|
||||
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||
return m_filePath.mid(2);
|
||||
#endif
|
||||
return m_filePath.mid(m_lastSeparator + 1);
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::path() const
|
||||
{
|
||||
findLastSeparator();
|
||||
if (m_lastSeparator == -1) {
|
||||
#if defined(Q_OS_WIN)
|
||||
if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||
return QFSFileEngine::currentPath(m_filePath.left(2));
|
||||
#endif
|
||||
return QString(QLatin1Char('.'));
|
||||
}
|
||||
if (m_lastSeparator == 0)
|
||||
return QString(QLatin1Char('/'));
|
||||
#if defined(Q_OS_WIN)
|
||||
if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||
return m_filePath.left(m_lastSeparator + 1);
|
||||
#endif
|
||||
return m_filePath.left(m_lastSeparator);
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::baseName() const
|
||||
{
|
||||
findFileNameSeparators();
|
||||
int length = -1;
|
||||
if (m_firstDotInFileName >= 0) {
|
||||
length = m_firstDotInFileName;
|
||||
if (m_lastSeparator != -1) // avoid off by one
|
||||
length--;
|
||||
}
|
||||
#if defined(Q_OS_WIN)
|
||||
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||
return m_filePath.mid(2, length - 2);
|
||||
#endif
|
||||
return m_filePath.mid(m_lastSeparator + 1, length);
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::completeBaseName() const
|
||||
{
|
||||
findFileNameSeparators();
|
||||
int length = -1;
|
||||
if (m_firstDotInFileName >= 0) {
|
||||
length = m_firstDotInFileName + m_lastDotInFileName;
|
||||
if (m_lastSeparator != -1) // avoid off by one
|
||||
length--;
|
||||
}
|
||||
#if defined(Q_OS_WIN)
|
||||
if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':'))
|
||||
return m_filePath.mid(2, length - 2);
|
||||
#endif
|
||||
return m_filePath.mid(m_lastSeparator + 1, length);
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::suffix() const
|
||||
{
|
||||
findFileNameSeparators();
|
||||
|
||||
if (m_lastDotInFileName == -1)
|
||||
return QString();
|
||||
|
||||
return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1);
|
||||
}
|
||||
|
||||
QString QFileSystemEntry::completeSuffix() const
|
||||
{
|
||||
findFileNameSeparators();
|
||||
if (m_firstDotInFileName == -1)
|
||||
return QString();
|
||||
|
||||
return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1);
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
bool QFileSystemEntry::isRelative() const
|
||||
{
|
||||
resolveFilePath();
|
||||
return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/')
|
||||
&& (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':'))));
|
||||
}
|
||||
|
||||
bool QFileSystemEntry::isAbsolute() const
|
||||
{
|
||||
resolveFilePath();
|
||||
return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3
|
||||
&& (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/'))
|
||||
|| (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/')))
|
||||
));
|
||||
}
|
||||
#else
|
||||
bool QFileSystemEntry::isRelative() const
|
||||
{
|
||||
return !isAbsolute();
|
||||
}
|
||||
|
||||
bool QFileSystemEntry::isAbsolute() const
|
||||
{
|
||||
resolveFilePath();
|
||||
return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/'));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
bool QFileSystemEntry::isDriveRoot() const
|
||||
{
|
||||
resolveFilePath();
|
||||
return (m_filePath.length() == 3
|
||||
&& m_filePath.at(0).isLetter() && m_filePath.at(1) == QLatin1Char(':')
|
||||
&& m_filePath.at(2) == QLatin1Char('/'));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool QFileSystemEntry::isRoot() const
|
||||
{
|
||||
resolveFilePath();
|
||||
if (m_filePath == QLatin1String("/")
|
||||
#if defined(Q_OS_WIN)
|
||||
|| isDriveRoot()
|
||||
|| isUncRoot(m_filePath)
|
||||
#endif
|
||||
)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QFileSystemEntry::isEmpty() const
|
||||
{
|
||||
return m_filePath.isEmpty() && m_nativeFilePath.isEmpty();
|
||||
}
|
||||
|
||||
// private methods
|
||||
|
||||
void QFileSystemEntry::findLastSeparator() const
|
||||
{
|
||||
if (m_lastSeparator == -2) {
|
||||
resolveFilePath();
|
||||
m_lastSeparator = -1;
|
||||
for (int i = m_filePath.size() - 1; i >= 0; --i) {
|
||||
if (m_filePath[i].unicode() == '/') {
|
||||
m_lastSeparator = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QFileSystemEntry::findFileNameSeparators() const
|
||||
{
|
||||
if (m_firstDotInFileName == -2) {
|
||||
resolveFilePath();
|
||||
int firstDotInFileName = -1;
|
||||
int lastDotInFileName = -1;
|
||||
int lastSeparator = m_lastSeparator;
|
||||
|
||||
int stop;
|
||||
if (lastSeparator < 0) {
|
||||
lastSeparator = -1;
|
||||
stop = 0;
|
||||
} else {
|
||||
stop = lastSeparator;
|
||||
}
|
||||
|
||||
int i = m_filePath.size() - 1;
|
||||
for (; i >= stop; --i) {
|
||||
if (m_filePath[i].unicode() == '.') {
|
||||
firstDotInFileName = lastDotInFileName = i;
|
||||
break;
|
||||
} else if (m_filePath[i].unicode() == '/') {
|
||||
lastSeparator = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastSeparator != i) {
|
||||
for (--i; i >= stop; --i) {
|
||||
if (m_filePath[i].unicode() == '.')
|
||||
firstDotInFileName = i;
|
||||
else if (m_filePath[i].unicode() == '/') {
|
||||
lastSeparator = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastSeparator = lastSeparator;
|
||||
m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator);
|
||||
if (lastDotInFileName == -1)
|
||||
m_lastDotInFileName = -1;
|
||||
else if (firstDotInFileName == lastDotInFileName)
|
||||
m_lastDotInFileName = 0;
|
||||
else
|
||||
m_lastDotInFileName = lastDotInFileName - firstDotInFileName;
|
||||
}
|
||||
}
|
||||
|
||||
bool QFileSystemEntry::isClean() const
|
||||
{
|
||||
resolveFilePath();
|
||||
int dots = 0;
|
||||
bool dotok = true; // checking for ".." or "." starts to relative paths
|
||||
bool slashok = true;
|
||||
for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); iter++) {
|
||||
if (*iter == QLatin1Char('/')) {
|
||||
if (dots == 1 || dots == 2)
|
||||
return false; // path contains "./" or "../"
|
||||
if (!slashok)
|
||||
return false; // path contains "//"
|
||||
dots = 0;
|
||||
dotok = true;
|
||||
slashok = false;
|
||||
} else if (dotok) {
|
||||
slashok = true;
|
||||
if (*iter == QLatin1Char('.')) {
|
||||
dots++;
|
||||
if (dots > 2)
|
||||
dotok = false;
|
||||
} else {
|
||||
//path element contains a character other than '.', it's clean
|
||||
dots = 0;
|
||||
dotok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (dots != 1 && dots != 2); // clean if path doesn't end in . or ..
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
106
src/app/core/backport/qfilesystementry_p.h
Normal file
106
src/app/core/backport/qfilesystementry_p.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFILESYSTEMENTRY_P_H
|
||||
#define QFILESYSTEMENTRY_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#define QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
|
||||
#endif
|
||||
|
||||
class QFileSystemEntry
|
||||
{
|
||||
public:
|
||||
|
||||
#ifndef QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16
|
||||
typedef QByteArray NativePath;
|
||||
#else
|
||||
typedef QString NativePath;
|
||||
#endif
|
||||
struct FromNativePath{};
|
||||
struct FromInternalPath{};
|
||||
|
||||
QFileSystemEntry();
|
||||
explicit QFileSystemEntry(const QString &filePath);
|
||||
|
||||
QFileSystemEntry(const QString &filePath, FromInternalPath dummy);
|
||||
QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath dummy);
|
||||
QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath);
|
||||
|
||||
QString filePath() const;
|
||||
QString fileName() const;
|
||||
QString path() const;
|
||||
NativePath nativeFilePath() const;
|
||||
QString baseName() const;
|
||||
QString completeBaseName() const;
|
||||
QString suffix() const;
|
||||
QString completeSuffix() const;
|
||||
bool isAbsolute() const;
|
||||
bool isRelative() const;
|
||||
bool isClean() const;
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
bool isDriveRoot() const;
|
||||
#endif
|
||||
bool isRoot() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
void clear()
|
||||
{
|
||||
*this = QFileSystemEntry();
|
||||
}
|
||||
|
||||
private:
|
||||
// creates the QString version out of the bytearray version
|
||||
void resolveFilePath() const;
|
||||
// creates the bytearray version out of the QString version
|
||||
void resolveNativeFilePath() const;
|
||||
// resolves the separator
|
||||
void findLastSeparator() const;
|
||||
// resolves the dots and the separator
|
||||
void findFileNameSeparators() const;
|
||||
|
||||
mutable QString m_filePath; // always has slashes as separator
|
||||
mutable NativePath m_nativeFilePath; // native encoding and separators
|
||||
|
||||
mutable qint16 m_lastSeparator; // index in m_filePath of last separator
|
||||
mutable qint16 m_firstDotInFileName; // index after m_filePath for first dot (.)
|
||||
mutable qint16 m_lastDotInFileName; // index after m_firstDotInFileName for last dot (.)
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // include guard
|
94
src/app/core/backport/qfilesystemiterator_p.h
Normal file
94
src/app/core/backport/qfilesystemiterator_p.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFILESYSTEMITERATOR_P_H
|
||||
#define QFILESYSTEMITERATOR_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QStringList>
|
||||
|
||||
#include "qfilesystementry_p.h"
|
||||
#include "qfilesystemmetadata_p.h"
|
||||
|
||||
// Platform-specific headers
|
||||
#if !defined(Q_OS_WIN)
|
||||
#include <QScopedPointer>
|
||||
#endif
|
||||
|
||||
class QFileSystemIterator
|
||||
{
|
||||
public:
|
||||
QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||
const QStringList &nameFilters, QDirIterator::IteratorFlags flags
|
||||
= QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
|
||||
~QFileSystemIterator();
|
||||
|
||||
bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData);
|
||||
|
||||
private:
|
||||
QFileSystemEntry::NativePath nativePath;
|
||||
|
||||
// Platform-specific data
|
||||
#if defined(Q_OS_WIN)
|
||||
QString dirPath;
|
||||
HANDLE findFileHandle;
|
||||
QStringList uncShares;
|
||||
bool uncFallback;
|
||||
int uncShareIndex;
|
||||
bool onlyDirs;
|
||||
#else
|
||||
QT_DIR *dir;
|
||||
QT_DIRENT *dirEntry;
|
||||
#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||
// for readdir_r
|
||||
QScopedPointer<QT_DIRENT, QScopedPointerPodDeleter> mt_file;
|
||||
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||
// for _readdir_r
|
||||
size_t direntSize;
|
||||
#endif
|
||||
#endif
|
||||
int lastError;
|
||||
#endif
|
||||
|
||||
Q_DISABLE_COPY(QFileSystemIterator)
|
||||
};
|
||||
|
||||
#endif // QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // include guard
|
112
src/app/core/backport/qfilesystemiterator_unix.cpp
Normal file
112
src/app/core/backport/qfilesystemiterator_unix.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qfilesystemiterator_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||
const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
|
||||
: nativePath(entry.nativeFilePath())
|
||||
, dir(0)
|
||||
, dirEntry(0)
|
||||
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||
, direntSize(0)
|
||||
#endif
|
||||
, lastError(0)
|
||||
{
|
||||
Q_UNUSED(filters)
|
||||
Q_UNUSED(nameFilters)
|
||||
Q_UNUSED(flags)
|
||||
|
||||
if ((dir = QT_OPENDIR(nativePath.constData())) == 0) {
|
||||
lastError = errno;
|
||||
} else {
|
||||
|
||||
if (!nativePath.endsWith('/'))
|
||||
nativePath.append('/');
|
||||
|
||||
#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||
// ### Race condition; we should use fpathconf and dirfd().
|
||||
size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
|
||||
if (maxPathName == size_t(-1))
|
||||
maxPathName = FILENAME_MAX;
|
||||
maxPathName += sizeof(QT_DIRENT) + 1;
|
||||
|
||||
QT_DIRENT *p = reinterpret_cast<QT_DIRENT*>(::malloc(maxPathName));
|
||||
Q_CHECK_PTR(p);
|
||||
|
||||
mt_file.reset(p);
|
||||
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||
direntSize = maxPathName;
|
||||
|
||||
// Include extra stat information in the readdir() call (d_stat member of dirent_extra_stat).
|
||||
// This is used in QFileSystemMetaData::fillFromDirEnt() to avoid extra stat() calls when iterating
|
||||
// over directories
|
||||
if (dircntl(dir, D_SETFLAG, D_FLAG_STAT) == -1)
|
||||
lastError = errno;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
QFileSystemIterator::~QFileSystemIterator()
|
||||
{
|
||||
if (dir)
|
||||
QT_CLOSEDIR(dir);
|
||||
}
|
||||
|
||||
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
|
||||
{
|
||||
if (!dir)
|
||||
return false;
|
||||
|
||||
#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R)
|
||||
lastError = _readdir_r(dir, mt_file.data(), &dirEntry, direntSize);
|
||||
if (lastError)
|
||||
return false;
|
||||
#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN)
|
||||
lastError = QT_READDIR_R(dir, mt_file.data(), &dirEntry);
|
||||
if (lastError)
|
||||
return false;
|
||||
#else
|
||||
// ### add local lock to prevent breaking reentrancy
|
||||
dirEntry = QT_READDIR(dir);
|
||||
#endif // _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
|
||||
if (dirEntry) {
|
||||
fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath());
|
||||
metaData.fillFromDirEnt(*dirEntry);
|
||||
return true;
|
||||
}
|
||||
|
||||
lastError = errno;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QT_NO_FILESYSTEMITERATOR
|
129
src/app/core/backport/qfilesystemiterator_win.cpp
Normal file
129
src/app/core/backport/qfilesystemiterator_win.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#if _WIN32_WINNT < 0x0500
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
|
||||
#include "qfilesystemiterator_p.h"
|
||||
#include "qfilesystemengine_p.h"
|
||||
#include "qplatformdefs.h"
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
bool done = true;
|
||||
|
||||
QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters,
|
||||
const QStringList &nameFilters, QDirIterator::IteratorFlags flags)
|
||||
: nativePath(entry.nativeFilePath())
|
||||
, dirPath(entry.filePath())
|
||||
, findFileHandle(INVALID_HANDLE_VALUE)
|
||||
, uncFallback(false)
|
||||
, uncShareIndex(0)
|
||||
, onlyDirs(false)
|
||||
{
|
||||
Q_UNUSED(nameFilters)
|
||||
Q_UNUSED(flags)
|
||||
if (nativePath.endsWith(QLatin1String(".lnk"))) {
|
||||
QFileSystemMetaData metaData;
|
||||
QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData);
|
||||
nativePath = link.nativeFilePath();
|
||||
}
|
||||
if (!nativePath.endsWith(QLatin1Char('\\')))
|
||||
nativePath.append(QLatin1Char('\\'));
|
||||
nativePath.append(QLatin1Char('*'));
|
||||
if (!dirPath.endsWith(QLatin1Char('/')))
|
||||
dirPath.append(QLatin1Char('/'));
|
||||
if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files))))
|
||||
onlyDirs = true;
|
||||
}
|
||||
|
||||
QFileSystemIterator::~QFileSystemIterator()
|
||||
{
|
||||
if (findFileHandle != INVALID_HANDLE_VALUE)
|
||||
FindClose(findFileHandle);
|
||||
}
|
||||
|
||||
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData)
|
||||
{
|
||||
bool haveData = false;
|
||||
WIN32_FIND_DATA findData;
|
||||
|
||||
if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) {
|
||||
haveData = true;
|
||||
int infoLevel = 0 ; // FindExInfoStandard;
|
||||
DWORD dwAdditionalFlags = 0;
|
||||
#ifndef Q_OS_WINCE
|
||||
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
|
||||
dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
|
||||
infoLevel = 1 ; // FindExInfoBasic;
|
||||
}
|
||||
#endif
|
||||
int searchOps = 0; // FindExSearchNameMatch
|
||||
if (onlyDirs)
|
||||
searchOps = 1 ; // FindExSearchLimitToDirectories
|
||||
findFileHandle = FindFirstFileEx((const wchar_t *)nativePath.utf16(), FINDEX_INFO_LEVELS(infoLevel), &findData,
|
||||
FINDEX_SEARCH_OPS(searchOps), 0, dwAdditionalFlags);
|
||||
if (findFileHandle == INVALID_HANDLE_VALUE) {
|
||||
if (nativePath.startsWith(QLatin1String("\\\\?\\UNC\\"))) {
|
||||
QStringList parts = nativePath.split(QLatin1Char('\\'), QString::SkipEmptyParts);
|
||||
if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer(
|
||||
QLatin1String("\\\\") + parts.at(2), &uncShares)) {
|
||||
if (uncShares.isEmpty())
|
||||
return false; // No shares found in the server
|
||||
else
|
||||
uncFallback = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback)
|
||||
return false;
|
||||
// Retrieve the new file information.
|
||||
if (!haveData) {
|
||||
if (uncFallback) {
|
||||
if (++uncShareIndex >= uncShares.count())
|
||||
return false;
|
||||
} else {
|
||||
if (!FindNextFile(findFileHandle, &findData))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Create the new file system entry & meta data.
|
||||
if (uncFallback) {
|
||||
fileEntry = QFileSystemEntry(dirPath + uncShares.at(uncShareIndex));
|
||||
metaData.fillFromFileAttribute(FILE_ATTRIBUTE_DIRECTORY);
|
||||
return true;
|
||||
} else {
|
||||
QString fileName = QString::fromWCharArray(findData.cFileName);
|
||||
fileEntry = QFileSystemEntry(dirPath + fileName);
|
||||
metaData = QFileSystemMetaData();
|
||||
if (!fileName.endsWith(QLatin1String(".lnk"))) {
|
||||
metaData.fillFromFindData(findData, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
341
src/app/core/backport/qfilesystemmetadata_p.h
Normal file
341
src/app/core/backport/qfilesystemmetadata_p.h
Normal file
|
@ -0,0 +1,341 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFILESYSTEMMETADATA_P_H
|
||||
#define QFILESYSTEMMETADATA_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include <QtGlobal>
|
||||
#include <QDateTime>
|
||||
#include "qabstractfileengine_p.h"
|
||||
|
||||
// Platform-specific includes
|
||||
#ifdef Q_OS_WIN
|
||||
# include <QtCore/qt_windows.h>
|
||||
# ifndef IO_REPARSE_TAG_SYMLINK
|
||||
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QFileSystemEngine;
|
||||
|
||||
class QFileSystemMetaData
|
||||
{
|
||||
public:
|
||||
QFileSystemMetaData()
|
||||
: knownFlagsMask(0)
|
||||
{
|
||||
}
|
||||
|
||||
enum MetaDataFlag {
|
||||
// Permissions, overlaps with QFile::Permissions
|
||||
OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001,
|
||||
GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010,
|
||||
UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100,
|
||||
OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000,
|
||||
|
||||
OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission,
|
||||
GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission,
|
||||
UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission,
|
||||
OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission,
|
||||
|
||||
ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission,
|
||||
WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission,
|
||||
ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission,
|
||||
|
||||
Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions,
|
||||
|
||||
// Type
|
||||
LinkType = 0x00010000,
|
||||
FileType = 0x00020000,
|
||||
DirectoryType = 0x00040000,
|
||||
#if defined(Q_OS_MACX)
|
||||
BundleType = 0x00080000,
|
||||
AliasType = 0x08000000,
|
||||
#else
|
||||
BundleType = 0x0,
|
||||
AliasType = 0x0,
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
|
||||
#else
|
||||
WinLnkType = 0x0,
|
||||
#endif
|
||||
SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
|
||||
|
||||
LegacyLinkType = LinkType | AliasType | WinLnkType,
|
||||
|
||||
Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType,
|
||||
|
||||
// Attributes
|
||||
HiddenAttribute = 0x00100000,
|
||||
SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
|
||||
ExistsAttribute = 0x00400000,
|
||||
|
||||
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute,
|
||||
|
||||
// Times
|
||||
CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
|
||||
ModificationTime = 0x02000000,
|
||||
AccessTime = 0x04000000,
|
||||
|
||||
Times = CreationTime | ModificationTime | AccessTime,
|
||||
|
||||
// Owner IDs
|
||||
UserId = 0x10000000,
|
||||
GroupId = 0x20000000,
|
||||
|
||||
OwnerIds = UserId | GroupId,
|
||||
|
||||
PosixStatFlags = QFileSystemMetaData::OtherPermissions
|
||||
| QFileSystemMetaData::GroupPermissions
|
||||
| QFileSystemMetaData::OwnerPermissions
|
||||
| QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::SequentialType
|
||||
| QFileSystemMetaData::SizeAttribute
|
||||
| QFileSystemMetaData::Times
|
||||
| QFileSystemMetaData::OwnerIds,
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
WinStatFlags = QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::HiddenAttribute
|
||||
| QFileSystemMetaData::ExistsAttribute
|
||||
| QFileSystemMetaData::SizeAttribute
|
||||
| QFileSystemMetaData::Times,
|
||||
#endif
|
||||
|
||||
AllMetaDataFlags = 0xFFFFFFFF
|
||||
|
||||
};
|
||||
Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag)
|
||||
|
||||
bool hasFlags(MetaDataFlags flags) const
|
||||
{
|
||||
return ((knownFlagsMask & flags) == flags);
|
||||
}
|
||||
|
||||
MetaDataFlags missingFlags(MetaDataFlags flags)
|
||||
{
|
||||
return flags & ~knownFlagsMask;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
knownFlagsMask = 0;
|
||||
}
|
||||
|
||||
void clearFlags(MetaDataFlags flags = AllMetaDataFlags)
|
||||
{
|
||||
knownFlagsMask &= ~flags;
|
||||
}
|
||||
|
||||
bool exists() const { return (entryFlags & ExistsAttribute); }
|
||||
|
||||
bool isLink() const { return (entryFlags & LinkType); }
|
||||
bool isFile() const { return (entryFlags & FileType); }
|
||||
bool isDirectory() const { return (entryFlags & DirectoryType); }
|
||||
bool isBundle() const;
|
||||
bool isAlias() const;
|
||||
bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
|
||||
bool isSequential() const { return (entryFlags & SequentialType); }
|
||||
bool isHidden() const { return (entryFlags & HiddenAttribute); }
|
||||
#if defined(Q_OS_WIN)
|
||||
bool isLnkFile() const { return (entryFlags & WinLnkType); }
|
||||
#else
|
||||
bool isLnkFile() const { return false; }
|
||||
#endif
|
||||
|
||||
qint64 size() const { return size_; }
|
||||
|
||||
QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
|
||||
|
||||
QDateTime creationTime() const;
|
||||
QDateTime modificationTime() const;
|
||||
QDateTime accessTime() const;
|
||||
|
||||
QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
|
||||
uint userId() const;
|
||||
uint groupId() const;
|
||||
uint ownerId(QAbstractFileEngine::FileOwner owner) const;
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
void fillFromStatBuf(const QT_STATBUF &statBuffer);
|
||||
void fillFromDirEnt(const QT_DIRENT &statBuffer);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false);
|
||||
inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false);
|
||||
inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo);
|
||||
#endif
|
||||
private:
|
||||
friend class QFileSystemEngine;
|
||||
|
||||
MetaDataFlags knownFlagsMask;
|
||||
MetaDataFlags entryFlags;
|
||||
|
||||
qint64 size_;
|
||||
|
||||
// Platform-specific data goes here:
|
||||
#if defined(Q_OS_WIN)
|
||||
DWORD fileAttribute_;
|
||||
FILETIME creationTime_;
|
||||
FILETIME lastAccessTime_;
|
||||
FILETIME lastWriteTime_;
|
||||
#else
|
||||
time_t creationTime_;
|
||||
time_t modificationTime_;
|
||||
time_t accessTime_;
|
||||
|
||||
uint userId_;
|
||||
uint groupId_;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
|
||||
inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
|
||||
#else
|
||||
inline bool QFileSystemMetaData::isBundle() const { return false; }
|
||||
inline bool QFileSystemMetaData::isAlias() const { return false; }
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_UNIX) || defined (Q_OS_WIN)
|
||||
inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const
|
||||
{
|
||||
switch (time) {
|
||||
case QAbstractFileEngine::ModificationTime:
|
||||
return modificationTime();
|
||||
|
||||
case QAbstractFileEngine::AccessTime:
|
||||
return accessTime();
|
||||
|
||||
case QAbstractFileEngine::CreationTime:
|
||||
return creationTime();
|
||||
}
|
||||
|
||||
return QDateTime();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromTime_t(creationTime_); }
|
||||
inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromTime_t(modificationTime_); }
|
||||
inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromTime_t(accessTime_); }
|
||||
|
||||
inline uint QFileSystemMetaData::userId() const { return userId_; }
|
||||
inline uint QFileSystemMetaData::groupId() const { return groupId_; }
|
||||
|
||||
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
||||
{
|
||||
if (owner == QAbstractFileEngine::OwnerUser)
|
||||
return userId();
|
||||
else
|
||||
return groupId();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
inline uint QFileSystemMetaData::userId() const { return (uint) -2; }
|
||||
inline uint QFileSystemMetaData::groupId() const { return (uint) -2; }
|
||||
inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const
|
||||
{
|
||||
if (owner == QAbstractFileEngine::OwnerUser)
|
||||
return userId();
|
||||
else
|
||||
return groupId();
|
||||
}
|
||||
|
||||
inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot)
|
||||
{
|
||||
fileAttribute_ = fileAttribute;
|
||||
// Ignore the hidden attribute for drives.
|
||||
if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN))
|
||||
entryFlags |= HiddenAttribute;
|
||||
entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
|
||||
entryFlags |= ExistsAttribute;
|
||||
knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
|
||||
}
|
||||
|
||||
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
|
||||
{
|
||||
fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
|
||||
creationTime_ = findData.ftCreationTime;
|
||||
lastAccessTime_ = findData.ftLastAccessTime;
|
||||
lastWriteTime_ = findData.ftLastWriteTime;
|
||||
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
size_ = 0;
|
||||
} else {
|
||||
size_ = findData.nFileSizeHigh;
|
||||
size_ <<= 32;
|
||||
size_ += findData.nFileSizeLow;
|
||||
}
|
||||
knownFlagsMask |= Times | SizeAttribute;
|
||||
if (setLinkType) {
|
||||
knownFlagsMask |= LinkType;
|
||||
entryFlags &= ~LinkType;
|
||||
#if !defined(Q_OS_WINCE)
|
||||
if ((fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
&& (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
|
||||
entryFlags |= LinkType;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
|
||||
{
|
||||
fillFromFileAttribute(fileInfo.dwFileAttributes);
|
||||
creationTime_ = fileInfo.ftCreationTime;
|
||||
lastAccessTime_ = fileInfo.ftLastAccessTime;
|
||||
lastWriteTime_ = fileInfo.ftLastWriteTime;
|
||||
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
size_ = 0;
|
||||
} else {
|
||||
size_ = fileInfo.nFileSizeHigh;
|
||||
size_ <<= 32;
|
||||
size_ += fileInfo.nFileSizeLow;
|
||||
}
|
||||
knownFlagsMask |= Times | SizeAttribute;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // include guard
|
942
src/app/core/backport/qfsfileengine.cpp
Normal file
942
src/app/core/backport/qfsfileengine.cpp
Normal file
|
@ -0,0 +1,942 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qfsfileengine_p.h"
|
||||
#include "qfsfileengine_iterator_p.h"
|
||||
#include "qfilesystemengine_p.h"
|
||||
#include <QDateTime>
|
||||
#include <QDirIterator>
|
||||
#include <QSet>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
|
||||
#if !defined(Q_OS_WINCE)
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if defined(Q_OS_UNIX)
|
||||
#include "qcore_unix_p.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(Q_OS_MAC)
|
||||
# include "qcore_mac_p.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# ifndef S_ISREG
|
||||
# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
|
||||
# endif
|
||||
# ifndef S_ISCHR
|
||||
# define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
|
||||
# endif
|
||||
# ifndef S_ISFIFO
|
||||
# define S_ISFIFO(x) false
|
||||
# endif
|
||||
# ifndef S_ISSOCK
|
||||
# define S_ISSOCK(x) false
|
||||
# endif
|
||||
# ifndef INVALID_FILE_ATTRIBUTES
|
||||
# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*! \class QFSFileEngine
|
||||
\inmodule QtCore
|
||||
\brief The QFSFileEngine class implements Qt's default file engine.
|
||||
\since 4.1
|
||||
\internal
|
||||
|
||||
This class is part of the file engine framework in Qt. If you only want to
|
||||
access files or directories, use QFile, QFileInfo or QDir instead.
|
||||
|
||||
QFSFileEngine is the default file engine for accessing regular files. It
|
||||
is provided for convenience; by subclassing this class, you can alter its
|
||||
behavior slightly, without having to write a complete QAbstractFileEngine
|
||||
subclass. To install your custom file engine, you must also subclass
|
||||
QAbstractFileEngineHandler and create an instance of your handler.
|
||||
|
||||
It can also be useful to create a QFSFileEngine object directly if you
|
||||
need to use the local file system inside QAbstractFileEngine::create(), in
|
||||
order to avoid recursion (as higher-level classes tend to call
|
||||
QAbstractFileEngine::create()).
|
||||
*/
|
||||
|
||||
//**************** QFSFileEnginePrivate
|
||||
QFSFileEnginePrivate::QFSFileEnginePrivate() : QAbstractFileEnginePrivate()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QFSFileEnginePrivate::init()
|
||||
{
|
||||
is_sequential = 0;
|
||||
tried_stat = 0;
|
||||
#if !defined(Q_OS_WINCE)
|
||||
need_lstat = 1;
|
||||
is_link = 0;
|
||||
#endif
|
||||
openMode = QIODevice::NotOpen;
|
||||
fd = -1;
|
||||
fh = 0;
|
||||
lastIOCommand = IOFlushCommand;
|
||||
lastFlushFailed = false;
|
||||
closeFileHandle = false;
|
||||
#ifdef Q_OS_WIN
|
||||
fileAttrib = INVALID_FILE_ATTRIBUTES;
|
||||
fileHandle = INVALID_HANDLE_VALUE;
|
||||
mapHandle = NULL;
|
||||
#ifndef Q_OS_WINCE
|
||||
cachedFd = -1;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QFSFileEngine for the file name \a file.
|
||||
*/
|
||||
QFSFileEngine::QFSFileEngine(const QString &file)
|
||||
: QAbstractFileEngine(*new QFSFileEnginePrivate)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
d->fileEntry = QFileSystemEntry(file);
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QFSFileEngine.
|
||||
*/
|
||||
QFSFileEngine::QFSFileEngine() : QAbstractFileEngine(*new QFSFileEnginePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QFSFileEngine::QFSFileEngine(QFSFileEnginePrivate &dd)
|
||||
: QAbstractFileEngine(dd)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs the QFSFileEngine.
|
||||
*/
|
||||
QFSFileEngine::~QFSFileEngine()
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
if (d->closeFileHandle) {
|
||||
if (d->fh) {
|
||||
int ret;
|
||||
do {
|
||||
ret = fclose(d->fh);
|
||||
} while (ret == EOF && errno == EINTR);
|
||||
} else if (d->fd != -1) {
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_CLOSE(d->fd);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
}
|
||||
}
|
||||
QList<uchar*> keys = d->maps.keys();
|
||||
for (int i = 0; i < keys.count(); ++i)
|
||||
unmap(keys.at(i));
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QFSFileEngine::setFileName(const QString &file)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
d->init();
|
||||
d->fileEntry = QFileSystemEntry(file);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::open(QIODevice::OpenMode openMode)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
if (d->fileEntry.isEmpty()) {
|
||||
qWarning("QFSFileEngine::open: No file name specified");
|
||||
setError(QFile::OpenError, QLatin1String("No file name specified"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Append implies WriteOnly.
|
||||
if (openMode & QFile::Append)
|
||||
openMode |= QFile::WriteOnly;
|
||||
|
||||
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||
openMode |= QFile::Truncate;
|
||||
|
||||
d->openMode = openMode;
|
||||
d->lastFlushFailed = false;
|
||||
d->tried_stat = 0;
|
||||
d->fh = 0;
|
||||
d->fd = -1;
|
||||
|
||||
return d->nativeOpen(openMode);
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the file handle \a fh in \a openMode mode. Returns \c true on
|
||||
success; otherwise returns \c false.
|
||||
*/
|
||||
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
|
||||
{
|
||||
return open(openMode, fh, QFile::DontCloseHandle);
|
||||
}
|
||||
|
||||
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
|
||||
// Append implies WriteOnly.
|
||||
if (openMode & QFile::Append)
|
||||
openMode |= QFile::WriteOnly;
|
||||
|
||||
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||
openMode |= QFile::Truncate;
|
||||
|
||||
d->openMode = openMode;
|
||||
d->lastFlushFailed = false;
|
||||
d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
|
||||
d->fileEntry.clear();
|
||||
d->tried_stat = 0;
|
||||
d->fd = -1;
|
||||
|
||||
return d->openFh(openMode, fh);
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the file handle \a fh using the open mode \a flags.
|
||||
*/
|
||||
bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
this->fh = fh;
|
||||
fd = -1;
|
||||
|
||||
// Seek to the end when in Append mode.
|
||||
if (openMode & QIODevice::Append) {
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_FSEEK(fh, 0, SEEK_END);
|
||||
} while (ret != 0 && errno == EINTR);
|
||||
|
||||
if (ret != 0) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(int(errno)));
|
||||
|
||||
this->openMode = QIODevice::NotOpen;
|
||||
this->fh = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens the file descriptor \a fd in \a openMode mode. Returns \c true
|
||||
on success; otherwise returns \c false.
|
||||
*/
|
||||
bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
|
||||
{
|
||||
return open(openMode, fd, QFile::DontCloseHandle);
|
||||
}
|
||||
|
||||
bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandleFlags handleFlags)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
|
||||
// Append implies WriteOnly.
|
||||
if (openMode & QFile::Append)
|
||||
openMode |= QFile::WriteOnly;
|
||||
|
||||
// WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
|
||||
if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
|
||||
openMode |= QFile::Truncate;
|
||||
|
||||
d->openMode = openMode;
|
||||
d->lastFlushFailed = false;
|
||||
d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
|
||||
d->fileEntry.clear();
|
||||
d->fh = 0;
|
||||
d->fd = -1;
|
||||
d->tried_stat = 0;
|
||||
|
||||
return d->openFd(openMode, fd);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Opens the file descriptor \a fd to the file engine, using the open mode \a
|
||||
flags.
|
||||
*/
|
||||
bool QFSFileEnginePrivate::openFd(QIODevice::OpenMode openMode, int fd)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
this->fd = fd;
|
||||
fh = 0;
|
||||
|
||||
// Seek to the end when in Append mode.
|
||||
if (openMode & QFile::Append) {
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_LSEEK(fd, 0, SEEK_END);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret == -1) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(int(errno)));
|
||||
|
||||
this->openMode = QIODevice::NotOpen;
|
||||
this->fd = -1;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::close()
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
d->openMode = QIODevice::NotOpen;
|
||||
return d->nativeClose();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::closeFdFh()
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
if (fd == -1 && !fh)
|
||||
return false;
|
||||
|
||||
// Flush the file if it's buffered, and if the last flush didn't fail.
|
||||
bool flushed = !fh || (!lastFlushFailed && q->flush());
|
||||
bool closed = true;
|
||||
tried_stat = 0;
|
||||
|
||||
// Close the file if we created the handle.
|
||||
if (closeFileHandle) {
|
||||
int ret;
|
||||
do {
|
||||
if (fh) {
|
||||
// Close buffered file.
|
||||
ret = fclose(fh) != 0 ? -1 : 0;
|
||||
} else {
|
||||
// Close unbuffered file.
|
||||
ret = QT_CLOSE(fd);
|
||||
}
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
// We must reset these guys regardless; calling close again after a
|
||||
// failed close causes crashes on some systems.
|
||||
fh = 0;
|
||||
fd = -1;
|
||||
closed = (ret == 0);
|
||||
}
|
||||
|
||||
// Report errors.
|
||||
if (!flushed || !closed) {
|
||||
if (flushed) {
|
||||
// If not flushed, we want the flush error to fall through.
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::flush()
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
if ((d->openMode & QIODevice::WriteOnly) == 0) {
|
||||
// Nothing in the write buffers, so flush succeeds in doing
|
||||
// nothing.
|
||||
return true;
|
||||
}
|
||||
return d->nativeFlush();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::syncToDisk()
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
if ((d->openMode & QIODevice::WriteOnly) == 0)
|
||||
return true;
|
||||
return d->nativeSyncToDisk();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::flushFh()
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
// Never try to flush again if the last flush failed. Otherwise you can
|
||||
// get crashes on some systems (AIX).
|
||||
if (lastFlushFailed)
|
||||
return false;
|
||||
|
||||
int ret = fflush(fh);
|
||||
|
||||
lastFlushFailed = (ret != 0);
|
||||
lastIOCommand = QFSFileEnginePrivate::IOFlushCommand;
|
||||
|
||||
if (ret != 0) {
|
||||
q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError,
|
||||
qt_error_string(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 QFSFileEngine::size() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
return d->nativeSize();
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::sizeFdFh() const
|
||||
{
|
||||
Q_Q(const QFSFileEngine);
|
||||
const_cast<QFSFileEngine *>(q)->flush();
|
||||
|
||||
tried_stat = 0;
|
||||
metaData.clearFlags(QFileSystemMetaData::SizeAttribute);
|
||||
if (!doStat(QFileSystemMetaData::SizeAttribute))
|
||||
return 0;
|
||||
return metaData.size();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 QFSFileEngine::pos() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
return d->nativePos();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::posFdFh() const
|
||||
{
|
||||
if (fh)
|
||||
return qint64(QT_FTELL(fh));
|
||||
return QT_LSEEK(fd, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::seek(qint64 pos)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
return d->nativeSeek(pos);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
// On Windows' stdlib implementation, the results of calling fread and
|
||||
// fwrite are undefined if not called either in sequence, or if preceded
|
||||
// with a call to fflush().
|
||||
if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush())
|
||||
return false;
|
||||
|
||||
if (pos < 0 || pos != qint64(QT_OFF_T(pos)))
|
||||
return false;
|
||||
|
||||
if (fh) {
|
||||
// Buffered stdlib mode.
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET);
|
||||
} while (ret != 0 && errno == EINTR);
|
||||
|
||||
if (ret != 0) {
|
||||
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Unbuffered stdio mode.
|
||||
if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) {
|
||||
qWarning() << "QFile::at: Cannot set file position" << pos;
|
||||
q->setError(QFile::PositionError, qt_error_string(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
int QFSFileEngine::handle() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
return d->nativeHandle();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 QFSFileEngine::read(char *data, qint64 maxlen)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
|
||||
// On Windows' stdlib implementation, the results of calling fread and
|
||||
// fwrite are undefined if not called either in sequence, or if preceded
|
||||
// with a call to fflush().
|
||||
if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
|
||||
flush();
|
||||
d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
|
||||
}
|
||||
|
||||
return d->nativeRead(data, maxlen);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
if (len < 0 || len != qint64(size_t(len))) {
|
||||
q->setError(QFile::ReadError, qt_error_string(EINVAL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64 readBytes = 0;
|
||||
bool eof = false;
|
||||
|
||||
if (fh) {
|
||||
// Buffered stdlib mode.
|
||||
|
||||
size_t result;
|
||||
bool retry = true;
|
||||
do {
|
||||
result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
|
||||
eof = feof(fh);
|
||||
if (retry && eof && result == 0) {
|
||||
// On Mac OS, this is needed, e.g., if a file was written to
|
||||
// through another stream since our last read. See test
|
||||
// tst_QFile::appendAndRead
|
||||
QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
|
||||
retry = false;
|
||||
continue;
|
||||
}
|
||||
readBytes += result;
|
||||
} while (!eof && (result == 0 ? errno == EINTR : readBytes < len));
|
||||
|
||||
} else if (fd != -1) {
|
||||
// Unbuffered stdio mode.
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
int result;
|
||||
#else
|
||||
ssize_t result;
|
||||
#endif
|
||||
do {
|
||||
result = QT_READ(fd, data + readBytes, size_t(len - readBytes));
|
||||
} while ((result == -1 && errno == EINTR)
|
||||
|| (result > 0 && (readBytes += result) < len));
|
||||
|
||||
eof = !(result == -1);
|
||||
}
|
||||
|
||||
if (!eof && readBytes == 0) {
|
||||
readBytes = -1;
|
||||
q->setError(QFile::ReadError, qt_error_string(errno));
|
||||
}
|
||||
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 QFSFileEngine::readLine(char *data, qint64 maxlen)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
|
||||
// On Windows' stdlib implementation, the results of calling fread and
|
||||
// fwrite are undefined if not called either in sequence, or if preceded
|
||||
// with a call to fflush().
|
||||
if (d->lastIOCommand != QFSFileEnginePrivate::IOReadCommand) {
|
||||
flush();
|
||||
d->lastIOCommand = QFSFileEnginePrivate::IOReadCommand;
|
||||
}
|
||||
|
||||
return d->nativeReadLine(data, maxlen);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
if (!fh)
|
||||
return q->QAbstractFileEngine::readLine(data, maxlen);
|
||||
|
||||
QT_OFF_T oldPos = 0;
|
||||
#ifdef Q_OS_WIN
|
||||
bool seq = q->isSequential();
|
||||
if (!seq)
|
||||
#endif
|
||||
oldPos = QT_FTELL(fh);
|
||||
|
||||
// QIODevice::readLine() passes maxlen - 1 to QFile::readLineData()
|
||||
// because it has made space for the '\0' at the end of data. But fgets
|
||||
// does the same, so we'd get two '\0' at the end - passing maxlen + 1
|
||||
// solves this.
|
||||
if (!fgets(data, int(maxlen + 1), fh)) {
|
||||
if (!feof(fh))
|
||||
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||
return -1; // error
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (seq)
|
||||
return qstrlen(data);
|
||||
#endif
|
||||
|
||||
qint64 lineLength = QT_FTELL(fh) - oldPos;
|
||||
return lineLength > 0 ? lineLength : qstrlen(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
qint64 QFSFileEngine::write(const char *data, qint64 len)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
|
||||
// On Windows' stdlib implementation, the results of calling fread and
|
||||
// fwrite are undefined if not called either in sequence, or if preceded
|
||||
// with a call to fflush().
|
||||
if (d->lastIOCommand != QFSFileEnginePrivate::IOWriteCommand) {
|
||||
flush();
|
||||
d->lastIOCommand = QFSFileEnginePrivate::IOWriteCommand;
|
||||
}
|
||||
|
||||
return d->nativeWrite(data, len);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
if (len < 0 || len != qint64(size_t(len))) {
|
||||
q->setError(QFile::WriteError, qt_error_string(EINVAL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64 writtenBytes = 0;
|
||||
|
||||
if (fh) {
|
||||
// Buffered stdlib mode.
|
||||
|
||||
size_t result;
|
||||
do {
|
||||
result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
|
||||
writtenBytes += result;
|
||||
} while (result == 0 ? errno == EINTR : writtenBytes < len);
|
||||
|
||||
} else if (fd != -1) {
|
||||
// Unbuffered stdio mode.
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
int result;
|
||||
#else
|
||||
ssize_t result;
|
||||
#endif
|
||||
do {
|
||||
result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes));
|
||||
} while ((result == -1 && errno == EINTR)
|
||||
|| (result > 0 && (writtenBytes += result) < len));
|
||||
}
|
||||
|
||||
if (len && writtenBytes == 0) {
|
||||
writtenBytes = -1;
|
||||
q->setError(errno == ENOSPC ? QFile::ResourceError : QFile::WriteError, qt_error_string(errno));
|
||||
}
|
||||
|
||||
return writtenBytes;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
|
||||
{
|
||||
return new QFSFileEngineIterator(filters, filterNames);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif // QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
|
||||
{
|
||||
return QAbstractFileEngine::entryList(filters, filterNames);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::isSequential() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
if (d->is_sequential == 0)
|
||||
d->is_sequential = d->nativeIsSequential() ? 1 : 2;
|
||||
return d->is_sequential == 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
#ifdef Q_OS_UNIX
|
||||
bool QFSFileEnginePrivate::isSequentialFdFh() const
|
||||
{
|
||||
if (doStat(QFileSystemMetaData::SequentialType))
|
||||
return metaData.isSequential();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
if (extension == AtEndExtension && d->fh && isSequential())
|
||||
return feof(d->fh);
|
||||
|
||||
if (extension == MapExtension) {
|
||||
const MapExtensionOption *options = (MapExtensionOption*)(option);
|
||||
MapExtensionReturn *returnValue = static_cast<MapExtensionReturn*>(output);
|
||||
returnValue->address = d->map(options->offset, options->size, options->flags);
|
||||
return (returnValue->address != 0);
|
||||
}
|
||||
if (extension == UnMapExtension) {
|
||||
UnMapExtensionOption *options = (UnMapExtensionOption*)option;
|
||||
return d->unmap(options->address);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::supportsExtension(Extension extension) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
if (extension == AtEndExtension && d->fh && isSequential())
|
||||
return true;
|
||||
if (extension == FastReadLineExtension && d->fh)
|
||||
return true;
|
||||
if (extension == FastReadLineExtension && d->fd != -1 && isSequential())
|
||||
return true;
|
||||
if (extension == UnMapExtension || extension == MapExtension)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \fn bool QFSFileEngine::caseSensitive() const
|
||||
Returns \c true for Windows, false for Unix.
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::copy(const QString ©Name)
|
||||
|
||||
For windows, copy the file to file \a copyName.
|
||||
|
||||
Not implemented for Unix.
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
|
||||
For Unix, returns the current working directory for the file
|
||||
engine.
|
||||
|
||||
For Windows, returns the canonicalized form of the current path used
|
||||
by the file engine for the drive specified by \a fileName. On
|
||||
Windows, each drive has its own current directory, so a different
|
||||
path is returned for file names that include different drive names
|
||||
(e.g. A: or C:).
|
||||
|
||||
\sa setCurrentPath()
|
||||
*/
|
||||
|
||||
/*! \fn QFileInfoList QFSFileEngine::drives()
|
||||
For Windows, returns the list of drives in the file system as a list
|
||||
of QFileInfo objects. On unix, Mac OS X and Windows CE, only the
|
||||
root path is returned. On Windows, this function returns all drives
|
||||
(A:\, C:\, D:\, etc.).
|
||||
|
||||
For Unix, the list contains just the root path "/".
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::fileName(FileName file) const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn QDateTime QFSFileEngine::fileTime(FileTime time) const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::homePath()
|
||||
Returns the home path of the current user.
|
||||
|
||||
\sa rootPath()
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::isRelativePath() const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::link(const QString &newName)
|
||||
|
||||
Creates a link from the file currently specified by fileName() to
|
||||
\a newName. What a link is depends on the underlying filesystem
|
||||
(be it a shortcut on Windows or a symbolic link on Unix). Returns
|
||||
true if successful; otherwise returns \c false.
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn uint QFSFileEngine::ownerId(FileOwner own) const
|
||||
In Unix, if stat() is successful, the \c uid is returned if
|
||||
\a own is the owner. Otherwise the \c gid is returned. If stat()
|
||||
is unsuccessful, -2 is reuturned.
|
||||
|
||||
For Windows, -2 is always returned.
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::owner(FileOwner own) const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::remove()
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::rename(const QString &newName)
|
||||
\reimp
|
||||
*/
|
||||
|
||||
|
||||
/*! \fn bool QFSFileEngine::renameOverwrite(const QString &newName)
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::rootPath()
|
||||
Returns the root path.
|
||||
|
||||
\sa homePath()
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::setCurrentPath(const QString &path)
|
||||
Sets the current path (e.g., for QDir), to \a path. Returns \c true if the
|
||||
new path exists; otherwise this function does nothing, and returns \c false.
|
||||
|
||||
\sa currentPath()
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::setPermissions(uint perms)
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn bool QFSFileEngine::setSize(qint64 size)
|
||||
\reimp
|
||||
*/
|
||||
|
||||
/*! \fn QString QFSFileEngine::tempPath()
|
||||
Returns the temporary path (i.e., a path in which it is safe
|
||||
to store temporary files).
|
||||
*/
|
||||
|
||||
/*! \fn QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const
|
||||
\internal
|
||||
*/
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QT_NO_FSFILEENGINE
|
85
src/app/core/backport/qfsfileengine_iterator.cpp
Normal file
85
src/app/core/backport/qfsfileengine_iterator.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qfsfileengine_iterator_p.h"
|
||||
#include "qfileinfo_p.h"
|
||||
#include <QVariant>
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames)
|
||||
: QAbstractFileEngineIterator(filters, filterNames)
|
||||
, done(false)
|
||||
{
|
||||
}
|
||||
|
||||
QFSFileEngineIterator::~QFSFileEngineIterator()
|
||||
{
|
||||
}
|
||||
|
||||
bool QFSFileEngineIterator::hasNext() const
|
||||
{
|
||||
if (!done && !nativeIterator) {
|
||||
nativeIterator.reset(new QFileSystemIterator(QFileSystemEntry(path()),
|
||||
filters(), nameFilters()));
|
||||
advance();
|
||||
}
|
||||
|
||||
return !done;
|
||||
}
|
||||
|
||||
QString QFSFileEngineIterator::next()
|
||||
{
|
||||
if (!hasNext())
|
||||
return QString();
|
||||
|
||||
advance();
|
||||
return currentFilePath();
|
||||
}
|
||||
|
||||
void QFSFileEngineIterator::advance() const
|
||||
{
|
||||
currentInfo = nextInfo;
|
||||
|
||||
QFileSystemEntry entry;
|
||||
QFileSystemMetaData data;
|
||||
if (nativeIterator->advance(entry, data)) {
|
||||
nextInfo = QFileInfo(new QFileInfoPrivate(entry, data));
|
||||
} else {
|
||||
done = true;
|
||||
nativeIterator.reset();
|
||||
}
|
||||
}
|
||||
|
||||
QString QFSFileEngineIterator::currentFileName() const
|
||||
{
|
||||
return currentInfo.fileName();
|
||||
}
|
||||
|
||||
QFileInfo QFSFileEngineIterator::currentFileInfo() const
|
||||
{
|
||||
return currentInfo;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QT_NO_FILESYSTEMITERATOR
|
70
src/app/core/backport/qfsfileengine_iterator_p.h
Normal file
70
src/app/core/backport/qfsfileengine_iterator_p.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFSFILEENGINE_ITERATOR_P_H
|
||||
#define QFSFILEENGINE_ITERATOR_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qabstractfileengine_p.h"
|
||||
#include "qfilesystemiterator_p.h"
|
||||
#include <QDir>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
class QFSFileEngineIteratorPrivate;
|
||||
class QFSFileEngineIteratorPlatformSpecificData;
|
||||
|
||||
class QFSFileEngineIterator : public QAbstractFileEngineIterator
|
||||
{
|
||||
public:
|
||||
QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames);
|
||||
~QFSFileEngineIterator();
|
||||
|
||||
QString next();
|
||||
bool hasNext() const;
|
||||
|
||||
QString currentFileName() const;
|
||||
QFileInfo currentFileInfo() const;
|
||||
|
||||
private:
|
||||
void advance() const;
|
||||
mutable QScopedPointer<QFileSystemIterator> nativeIterator;
|
||||
mutable QFileInfo currentInfo;
|
||||
mutable QFileInfo nextInfo;
|
||||
mutable bool done;
|
||||
};
|
||||
|
||||
#endif // QT_NO_FILESYSTEMITERATOR
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QFSFILEENGINE_ITERATOR_P_H
|
218
src/app/core/backport/qfsfileengine_p.h
Normal file
218
src/app/core/backport/qfsfileengine_p.h
Normal file
|
@ -0,0 +1,218 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QFSFILEENGINE_P_H
|
||||
#define QFSFILEENGINE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qabstractfileengine_p.h"
|
||||
#include "qfilesystementry_p.h"
|
||||
#include "qfilesystemmetadata_p.h"
|
||||
#include <QHash>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
|
||||
#if defined(Q_OS_WINCE_STD) && _WIN32_WCE < 0x600
|
||||
#define Q_USE_DEPRECATED_MAP_API 1
|
||||
#endif
|
||||
|
||||
class QFSFileEnginePrivate;
|
||||
|
||||
class QFSFileEngine : public QAbstractFileEngine
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QFSFileEngine)
|
||||
public:
|
||||
QFSFileEngine();
|
||||
explicit QFSFileEngine(const QString &file);
|
||||
~QFSFileEngine();
|
||||
|
||||
bool open(QIODevice::OpenMode openMode);
|
||||
bool open(QIODevice::OpenMode flags, FILE *fh);
|
||||
bool close();
|
||||
bool flush();
|
||||
bool syncToDisk();
|
||||
qint64 size() const;
|
||||
qint64 pos() const;
|
||||
bool seek(qint64);
|
||||
bool isSequential() const;
|
||||
bool remove();
|
||||
bool copy(const QString &newName);
|
||||
bool rename(const QString &newName);
|
||||
bool renameOverwrite(const QString &newName);
|
||||
bool link(const QString &newName);
|
||||
bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||
bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||
bool setSize(qint64 size);
|
||||
bool caseSensitive() const;
|
||||
bool isRelativePath() const;
|
||||
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||
FileFlags fileFlags(FileFlags type) const;
|
||||
bool setPermissions(uint perms);
|
||||
QString fileName(FileName file) const;
|
||||
uint ownerId(FileOwner) const;
|
||||
QString owner(FileOwner) const;
|
||||
QDateTime fileTime(FileTime time) const;
|
||||
void setFileName(const QString &file);
|
||||
int handle() const;
|
||||
|
||||
#ifndef QT_NO_FILESYSTEMITERATOR
|
||||
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||
Iterator *endEntryList();
|
||||
#endif
|
||||
|
||||
qint64 read(char *data, qint64 maxlen);
|
||||
qint64 readLine(char *data, qint64 maxlen);
|
||||
qint64 write(const char *data, qint64 len);
|
||||
|
||||
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||
bool supportsExtension(Extension extension) const;
|
||||
|
||||
//FS only!!
|
||||
bool open(QIODevice::OpenMode flags, int fd);
|
||||
bool open(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags);
|
||||
bool open(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags);
|
||||
static bool setCurrentPath(const QString &path);
|
||||
static QString currentPath(const QString &path = QString());
|
||||
static QString homePath();
|
||||
static QString rootPath();
|
||||
static QString tempPath();
|
||||
static QFileInfoList drives();
|
||||
|
||||
protected:
|
||||
QFSFileEngine(QFSFileEnginePrivate &dd);
|
||||
};
|
||||
|
||||
class QFSFileEnginePrivate : public QAbstractFileEnginePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QFSFileEngine)
|
||||
|
||||
public:
|
||||
#ifdef Q_OS_WIN
|
||||
static QString longFileName(const QString &path);
|
||||
#endif
|
||||
|
||||
QFileSystemEntry fileEntry;
|
||||
QIODevice::OpenMode openMode;
|
||||
|
||||
bool nativeOpen(QIODevice::OpenMode openMode);
|
||||
bool openFh(QIODevice::OpenMode flags, FILE *fh);
|
||||
bool openFd(QIODevice::OpenMode flags, int fd);
|
||||
bool nativeClose();
|
||||
bool closeFdFh();
|
||||
bool nativeFlush();
|
||||
bool nativeSyncToDisk();
|
||||
bool flushFh();
|
||||
qint64 nativeSize() const;
|
||||
#ifndef Q_OS_WIN
|
||||
qint64 sizeFdFh() const;
|
||||
#endif
|
||||
qint64 nativePos() const;
|
||||
qint64 posFdFh() const;
|
||||
bool nativeSeek(qint64);
|
||||
bool seekFdFh(qint64);
|
||||
qint64 nativeRead(char *data, qint64 maxlen);
|
||||
qint64 readFdFh(char *data, qint64 maxlen);
|
||||
qint64 nativeReadLine(char *data, qint64 maxlen);
|
||||
qint64 readLineFdFh(char *data, qint64 maxlen);
|
||||
qint64 nativeWrite(const char *data, qint64 len);
|
||||
qint64 writeFdFh(const char *data, qint64 len);
|
||||
int nativeHandle() const;
|
||||
bool nativeIsSequential() const;
|
||||
#ifndef Q_OS_WIN
|
||||
bool isSequentialFdFh() const;
|
||||
#endif
|
||||
|
||||
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
|
||||
bool unmap(uchar *ptr);
|
||||
|
||||
mutable QFileSystemMetaData metaData;
|
||||
|
||||
FILE *fh;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
HANDLE fileHandle;
|
||||
HANDLE mapHandle;
|
||||
QHash<uchar *, DWORD /* offset % AllocationGranularity */> maps;
|
||||
|
||||
#ifndef Q_OS_WINCE
|
||||
mutable int cachedFd;
|
||||
#endif
|
||||
|
||||
mutable DWORD fileAttrib;
|
||||
#else
|
||||
QHash<uchar *, QPair<int /*offset % PageSize*/, size_t /*length + offset % PageSize*/> > maps;
|
||||
#endif
|
||||
int fd;
|
||||
|
||||
enum LastIOCommand
|
||||
{
|
||||
IOFlushCommand,
|
||||
IOReadCommand,
|
||||
IOWriteCommand
|
||||
};
|
||||
LastIOCommand lastIOCommand;
|
||||
bool lastFlushFailed;
|
||||
bool closeFileHandle;
|
||||
|
||||
mutable uint is_sequential : 2;
|
||||
mutable uint could_stat : 1;
|
||||
mutable uint tried_stat : 1;
|
||||
#if !defined(Q_OS_WINCE)
|
||||
mutable uint need_lstat : 1;
|
||||
mutable uint is_link : 1;
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
bool doStat(QFileSystemMetaData::MetaDataFlags flags) const;
|
||||
#else
|
||||
bool doStat(QFileSystemMetaData::MetaDataFlags flags = QFileSystemMetaData::PosixStatFlags) const;
|
||||
#endif
|
||||
bool isSymlink() const;
|
||||
|
||||
#if defined(Q_OS_WIN32)
|
||||
int sysOpen(const QString &, int flags);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
QFSFileEnginePrivate();
|
||||
|
||||
void init();
|
||||
|
||||
QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const;
|
||||
};
|
||||
|
||||
#endif // QT_NO_FSFILEENGINE
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QFSFILEENGINE_P_H
|
749
src/app/core/backport/qfsfileengine_unix.cpp
Normal file
749
src/app/core/backport/qfsfileengine_unix.cpp
Normal file
|
@ -0,0 +1,749 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qabstractfileengine_p.h"
|
||||
#include "qfsfileengine_p.h"
|
||||
#include "qcore_unix_p.h"
|
||||
#include "qfilesystementry_p.h"
|
||||
#include "qfilesystemengine_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_FSFILEENGINE
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include <QVarLengthArray>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#if !defined(QWS) && defined(Q_OS_MAC)
|
||||
# include "qcore_mac_p.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns the stdlib open string corresponding to a QIODevice::OpenMode.
|
||||
*/
|
||||
static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QFileSystemEntry &fileEntry,
|
||||
QFileSystemMetaData &metaData)
|
||||
{
|
||||
QByteArray mode;
|
||||
if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) {
|
||||
mode = "rb";
|
||||
if (flags & QIODevice::WriteOnly) {
|
||||
metaData.clearFlags(QFileSystemMetaData::FileType);
|
||||
if (!fileEntry.isEmpty()
|
||||
&& QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::FileType)
|
||||
&& metaData.isFile()) {
|
||||
mode += '+';
|
||||
} else {
|
||||
mode = "wb+";
|
||||
}
|
||||
}
|
||||
} else if (flags & QIODevice::WriteOnly) {
|
||||
mode = "wb";
|
||||
if (flags & QIODevice::ReadOnly)
|
||||
mode += '+';
|
||||
}
|
||||
if (flags & QIODevice::Append) {
|
||||
mode = "ab";
|
||||
if (flags & QIODevice::ReadOnly)
|
||||
mode += '+';
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207
|
||||
// must be glibc >= 2.7
|
||||
mode += 'e';
|
||||
#endif
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns the stdio open flags corresponding to a QIODevice::OpenMode.
|
||||
*/
|
||||
static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
|
||||
{
|
||||
int oflags = QT_OPEN_RDONLY;
|
||||
#ifdef QT_LARGEFILE_SUPPORT
|
||||
oflags |= QT_OPEN_LARGEFILE;
|
||||
#endif
|
||||
|
||||
if ((mode & QFile::ReadWrite) == QFile::ReadWrite) {
|
||||
oflags = QT_OPEN_RDWR | QT_OPEN_CREAT;
|
||||
} else if (mode & QFile::WriteOnly) {
|
||||
oflags = QT_OPEN_WRONLY | QT_OPEN_CREAT;
|
||||
}
|
||||
|
||||
if (mode & QFile::Append) {
|
||||
oflags |= QT_OPEN_APPEND;
|
||||
} else if (mode & QFile::WriteOnly) {
|
||||
if ((mode & QFile::Truncate) || !(mode & QFile::ReadOnly))
|
||||
oflags |= QT_OPEN_TRUNC;
|
||||
}
|
||||
|
||||
return oflags;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Sets the file descriptor to close on exec. That is, the file
|
||||
descriptor is not inherited by child processes.
|
||||
*/
|
||||
static inline bool setCloseOnExec(int fd)
|
||||
{
|
||||
return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
if (openMode & QIODevice::Unbuffered) {
|
||||
int flags = openModeToOpenFlags(openMode);
|
||||
|
||||
// Try to open the file in unbuffered mode.
|
||||
do {
|
||||
fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
|
||||
} while (fd == -1 && errno == EINTR);
|
||||
|
||||
// On failure, return and report the error.
|
||||
if (fd == -1) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(openMode & QIODevice::WriteOnly)) {
|
||||
// we don't need this check if we tried to open for writing because then
|
||||
// we had received EISDIR anyway.
|
||||
if (QFileSystemEngine::fillMetaData(fd, metaData)
|
||||
&& metaData.isDirectory()) {
|
||||
q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
|
||||
QT_CLOSE(fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Seek to the end when in Append mode.
|
||||
if (flags & QFile::Append) {
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_LSEEK(fd, 0, SEEK_END);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret == -1) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(int(errno)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fh = 0;
|
||||
} else {
|
||||
QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);
|
||||
|
||||
// Try to open the file in buffered mode.
|
||||
do {
|
||||
fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
|
||||
} while (!fh && errno == EINTR);
|
||||
|
||||
// On failure, return and report the error.
|
||||
if (!fh) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(int(errno)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(openMode & QIODevice::WriteOnly)) {
|
||||
// we don't need this check if we tried to open for writing because then
|
||||
// we had received EISDIR anyway.
|
||||
if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
|
||||
&& metaData.isDirectory()) {
|
||||
q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
|
||||
fclose(fh);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setCloseOnExec(fileno(fh)); // ignore failure
|
||||
|
||||
// Seek to the end when in Append mode.
|
||||
if (openMode & QIODevice::Append) {
|
||||
int ret;
|
||||
do {
|
||||
ret = QT_FSEEK(fh, 0, SEEK_END);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret == -1) {
|
||||
q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
|
||||
qt_error_string(int(errno)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
closeFileHandle = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeClose()
|
||||
{
|
||||
return closeFdFh();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeFlush()
|
||||
{
|
||||
return fh ? flushFh() : fd != -1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\since 5.1
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeSyncToDisk()
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
|
||||
const int ret = fdatasync(nativeHandle());
|
||||
#else
|
||||
const int ret = fsync(nativeHandle());
|
||||
#endif
|
||||
if (ret != 0)
|
||||
q->setError(QFile::WriteError, qt_error_string(errno));
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
|
||||
if (fh && nativeIsSequential()) {
|
||||
size_t readBytes = 0;
|
||||
int oldFlags = fcntl(QT_FILENO(fh), F_GETFL);
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
// Unix: Make the underlying file descriptor non-blocking
|
||||
if ((oldFlags & O_NONBLOCK) == 0)
|
||||
fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK);
|
||||
|
||||
// Cross platform stdlib read
|
||||
size_t read = 0;
|
||||
do {
|
||||
read = fread(data + readBytes, 1, size_t(len - readBytes), fh);
|
||||
} while (read == 0 && !feof(fh) && errno == EINTR);
|
||||
if (read > 0) {
|
||||
readBytes += read;
|
||||
break;
|
||||
} else {
|
||||
if (readBytes)
|
||||
break;
|
||||
readBytes = read;
|
||||
}
|
||||
|
||||
// Unix: Restore the blocking state of the underlying socket
|
||||
if ((oldFlags & O_NONBLOCK) == 0) {
|
||||
fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
|
||||
if (readBytes == 0) {
|
||||
int readByte = 0;
|
||||
do {
|
||||
readByte = fgetc(fh);
|
||||
} while (readByte == -1 && errno == EINTR);
|
||||
if (readByte != -1) {
|
||||
*data = uchar(readByte);
|
||||
readBytes += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unix: Restore the blocking state of the underlying socket
|
||||
if ((oldFlags & O_NONBLOCK) == 0) {
|
||||
fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
|
||||
}
|
||||
if (readBytes == 0 && !feof(fh)) {
|
||||
// if we didn't read anything and we're not at EOF, it must be an error
|
||||
q->setError(QFile::ReadError, qt_error_string(int(errno)));
|
||||
return -1;
|
||||
}
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
return readFdFh(data, len);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::nativeReadLine(char *data, qint64 maxlen)
|
||||
{
|
||||
return readLineFdFh(data, maxlen);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
|
||||
{
|
||||
return writeFdFh(data, len);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QFSFileEnginePrivate::nativePos() const
|
||||
{
|
||||
return posFdFh();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeSeek(qint64 pos)
|
||||
{
|
||||
return seekFdFh(pos);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
int QFSFileEnginePrivate::nativeHandle() const
|
||||
{
|
||||
return fh ? fileno(fh) : fd;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QFSFileEnginePrivate::nativeIsSequential() const
|
||||
{
|
||||
return isSequentialFdFh();
|
||||
}
|
||||
|
||||
bool QFSFileEngine::remove()
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
QSystemError error;
|
||||
bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
|
||||
d->metaData.clear();
|
||||
if (!ret) {
|
||||
setError(QFile::RemoveError, error.toString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QFSFileEngine::copy(const QString &newName)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
QSystemError error;
|
||||
bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(newName), error);
|
||||
if (!ret) {
|
||||
setError(QFile::CopyError, error.toString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QFSFileEngine::renameOverwrite(const QString &newName)
|
||||
{
|
||||
// On Unix, rename() overwrites.
|
||||
return rename(newName);
|
||||
}
|
||||
|
||||
bool QFSFileEngine::rename(const QString &newName)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
QSystemError error;
|
||||
bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
|
||||
|
||||
if (!ret) {
|
||||
setError(QFile::RenameError, error.toString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QFSFileEngine::link(const QString &newName)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
QSystemError error;
|
||||
bool ret = QFileSystemEngine::createLink(d->fileEntry, QFileSystemEntry(newName), error);
|
||||
if (!ret) {
|
||||
setError(QFile::RenameError, error.toString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
qint64 QFSFileEnginePrivate::nativeSize() const
|
||||
{
|
||||
return sizeFdFh();
|
||||
}
|
||||
|
||||
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
|
||||
{
|
||||
return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
|
||||
}
|
||||
|
||||
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
|
||||
{
|
||||
return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
|
||||
}
|
||||
|
||||
bool QFSFileEngine::caseSensitive() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QFSFileEngine::setCurrentPath(const QString &path)
|
||||
{
|
||||
return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path));
|
||||
}
|
||||
|
||||
QString QFSFileEngine::currentPath(const QString &)
|
||||
{
|
||||
return QFileSystemEngine::currentPath().filePath();
|
||||
}
|
||||
|
||||
QString QFSFileEngine::homePath()
|
||||
{
|
||||
return QFileSystemEngine::homePath();
|
||||
}
|
||||
|
||||
QString QFSFileEngine::rootPath()
|
||||
{
|
||||
return QFileSystemEngine::rootPath();
|
||||
}
|
||||
|
||||
QString QFSFileEngine::tempPath()
|
||||
{
|
||||
return QFileSystemEngine::tempPath();
|
||||
}
|
||||
|
||||
QFileInfoList QFSFileEngine::drives()
|
||||
{
|
||||
QFileInfoList ret;
|
||||
ret.append(QFileInfo(rootPath()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
|
||||
{
|
||||
if (!tried_stat || !metaData.hasFlags(flags)) {
|
||||
tried_stat = 1;
|
||||
|
||||
int localFd = fd;
|
||||
if (fh && fileEntry.isEmpty())
|
||||
localFd = QT_FILENO(fh);
|
||||
if (localFd != -1)
|
||||
QFileSystemEngine::fillMetaData(localFd, metaData);
|
||||
|
||||
if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
|
||||
QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags));
|
||||
}
|
||||
|
||||
return metaData.exists();
|
||||
}
|
||||
|
||||
bool QFSFileEnginePrivate::isSymlink() const
|
||||
{
|
||||
if (!metaData.hasFlags(QFileSystemMetaData::LinkType))
|
||||
QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::LinkType);
|
||||
|
||||
return metaData.isLink();
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
|
||||
if (type & Refresh)
|
||||
d->metaData.clear();
|
||||
|
||||
QAbstractFileEngine::FileFlags ret = 0;
|
||||
|
||||
if (type & FlagsMask)
|
||||
ret |= LocalDiskFlag;
|
||||
|
||||
bool exists;
|
||||
{
|
||||
QFileSystemMetaData::MetaDataFlags queryFlags = 0;
|
||||
|
||||
queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
|
||||
& QFileSystemMetaData::Permissions;
|
||||
|
||||
if (type & TypesMask)
|
||||
queryFlags |= QFileSystemMetaData::AliasType
|
||||
| QFileSystemMetaData::LinkType
|
||||
| QFileSystemMetaData::FileType
|
||||
| QFileSystemMetaData::DirectoryType
|
||||
| QFileSystemMetaData::BundleType;
|
||||
|
||||
if (type & FlagsMask)
|
||||
queryFlags |= QFileSystemMetaData::HiddenAttribute
|
||||
| QFileSystemMetaData::ExistsAttribute;
|
||||
|
||||
queryFlags |= QFileSystemMetaData::LinkType;
|
||||
|
||||
exists = d->doStat(queryFlags);
|
||||
}
|
||||
|
||||
if (!exists && !d->metaData.isLink())
|
||||
return ret;
|
||||
|
||||
if (exists && (type & PermsMask))
|
||||
ret |= FileFlags(uint(d->metaData.permissions()));
|
||||
|
||||
if (type & TypesMask) {
|
||||
if (d->metaData.isAlias()) {
|
||||
ret |= LinkType;
|
||||
} else {
|
||||
if ((type & LinkType) && d->metaData.isLink())
|
||||
ret |= LinkType;
|
||||
if (exists) {
|
||||
if (d->metaData.isFile()) {
|
||||
ret |= FileType;
|
||||
} else if (d->metaData.isDirectory()) {
|
||||
ret |= DirectoryType;
|
||||
if ((type & BundleType) && d->metaData.isBundle())
|
||||
ret |= BundleType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type & FlagsMask) {
|
||||
if (exists)
|
||||
ret |= ExistsFlag;
|
||||
if (d->fileEntry.isRoot())
|
||||
ret |= RootFlag;
|
||||
else if (d->metaData.isHidden())
|
||||
ret |= HiddenFlag;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString QFSFileEngine::fileName(FileName file) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
if (file == BundleName) {
|
||||
return QFileSystemEngine::bundleName(d->fileEntry);
|
||||
} else if (file == BaseName) {
|
||||
return d->fileEntry.fileName();
|
||||
} else if (file == PathName) {
|
||||
return d->fileEntry.path();
|
||||
} else if (file == AbsoluteName || file == AbsolutePathName) {
|
||||
QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry));
|
||||
if (file == AbsolutePathName) {
|
||||
return entry.path();
|
||||
}
|
||||
return entry.filePath();
|
||||
} else if (file == CanonicalName || file == CanonicalPathName) {
|
||||
QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
|
||||
if (file == CanonicalPathName)
|
||||
return entry.path();
|
||||
return entry.filePath();
|
||||
} else if (file == LinkName) {
|
||||
if (d->isSymlink()) {
|
||||
QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
|
||||
return entry.filePath();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
return d->fileEntry.filePath();
|
||||
}
|
||||
|
||||
bool QFSFileEngine::isRelativePath() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
return d->fileEntry.filePath().length() ? d->fileEntry.filePath()[0] != QLatin1Char('/') : true;
|
||||
}
|
||||
|
||||
uint QFSFileEngine::ownerId(FileOwner own) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
static const uint nobodyID = (uint) -2;
|
||||
|
||||
if (d->doStat(QFileSystemMetaData::OwnerIds))
|
||||
return d->metaData.ownerId(own);
|
||||
|
||||
return nobodyID;
|
||||
}
|
||||
|
||||
QString QFSFileEngine::owner(FileOwner own) const
|
||||
{
|
||||
if (own == OwnerUser)
|
||||
return QFileSystemEngine::resolveUserName(ownerId(own));
|
||||
return QFileSystemEngine::resolveGroupName(ownerId(own));
|
||||
}
|
||||
|
||||
bool QFSFileEngine::setPermissions(uint perms)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
QSystemError error;
|
||||
if (!QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0)) {
|
||||
setError(QFile::PermissionsError, error.toString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QFSFileEngine::setSize(qint64 size)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
bool ret = false;
|
||||
if (d->fd != -1)
|
||||
ret = QT_FTRUNCATE(d->fd, size) == 0;
|
||||
else if (d->fh)
|
||||
ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0;
|
||||
else
|
||||
ret = QT_TRUNCATE(d->fileEntry.nativeFilePath().constData(), size) == 0;
|
||||
if (!ret)
|
||||
setError(QFile::ResizeError, qt_error_string(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
QDateTime QFSFileEngine::fileTime(FileTime time) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
|
||||
if (d->doStat(QFileSystemMetaData::Times))
|
||||
return d->metaData.fileTime(time);
|
||||
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
|
||||
{
|
||||
Q_Q(QFSFileEngine);
|
||||
Q_UNUSED(flags);
|
||||
if (openMode == QIODevice::NotOpen) {
|
||||
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offset < 0 || offset != qint64(QT_OFF_T(offset))
|
||||
|| size < 0 || quint64(size) > quint64(size_t(-1))) {
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we know the mapping will extend beyond EOF, fail early to avoid
|
||||
// undefined behavior. Otherwise, let mmap have its say.
|
||||
if (doStat(QFileSystemMetaData::SizeAttribute)
|
||||
&& (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset)))
|
||||
qWarning("QFSFileEngine::map: Mapping a file beyond its size is not portable");
|
||||
|
||||
int access = 0;
|
||||
if (openMode & QIODevice::ReadOnly) access |= PROT_READ;
|
||||
if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE;
|
||||
|
||||
#if defined(Q_OS_INTEGRITY)
|
||||
int pageSize = sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
int pageSize = getpagesize();
|
||||
#endif
|
||||
int extra = offset % pageSize;
|
||||
|
||||
if (quint64(size + extra) > quint64((size_t)-1)) {
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t realSize = (size_t)size + extra;
|
||||
QT_OFF_T realOffset = QT_OFF_T(offset);
|
||||
realOffset &= ~(QT_OFF_T(pageSize - 1));
|
||||
|
||||
void *mapAddress = QT_MMAP((void*)0, realSize,
|
||||
access, MAP_SHARED, nativeHandle(), realOffset);
|
||||
if (MAP_FAILED != mapAddress) {
|
||||
uchar *address = extra + static_cast<uchar*>(mapAddress);
|
||||
maps[address] = QPair<int,size_t>(extra, realSize);
|
||||
return address;
|
||||
}
|
||||
|
||||
switch(errno) {
|
||||
case EBADF:
|
||||
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
|
||||
break;
|
||||
case ENFILE:
|
||||
case ENOMEM:
|
||||
q->setError(QFile::ResourceError, qt_error_string(int(errno)));
|
||||
break;
|
||||
case EINVAL:
|
||||
// size are out of bounds
|
||||
default:
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(int(errno)));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QFSFileEnginePrivate::unmap(uchar *ptr)
|
||||
{
|
||||
#if !defined(Q_OS_INTEGRITY)
|
||||
Q_Q(QFSFileEngine);
|
||||
if (!maps.contains(ptr)) {
|
||||
q->setError(QFile::PermissionsError, qt_error_string(EACCES));
|
||||
return false;
|
||||
}
|
||||
|
||||
uchar *start = ptr - maps[ptr].first;
|
||||
size_t len = maps[ptr].second;
|
||||
if (-1 == munmap(start, len)) {
|
||||
q->setError(QFile::UnspecifiedError, qt_error_string(errno));
|
||||
return false;
|
||||
}
|
||||
maps.remove(ptr);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // QT_NO_FSFILEENGINE
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
1053
src/app/core/backport/qfsfileengine_win.cpp
Normal file
1053
src/app/core/backport/qfsfileengine_win.cpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -210,7 +210,7 @@ bool QLockFile::tryLock(int timeout)
|
|||
if (!d->isLocked && d->isApparentlyStale()) {
|
||||
// Stale lock from another thread/process
|
||||
// Ensure two processes don't remove it at the same time
|
||||
QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));
|
||||
QLockFile rmlock(d->fileName + QStringLiteral(".rmlock"));
|
||||
if (rmlock.tryLock()) {
|
||||
if (d->isApparentlyStale() && d->removeStaleLock())
|
||||
continue;
|
||||
|
@ -220,7 +220,7 @@ bool QLockFile::tryLock(int timeout)
|
|||
}
|
||||
if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout)))
|
||||
return false;
|
||||
QLockFileThread::msleep(sleepTime);
|
||||
QThread::msleep(sleepTime);
|
||||
if (sleepTime < 5 * 1000)
|
||||
sleepTime *= 2;
|
||||
}
|
193
src/app/core/backport/qlockfile_unix.cpp
Normal file
193
src/app/core/backport/qlockfile_unix.cpp
Normal file
|
@ -0,0 +1,193 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qlockfile_p.h"
|
||||
|
||||
#include <QTemporaryFile>
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "qcore_unix_p.h" // qt_safe_open
|
||||
#include "qabstractfileengine_p.h"
|
||||
//#include "qtemporaryfile_p.h"
|
||||
|
||||
#include <sys/file.h> // flock
|
||||
#include <sys/types.h> // kill
|
||||
#include <signal.h> // kill
|
||||
#include <unistd.h> // gethostname
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
|
||||
{
|
||||
QByteArray hostName(512, Qt::Uninitialized);
|
||||
if (gethostname(hostName.data(), hostName.size()) == -1)
|
||||
return QByteArray();
|
||||
hostName.truncate(strlen(hostName.data()));
|
||||
return hostName;
|
||||
}
|
||||
|
||||
// ### merge into qt_safe_write?
|
||||
static qint64 qt_write_loop(int fd, const char *data, qint64 len)
|
||||
{
|
||||
qint64 pos = 0;
|
||||
while (pos < len) {
|
||||
const qint64 ret = qt_safe_write(fd, data + pos, len - pos);
|
||||
if (ret == -1) // e.g. partition full
|
||||
return pos;
|
||||
pos += ret;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
int QLockFilePrivate::checkFcntlWorksAfterFlock()
|
||||
{
|
||||
#ifndef QT_NO_TEMPORARYFILE
|
||||
QTemporaryFile file;
|
||||
if (!file.open())
|
||||
return 0;
|
||||
const int fd = file.d_func()->engine()->handle();
|
||||
#if defined(LOCK_EX) && defined(LOCK_NB)
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
|
||||
return 0;
|
||||
#endif
|
||||
struct flock flockData;
|
||||
flockData.l_type = F_WRLCK;
|
||||
flockData.l_whence = SEEK_SET;
|
||||
flockData.l_start = 0;
|
||||
flockData.l_len = 0; // 0 = entire file
|
||||
flockData.l_pid = getpid();
|
||||
if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
|
||||
return 0;
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1);
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Checks that the OS isn't using POSIX locks to emulate flock().
|
||||
Mac OS X is one of those.
|
||||
*/
|
||||
static bool fcntlWorksAfterFlock()
|
||||
{
|
||||
int value = fcntlOK.load();
|
||||
if (Q_UNLIKELY(value == -1)) {
|
||||
value = QLockFilePrivate::checkFcntlWorksAfterFlock();
|
||||
fcntlOK.store(value);
|
||||
}
|
||||
return value == 1;
|
||||
}
|
||||
|
||||
static bool setNativeLocks(int fd)
|
||||
{
|
||||
#if defined(LOCK_EX) && defined(LOCK_NB)
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
|
||||
return false;
|
||||
#endif
|
||||
struct flock flockData;
|
||||
flockData.l_type = F_WRLCK;
|
||||
flockData.l_whence = SEEK_SET;
|
||||
flockData.l_start = 0;
|
||||
flockData.l_len = 0; // 0 = entire file
|
||||
flockData.l_pid = getpid();
|
||||
if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
QLockFile::LockError QLockFilePrivate::tryLock_sys()
|
||||
{
|
||||
// Assemble data, to write in a single call to write
|
||||
// (otherwise we'd have to check every write call)
|
||||
// Use operator% from the fast builder to avoid multiple memory allocations.
|
||||
QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n'
|
||||
% qAppName().toUtf8() % '\n'
|
||||
% localHostName() % '\n';
|
||||
|
||||
const QByteArray lockFileName = QFile::encodeName(fileName);
|
||||
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||
if (fd < 0) {
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
return QLockFile::LockFailedError;
|
||||
case EACCES:
|
||||
case EROFS:
|
||||
return QLockFile::PermissionError;
|
||||
default:
|
||||
return QLockFile::UnknownError;
|
||||
}
|
||||
}
|
||||
// Ensure nobody else can delete the file while we have it
|
||||
if (!setNativeLocks(fd))
|
||||
qWarning() << "setNativeLocks failed:" << strerror(errno);
|
||||
|
||||
// We hold the lock, continue.
|
||||
fileHandle = fd;
|
||||
|
||||
QLockFile::LockError error = QLockFile::NoError;
|
||||
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size())
|
||||
error = QLockFile::UnknownError; // partition full
|
||||
return error;
|
||||
}
|
||||
|
||||
bool QLockFilePrivate::removeStaleLock()
|
||||
{
|
||||
const QByteArray lockFileName = QFile::encodeName(fileName);
|
||||
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
|
||||
if (fd < 0) // gone already?
|
||||
return false;
|
||||
bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
|
||||
close(fd);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
if (!getLockInfo(&pid, &hostname, &appname))
|
||||
return false;
|
||||
if (hostname == QString::fromLocal8Bit(localHostName())) {
|
||||
if (::kill(pid, 0) == -1 && errno == ESRCH)
|
||||
return true; // PID doesn't exist anymore
|
||||
}
|
||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||
return staleLockTime > 0 && age > staleLockTime;
|
||||
}
|
||||
|
||||
void QLockFile::unlock()
|
||||
{
|
||||
Q_D(QLockFile);
|
||||
if (!d->isLocked)
|
||||
return;
|
||||
close(d->fileHandle);
|
||||
d->fileHandle = -1;
|
||||
QFile::remove(d->fileName);
|
||||
d->lockError = QLockFile::NoError;
|
||||
d->isLocked = false;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
116
src/app/core/backport/qlockfile_win.cpp
Normal file
116
src/app/core/backport/qlockfile_win.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qlockfile_p.h"
|
||||
#include "qfilesystementry_p.h"
|
||||
#include <qt_windows.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
QLockFile::LockError QLockFilePrivate::tryLock_sys()
|
||||
{
|
||||
SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
|
||||
const QFileSystemEntry fileEntry(fileName);
|
||||
// When writing, allow others to read.
|
||||
// When reading, QFile will allow others to read and write, all good.
|
||||
// Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
|
||||
// but Windows doesn't allow recreating it while this handle is open anyway,
|
||||
// so this would only create confusion (can't lock, but no lock file to read from).
|
||||
const DWORD dwShareMode = FILE_SHARE_READ;
|
||||
HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
|
||||
GENERIC_WRITE,
|
||||
dwShareMode,
|
||||
&securityAtts,
|
||||
CREATE_NEW, // error if already exists
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fh == INVALID_HANDLE_VALUE) {
|
||||
const DWORD lastError = GetLastError();
|
||||
switch (lastError) {
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
case ERROR_FILE_EXISTS:
|
||||
case ERROR_ACCESS_DENIED: // readonly file, or file still in use by another process. Assume the latter, since we don't create it readonly.
|
||||
return QLockFile::LockFailedError;
|
||||
default:
|
||||
qWarning() << "Got unexpected locking error" << lastError;
|
||||
return QLockFile::UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
// We hold the lock, continue.
|
||||
fileHandle = fh;
|
||||
// Assemble data, to write in a single call to write
|
||||
// (otherwise we'd have to check every write call)
|
||||
QByteArray fileData;
|
||||
fileData += QByteArray::number(QCoreApplication::applicationPid());
|
||||
fileData += '\n';
|
||||
fileData += qAppName().toUtf8();
|
||||
fileData += '\n';
|
||||
//fileData += localHostname(); // gethostname requires winsock init, see QHostInfo...
|
||||
fileData += '\n';
|
||||
DWORD bytesWritten = 0;
|
||||
QLockFile::LockError error = QLockFile::NoError;
|
||||
if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh))
|
||||
error = QLockFile::UnknownError; // partition full
|
||||
return error;
|
||||
}
|
||||
|
||||
bool QLockFilePrivate::removeStaleLock()
|
||||
{
|
||||
// QFile::remove fails on Windows if the other process is still using the file, so it's not stale.
|
||||
return QFile::remove(fileName);
|
||||
}
|
||||
|
||||
bool QLockFilePrivate::isApparentlyStale() const
|
||||
{
|
||||
qint64 pid;
|
||||
QString hostname, appname;
|
||||
if (!getLockInfo(&pid, &hostname, &appname))
|
||||
return false;
|
||||
|
||||
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
if (!procHandle)
|
||||
return true;
|
||||
// We got a handle but check if process is still alive
|
||||
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
::CloseHandle(procHandle);
|
||||
if (dwR == WAIT_TIMEOUT)
|
||||
return true;
|
||||
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
|
||||
return staleLockTime > 0 && age > staleLockTime;
|
||||
}
|
||||
|
||||
void QLockFile::unlock()
|
||||
{
|
||||
Q_D(QLockFile);
|
||||
if (!d->isLocked)
|
||||
return;
|
||||
CloseHandle(d->fileHandle);
|
||||
QFile::remove(d->fileName);
|
||||
d->lockError = QLockFile::NoError;
|
||||
d->isLocked = false;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
133
src/app/core/backport/qmutexpool.cpp
Normal file
133
src/app/core/backport/qmutexpool.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qatomic.h"
|
||||
#include "qmutexpool_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
|
||||
|
||||
/*!
|
||||
\class QMutexPool
|
||||
\inmodule QtCore
|
||||
\brief The QMutexPool class provides a pool of QMutex objects.
|
||||
|
||||
\internal
|
||||
|
||||
\ingroup thread
|
||||
|
||||
QMutexPool is a convenience class that provides access to a fixed
|
||||
number of QMutex objects.
|
||||
|
||||
Typical use of a QMutexPool is in situations where it is not
|
||||
possible or feasible to use one QMutex for every protected object.
|
||||
The mutex pool will return a mutex based on the address of the
|
||||
object that needs protection.
|
||||
|
||||
For example, consider this simple class:
|
||||
|
||||
\snippet code/src_corelib_thread_qmutexpool.cpp 0
|
||||
|
||||
Adding a QMutex member to the Number class does not make sense,
|
||||
because it is so small. However, in order to ensure that access to
|
||||
each Number is protected, you need to use a mutex. In this case, a
|
||||
QMutexPool would be ideal.
|
||||
|
||||
Code to calculate the square of a number would then look something
|
||||
like this:
|
||||
|
||||
\snippet code/src_corelib_thread_qmutexpool.cpp 1
|
||||
|
||||
This function will safely calculate the square of a number, since
|
||||
it uses a mutex from a QMutexPool. The mutex is locked and
|
||||
unlocked automatically by the QMutexLocker class. See the
|
||||
QMutexLocker documentation for more details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a QMutexPool, reserving space for \a size QMutexes. All
|
||||
mutexes in the pool are created with \a recursionMode. By default,
|
||||
all mutexes are non-recursive.
|
||||
|
||||
The QMutexes are created when needed, and deleted when the
|
||||
QMutexPool is destructed.
|
||||
*/
|
||||
QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
|
||||
: mutexes(size), recursionMode(recursionMode)
|
||||
{
|
||||
for (int index = 0; index < mutexes.count(); ++index) {
|
||||
mutexes[index].store(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs a QMutexPool. All QMutexes that were created by the pool
|
||||
are deleted.
|
||||
*/
|
||||
QMutexPool::~QMutexPool()
|
||||
{
|
||||
for (int index = 0; index < mutexes.count(); ++index)
|
||||
delete mutexes[index].load();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the global QMutexPool instance.
|
||||
*/
|
||||
QMutexPool *QMutexPool::instance()
|
||||
{
|
||||
return globalMutexPool();
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QMutexPool::get(const void *address)
|
||||
Returns a QMutex from the pool. QMutexPool uses the value \a address
|
||||
to determine which mutex is returned from the pool.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
create the mutex for the given index
|
||||
*/
|
||||
QMutex *QMutexPool::createMutex(int index)
|
||||
{
|
||||
// mutex not created, create one
|
||||
QMutex *newMutex = new QMutex(recursionMode);
|
||||
if (!mutexes[index].testAndSetRelease(0, newMutex))
|
||||
delete newMutex;
|
||||
return mutexes[index].load();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QMutex from the global mutex pool.
|
||||
*/
|
||||
QMutex *QMutexPool::globalInstanceGet(const void *address)
|
||||
{
|
||||
QMutexPool * const globalInstance = globalMutexPool();
|
||||
if (globalInstance == 0)
|
||||
return 0;
|
||||
return globalInstance->get(address);
|
||||
}
|
||||
|
||||
#endif // QT_NO_THREAD
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
70
src/app/core/backport/qmutexpool_p.h
Normal file
70
src/app/core/backport/qmutexpool_p.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMUTEXPOOL_P_H
|
||||
#define QMUTEXPOOL_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of QSettings. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "QtCore/qatomic.h"
|
||||
#include <QMutex>
|
||||
#include <QVarLengthArray>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
|
||||
class QMutexPool
|
||||
{
|
||||
public:
|
||||
explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131);
|
||||
~QMutexPool();
|
||||
|
||||
inline QMutex *get(const void *address) {
|
||||
int index = uint(quintptr(address)) % mutexes.count();
|
||||
QMutex *m = mutexes[index].load();
|
||||
if (m)
|
||||
return m;
|
||||
else
|
||||
return createMutex(index);
|
||||
}
|
||||
static QMutexPool *instance();
|
||||
static QMutex *globalInstanceGet(const void *address);
|
||||
|
||||
private:
|
||||
QMutex *createMutex(int index);
|
||||
QVarLengthArray<QAtomicPointer<QMutex>, 131> mutexes;
|
||||
QMutex::RecursionMode recursionMode;
|
||||
};
|
||||
|
||||
#endif // QT_NO_THREAD
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QMUTEXPOOL_P_H
|
77
src/app/core/backport/qresource.h
Normal file
77
src/app/core/backport/qresource.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QRESOURCE_H
|
||||
#define QRESOURCE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QLocale>
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QResourcePrivate;
|
||||
|
||||
class QResource
|
||||
{
|
||||
public:
|
||||
QResource(const QString &file=QString(), const QLocale &locale=QLocale());
|
||||
~QResource();
|
||||
|
||||
void setFileName(const QString &file);
|
||||
QString fileName() const;
|
||||
QString absoluteFilePath() const;
|
||||
|
||||
void setLocale(const QLocale &locale);
|
||||
QLocale locale() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
bool isCompressed() const;
|
||||
qint64 size() const;
|
||||
const uchar *data() const;
|
||||
|
||||
static void addSearchPath(const QString &path);
|
||||
static QStringList searchPaths();
|
||||
|
||||
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
|
||||
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());
|
||||
|
||||
static bool registerResource(const uchar *rccData, const QString &resourceRoot=QString());
|
||||
static bool unregisterResource(const uchar *rccData, const QString &resourceRoot=QString());
|
||||
|
||||
protected:
|
||||
friend class QResourceFileEngine;
|
||||
friend class QResourceFileEngineIterator;
|
||||
bool isDir() const;
|
||||
inline bool isFile() const { return !isDir(); }
|
||||
QStringList children() const;
|
||||
|
||||
protected:
|
||||
QScopedPointer<QResourcePrivate> d_ptr;
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QResource)
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QRESOURCE_H
|
98
src/app/core/backport/qresource_p.h
Normal file
98
src/app/core/backport/qresource_p.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QRESOURCE_P_H
|
||||
#define QRESOURCE_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qabstractfileengine_p.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QResourceFileEnginePrivate;
|
||||
class QResourceFileEngine : public QAbstractFileEngine
|
||||
{
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QResourceFileEngine)
|
||||
public:
|
||||
explicit QResourceFileEngine(const QString &path);
|
||||
~QResourceFileEngine();
|
||||
|
||||
virtual void setFileName(const QString &file);
|
||||
|
||||
virtual bool open(QIODevice::OpenMode flags) ;
|
||||
virtual bool close();
|
||||
virtual bool flush();
|
||||
virtual qint64 size() const;
|
||||
virtual qint64 pos() const;
|
||||
virtual bool atEnd() const;
|
||||
virtual bool seek(qint64);
|
||||
virtual qint64 read(char *data, qint64 maxlen);
|
||||
virtual qint64 write(const char *data, qint64 len);
|
||||
|
||||
virtual bool remove();
|
||||
virtual bool copy(const QString &newName);
|
||||
virtual bool rename(const QString &newName);
|
||||
virtual bool link(const QString &newName);
|
||||
|
||||
virtual bool isSequential() const;
|
||||
|
||||
virtual bool isRelativePath() const;
|
||||
|
||||
virtual bool mkdir(const QString &dirName, bool createParentDirectories) const;
|
||||
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const;
|
||||
|
||||
virtual bool setSize(qint64 size);
|
||||
|
||||
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||
|
||||
virtual bool caseSensitive() const;
|
||||
|
||||
virtual FileFlags fileFlags(FileFlags type) const;
|
||||
|
||||
virtual bool setPermissions(uint perms);
|
||||
|
||||
virtual QString fileName(QAbstractFileEngine::FileName file) const;
|
||||
|
||||
virtual uint ownerId(FileOwner) const;
|
||||
virtual QString owner(FileOwner) const;
|
||||
|
||||
virtual QDateTime fileTime(FileTime time) const;
|
||||
|
||||
virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
|
||||
virtual Iterator *endEntryList();
|
||||
|
||||
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0);
|
||||
bool supportsExtension(Extension extension) const;
|
||||
};
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QRESOURCE_P_H
|
154
src/app/core/backport/qsystemerror.cpp
Normal file
154
src/app/core/backport/qsystemerror.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "qsystemerror_p.h"
|
||||
#if !defined(Q_OS_WINCE)
|
||||
# include <errno.h>
|
||||
# if defined(Q_CC_MSVC)
|
||||
# include <crtdbg.h>
|
||||
# endif
|
||||
#else
|
||||
# if (_WIN32_WCE >= 0x700)
|
||||
# include <errno.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
# include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
|
||||
defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
|
||||
namespace {
|
||||
// There are two incompatible versions of strerror_r:
|
||||
// a) the XSI/POSIX.1 version, which returns an int,
|
||||
// indicating success or not
|
||||
// b) the GNU version, which returns a char*, which may or may not
|
||||
// be the beginning of the buffer we used
|
||||
// The GNU libc manpage for strerror_r says you should use the XSI
|
||||
// version in portable code. However, it's impossible to do that if
|
||||
// _GNU_SOURCE is defined so we use C++ overloading to decide what to do
|
||||
// depending on the return type
|
||||
static inline QString fromstrerror_helper(int, const QByteArray &buf)
|
||||
{
|
||||
return QString::fromLocal8Bit(buf);
|
||||
}
|
||||
static inline QString fromstrerror_helper(const char *str, const QByteArray &)
|
||||
{
|
||||
return QString::fromLocal8Bit(str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static QString windowsErrorString(int errorCode)
|
||||
{
|
||||
QString ret;
|
||||
#ifndef Q_OS_WINRT
|
||||
wchar_t *string = 0;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errorCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&string,
|
||||
0,
|
||||
NULL);
|
||||
ret = QString::fromWCharArray(string);
|
||||
LocalFree((HLOCAL)string);
|
||||
#else
|
||||
wchar_t errorString[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errorCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&errorString,
|
||||
sizeof(errorString)/sizeof(wchar_t),
|
||||
NULL);
|
||||
ret = QString::fromWCharArray(errorString);
|
||||
#endif // Q_OS_WINRT
|
||||
|
||||
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
|
||||
ret = QString::fromLatin1("The specified module could not be found.");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static QString standardLibraryErrorString(int errorCode)
|
||||
{
|
||||
const char *s = 0;
|
||||
QString ret;
|
||||
switch (errorCode) {
|
||||
case 0:
|
||||
break;
|
||||
case EACCES:
|
||||
s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
|
||||
break;
|
||||
case EMFILE:
|
||||
s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
|
||||
break;
|
||||
case ENOENT:
|
||||
s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
|
||||
break;
|
||||
case ENOSPC:
|
||||
s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
|
||||
break;
|
||||
default: {
|
||||
#ifdef Q_OS_WINCE
|
||||
ret = windowsErrorString(errorCode);
|
||||
#else
|
||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
|
||||
QByteArray buf(1024, '\0');
|
||||
ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
|
||||
#else
|
||||
ret = QString::fromLocal8Bit(strerror(errorCode));
|
||||
#endif
|
||||
#endif
|
||||
break; }
|
||||
}
|
||||
if (s) {
|
||||
// ######## this breaks moc build currently
|
||||
// ret = QCoreApplication::translate("QIODevice", s);
|
||||
ret = QString::fromLatin1(s);
|
||||
}
|
||||
return ret.trimmed();
|
||||
}
|
||||
|
||||
QString QSystemError::toString()
|
||||
{
|
||||
switch(errorScope) {
|
||||
case NativeError:
|
||||
#if defined (Q_OS_WIN)
|
||||
return windowsErrorString(errorCode);
|
||||
#else
|
||||
//unix: fall through as native and standard library are the same
|
||||
#endif
|
||||
case StandardLibraryError:
|
||||
return standardLibraryErrorString(errorCode);
|
||||
default:
|
||||
qWarning("invalid error scope");
|
||||
//fall through
|
||||
case NoError:
|
||||
return QLatin1String("No error");
|
||||
}
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
85
src/app/core/backport/qsystemerror_p.h
Normal file
85
src/app/core/backport/qsystemerror_p.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QSYSTEMERROR_P_H
|
||||
#define QSYSTEMERROR_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QString>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
class QSystemError
|
||||
{
|
||||
public:
|
||||
enum ErrorScope
|
||||
{
|
||||
NoError,
|
||||
StandardLibraryError,
|
||||
NativeError
|
||||
};
|
||||
|
||||
inline QSystemError(int error, ErrorScope scope);
|
||||
inline QSystemError();
|
||||
|
||||
QString toString();
|
||||
inline ErrorScope scope();
|
||||
inline int error();
|
||||
|
||||
//data members
|
||||
int errorCode;
|
||||
ErrorScope errorScope;
|
||||
};
|
||||
|
||||
QSystemError::QSystemError(int error, QSystemError::ErrorScope scope)
|
||||
: errorCode(error), errorScope(scope)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QSystemError::QSystemError()
|
||||
: errorCode(0), errorScope(NoError)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QSystemError::ErrorScope QSystemError::scope()
|
||||
{
|
||||
return errorScope;
|
||||
}
|
||||
|
||||
int QSystemError::error()
|
||||
{
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif // QSYSTEMERROR_P_H
|
90
src/app/core/backport/qsystemlibrary_p.h
Normal file
90
src/app/core/backport/qsystemlibrary_p.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QSYSTEMLIBRARY_P_H
|
||||
#define QSYSTEMLIBRARY_P_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <QString>
|
||||
# include <qt_windows.h>
|
||||
|
||||
class QSystemLibrary
|
||||
{
|
||||
public:
|
||||
explicit QSystemLibrary(const QString &libraryName)
|
||||
{
|
||||
m_libraryName = libraryName;
|
||||
m_handle = 0;
|
||||
m_didLoad = false;
|
||||
}
|
||||
|
||||
explicit QSystemLibrary(const wchar_t *libraryName)
|
||||
{
|
||||
m_libraryName = QString::fromWCharArray(libraryName);
|
||||
m_handle = 0;
|
||||
m_didLoad = false;
|
||||
}
|
||||
|
||||
bool load(bool onlySystemDirectory = true)
|
||||
{
|
||||
m_handle = load((const wchar_t *)m_libraryName.utf16(), onlySystemDirectory);
|
||||
m_didLoad = true;
|
||||
return (m_handle != 0);
|
||||
}
|
||||
|
||||
bool isLoaded()
|
||||
{
|
||||
return (m_handle != 0);
|
||||
}
|
||||
|
||||
QFunctionPointer resolve(const char *symbol)
|
||||
{
|
||||
if (!m_didLoad)
|
||||
load();
|
||||
if (!m_handle)
|
||||
return 0;
|
||||
#ifdef Q_OS_WINCE
|
||||
return QFunctionPointer(GetProcAddress(m_handle, (const wchar_t*)QString::fromLatin1(symbol).utf16()));
|
||||
#else
|
||||
return QFunctionPointer(GetProcAddress(m_handle, symbol));
|
||||
#endif
|
||||
}
|
||||
|
||||
static QFunctionPointer resolve(const QString &libraryName, const char *symbol)
|
||||
{
|
||||
return QSystemLibrary(libraryName).resolve(symbol);
|
||||
}
|
||||
|
||||
static Q_CORE_EXPORT HINSTANCE load(const wchar_t *lpFileName, bool onlySystemDirectory = true);
|
||||
private:
|
||||
HINSTANCE m_handle;
|
||||
QString m_libraryName;
|
||||
bool m_didLoad;
|
||||
};
|
||||
|
||||
#endif //Q_OS_WIN
|
||||
|
||||
#endif //QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
|
||||
#endif //QSYSTEMLIBRARY_P_H
|
|
@ -5,15 +5,67 @@ HEADERS += \
|
|||
$$PWD/vapplication.h \
|
||||
$$PWD/undoevent.h \
|
||||
$$PWD/vsettings.h \
|
||||
$$PWD/qcommandlineoption.h \
|
||||
$$PWD/qcommandlineparser.h \
|
||||
$$PWD/qlockfile.h \
|
||||
$$PWD/qlockfile_p.h
|
||||
$$PWD/backport/qcommandlineoption.h \
|
||||
$$PWD/backport/qcommandlineparser.h \
|
||||
$$PWD/backport/qlockfile.h \
|
||||
$$PWD/backport/qlockfile_p.h \
|
||||
$$PWD/backport/qfilesystementry_p.h \
|
||||
$$PWD/backport/qfsfileengine_p.h \
|
||||
$$PWD/backport/qabstractfileengine_p.h \
|
||||
$$PWD/backport/qresource_p.h \
|
||||
$$PWD/backport/qresource.h \
|
||||
$$PWD/backport/qfilesystemmetadata_p.h \
|
||||
$$PWD/backport/qfilesystemengine_p.h \
|
||||
$$PWD/backport/qsystemerror_p.h \
|
||||
$$PWD/backport/qfsfileengine_iterator_p.h \
|
||||
$$PWD/backport/qfilesystemiterator_p.h \
|
||||
$$PWD/backport/qfileinfo_p.h \
|
||||
$$PWD/backport/qmutexpool_p.h \
|
||||
$$PWD/backport/qsystemlibrary_p.h \
|
||||
|
||||
unix:!macx {
|
||||
HEADERS += \
|
||||
$$PWD/backport/qcore_unix_p.h
|
||||
}
|
||||
|
||||
unix:macx {
|
||||
HEADERS += \
|
||||
$$PWD/backport/qcore_mac_p.h
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/vapplication.cpp \
|
||||
$$PWD/undoevent.cpp \
|
||||
$$PWD/vsettings.cpp \
|
||||
$$PWD/qcommandlineoption.cpp \
|
||||
$$PWD/qcommandlineparser.cpp \
|
||||
$$PWD/qlockfile.cpp
|
||||
$$PWD/backport/qcommandlineoption.cpp \
|
||||
$$PWD/backport/qcommandlineparser.cpp \
|
||||
$$PWD/backport/qlockfile.cpp \
|
||||
$$PWD/backport/qfilesystementry.cpp \
|
||||
$$PWD/backport/qfsfileengine.cpp \
|
||||
$$PWD/backport/qabstractfileengine.cpp \
|
||||
$$PWD/backport/qfilesystemengine.cpp \
|
||||
$$PWD/backport/qsystemerror.cpp \
|
||||
$$PWD/backport/qfsfileengine_iterator.cpp \
|
||||
$$PWD/backport/qmutexpool.cpp
|
||||
|
||||
unix:!macx {
|
||||
SOURCES += \
|
||||
$$PWD/backport/qlockfile_unix.cpp \
|
||||
$$PWD/backport/qfilesystemiterator_unix.cpp \
|
||||
$$PWD/backport/qfsfileengine_unix.cpp \
|
||||
$$PWD/backport/qfilesystemengine_unix.cpp \
|
||||
$$PWD/backport/qcore_unix.cpp
|
||||
}
|
||||
|
||||
unix:macx {
|
||||
SOURCES += \
|
||||
$$PWD/backport/qcore_mac.cpp
|
||||
}
|
||||
|
||||
win32 {
|
||||
SOURCES += \
|
||||
$$PWD/backport/qlockfile_win.cpp \
|
||||
$$PWD/backport/qfilesystemiterator_win.cpp \
|
||||
$$PWD/backport/qfsfileengine_win.cpp \
|
||||
$$PWD/backport/qfilesystemengine_win.cpp
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include <QThread>
|
||||
#include <QDateTime>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
# include "qlockfile.h"
|
||||
# include "backport/qlockfile.h"
|
||||
#else
|
||||
# include <QLockFile>
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
|
||||
# include "../core/qcommandlineparser.h"
|
||||
# include "../core/backport/qcommandlineparser.h"
|
||||
#else
|
||||
# include <QCommandLineParser>
|
||||
#endif
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
#include <QDesktopWidget>
|
||||
#include <QDesktopServices>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||
# include "core/qlockfile.h"
|
||||
# include "core/backport/qlockfile.h"
|
||||
#else
|
||||
# include <QLockFile>
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user