?? qfsfileengine.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qfsfileengine_p.h"#include "qdatetime.h"#include <errno.h>#include <stdio.h>#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#endif/*! \class QFSFileEngine \brief The QFSFileEngine class implements Qt's default file engine. \since 4.1 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()).*///**************** QFSFileEnginePrivateQFSFileEnginePrivate::QFSFileEnginePrivate() : QAbstractFileEnginePrivate(){ sequential = 0; tried_stat = 0;#ifdef Q_OS_UNIX need_lstat = 1; is_link = 0;#endif is_readonly = 0; fd = -1; fh = 0; lastIOCommand = IOFlushCommand; lastFlushFailed = false; closeFileHandle = false; init();}/*! Constructs a QFSFileEngine for the file name \a file.*/QFSFileEngine::QFSFileEngine(const QString &file) : QAbstractFileEngine(*new QFSFileEnginePrivate){ Q_D(QFSFileEngine); d->file = QFSFileEnginePrivate::fixToQtSlashes(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); } }}/*! \reimp*/void QFSFileEngine::setFileName(const QString &file){ Q_D(QFSFileEngine); d->file = QFSFileEnginePrivate::fixToQtSlashes(file); d->tried_stat = 0;}static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString &fileName = QString()){ QByteArray mode; if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) { mode = "rb"; if (flags & QIODevice::WriteOnly) { if (!fileName.isEmpty() &&QFile::exists(fileName)) mode = "rb+"; 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 += "+"; } return mode;}/*! \reimp*/bool QFSFileEngine::open(QIODevice::OpenMode flags){ Q_D(QFSFileEngine); d->lastFlushFailed = false; if (d->file.isEmpty()) { qWarning("QFSFileEngine::open: No file name specified"); setError(QFile::OpenError, QLatin1String("No file name specified")); return false; } if (flags & QFile::Append) flags |= QFile::WriteOnly;#ifdef Q_OS_WIN if (d->file.startsWith("//./")) {#endif do {#if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 d->fh = 0; fopen_s(&d->fh, QFile::encodeName(QDir::toNativeSeparators(d->file)).constData(), openModeToFopenMode(flags, d->file).constData());#else d->fh = QT_FOPEN(QFile::encodeName(QDir::toNativeSeparators(d->file)).constData(), openModeToFopenMode(flags, d->file).constData());#endif } while (!d->fh && errno == EINTR); if (!d->fh) { setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } if ((flags & QIODevice::WriteOnly) == 0) d->is_readonly = 1; if (flags & QIODevice::Unbuffered) setvbuf(d->fh, 0, _IONBF, 0); if (flags & QIODevice::Append) { int ret; do { ret = QT_FSEEK(d->fh, 0, SEEK_END); } while (ret == -1 && errno == EINTR); } d->closeFileHandle = true; d->fd = QT_FILENO(d->fh); QT_STATBUF st; if (QT_FSTAT(QT_FILENO(d->fh), &st) != 0)#ifdef Q_OS_UNIX return false;#endif d->sequential = S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode); return true;#ifdef Q_OS_WIN } else {#endif int oflags = QT_OPEN_RDONLY; if ((flags & QFile::ReadWrite) == QFile::ReadWrite) { oflags = QT_OPEN_RDWR | QT_OPEN_CREAT; } else if (flags & QFile::WriteOnly) { oflags = QT_OPEN_WRONLY | QT_OPEN_CREAT; } if (flags & QFile::Append) { oflags |= QT_OPEN_APPEND; } else if (flags & QFile::WriteOnly) { if ((flags & QFile::Truncate) || !(flags & QFile::ReadOnly)) oflags |= QT_OPEN_TRUNC; }#if defined(Q_OS_MSDOS) || defined(Q_OS_WIN32) || defined(Q_OS_OS2) oflags |= QT_OPEN_BINARY; // we handle all text translations our self.#endif d->fd = d->sysOpen(d->file, oflags); if(d->fd != -1) { // Before appending, seek to the end of the file to allow // at() to return the correct position before ::write() // has been called. if (flags & QFile::Append) QT_LSEEK(d->fd, 0, SEEK_END); d->closeFileHandle = true; d->sequential = 0; struct stat st; ::fstat(d->fd, &st); if ((st.st_mode & S_IFMT) != S_IFREG) d->sequential = 1; return true; } setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno)); return false;#ifdef Q_OS_WIN }#endif}/*! Opens the file descriptor \a fd to the file engine, using the open mode \a flags.*/bool QFSFileEngine::open(QIODevice::OpenMode flags, int fd){ Q_D(QFSFileEngine); d->lastFlushFailed = false; d->closeFileHandle = false;#ifdef Q_OS_UNIX d->fh = fdopen(fd, openModeToFopenMode(flags).constData()); if (!d->fh) { setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } if ((flags & QIODevice::WriteOnly) == 0) d->is_readonly = 1; if (flags & QIODevice::Unbuffered) setvbuf(d->fh, 0, _IONBF, 0); if (flags & QIODevice::Append) { int ret; do { ret = QT_FSEEK(d->fh, 0, SEEK_END); } while (ret == -1 && errno == EINTR); } d->fd = QT_FILENO(d->fh); QT_STATBUF st; if (QT_FSTAT(QT_FILENO(d->fh), &st) != 0) return false; d->sequential = S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode); return true;#else Q_UNUSED(flags); d->fd = fd; if(d->fd != -1) { d->sequential = 0; struct stat st; ::fstat(d->fd, &st); if ((st.st_mode & QT_STAT_MASK) != QT_STAT_REG || !fd) //stdin is non seekable d->sequential = 1; return true; } return false;#endif}/*! Opens the file handle \a fh using the open mode \a flags.*/bool QFSFileEngine::open(QIODevice::OpenMode flags, FILE *fh){ Q_D(QFSFileEngine); d->lastFlushFailed = false; Q_UNUSED(flags); d->fh = fh; d->fd = QT_FILENO(fh); QT_STATBUF st; if (QT_FSTAT(QT_FILENO(fh), &st) != 0) return false;#ifdef Q_OS_WIN32 HANDLE hnd = (HANDLE)_get_osfhandle(d->fd); if (hnd == INVALID_HANDLE_VALUE) return false; DWORD ftype = ::GetFileType(hnd); d->sequential = ftype == FILE_TYPE_CHAR || ftype == FILE_TYPE_PIPE;#else d->sequential = S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode);#endif d->closeFileHandle = false;#ifdef Q_OS_UNIX if ((flags & QIODevice::WriteOnly) == 0) d->is_readonly = 1;#endif return true;}/*! \reimp*/bool QFSFileEngine::close(){ Q_D(QFSFileEngine); bool flushed = !d->lastFlushFailed && flush(); d->tried_stat = 0; if (d->fh) { bool closed = true; if (d->closeFileHandle) { int ret; do { ret = fclose(d->fh); } while (ret == EOF && errno == EINTR); closed = (ret == 0); } d->fh = 0; d->fd = -1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -