diff --git a/src/Nazara/Core/Posix/FileImpl.cpp b/src/Nazara/Core/Posix/FileImpl.cpp new file mode 100644 index 000000000..09584ceea --- /dev/null +++ b/src/Nazara/Core/Posix/FileImpl.cpp @@ -0,0 +1,249 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +NzFileImpl::NzFileImpl(const NzFile* parent) : +m_endOfFile(false), +m_endOfFileUpdated(true) +{ + NazaraUnused(parent); +} + +void NzFileImpl::Close() +{ + close(m_fileDescriptor); +} + +bool NzFileImpl::EndOfFile() const +{ + if (!m_endOfFileUpdated) + { + stat64 fileSize; + if (fstat64(m_handle, &fileSize) == -1) + fileSize.st_size = 0; + + m_endOfFile = (GetCursorPos() >= static_cast(fileSize.st_size)); + m_endOfFileUpdated = true; + } + + return m_endOfFile; +} + +void NzFileImpl::Flush() +{ + if (fsync(m_fileDescriptor) == -1) + NazaraError("Unable to flush file: " + NzGetLastSystemError()); +} + +nzUInt64 NzFileImpl::GetCursorPos() const +{ + off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR); + return static_cast(position); +} + +bool NzFileImpl::Open(const NzString& filePath, unsigned int mode) +{ + int flags; + mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + + if (mode & NzFile::ReadOnly) + flags = O_RDONLY; + + else if (mode & NzFile::ReadWrite) + { + flags = O_CREAT | O_RDWR; + + if (mode & NzFile::Append) + flags |= O_APPEND; + + if (mode & NzFile::Truncate) + flags |= O_TRUNC; + + } + else if (mode & NzFile::WriteOnly) + { + flags = O_CREAT | O_WRONLY; + + if (mode & NzFile::Append) + flags |= O_APPEND; + + if (mode & NzFile::Truncate) + flags |= O_TRUNC; + } + else + return false; + +// TODO: lock +// if ((mode & NzFile::Lock) == 0) +// shareMode |= FILE_SHARE_WRITE; + + const char* path = filePath.GetConstBuffer(); + + m_fileDescriptor = open64(path, flags, permissions); + return m_fileDescriptor != -1; +} + +std::size_t NzFileImpl::Read(void* buffer, std::size_t size) +{ + ssize_t bytes; + if ((bytes = read(m_fileDescriptor, buffer, size)) != -1) + { + m_endOfFile = (static_cast(bytes) != size); + m_endOfFileUpdated = true; + + return static_cast(bytes); + } + else + return 0; +} + +bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset) +{ + int moveMethod; + switch (pos) + { + case NzFile::AtBegin: + moveMethod = SEEK_SET; + break; + + case NzFile::AtCurrent: + moveMethod = SEEK_CUR; + break; + + case NzFile::AtEnd: + moveMethod = SEEK_END; + break; + + default: + NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')'); + return false; + } + + m_endOfFileUpdated = false; + + return lseek64(m_fileDescriptor, offset, moveMethod) != -1; +} + +std::size_t NzFileImpl::Write(const void* buffer, std::size_t size) +{ + lockf64(m_fileDescriptor, F_LOCK, size); + ssize_t written = write(m_fileDescriptor, buffer, size); + lockf64(m_fileDescriptor, F_ULOCK, size); + + m_endOfFileUpdated = false; + + return written; +} + +bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath) +{ + int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY); + if (fd1 == -1) + { + NazaraError("Fail to open input file (" + sourcePath + "): " + NzGetLastSystemError()); + return false; + } + + mode_t permissions; // TODO : get permission from first file + int fd2 = open64(sourcePath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions); + if (fd2 == -1) + { + NazaraError("Fail to open output file (" + targetPath + "): " + NzGetLastSystemError()); // TODO: more info ? + return false; + } + + + char buffer[512]; + ssize_t bytes; + do + { + bytes = read(fd1,buffer,512); + if (bytes == -1) + { + close(fd1); + close(fd2); + NazaraError("An error occured from copy : " + NzGetLastSystemError()); + return false; + } + write(fd2,buffer,bytes); + + } while (bytes == 512); +} + +bool NzFileImpl::Delete(const NzString& filePath) +{ + const char* path = filePath.GetConstBuffer(); + bool success = unlink(path) != -1; + + if (success) + return true; + else + { + NazaraError("Failed to delete file (" + filePath + "): " + NzGetLastSystemError()); + return false; + } +} + +bool NzFileImpl::Exists(const NzString& filePath) +{ + char* path = filePath.GetConstBuffer(); + if (access(path, F_OK) != -1) + return true; + return false; +} + +time_t NzFileImpl::GetCreationTime(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return NzFileTimeToTime(std::ctime(&stats.st_ctim)); // not sure ? +} + +time_t NzFileImpl::GetLastAccessTime(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return NzFileTimeToTime(std::ctime(&stats.st_atim)); +} + +time_t NzFileImpl::GetLastWriteTime(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return NzFileTimeToTime(std::ctime(&stats.st_mtim)); +} + +nzUInt64 NzFileImpl::GetSize(const NzString& filePath) +{ + struct stat64 stats; + stat64(filePath.GetConstBuffer(), &stats); + + return static_cast(stats.st_size); +} + +bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath) +{ + const char* path = sourcePath.GetConstBuffer(); + const char* newPath = targetPath.GetConstBuffer(); + + bool success = std::rename(path, newPath) != -1; + + if (success) + return true; + else + { + NazaraError("Unable to rename file: " + NzGetLastSystemError()); + return false; + } +} diff --git a/src/Nazara/Core/Posix/FileImpl.hpp b/src/Nazara/Core/Posix/FileImpl.hpp new file mode 100644 index 000000000..d6ed7d378 --- /dev/null +++ b/src/Nazara/Core/Posix/FileImpl.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_FILEIMPL_HPP +#define NAZARA_FILEIMPL_HPP + +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +class NzFile; +class NzString; + +class NzFileImpl : NzNonCopyable +{ + public: + NzFileImpl(const NzFile* parent); + ~NzFileImpl() = default; + + void Close(); + bool EndOfFile() const; + void Flush(); + nzUInt64 GetCursorPos() const; + bool Open(const NzString& filePath, unsigned int mode); + std::size_t Read(void* buffer, std::size_t size); + bool SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset); + std::size_t Write(const void* buffer, std::size_t size); + + static bool Copy(const NzString& sourcePath, const NzString& targetPath); + static bool Delete(const NzString& filePath); + static bool Exists(const NzString& filePath); + static time_t GetCreationTime(const NzString& filePath); + static time_t GetLastAccessTime(const NzString& filePath); + static time_t GetLastWriteTime(const NzString& filePath); + static nzUInt64 GetSize(const NzString& filePath); + static bool Rename(const NzString& sourcePath, const NzString& targetPath); + + private: + int m_fileDescriptor; + FILE* m_handle; + mutable bool m_endOfFile; + mutable bool m_endOfFileUpdated; +}; + +#endif // NAZARA_FILEIMPL_HPP