/*! * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file FileHandler.cpp * \author (last) Peter Lucia * \date (last) 15-Oct-2020 * \author (original) Behrouz NematiPour * \date (original) 26-Aug-2020 * */ #include "FileHandler.h" //Qt #include #include #include #include #include #include #include // Project #include "Logger.h" // namespace using namespace Storage; /*! * \brief FileHandler::write * \details Writes the content of vContent into the file vFileName. * \param vFileName - Source file name * \param vContent - The content which is going to be written in the file. * \param vAppend - if set to true the content will be appended at the end of the file. * \return false if file can't be opened. */ void FileHandler::errOut(const QString &vMessage) { static uint count; static QString mCritical; // coco begin validated : This has been manually test. Needs file system access to produce errors for hundred times. if (mCritical != vMessage || !(count % 1000)) { // coco end count = 0; mCritical = vMessage; QTextStream err(stderr); err << "FS" << " " << QDate::currentDate().toString("yyyy_MM_dd") << " " << QTime::currentTime().toString("HH:mm:ss" ) << " " << mCritical << endl; } ++count; } /*! * \brief FileHandler::write * \details writes content vContent into the file vFileName. * appends to the file if vAppend is true otherwise overwrites the file content with vContent * \param vFileName - Source file name * \param vContent - content to be written into file. * \param vAppend - append (true) or overwrite (false) * \return false if file can't be opened for write. */ bool FileHandler::write(const QString &vFileName, const QString &vContent, bool vAppend) { QFile file(vFileName); QFile::OpenMode openMode = vAppend ? QFile::Text | QFile::Append : QFile::Text | QFile::WriteOnly; // coco begin validated : This has been manually test. Needs file system access to make file the way it can't be opened for writing. if (! file.open(openMode)) { QString msg = QString("Can't open file for write (%1).Possible corrupted file system").arg(vFileName); // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. errOut (msg); return false; } // coco end QTextStream out(&file); out << vContent; out.flush(); return true; } /*! * \brief FileHandler::read * \details reads file vFilename content into vContent variable. * \param vFileName - Source file name * \param vContent - The content of the file which will be set when done. * \return false if file can't be opened. */ bool FileHandler::read(const QString &vFileName, QString &vContent) { QFile file(vFileName); if (! file.open(QFile::Text | QFile::ReadOnly)) { QString msg = QString("Can't open file for read (%1).Possible corrupted file system").arg(vFileName); // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. errOut (msg); return false; } QTextStream in(&file); vContent = in.readAll(); return true; } /*! * \brief FileHandler::readJSON * \details reads the provided filename's JSON content into the vContent variable. * \param vFileName - Source file name * \param vContent - The content of the file which will be written to when done. * \return false if file can't be read */ bool FileHandler::readJSON(const QString &vFileName, QJsonObject &vContent) { QFile file(vFileName); if (! file.open(QFile::Text | QFile::ReadOnly)) { errOut(QObject::tr("Can't open file for read (%1).Possible corrupted file system").arg(vFileName)); return false; } QTextStream in(&file); QString content = in.readAll(); QJsonDocument doc = QJsonDocument::fromJson(content.toUtf8()); vContent = doc.object(); return true; } /*! * \brief FileHandler::copyFolder * \details Copies all the file and folders recursively. * \param vSource - The source folder * \param vDestination - The destination folder * \return Tue on successful execution. * \note This method uses the Linux "cp -r vSource vDestination" command * Not a Thread-Safe. * */ int FileHandler::copyFolder(const QString &vSource, const QString &vDestination ) { // coco begin validated: This needs user interaction to export to USB device // has been tested manually since currently it is the only place it has been used. QString cp = "cp"; QStringList arguments; arguments << "-r" << vSource << vDestination; int result = QProcess::execute(cp, arguments); return result; } // coco end /*! * \brief FileHandler::removeFiles * \details * \param vFolder * \param vFilter * \param vDateOlderThan * \return */ int FileHandler::removeFiles(const QStringList &vFolders, const QStringList &vNameFilter, const QDate &vDateOlderThan) { int countRemoved = 0; for (const auto &folder : vFolders) { QDir dir(folder); dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); dir.setSorting(QDir::Time | QDir::Reversed); QFileInfoList infoList = dir.entryInfoList(vNameFilter); for (const auto &info : infoList) { QDateTime fileTime = info.lastModified(); QString fileName = info.absoluteFilePath(); // coco begin validated : This has been manually tested since requires to change in file system to reproduce the error. if (fileTime.isValid()) { if (fileTime.date() <= vDateOlderThan) { if (QFile::remove(fileName)) { ++countRemoved; errOut(QString("%1 File(s) %2 removed").arg(countRemoved).arg(fileName)); } else { errOut(QString("Can't delete file : ") + fileName); } } } else { errOut(QString("Can't get last modified date of file : ") + fileName); } // coco end } } return countRemoved; } /*! * \brief FileHandler::makeFolder * \details Create the folder vFolder if it doesn't exist. * \param vFolder - the folder to create * \return true on successful creation */ bool FileHandler::makeFolder(const QString &vFolder) { QDir dir(vFolder); if ( ! dir.exists(vFolder) ) { if ( ! dir.mkpath(vFolder) ) { QString msg = "Can't create folder " + vFolder; // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. errOut(msg); return false; } } return true; } /*! * \brief FileHandler::isMounted * \param vPath - the rootPath of the device mount point * \return true - if the given vPath is not empty and is in list of mounted devices * if so it also has to be ready and valid. */ bool FileHandler::isMounted(const QString &vPath, bool *vIsReadOnly) { // coco begin validated: Needed User Interaction to make the device not ready so tested manually bool mounted = false; // removing the extra '/' from the vPath if there is to be able to compare to the root path of the storage QString path = vPath.trimmed(); if (path.isEmpty()) return false; int lastIndex = path.size() - 1; if (path.at(lastIndex) == "/") path.remove(lastIndex, 1); // check to see if the path in the list of mounted rootPaths foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) { if (storage.isValid() && storage.isReady()) { if ( storage.rootPath() == path ) { if (vIsReadOnly) *vIsReadOnly = storage.isReadOnly(); mounted = true; break; } } } return mounted; } // coco end