2 * Neptune - Files :: XBMC Implementation
4 * Copyright (c) 2002-2008, Axiomatic Systems, LLC.
7 * SPDX-License-Identifier: BSD-3-Clause
8 * See LICENSES/README.md for more information.
11 /*----------------------------------------------------------------------
13 +---------------------------------------------------------------------*/
15 #include "FileFactory.h"
20 #include <Neptune/Source/Core/NptDebug.h>
21 #include <Neptune/Source/Core/NptFile.h>
22 #include <Neptune/Source/Core/NptStrings.h>
23 #include <Neptune/Source/Core/NptUtils.h>
26 #define S_IWUSR _S_IWRITE
27 #define S_ISDIR(m) ((m & _S_IFDIR) != 0)
28 #define S_ISREG(m) ((m & _S_IFREG) != 0)
31 using namespace XFILE
;
33 typedef NPT_Reference
<IFile
> NPT_XbmcFileReference
;
35 /*----------------------------------------------------------------------
37 +---------------------------------------------------------------------*/
38 class NPT_XbmcFileStream
41 // constructors and destructor
42 explicit NPT_XbmcFileStream(const NPT_XbmcFileReference
& file
) : m_FileReference(file
) {}
44 // NPT_FileInterface methods
45 NPT_Result
Seek(NPT_Position offset
);
46 NPT_Result
Tell(NPT_Position
& offset
);
50 // constructors and destructors
51 virtual ~NPT_XbmcFileStream() = default;
54 NPT_XbmcFileReference m_FileReference
;
57 /*----------------------------------------------------------------------
58 | NPT_XbmcFileStream::Seek
59 +---------------------------------------------------------------------*/
61 NPT_XbmcFileStream::Seek(NPT_Position offset
)
65 result
= m_FileReference
->Seek(offset
, SEEK_SET
) ;
73 /*----------------------------------------------------------------------
74 | NPT_XbmcFileStream::Tell
75 +---------------------------------------------------------------------*/
77 NPT_XbmcFileStream::Tell(NPT_Position
& offset
)
79 int64_t result
= m_FileReference
->GetPosition();
81 offset
= (NPT_Position
)result
;
88 /*----------------------------------------------------------------------
89 | NPT_XbmcFileStream::Flush
90 +---------------------------------------------------------------------*/
92 NPT_XbmcFileStream::Flush()
94 m_FileReference
->Flush();
98 /*----------------------------------------------------------------------
99 | NPT_XbmcFileInputStream
100 +---------------------------------------------------------------------*/
101 class NPT_XbmcFileInputStream
: public NPT_InputStream
,
102 private NPT_XbmcFileStream
106 // constructors and destructor
107 explicit NPT_XbmcFileInputStream(NPT_XbmcFileReference
& file
) :
108 NPT_XbmcFileStream(file
) {}
110 // NPT_InputStream methods
111 NPT_Result
Read(void* buffer
,
112 NPT_Size bytes_to_read
,
113 NPT_Size
* bytes_read
) override
;
114 NPT_Result
Seek(NPT_Position offset
) override
{
115 return NPT_XbmcFileStream::Seek(offset
);
117 NPT_Result
Tell(NPT_Position
& offset
) override
{
118 return NPT_XbmcFileStream::Tell(offset
);
120 NPT_Result
GetSize(NPT_LargeSize
& size
) override
;
121 NPT_Result
GetAvailable(NPT_LargeSize
& available
) override
;
124 /*----------------------------------------------------------------------
125 | NPT_XbmcFileInputStream::Read
126 +---------------------------------------------------------------------*/
128 NPT_XbmcFileInputStream::Read(void* buffer
,
129 NPT_Size bytes_to_read
,
130 NPT_Size
* bytes_read
)
132 unsigned int nb_read
;
134 // check the parameters
135 if (buffer
== NULL
) {
136 return NPT_ERROR_INVALID_PARAMETERS
;
139 // read from the file
140 nb_read
= m_FileReference
->Read(buffer
, bytes_to_read
);
142 if (bytes_read
) *bytes_read
= (NPT_Size
)nb_read
;
145 if (bytes_read
) *bytes_read
= 0;
146 return NPT_ERROR_EOS
;
147 //} else { // currently no way to indicate failure
148 // if (bytes_read) *bytes_read = 0;
149 // return NPT_ERROR_READ_FAILED;
153 /*----------------------------------------------------------------------
154 | NPT_XbmcFileInputStream::GetSize
155 +---------------------------------------------------------------------*/
157 NPT_XbmcFileInputStream::GetSize(NPT_LargeSize
& size
)
159 size
= m_FileReference
->GetLength();
163 /*----------------------------------------------------------------------
164 | NPT_XbmcFileInputStream::GetAvailable
165 +---------------------------------------------------------------------*/
167 NPT_XbmcFileInputStream::GetAvailable(NPT_LargeSize
& available
)
169 int64_t offset
= m_FileReference
->GetPosition();
170 NPT_LargeSize size
= 0;
172 if (NPT_SUCCEEDED(GetSize(size
)) && offset
>= 0 && (NPT_LargeSize
)offset
<= size
) {
173 available
= size
- offset
;
181 /*----------------------------------------------------------------------
182 | NPT_XbmcFileOutputStream
183 +---------------------------------------------------------------------*/
184 class NPT_XbmcFileOutputStream
: public NPT_OutputStream
,
185 private NPT_XbmcFileStream
188 // constructors and destructor
189 explicit NPT_XbmcFileOutputStream(NPT_XbmcFileReference
& file
) :
190 NPT_XbmcFileStream(file
) {}
192 // NPT_OutputStream methods
193 NPT_Result
Write(const void* buffer
,
194 NPT_Size bytes_to_write
,
195 NPT_Size
* bytes_written
) override
;
196 NPT_Result
Seek(NPT_Position offset
) override
{
197 return NPT_XbmcFileStream::Seek(offset
);
199 NPT_Result
Tell(NPT_Position
& offset
) override
{
200 return NPT_XbmcFileStream::Tell(offset
);
202 NPT_Result
Flush() override
{
203 return NPT_XbmcFileStream::Flush();
207 /*----------------------------------------------------------------------
208 | NPT_XbmcFileOutputStream::Write
209 +---------------------------------------------------------------------*/
211 NPT_XbmcFileOutputStream::Write(const void* buffer
,
212 NPT_Size bytes_to_write
,
213 NPT_Size
* bytes_written
)
216 nb_written
= m_FileReference
->Write(buffer
, bytes_to_write
);
218 if (nb_written
> 0) {
219 if (bytes_written
) *bytes_written
= (NPT_Size
)nb_written
;
222 if (bytes_written
) *bytes_written
= 0;
223 return NPT_ERROR_WRITE_FAILED
;
227 /*----------------------------------------------------------------------
229 +---------------------------------------------------------------------*/
230 class NPT_XbmcFile
: public NPT_FileInterface
233 // constructors and destructor
234 explicit NPT_XbmcFile(NPT_File
& delegator
);
235 ~NPT_XbmcFile() override
;
237 // NPT_FileInterface methods
238 NPT_Result
Open(OpenMode mode
) override
;
239 NPT_Result
Close() override
;
240 NPT_Result
GetInputStream(NPT_InputStreamReference
& stream
) override
;
241 NPT_Result
GetOutputStream(NPT_OutputStreamReference
& stream
) override
;
245 NPT_File
& m_Delegator
;
247 NPT_XbmcFileReference m_FileReference
;
250 /*----------------------------------------------------------------------
251 | NPT_XbmcFile::NPT_XbmcFile
252 +---------------------------------------------------------------------*/
253 NPT_XbmcFile::NPT_XbmcFile(NPT_File
& delegator
) :
254 m_Delegator(delegator
),
259 /*----------------------------------------------------------------------
260 | NPT_XbmcFile::~NPT_XbmcFile
261 +---------------------------------------------------------------------*/
262 NPT_XbmcFile::~NPT_XbmcFile()
267 /*----------------------------------------------------------------------
269 +---------------------------------------------------------------------*/
271 NPT_XbmcFile::Open(NPT_File::OpenMode mode
)
273 NPT_XbmcFileReference file
;
275 // check if we're already open
276 if (!m_FileReference
.IsNull()) {
277 return NPT_ERROR_FILE_ALREADY_OPEN
;
283 // check for special names
284 const char* name
= (const char*)m_Delegator
.GetPath();
285 if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_INPUT
)) {
286 return NPT_ERROR_FILE_NOT_READABLE
;
287 } else if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_OUTPUT
)) {
288 return NPT_ERROR_FILE_NOT_WRITABLE
;
289 } else if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_ERROR
)) {
290 return NPT_ERROR_FILE_NOT_WRITABLE
;
293 file
= CFileFactory::CreateLoader(name
);
295 return NPT_ERROR_NO_SUCH_FILE
;
299 CURL
* url
= new CURL(name
);
302 if (mode
& NPT_FILE_OPEN_MODE_WRITE
) {
303 result
= file
->OpenForWrite(*url
, (mode
& NPT_FILE_OPEN_MODE_TRUNCATE
)?true:false);
305 result
= file
->Open(*url
);
309 if (!result
) return NPT_ERROR_NO_SUCH_FILE
;
313 m_FileReference
= file
;
318 /*----------------------------------------------------------------------
319 | NPT_XbmcFile::Close
320 +---------------------------------------------------------------------*/
322 NPT_XbmcFile::Close()
324 // release the file reference
325 m_FileReference
= NULL
;
333 /*----------------------------------------------------------------------
334 | NPT_XbmcFile::GetInputStream
335 +---------------------------------------------------------------------*/
337 NPT_XbmcFile::GetInputStream(NPT_InputStreamReference
& stream
)
342 // check that the file is open
343 if (m_FileReference
.IsNull()) return NPT_ERROR_FILE_NOT_OPEN
;
345 // check that the mode is compatible
346 if (!(m_Mode
& NPT_FILE_OPEN_MODE_READ
)) {
347 return NPT_ERROR_FILE_NOT_READABLE
;
351 stream
= new NPT_XbmcFileInputStream(m_FileReference
);
356 /*----------------------------------------------------------------------
357 | NPT_XbmcFile::GetOutputStream
358 +---------------------------------------------------------------------*/
360 NPT_XbmcFile::GetOutputStream(NPT_OutputStreamReference
& stream
)
365 // check that the file is open
366 if (m_FileReference
.IsNull()) return NPT_ERROR_FILE_NOT_OPEN
;
368 // check that the mode is compatible
369 if (!(m_Mode
& NPT_FILE_OPEN_MODE_WRITE
)) {
370 return NPT_ERROR_FILE_NOT_WRITABLE
;
374 stream
= new NPT_XbmcFileOutputStream(m_FileReference
);
382 case EACCES
: return NPT_ERROR_PERMISSION_DENIED
;
383 case EPERM
: return NPT_ERROR_PERMISSION_DENIED
;
384 case ENOENT
: return NPT_ERROR_NO_SUCH_FILE
;
385 case ENAMETOOLONG
: return NPT_ERROR_INVALID_PARAMETERS
;
386 case EBUSY
: return NPT_ERROR_FILE_BUSY
;
387 case EROFS
: return NPT_ERROR_FILE_NOT_WRITABLE
;
388 case ENOTDIR
: return NPT_ERROR_FILE_NOT_DIRECTORY
;
389 case EEXIST
: return NPT_ERROR_FILE_ALREADY_EXISTS
;
390 case ENOSPC
: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE
;
391 case ENOTEMPTY
: return NPT_ERROR_DIRECTORY_NOT_EMPTY
;
392 default: return NPT_ERROR_ERRNO(err
);
395 /*----------------------------------------------------------------------
396 | NPT_FilePath::Separator
397 +---------------------------------------------------------------------*/
398 const char* const NPT_FilePath::Separator
= "/";
400 /*----------------------------------------------------------------------
402 +---------------------------------------------------------------------*/
403 NPT_File::NPT_File(const char* path
) : m_Path(path
)
405 m_Delegate
= new NPT_XbmcFile(*this);
408 /*----------------------------------------------------------------------
409 | NPT_File::operator=
410 +---------------------------------------------------------------------*/
412 NPT_File::operator=(const NPT_File
& file
)
416 m_Path
= file
.m_Path
;
417 m_Delegate
= new NPT_XbmcFile(*this);
422 /*----------------------------------------------------------------------
424 +---------------------------------------------------------------------*/
426 NPT_File::GetRoots(NPT_List
<NPT_String
>& roots
)
431 /*----------------------------------------------------------------------
432 | NPT_File::CreateDir
433 +---------------------------------------------------------------------*/
435 NPT_File::CreateDir(const char* path
)
437 return NPT_ERROR_PERMISSION_DENIED
;
440 /*----------------------------------------------------------------------
441 | NPT_File::RemoveFile
442 +---------------------------------------------------------------------*/
444 NPT_File::RemoveFile(const char* path
)
446 return NPT_ERROR_PERMISSION_DENIED
;
449 /*----------------------------------------------------------------------
450 | NPT_File::RemoveDir
451 +---------------------------------------------------------------------*/
453 NPT_File::RemoveDir(const char* path
)
455 return NPT_ERROR_PERMISSION_DENIED
;
458 /*----------------------------------------------------------------------
460 +---------------------------------------------------------------------*/
462 NPT_File::Rename(const char* from_path
, const char* to_path
)
464 return NPT_ERROR_PERMISSION_DENIED
;
467 /*----------------------------------------------------------------------
469 +---------------------------------------------------------------------*/
471 NPT_File::ListDir(const char* path
,
472 NPT_List
<NPT_String
>& entries
,
473 NPT_Ordinal start
/* = 0 */,
474 NPT_Cardinal max
/* = 0 */)
479 /*----------------------------------------------------------------------
480 | NPT_File::GetWorkingDir
481 +---------------------------------------------------------------------*/
483 NPT_File::GetWorkingDir(NPT_String
& path
)
488 /*----------------------------------------------------------------------
490 +---------------------------------------------------------------------*/
492 NPT_File::GetInfo(const char* path
, NPT_FileInfo
* info
)
494 struct __stat64 stat_buffer
= {};
500 *info
= NPT_FileInfo();
502 result
= CFile::Stat(path
, &stat_buffer
);
504 return MapErrno(errno
);
507 info
->m_Size
= stat_buffer
.st_size
;
508 if (S_ISREG(stat_buffer
.st_mode
))
510 info
->m_Type
= NPT_FileInfo::FILE_TYPE_REGULAR
;
512 else if (S_ISDIR(stat_buffer
.st_mode
))
514 info
->m_Type
= NPT_FileInfo::FILE_TYPE_DIRECTORY
;
518 info
->m_Type
= NPT_FileInfo::FILE_TYPE_OTHER
;
520 info
->m_AttributesMask
&= NPT_FILE_ATTRIBUTE_READ_ONLY
;
521 if ((stat_buffer
.st_mode
& S_IWUSR
) == 0)
523 info
->m_Attributes
&= NPT_FILE_ATTRIBUTE_READ_ONLY
;
525 info
->m_CreationTime
.SetSeconds(0);
526 info
->m_ModificationTime
.SetSeconds(stat_buffer
.st_mtime
);