Merge pull request #25959 from neo1973/TagLib_deprecation_warnings
[xbmc.git] / lib / libUPnP / Neptune / Source / System / Android / NptAndroidFile.cpp
blob5d7f619793b72381dfaab4c05e184671254d9ef2
1 /*****************************************************************
3 | Neptune - Files :: Android Implementation
5 | (c) 2001-2016 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
8 ****************************************************************/
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #include "NptConfig.h"
14 #include "NptUtils.h"
15 #include "NptFile.h"
16 #include "NptThreads.h"
17 #include "NptInterfaces.h"
18 #include "NptStrings.h"
19 #include "NptDebug.h"
21 #include <errno.h>
22 #include <unistd.h>
23 #include <fcntl.h>
25 /*----------------------------------------------------------------------
26 | MapErrno
27 +---------------------------------------------------------------------*/
28 static NPT_Result
29 MapErrno(int err) {
30 switch (err) {
31 case EACCES: return NPT_ERROR_PERMISSION_DENIED;
32 case EPERM: return NPT_ERROR_PERMISSION_DENIED;
33 case ENOENT: return NPT_ERROR_NO_SUCH_FILE;
34 #if defined(ENAMETOOLONG)
35 case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
36 #endif
37 case EBUSY: return NPT_ERROR_FILE_BUSY;
38 case EROFS: return NPT_ERROR_FILE_NOT_WRITABLE;
39 case ENOTDIR: return NPT_ERROR_FILE_NOT_DIRECTORY;
40 default: return NPT_ERROR_ERRNO(err);
44 /*----------------------------------------------------------------------
45 | NPT_AndroidFileWrapper
46 +---------------------------------------------------------------------*/
47 class NPT_AndroidFileWrapper
49 public:
50 // constructors and destructor
51 NPT_AndroidFileWrapper(int fd, const char* name) : m_FD(fd), m_Position(0), m_Name(name) {}
52 ~NPT_AndroidFileWrapper() {
53 if (m_FD >= 0 &&
54 m_FD != STDIN_FILENO &&
55 m_FD != STDOUT_FILENO &&
56 m_FD != STDERR_FILENO) {
57 close(m_FD);
61 // members
62 int m_FD;
63 NPT_Position m_Position;
64 NPT_String m_Name;
67 typedef NPT_Reference<NPT_AndroidFileWrapper> NPT_AndroidFileReference;
69 /*----------------------------------------------------------------------
70 | NPT_AndroidFileStream
71 +---------------------------------------------------------------------*/
72 class NPT_AndroidFileStream
74 public:
75 // constructors and destructor
76 NPT_AndroidFileStream(NPT_AndroidFileReference file) :
77 m_FileReference(file) {}
79 // NPT_FileInterface methods
80 NPT_Result Seek(NPT_Position offset);
81 NPT_Result Tell(NPT_Position& offset);
82 NPT_Result Flush();
84 protected:
85 // constructors and destructors
86 virtual ~NPT_AndroidFileStream() {}
88 // members
89 NPT_AndroidFileReference m_FileReference;
92 /*----------------------------------------------------------------------
93 | NPT_AndroidFileStream::Seek
94 +---------------------------------------------------------------------*/
95 NPT_Result
96 NPT_AndroidFileStream::Seek(NPT_Position offset)
98 off64_t result = lseek64(m_FileReference->m_FD, offset, SEEK_SET);
99 if (result < 0) {
100 return MapErrno(errno);
103 m_FileReference->m_Position = offset;
105 return NPT_SUCCESS;
108 /*----------------------------------------------------------------------
109 | NPT_AndroidFileStream::Tell
110 +---------------------------------------------------------------------*/
111 NPT_Result
112 NPT_AndroidFileStream::Tell(NPT_Position& offset)
114 offset = m_FileReference->m_Position;
115 return NPT_SUCCESS;
118 /*----------------------------------------------------------------------
119 | NPT_AndroidFileStream::Flush
120 +---------------------------------------------------------------------*/
121 NPT_Result
122 NPT_AndroidFileStream::Flush()
124 return NPT_SUCCESS;
127 /*----------------------------------------------------------------------
128 | NPT_AndroidFileInputStream
129 +---------------------------------------------------------------------*/
130 class NPT_AndroidFileInputStream : public NPT_InputStream,
131 private NPT_AndroidFileStream
134 public:
135 // constructors and destructor
136 NPT_AndroidFileInputStream(NPT_AndroidFileReference& file) :
137 NPT_AndroidFileStream(file) {}
139 // NPT_InputStream methods
140 NPT_Result Read(void* buffer,
141 NPT_Size bytes_to_read,
142 NPT_Size* bytes_read);
143 NPT_Result Seek(NPT_Position offset) {
144 return NPT_AndroidFileStream::Seek(offset);
146 NPT_Result Tell(NPT_Position& offset) {
147 return NPT_AndroidFileStream::Tell(offset);
149 NPT_Result GetSize(NPT_LargeSize& size);
150 NPT_Result GetAvailable(NPT_LargeSize& available);
153 /*----------------------------------------------------------------------
154 | NPT_AndroidFileInputStream::Read
155 +---------------------------------------------------------------------*/
156 NPT_Result
157 NPT_AndroidFileInputStream::Read(void* buffer,
158 NPT_Size bytes_to_read,
159 NPT_Size* bytes_read)
161 // check the parameters
162 if (buffer == NULL) {
163 return NPT_ERROR_INVALID_PARAMETERS;
166 // read from the file
167 ssize_t nb_read = read(m_FileReference->m_FD, buffer, bytes_to_read);
168 if (nb_read > 0) {
169 if (bytes_read) *bytes_read = (NPT_Size)nb_read;
170 m_FileReference->m_Position += nb_read;
171 return NPT_SUCCESS;
172 } else if (nb_read == 0) {
173 if (bytes_read) *bytes_read = 0;
174 return NPT_ERROR_EOS;
175 } else {
176 if (bytes_read) *bytes_read = 0;
177 return MapErrno(errno);
181 /*----------------------------------------------------------------------
182 | NPT_AndroidFileInputStream::GetSize
183 +---------------------------------------------------------------------*/
184 NPT_Result
185 NPT_AndroidFileInputStream::GetSize(NPT_LargeSize& size)
187 NPT_FileInfo file_info;
188 NPT_Result result = NPT_File::GetInfo(m_FileReference->m_Name, &file_info);
189 if (NPT_FAILED(result)) return result;
190 size = file_info.m_Size;
192 return NPT_SUCCESS;
195 /*----------------------------------------------------------------------
196 | NPT_AndroidFileInputStream::GetAvailable
197 +---------------------------------------------------------------------*/
198 NPT_Result
199 NPT_AndroidFileInputStream::GetAvailable(NPT_LargeSize& available)
201 NPT_LargeSize size = 0;
203 if (NPT_SUCCEEDED(GetSize(size)) && m_FileReference->m_Position <= size) {
204 available = size - m_FileReference->m_Position;
205 return NPT_SUCCESS;
206 } else {
207 available = 0;
208 return NPT_FAILURE;
212 /*----------------------------------------------------------------------
213 | NPT_AndroidFileOutputStream
214 +---------------------------------------------------------------------*/
215 class NPT_AndroidFileOutputStream : public NPT_OutputStream,
216 private NPT_AndroidFileStream
218 public:
219 // constructors and destructor
220 NPT_AndroidFileOutputStream(NPT_AndroidFileReference& file) :
221 NPT_AndroidFileStream(file) {}
223 // NPT_InputStream methods
224 NPT_Result Write(const void* buffer,
225 NPT_Size bytes_to_write,
226 NPT_Size* bytes_written);
227 NPT_Result Seek(NPT_Position offset) {
228 return NPT_AndroidFileStream::Seek(offset);
230 NPT_Result Tell(NPT_Position& offset) {
231 return NPT_AndroidFileStream::Tell(offset);
233 NPT_Result Flush() {
234 return NPT_AndroidFileStream::Flush();
238 /*----------------------------------------------------------------------
239 | NPT_AndroidFileOutputStream::Write
240 +---------------------------------------------------------------------*/
241 NPT_Result
242 NPT_AndroidFileOutputStream::Write(const void* buffer,
243 NPT_Size bytes_to_write,
244 NPT_Size* bytes_written)
246 if (bytes_to_write == 0) {
247 if (bytes_written) *bytes_written = 0;
248 return NPT_SUCCESS;
251 ssize_t nb_written = write(m_FileReference->m_FD, buffer, bytes_to_write);
253 if (nb_written > 0) {
254 if (bytes_written) *bytes_written = (NPT_Size)nb_written;
255 m_FileReference->m_Position += nb_written;
256 return NPT_SUCCESS;
257 } else {
258 if (bytes_written) *bytes_written = 0;
259 return MapErrno(errno);
263 /*----------------------------------------------------------------------
264 | NPT_AndroidFile
265 +---------------------------------------------------------------------*/
266 class NPT_AndroidFile: public NPT_FileInterface
268 public:
269 // constructors and destructor
270 NPT_AndroidFile(NPT_File& delegator);
271 ~NPT_AndroidFile();
273 // NPT_FileInterface methods
274 NPT_Result Open(OpenMode mode);
275 NPT_Result Close();
276 NPT_Result GetInputStream(NPT_InputStreamReference& stream);
277 NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
279 private:
280 // members
281 NPT_File& m_Delegator;
282 OpenMode m_Mode;
283 NPT_AndroidFileReference m_FileReference;
286 /*----------------------------------------------------------------------
287 | NPT_AndroidFile::NPT_AndroidFile
288 +---------------------------------------------------------------------*/
289 NPT_AndroidFile::NPT_AndroidFile(NPT_File& delegator) :
290 m_Delegator(delegator),
291 m_Mode(0)
295 /*----------------------------------------------------------------------
296 | NPT_AndroidFile::~NPT_AndroidFile
297 +---------------------------------------------------------------------*/
298 NPT_AndroidFile::~NPT_AndroidFile()
300 Close();
303 /*----------------------------------------------------------------------
304 | NPT_AndroidFile::Open
305 +---------------------------------------------------------------------*/
306 NPT_Result
307 NPT_AndroidFile::Open(NPT_File::OpenMode mode)
309 // check if we're already open
310 if (!m_FileReference.IsNull()) {
311 return NPT_ERROR_FILE_ALREADY_OPEN;
314 // store the mode
315 m_Mode = mode;
317 // check for special names
318 const char* name = (const char*)m_Delegator.GetPath();
319 int fd = -1;
320 if (NPT_StringsEqual(name, NPT_FILE_STANDARD_INPUT)) {
321 fd = STDIN_FILENO;
322 } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_OUTPUT)) {
323 fd = STDOUT_FILENO;
324 } else if (NPT_StringsEqual(name, NPT_FILE_STANDARD_ERROR)) {
325 fd = STDERR_FILENO;
326 } else {
327 int open_flags = 0;
328 int create_perm = 0;
330 if (mode & NPT_FILE_OPEN_MODE_WRITE) {
331 if (mode & NPT_FILE_OPEN_MODE_READ) {
332 open_flags |= O_RDWR;
333 } else {
334 open_flags |= O_WRONLY;
336 if (mode & NPT_FILE_OPEN_MODE_APPEND) {
337 open_flags |= O_APPEND;
339 if (mode & NPT_FILE_OPEN_MODE_CREATE) {
340 open_flags |= O_CREAT;
341 create_perm = 0666;
343 if (mode & NPT_FILE_OPEN_MODE_TRUNCATE) {
344 open_flags |= O_TRUNC;
346 } else {
347 open_flags |= O_RDONLY;
350 fd = open(name, open_flags, create_perm);
352 // test the result of the open
353 if (fd < 0) return MapErrno(errno);
356 // create a reference to the file descriptor
357 m_FileReference = new NPT_AndroidFileWrapper(fd, name);
359 return NPT_SUCCESS;
362 /*----------------------------------------------------------------------
363 | NPT_AndroidFile::Close
364 +---------------------------------------------------------------------*/
365 NPT_Result
366 NPT_AndroidFile::Close()
368 // release the file reference
369 m_FileReference = NULL;
371 // reset the mode
372 m_Mode = 0;
374 return NPT_SUCCESS;
377 /*----------------------------------------------------------------------
378 | NPT_AndroidFile::GetInputStream
379 +---------------------------------------------------------------------*/
380 NPT_Result
381 NPT_AndroidFile::GetInputStream(NPT_InputStreamReference& stream)
383 // default value
384 stream = NULL;
386 // check that the file is open
387 if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
389 // check that the mode is compatible
390 if (!(m_Mode & NPT_FILE_OPEN_MODE_READ)) {
391 return NPT_ERROR_FILE_NOT_READABLE;
394 // create a stream
395 stream = new NPT_AndroidFileInputStream(m_FileReference);
397 return NPT_SUCCESS;
400 /*----------------------------------------------------------------------
401 | NPT_AndroidFile::GetOutputStream
402 +---------------------------------------------------------------------*/
403 NPT_Result
404 NPT_AndroidFile::GetOutputStream(NPT_OutputStreamReference& stream)
406 // default value
407 stream = NULL;
409 // check that the file is open
410 if (m_FileReference.IsNull()) return NPT_ERROR_FILE_NOT_OPEN;
412 // check that the mode is compatible
413 if (!(m_Mode & NPT_FILE_OPEN_MODE_WRITE)) {
414 return NPT_ERROR_FILE_NOT_WRITABLE;
417 // create a stream
418 stream = new NPT_AndroidFileOutputStream(m_FileReference);
420 return NPT_SUCCESS;
423 /*----------------------------------------------------------------------
424 | NPT_File::NPT_File
425 +---------------------------------------------------------------------*/
426 NPT_File::NPT_File(const char* path) : m_Path(path), m_IsSpecial(false)
428 m_Delegate = new NPT_AndroidFile(*this);
430 if (NPT_StringsEqual(path, NPT_FILE_STANDARD_INPUT) ||
431 NPT_StringsEqual(path, NPT_FILE_STANDARD_OUTPUT) ||
432 NPT_StringsEqual(path, NPT_FILE_STANDARD_ERROR)) {
433 m_IsSpecial = true;
437 /*----------------------------------------------------------------------
438 | NPT_File::operator=
439 +---------------------------------------------------------------------*/
440 NPT_File&
441 NPT_File::operator=(const NPT_File& file)
443 if (this != &file) {
444 delete m_Delegate;
445 m_Path = file.m_Path;
446 m_IsSpecial = file.m_IsSpecial;
447 m_Delegate = new NPT_AndroidFile(*this);
449 return *this;