📄 qfsfileengine_unix.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 "qplatformdefs.h"#include "qabstractfileengine.h"#include "private/qfsfileengine_p.h"#ifndef QT_NO_REGEXP# include "qregexp.h"#endif#include "qfile.h"#include "qdir.h"#include "qdatetime.h"#include "qdebug.h"#include "qvarlengtharray.h"#include <stdlib.h>#include <limits.h>#include <errno.h>#if !defined(QWS) && defined(Q_OS_MAC)# include <private/qcore_mac_p.h>#endif/*! \internal Returns the stdlib open string corresponding to a QIODevice::OpenMode.*/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;}/*! \internal Returns the stdio open flags corresponding to a QIODevice::OpenMode.*/static 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*/void QFSFileEnginePrivate::nativeInitFileName(){ nativeFilePath = QFile::encodeName(filePath);}/*! \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(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; } // 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, filePath); // Try to open the file in buffered mode. do { fh = QT_FOPEN(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; } // 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*/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 int v = 1; if ((oldFlags & O_NONBLOCK) == 0) fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK, &v, sizeof(v)); // 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) { int v = 1; fcntl(QT_FILENO(fh), F_SETFL, oldFlags, &v, sizeof(v)); 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) { int v = 1; fcntl(QT_FILENO(fh), F_SETFL, oldFlags, &v, sizeof(v)); } if (readBytes == 0) { 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); return unlink(d->nativeFilePath.constData()) == 0;}bool QFSFileEngine::copy(const QString &){ // ### Add copy code for Unix here return false;}bool QFSFileEngine::rename(const QString &newName){ Q_D(QFSFileEngine); return ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0;}bool QFSFileEngine::link(const QString &newName){ Q_D(QFSFileEngine); return ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0;}qint64 QFSFileEnginePrivate::nativeSize() const{ return sizeFdFh();}bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const{ QString dirName = name; if (createParentDirectories) { 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) { QByteArray chunk = QFile::encodeName(dirName.left(slash)); QT_STATBUF st; if (QT_STAT(chunk, &st) != -1) { if ((st.st_mode & S_IFMT) != S_IFDIR) return false; } else if (::mkdir(chunk, 0777) != 0) { return false; } } } return true; }#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s if (dirName[dirName.length() - 1] == QLatin1Char('/')) dirName = dirName.left(dirName.length() - 1);#endif return (::mkdir(QFile::encodeName(dirName), 0777) == 0);}bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const{ QString dirName = name; if (recurseParentDirectories) { dirName = QDir::cleanPath(dirName); for(int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { QByteArray chunk = QFile::encodeName(dirName.left(slash)); QT_STATBUF st; if (QT_STAT(chunk, &st) != -1) { if ((st.st_mode & S_IFMT) != S_IFDIR) return false; if (::rmdir(chunk) != 0) return oldslash != 0; } else { return false; } slash = dirName.lastIndexOf(QDir::separator(), oldslash-1); } return true; } return ::rmdir(QFile::encodeName(dirName)) == 0;}bool QFSFileEngine::caseSensitive() const{ return true;}bool QFSFileEngine::setCurrentPath(const QString &path){ int r; r = ::chdir(QFile::encodeName(path)); return r >= 0;}QString QFSFileEngine::currentPath(const QString &){ QString result; QT_STATBUF st; if (QT_STAT(".", &st) == 0) {#if defined(__GLIBC__) && !defined(PATH_MAX) char *currentName = ::get_current_dir_name(); if (currentName) { result = QFile::decodeName(QByteArray(currentName)); ::free(currentName); }#else char currentName[PATH_MAX+1]; if (::getcwd(currentName, PATH_MAX)) result = QFile::decodeName(QByteArray(currentName));#endif#if defined(QT_DEBUG) if (result.isNull()) qWarning("QDir::currentPath: getcwd() failed");#endif } else {#if defined(QT_DEBUG) qWarning("QDir::currentPath: stat(\".\") failed");#endif } return result;}QString QFSFileEngine::homePath(){ QString home = QFile::decodeName(qgetenv("HOME")); if (home.isNull()) home = rootPath(); return home;}QString QFSFileEngine::rootPath(){ return QString::fromLatin1("/");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -