// Copyright (C) 2015 Alexandre Janniaux // 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 namespace Nz { FileImpl::FileImpl(const File* parent) : m_endOfFile(false), m_endOfFileUpdated(true) { NazaraUnused(parent); } void FileImpl::Close() { if (m_fileDescriptor != -1) close(m_fileDescriptor); } bool FileImpl::EndOfFile() const { if (!m_endOfFileUpdated) { struct stat64 fileSize; if (fstat64(m_fileDescriptor, &fileSize) == -1) fileSize.st_size = 0; m_endOfFile = (GetCursorPos() >= static_cast(fileSize.st_size)); m_endOfFileUpdated = true; } return m_endOfFile; } void FileImpl::Flush() { if (fsync(m_fileDescriptor) == -1) NazaraError("Unable to flush file: " + Error::GetLastSystemError()); } UInt64 FileImpl::GetCursorPos() const { off64_t position = lseek64(m_fileDescriptor, 0, SEEK_CUR); return static_cast(position); } bool FileImpl::Open(const String& filePath, UInt32 mode) { int flags; mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if ((mode & OpenMode_ReadWrite) == OpenMode_ReadWrite) flags = O_CREAT | O_RDWR; else if ((mode & OpenMode_ReadOnly) == OpenMode_ReadOnly) flags = O_RDONLY; else if ((mode & OpenMode_WriteOnly) == OpenMode_WriteOnly) flags = O_CREAT | O_WRONLY; else return false; if (mode & OpenMode_Append) flags |= O_APPEND; if (mode & OpenMode_Truncate) flags |= O_TRUNC; ///TODO: lock //if ((mode & OpenMode_Lock) == 0) // shareMode |= FILE_SHARE_WRITE; m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions); return m_fileDescriptor != -1; } std::size_t FileImpl::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 FileImpl::SetCursorPos(CursorPosition pos, Int64 offset) { int moveMethod; switch (pos) { case CursorPosition_AtBegin: moveMethod = SEEK_SET; break; case CursorPosition_AtCurrent: moveMethod = SEEK_CUR; break; case CursorPosition_AtEnd: moveMethod = SEEK_END; break; default: NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')'); return false; } m_endOfFileUpdated = false; return lseek64(m_fileDescriptor, offset, moveMethod) != -1; } bool FileImpl::SetSize(UInt64 size) { return ftruncate64(m_fileDescriptor, size) != 0; } std::size_t FileImpl::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 FileImpl::Copy(const String& sourcePath, const String& targetPath) { int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY); if (fd1 == -1) { NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError()); return false; } mode_t permissions; // TODO : get permission from first file int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions); if (fd2 == -1) { NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ? close(fd1); 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 : " + Error::GetLastSystemError()); return false; } write(fd2,buffer,bytes); } while (bytes == 512); close(fd1); close(fd2); return true; } bool FileImpl::Delete(const String& filePath) { bool success = unlink(filePath.GetConstBuffer()) != -1; if (success) return true; else { NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError()); return false; } } bool FileImpl::Exists(const String& filePath) { const char* path = filePath.GetConstBuffer(); if (access(path, F_OK) != -1) return true; return false; } time_t FileImpl::GetCreationTime(const String& filePath) { NazaraWarning("Posix has no creation time information"); return 0; } time_t FileImpl::GetLastAccessTime(const String& filePath) { struct stat64 stats; stat64(filePath.GetConstBuffer(), &stats); return stats.st_atime; } time_t FileImpl::GetLastWriteTime(const String& filePath) { struct stat64 stats; stat64(filePath.GetConstBuffer(), &stats); return stats.st_mtime; } UInt64 FileImpl::GetSize(const String& filePath) { struct stat64 stats; stat64(filePath.GetConstBuffer(), &stats); return static_cast(stats.st_size); } bool FileImpl::Rename(const String& sourcePath, const String& targetPath) { bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1; if (success) return true; else { NazaraError("Unable to rename file: " + Error::GetLastSystemError()); return false; } } }