summaryrefslogtreecommitdiffstats
path: root/xbmc/filesystem/NptXbmcFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/filesystem/NptXbmcFile.cpp')
-rw-r--r--xbmc/filesystem/NptXbmcFile.cpp534
1 files changed, 534 insertions, 0 deletions
diff --git a/xbmc/filesystem/NptXbmcFile.cpp b/xbmc/filesystem/NptXbmcFile.cpp
new file mode 100644
index 0000000..bcbdea1
--- /dev/null
+++ b/xbmc/filesystem/NptXbmcFile.cpp
@@ -0,0 +1,534 @@
+/*
+ * Neptune - Files :: XBMC Implementation
+ *
+ * Copyright (c) 2002-2008, Axiomatic Systems, LLC.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * See LICENSES/README.md for more information.
+ */
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "File.h"
+#include "FileFactory.h"
+#include "PasswordManager.h"
+#include "URL.h"
+#include "utils/URIUtils.h"
+
+#include <limits>
+
+#include <Neptune/Source/Core/NptDebug.h>
+#include <Neptune/Source/Core/NptFile.h>
+#include <Neptune/Source/Core/NptStrings.h>
+#include <Neptune/Source/Core/NptUtils.h>
+
+#ifdef TARGET_WINDOWS
+#define S_IWUSR _S_IWRITE
+#define S_ISDIR(m) ((m & _S_IFDIR) != 0)
+#define S_ISREG(m) ((m & _S_IFREG) != 0)
+#endif
+
+using namespace XFILE;
+
+typedef NPT_Reference<IFile> NPT_XbmcFileReference;
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileStream
++---------------------------------------------------------------------*/
+class NPT_XbmcFileStream
+{
+public:
+ // constructors and destructor
+ explicit NPT_XbmcFileStream(const NPT_XbmcFileReference& file) : m_FileReference(file) {}
+
+ // NPT_FileInterface methods
+ NPT_Result Seek(NPT_Position offset);
+ NPT_Result Tell(NPT_Position& offset);
+ NPT_Result Flush();
+
+protected:
+ // constructors and destructors
+ virtual ~NPT_XbmcFileStream() = default;
+
+ // members
+ NPT_XbmcFileReference m_FileReference;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileStream::Seek
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileStream::Seek(NPT_Position offset)
+{
+ int64_t result;
+
+ result = m_FileReference->Seek(offset, SEEK_SET) ;
+ if (result >= 0) {
+ return NPT_SUCCESS;
+ } else {
+ return NPT_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileStream::Tell
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileStream::Tell(NPT_Position& offset)
+{
+ int64_t result = m_FileReference->GetPosition();
+ if (result >= 0) {
+ offset = (NPT_Position)result;
+ return NPT_SUCCESS;
+ } else {
+ return NPT_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileStream::Flush()
+{
+ m_FileReference->Flush();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileInputStream
++---------------------------------------------------------------------*/
+class NPT_XbmcFileInputStream : public NPT_InputStream,
+ private NPT_XbmcFileStream
+
+{
+public:
+ // constructors and destructor
+ explicit NPT_XbmcFileInputStream(NPT_XbmcFileReference& file) :
+ NPT_XbmcFileStream(file) {}
+
+ // NPT_InputStream methods
+ NPT_Result Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read) override;
+ NPT_Result Seek(NPT_Position offset) override {
+ return NPT_XbmcFileStream::Seek(offset);
+ }
+ NPT_Result Tell(NPT_Position& offset) override {
+ return NPT_XbmcFileStream::Tell(offset);
+ }
+ NPT_Result GetSize(NPT_LargeSize& size) override;
+ NPT_Result GetAvailable(NPT_LargeSize& available) override;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileInputStream::Read
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileInputStream::Read(void* buffer,
+ NPT_Size bytes_to_read,
+ NPT_Size* bytes_read)
+{
+ unsigned int nb_read;
+
+ // check the parameters
+ if (buffer == NULL) {
+ return NPT_ERROR_INVALID_PARAMETERS;
+ }
+
+ // read from the file
+ nb_read = m_FileReference->Read(buffer, bytes_to_read);
+ if (nb_read > 0) {
+ if (bytes_read) *bytes_read = (NPT_Size)nb_read;
+ return NPT_SUCCESS;
+ } else {
+ if (bytes_read) *bytes_read = 0;
+ return NPT_ERROR_EOS;
+ //} else { // currently no way to indicate failure
+ // if (bytes_read) *bytes_read = 0;
+ // return NPT_ERROR_READ_FAILED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileInputStream::GetSize
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileInputStream::GetSize(NPT_LargeSize& size)
+{
+ size = m_FileReference->GetLength();
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileInputStream::GetAvailable
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileInputStream::GetAvailable(NPT_LargeSize& available)
+{
+ int64_t offset = m_FileReference->GetPosition();
+ NPT_LargeSize size = 0;
+
+ if (NPT_SUCCEEDED(GetSize(size)) && offset >= 0 && (NPT_LargeSize)offset <= size) {
+ available = size - offset;
+ return NPT_SUCCESS;
+ } else {
+ available = 0;
+ return NPT_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileOutputStream
++---------------------------------------------------------------------*/
+class NPT_XbmcFileOutputStream : public NPT_OutputStream,
+ private NPT_XbmcFileStream
+{
+public:
+ // constructors and destructor
+ explicit NPT_XbmcFileOutputStream(NPT_XbmcFileReference& file) :
+ NPT_XbmcFileStream(file) {}
+
+ // NPT_OutputStream methods
+ NPT_Result Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written) override;
+ NPT_Result Seek(NPT_Position offset) override {
+ return NPT_XbmcFileStream::Seek(offset);
+ }
+ NPT_Result Tell(NPT_Position& offset) override {
+ return NPT_XbmcFileStream::Tell(offset);
+ }
+ NPT_Result Flush() override {
+ return NPT_XbmcFileStream::Flush();
+ }
+};
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFileOutputStream::Write
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFileOutputStream::Write(const void* buffer,
+ NPT_Size bytes_to_write,
+ NPT_Size* bytes_written)
+{
+ int nb_written;
+ nb_written = m_FileReference->Write(buffer, bytes_to_write);
+
+ if (nb_written > 0) {
+ if (bytes_written) *bytes_written = (NPT_Size)nb_written;
+ return NPT_SUCCESS;
+ } else {
+ if (bytes_written) *bytes_written = 0;
+ return NPT_ERROR_WRITE_FAILED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile
++---------------------------------------------------------------------*/
+class NPT_XbmcFile: public NPT_FileInterface
+{
+public:
+ // constructors and destructor
+ explicit NPT_XbmcFile(NPT_File& delegator);
+ ~NPT_XbmcFile() override;
+
+ // NPT_FileInterface methods
+ NPT_Result Open(OpenMode mode) override;
+ NPT_Result Close() override;
+ NPT_Result GetInputStream(NPT_InputStreamReference& stream) override;
+ NPT_Result GetOutputStream(NPT_OutputStreamReference& stream) override;
+
+private:
+ // members
+ NPT_File& m_Delegator;
+ OpenMode m_Mode;
+ NPT_XbmcFileReference m_FileReference;
+};
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::NPT_XbmcFile
++---------------------------------------------------------------------*/
+NPT_XbmcFile::NPT_XbmcFile(NPT_File& delegator) :
+ m_Delegator(delegator),
+ m_Mode(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::~NPT_XbmcFile
++---------------------------------------------------------------------*/
+NPT_XbmcFile::~NPT_XbmcFile()
+{
+ Close();
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::Open
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFile::Open(NPT_File::OpenMode mode)
+{
+ NPT_XbmcFileReference file;
+
+ // check if we're already open
+ if (!m_FileReference.IsNull()) {
+ return NPT_ERROR_FILE_ALREADY_OPEN;
+ }
+
+ // store the mode
+ m_Mode = mode;
+
+ // check for special names
+ const char* name = (const char*)m_Delegator.GetPath();
+ if (NPT_StringsEqual(name, NPT_FILE_STANDARD_INPUT)) {
+ return NPT_ERROR_FILE_NOT_READABLE;
+ } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_OUTPUT)) {
+ return NPT_ERROR_FILE_NOT_WRITABLE;
+ } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_ERROR)) {
+ return NPT_ERROR_FILE_NOT_WRITABLE;
+ } else {
+
+ file = CFileFactory::CreateLoader(name);
+ if (file.IsNull()) {
+ return NPT_ERROR_NO_SUCH_FILE;
+ }
+
+ bool result;
+ CURL url(URIUtils::SubstitutePath(name));
+
+ if (CPasswordManager::GetInstance().IsURLSupported(url) && url.GetUserName().empty())
+ CPasswordManager::GetInstance().AuthenticateURL(url);
+
+ // compute mode
+ if (mode & NPT_FILE_OPEN_MODE_WRITE)
+ result = file->OpenForWrite(url, (mode & NPT_FILE_OPEN_MODE_TRUNCATE) ? true : false);
+ else
+ result = file->Open(url);
+
+ if (!result) return NPT_ERROR_NO_SUCH_FILE;
+ }
+
+ // store reference
+ m_FileReference = file;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::Close
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFile::Close()
+{
+ // release the file reference
+ m_FileReference = NULL;
+
+ // reset the mode
+ m_Mode = 0;
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::GetInputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFile::GetInputStream(NPT_InputStreamReference& stream)
+{
+ // default value
+ stream = NULL;
+
+ // check that the file is open
+ if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+ // check that the mode is compatible
+ if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) {
+ return NPT_ERROR_FILE_NOT_READABLE;
+ }
+
+ // create a stream
+ stream = new NPT_XbmcFileInputStream(m_FileReference);
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| NPT_XbmcFile::GetOutputStream
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_XbmcFile::GetOutputStream(NPT_OutputStreamReference& stream)
+{
+ // default value
+ stream = NULL;
+
+ // check that the file is open
+ if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
+
+ // check that the mode is compatible
+ if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) {
+ return NPT_ERROR_FILE_NOT_WRITABLE;
+ }
+
+ // create a stream
+ stream = new NPT_XbmcFileOutputStream(m_FileReference);
+
+ return NPT_SUCCESS;
+}
+
+static NPT_Result
+MapErrno(int err) {
+ switch (err) {
+ case EACCES: return NPT_ERROR_PERMISSION_DENIED;
+ case EPERM: return NPT_ERROR_PERMISSION_DENIED;
+ case ENOENT: return NPT_ERROR_NO_SUCH_FILE;
+ case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
+ case EBUSY: return NPT_ERROR_FILE_BUSY;
+ case EROFS: return NPT_ERROR_FILE_NOT_WRITABLE;
+ case ENOTDIR: return NPT_ERROR_FILE_NOT_DIRECTORY;
+ case EEXIST: return NPT_ERROR_FILE_ALREADY_EXISTS;
+ case ENOSPC: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE;
+ case ENOTEMPTY: return NPT_ERROR_DIRECTORY_NOT_EMPTY;
+ default: return NPT_ERROR_ERRNO(err);
+ }
+}
+/*----------------------------------------------------------------------
+| NPT_FilePath::Separator
++---------------------------------------------------------------------*/
+const char* const NPT_FilePath::Separator = "/";
+
+/*----------------------------------------------------------------------
+| NPT_File::NPT_File
++---------------------------------------------------------------------*/
+NPT_File::NPT_File(const char* path) : m_Path(path)
+{
+ m_Delegate = new NPT_XbmcFile(*this);
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::operator=
++---------------------------------------------------------------------*/
+NPT_File&
+NPT_File::operator=(const NPT_File& file)
+{
+ if (this != &file) {
+ delete m_Delegate;
+ m_Path = file.m_Path;
+ m_Delegate = new NPT_XbmcFile(*this);
+ }
+ return *this;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetRoots
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetRoots(NPT_List<NPT_String>& roots)
+{
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::CreateDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::CreateDir(const char* path)
+{
+ return NPT_ERROR_PERMISSION_DENIED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::RemoveFile
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::RemoveFile(const char* path)
+{
+ return NPT_ERROR_PERMISSION_DENIED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::RemoveDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::RemoveDir(const char* path)
+{
+ return NPT_ERROR_PERMISSION_DENIED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::Rename
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::Rename(const char* from_path, const char* to_path)
+{
+ return NPT_ERROR_PERMISSION_DENIED;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::ListDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::ListDir(const char* path,
+ NPT_List<NPT_String>& entries,
+ NPT_Ordinal start /* = 0 */,
+ NPT_Cardinal max /* = 0 */)
+{
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetWorkingDir
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetWorkingDir(NPT_String& path)
+{
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| NPT_File::GetInfo
++---------------------------------------------------------------------*/
+NPT_Result
+NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
+{
+ struct __stat64 stat_buffer = {};
+ int result;
+
+ if (!info)
+ return NPT_FAILURE;
+
+ *info = NPT_FileInfo();
+
+ result = CFile::Stat(path, &stat_buffer);
+ if (result != 0)
+ return MapErrno(errno);
+ if (info)
+ {
+ info->m_Size = stat_buffer.st_size;
+ if (S_ISREG(stat_buffer.st_mode))
+ {
+ info->m_Type = NPT_FileInfo::FILE_TYPE_REGULAR;
+ }
+ else if (S_ISDIR(stat_buffer.st_mode))
+ {
+ info->m_Type = NPT_FileInfo::FILE_TYPE_DIRECTORY;
+ }
+ else
+ {
+ info->m_Type = NPT_FileInfo::FILE_TYPE_OTHER;
+ }
+ info->m_AttributesMask &= NPT_FILE_ATTRIBUTE_READ_ONLY;
+ if ((stat_buffer.st_mode & S_IWUSR) == 0)
+ {
+ info->m_Attributes &= NPT_FILE_ATTRIBUTE_READ_ONLY;
+ }
+ info->m_CreationTime.SetSeconds(0);
+ info->m_ModificationTime.SetSeconds(stat_buffer.st_mtime);
+ }
+
+ return NPT_SUCCESS;
+}
+