//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); }
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; }
//static QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) { if (entry.isEmpty() || entry.isRoot()) return entry; #if !defined(Q_OS_MAC) && _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_MAC) # if !defined(QT_NO_CORESERVICES) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { ret = realpath(entry.nativeFilePath().constData(), (char*)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 ret = (char*)malloc(PATH_MAX); realpath(entry.nativeFilePath().constData(), (char*)ret); # endif //!defined(QT_NO_CORESERVICES) # else #ifdef Q_OS_ANDROID ret = (char*)malloc(PATH_MAX); memset(ret, 0, PATH_MAX); ret = realpath(entry.nativeFilePath().constData(), ret); #else ret = realpath(entry.nativeFilePath().constData(), (char*)0); #endif ret = realpath(entry.nativeFilePath().constData(), (char*)0); # endif //defined(Q_OS_MAC) 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 }
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) { //1st time, lastError is result of dirHandle.Open(), entries.Count() is 0 and entryIndex is -1 so initial read is triggered //subsequent times, read is triggered each time we reach the end of the entry list //final time, lastError is KErrEof so we don't need to read anymore. ++entryIndex; if (lastError == KErrNone && entryIndex >= entries.Count()) { lastError = dirHandle.Read(entries); entryIndex = 0; } //each call to advance() gets the next entry from the entry list. //from the final (or only) read call, KErrEof is returned together with a full buffer so we still need to go through the list if ((lastError == KErrNone || lastError == KErrEof) && entryIndex < entries.Count()) { Q_ASSERT(entryIndex >= 0); const TEntry &entry(entries[entryIndex]); fileEntry = QFileSystemEntry(nativePath + qt_TDesC2QString(entry.iName), QFileSystemEntry::FromNativePath()); metaData.fillFromTEntry(entry); return true; } //TODO: error reporting, to allow user to distinguish empty directory from error condition. return false; }
/*! Opens the file descriptor specified by \a file in the mode given by \a openMode. Returns true on success; otherwise returns false. The \a handleFlags argument specifies whether the file handle will be closed by Qt. See the QFile::FileHandleFlags documentation for more information. */ bool QFSFileEngine::open(QIODevice::OpenMode openMode, const RFile &file, 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; #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API //RFile64 adds only functions to RFile, no data members d->symbianFile = static_cast<const RFile64&>(file); #else d->symbianFile = file; #endif TInt ret; d->symbianFilePos = 0; if (openMode & QFile::Append) { // Seek to the end when in Append mode. ret = d->symbianFile.Size(d->symbianFilePos); } else { // Seek to current otherwise ret = d->symbianFile.Seek(ESeekCurrent, d->symbianFilePos); } if (ret != KErrNone) { setError(QFile::OpenError, QSystemError(ret, QSystemError::NativeError).toString()); d->openMode = QIODevice::NotOpen; #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API d->symbianFile = RFile64(); #else d->symbianFile = RFile(); #endif return false; } // Extract filename (best effort) TFileName fn; TInt err = d->symbianFile.FullName(fn); if (err == KErrNone) d->fileEntry = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath()); else d->fileEntry.clear(); return true; }
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::copy(const QString ©Name) { Q_D(QFSFileEngine); QSystemError error; bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error); if (!ret) setError(QFile::CopyError, 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; }
bool QFSFileEngineIterator::hasNext() const { if (!done && !nativeIterator) { nativeIterator.reset(new QFileSystemIterator(QFileSystemEntry(path()), filters(), nameFilters())); advance(); } return !done; }
//static QFileSystemEntry QFileSystemEngine::currentPath() { TFileName fn; QFileSystemEntry ret; TInt r = qt_s60GetRFs().SessionPath(fn); if(r == KErrNone) { //remove terminating slash from non root paths (session path is clean, absolute and always ends in a \) if(fn.Length() > 3 && fn[fn.Length() - 1] == '\\') fn.SetLength(fn.Length() - 1); ret = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath()); } return ret; }
//static QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) { if (entry.isEmpty() || entry.isRoot()) return entry; QFileSystemEntry result = absoluteName(entry); if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute)) fillMetaData(result, data, QFileSystemMetaData::ExistsAttribute); if (!data.exists()) { // file doesn't exist return QFileSystemEntry(); } else { return result; } }
bool QFSFileEngine::renameOverwrite(const QString &newName) { Q_D(QFSFileEngine); #if defined(Q_OS_WINCE) // Windows Embedded Compact 7 does not have MoveFileEx, simulate it with the following sequence: // 1. DeleteAndRenameFile (Should work on RAM FS when both files exist) // 2. DeleteFile/MoveFile (Should work on all file systems) // // DeleteFile/MoveFile fallback implementation violates atomicity, but it is more acceptable than // alternative CopyFile/DeleteFile sequence for the following reasons: // // 1. DeleteFile/MoveFile is way faster than CopyFile/DeleteFile and thus more atomic. // 2. Given the intended use case of this function in QSaveFile, DeleteFile/MoveFile sequence will // delete the old content, but leave a file "filename.ext.XXXXXX" in the same directory if MoveFile fails. // With CopyFile/DeleteFile sequence, it can happen that new data is partially copied to target file // (because CopyFile is not atomic either), thus leaving *some* content to target file. // This makes the need for application level recovery harder to detect than in DeleteFile/MoveFile // sequence where target file simply does not exist. // bool ret = ::DeleteAndRenameFile((wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(), (wchar_t*)d->fileEntry.nativeFilePath().utf16()) != 0; if (!ret) { ret = ::DeleteFile((wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16()) != 0; if (ret || ::GetLastError() == ERROR_FILE_NOT_FOUND) ret = ::MoveFile((wchar_t*)d->fileEntry.nativeFilePath().utf16(), (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16()) != 0; } #else bool ret = ::MoveFileEx((wchar_t*)d->fileEntry.nativeFilePath().utf16(), (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(), MOVEFILE_REPLACE_EXISTING) != 0; #endif if (!ret) setError(QFile::RenameError, QSystemError(::GetLastError(), QSystemError::NativeError).toString()); return ret; }
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); }
//static QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) { QString orig = entry.filePath(); const bool isAbsolute = entry.isAbsolute(); const bool isDirty = !entry.isClean(); if (isAbsolute && !isDirty) return entry; const bool isRelative = entry.isRelative(); const bool needsDrive = (!orig.isEmpty() && orig.at(0).unicode() == '/'); const bool isDriveLetter = !needsDrive && !isAbsolute && !isRelative && orig.length() == 2; const bool isDriveRelative = !needsDrive && !isAbsolute && !isRelative && orig.length() > 2; QString result; if (needsDrive || isDriveLetter || isDriveRelative || !isAbsolute || orig.isEmpty()) { QFileSystemEntry cur(currentPath()); if(needsDrive) result = cur.filePath().left(2); else if(isDriveRelative && cur.filePath().at(0) != orig.at(0)) result = orig.left(2); // for BC, see tst_QFileInfo::absolutePath(<not current drive>:my.dll) else result = cur.filePath(); if(isDriveLetter) { result[0] = orig.at(0); //copy drive letter orig.clear(); } if(isDriveRelative) { orig = orig.mid(2); //discard the drive specifier from orig } } if (!orig.isEmpty() && !(orig.length() == 1 && orig.at(0).unicode() == '.')) { if (!result.isEmpty() && !result.endsWith(QLatin1Char('/'))) result.append(QLatin1Char('/')); result.append(orig); } return QFileSystemEntry(symbianCleanAbsolutePath(result), QFileSystemEntry::FromInternalPath()); }
//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) && !defined(Q_OS_HAIKU) && _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_DARWIN) 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; } # elif defined(Q_OS_ANDROID) // On some Android versions, realpath() will return a path even if it does not exist // To work around this, we check existence in advance. if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute)) fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute); if (!data.exists()) { ret = 0; errno = ENOENT; } 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; } } # 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 }
QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); if (file == BaseName) { return d->fileEntry.fileName(); } else if (file == PathName) { return d->fileEntry.path(); } else if (file == AbsoluteName || file == AbsolutePathName) { QString ret; if (!isRelativePath()) { #if !defined(Q_OS_WINCE) if (d->fileEntry.filePath().startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt d->fileEntry.filePath().size() == 2 || // It's a drive letter that needs to get a working dir appended (d->fileEntry.filePath().size() > 2 && d->fileEntry.filePath().at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt d->fileEntry.filePath().contains(QLatin1String("/../")) || d->fileEntry.filePath().contains(QLatin1String("/./")) || d->fileEntry.filePath().endsWith(QLatin1String("/..")) || d->fileEntry.filePath().endsWith(QLatin1String("/."))) { ret = QDir::fromNativeSeparators(QFileSystemEngine::nativeAbsoluteFilePath(d->fileEntry.filePath())); } else #endif { ret = d->fileEntry.filePath(); } } else { ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->fileEntry.filePath()); } // The path should be absolute at this point. // From the docs : // Absolute paths begin with the directory separator "/" // (optionally preceded by a drive specification under Windows). if (ret.at(0) != QLatin1Char('/')) { Q_ASSERT(ret.length() >= 2); Q_ASSERT(ret.at(0).isLetter()); Q_ASSERT(ret.at(1) == QLatin1Char(':')); // Force uppercase drive letters. ret[0] = ret.at(0).toUpper(); } if (file == AbsolutePathName) { int slash = ret.lastIndexOf(QLatin1Char('/')); if (slash < 0) return ret; else if (ret.at(0) != QLatin1Char('/') && slash == 2) return ret.left(3); // include the slash else return ret.left(slash > 0 ? slash : 1); } return ret; } else if (file == CanonicalName || file == CanonicalPathName) { if (!(fileFlags(ExistsFlag) & ExistsFlag)) return QString(); QFileSystemEntry entry(QFileSystemEngine::canonicalName(QFileSystemEntry(fileName(AbsoluteName)), d->metaData)); if (file == CanonicalPathName) return entry.path(); return entry.filePath(); } else if (file == LinkName) { return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath(); } else if (file == BundleName) { return QString(); } return d->fileEntry.filePath(); }
//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 }
/*! \reimp */ void QFSFileEngine::setFileName(const QString &file) { Q_D(QFSFileEngine); d->init(); d->fileEntry = QFileSystemEntry(file); }
/*! Constructs a QFSFileEngine for the file name \a file. */ QFSFileEngine::QFSFileEngine(const QString &file) : QAbstractFileEngine(*new QFSFileEnginePrivate) { Q_D(QFSFileEngine); d->fileEntry = QFileSystemEntry(file); }
bool QFile::rename(const QString &newName) { Q_D(QFile); if (d->fileName.isEmpty()) { qWarning("QFile::rename: Empty or null file name"); return false; } if (d->fileName == newName) { d->setError(QFile::RenameError, tr("Destination file is the same file.")); return false; } if (!exists()) { d->setError(QFile::RenameError, tr("Source file does not exist.")); return false; } // If the file exists and it is a case-changing rename ("foo" -> "Foo"), // compare Ids to make sure it really is a different file. if (QFile::exists(newName)) { if (d->fileName.compare(newName, Qt::CaseInsensitive) || QFileSystemEngine::id(QFileSystemEntry(d->fileName)) != QFileSystemEngine::id(QFileSystemEntry(newName))) { // ### Race condition. If a file is moved in after this, it /will/ be // overwritten. On Unix, the proper solution is to use hardlinks: // return ::link(old, new) && ::remove(old); d->setError(QFile::RenameError, tr("Destination file exists")); return false; } #ifndef QT_NO_TEMPORARYFILE // This #ifndef disables the workaround it encloses. Therefore, this configuration is not recommended. #ifdef Q_OS_LINUX // rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive // FS, such as FAT32. Move the file away and rename in 2 steps to work around. QTemporaryFile tempFile(d->fileName + QStringLiteral(".XXXXXX")); tempFile.setAutoRemove(false); if (!tempFile.open(QIODevice::ReadWrite)) { d->setError(QFile::RenameError, tempFile.errorString()); return false; } tempFile.close(); if (!d->engine()->rename(tempFile.fileName())) { d->setError(QFile::RenameError, tr("Error while renaming.")); return false; } if (tempFile.rename(newName)) { d->fileEngine->setFileName(newName); d->fileName = newName; return true; } d->setError(QFile::RenameError, tempFile.errorString()); // We need to restore the original file. if (!tempFile.rename(d->fileName)) { d->setError(QFile::RenameError, errorString() + QLatin1Char('\n') + tr("Unable to restore from %1: %2"). arg(QDir::toNativeSeparators(tempFile.fileName()), tempFile.errorString())); } return false; #endif // Q_OS_LINUX #endif // QT_NO_TEMPORARYFILE } unsetError(); close(); if(error() == QFile::NoError) { if (d->engine()->rename(newName)) { unsetError(); // engine was able to handle the new name so we just reset it d->fileEngine->setFileName(newName); d->fileName = newName; return true; } if (isSequential()) { d->setError(QFile::RenameError, tr("Will not rename sequential file using block copy")); return false; } QFile out(newName); if (open(QIODevice::ReadOnly)) { if (out.open(QIODevice::WriteOnly | QIODevice::Truncate)) { bool error = false; char block[4096]; qint64 bytes; while ((bytes = read(block, sizeof(block))) > 0) { if (bytes != out.write(block, bytes)) { d->setError(QFile::RenameError, out.errorString()); error = true; break; } } if (bytes == -1) { d->setError(QFile::RenameError, errorString()); error = true; } if(!error) { if (!remove()) { d->setError(QFile::RenameError, tr("Cannot remove source file")); error = true; } } if (error) { out.remove(); } else { d->fileEngine->setFileName(newName); setPermissions(permissions()); unsetError(); setFileName(newName); } close(); return !error; } close(); } d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString()); } return false; }
bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) { Q_D(QFSFileEngine); Q_ASSERT(!isReallyOpen()); openMode |= QIODevice::ReadWrite; if (!filePathIsTemplate) return QFSFileEngine::open(openMode); QString qfilename = d->fileEntry.filePath(); // Ensure there is a placeholder mask uint phPos = qfilename.length(); uint phLength = 0; while (phPos != 0) { --phPos; if (qfilename[phPos] == QLatin1Char('X')) { ++phLength; continue; } if (phLength >= 6 || qfilename[phPos] == QLatin1Char('/')) { ++phPos; break; } // start over phLength = 0; } if (phLength < 6) qfilename.append(QLatin1String(".XXXXXX")); // "Nativify" :-) QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName( QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath())) .nativeFilePath(); // Find mask in native path phPos = filename.length(); phLength = 0; while (phPos != 0) { --phPos; if (filename[phPos] == Latin1Char('X')) { ++phLength; continue; } if (phLength >= 6) { ++phPos; break; } // start over phLength = 0; } Q_ASSERT(phLength >= 6); QSystemError error; #if defined(Q_OS_WIN) NativeFileHandle &file = d->fileHandle; #else // POSIX NativeFileHandle &file = d->fd; #endif if (!createFileFromTemplate(file, filename, phPos, phLength, error)) { setError(QFile::OpenError, error.toString()); return false; } d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath()); #if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; #endif filePathIsTemplate = false; d->openMode = openMode; d->lastFlushFailed = false; d->tried_stat = 0; return true; }
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const { return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories); }
/*! Constructs a QDirIterator that can iterate over \a path. You can pass options via \a flags to decide how the directory should be iterated. By default, \a flags is NoIteratorFlags, which provides the same behavior as in QDir::entryList(). \note To list symlinks that point to non existing files, QDir::System must be passed to the flags. \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), QDir::NoFilter, flags)) { }
bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const { return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories); }
//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(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) { 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(); }
bool QFSFileEngine::setCurrentPath(const QString &path) { return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path)); }
void QTemporaryFileEngine::setFileTemplate(const QString &fileTemplate) { Q_D(QFSFileEngine); if (filePathIsTemplate) d->fileEntry = QFileSystemEntry(fileTemplate); }
/*! Constructs a QDirIterator that can iterate over \a path, using \a nameFilters and \a filters. You can pass options via \a flags to decide how the directory should be iterated. By default, \a flags is NoIteratorFlags, which provides the same behavior as QDir::entryList(). \note To list symlinks that point to non existing files, QDir::System must be passed to the flags. \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, const QStringList &nameFilters, QDir::Filters filters, IteratorFlags flags) : d(new QDirIteratorPrivate(QFileSystemEntry(path), nameFilters, filters, flags)) { }
//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_DARWIN) { QCFString path = CFStringCreateWithFileSystemRepresentation(0, QFile::encodeName(QDir::cleanPath(link.filePath())).data()); if (!path) return QFileSystemEntry(); QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, data.hasFlags(QFileSystemMetaData::DirectoryType)); if (!url) return QFileSystemEntry(); QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL); if (!bookmarkData) return QFileSystemEntry(); QCFType<CFURLRef> resolvedUrl = CFURLCreateByResolvingBookmarkData(0, bookmarkData, (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL); if (!resolvedUrl) return QFileSystemEntry(); QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle)); if (!cfstr) return QFileSystemEntry(); return QFileSystemEntry(QCFString::toQString(cfstr)); } #endif return QFileSystemEntry(); }