1 /*****************************************************************
3 | Neptune - Files :: Android Implementation
5 | (c) 2001-2016 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
8 ****************************************************************/
10 /*----------------------------------------------------------------------
12 +---------------------------------------------------------------------*/
13 #include "NptConfig.h"
16 #include "NptThreads.h"
17 #include "NptInterfaces.h"
18 #include "NptStrings.h"
25 /*----------------------------------------------------------------------
27 +---------------------------------------------------------------------*/
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
;
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
50 // constructors and destructor
51 NPT_AndroidFileWrapper(int fd
, const char* name
) : m_FD(fd
), m_Position(0), m_Name(name
) {}
52 ~NPT_AndroidFileWrapper() {
54 m_FD
!= STDIN_FILENO
&&
55 m_FD
!= STDOUT_FILENO
&&
56 m_FD
!= STDERR_FILENO
) {
63 NPT_Position m_Position
;
67 typedef NPT_Reference
<NPT_AndroidFileWrapper
> NPT_AndroidFileReference
;
69 /*----------------------------------------------------------------------
70 | NPT_AndroidFileStream
71 +---------------------------------------------------------------------*/
72 class NPT_AndroidFileStream
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
);
85 // constructors and destructors
86 virtual ~NPT_AndroidFileStream() {}
89 NPT_AndroidFileReference m_FileReference
;
92 /*----------------------------------------------------------------------
93 | NPT_AndroidFileStream::Seek
94 +---------------------------------------------------------------------*/
96 NPT_AndroidFileStream::Seek(NPT_Position offset
)
98 off64_t result
= lseek64(m_FileReference
->m_FD
, offset
, SEEK_SET
);
100 return MapErrno(errno
);
103 m_FileReference
->m_Position
= offset
;
108 /*----------------------------------------------------------------------
109 | NPT_AndroidFileStream::Tell
110 +---------------------------------------------------------------------*/
112 NPT_AndroidFileStream::Tell(NPT_Position
& offset
)
114 offset
= m_FileReference
->m_Position
;
118 /*----------------------------------------------------------------------
119 | NPT_AndroidFileStream::Flush
120 +---------------------------------------------------------------------*/
122 NPT_AndroidFileStream::Flush()
127 /*----------------------------------------------------------------------
128 | NPT_AndroidFileInputStream
129 +---------------------------------------------------------------------*/
130 class NPT_AndroidFileInputStream
: public NPT_InputStream
,
131 private NPT_AndroidFileStream
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 +---------------------------------------------------------------------*/
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
);
169 if (bytes_read
) *bytes_read
= (NPT_Size
)nb_read
;
170 m_FileReference
->m_Position
+= nb_read
;
172 } else if (nb_read
== 0) {
173 if (bytes_read
) *bytes_read
= 0;
174 return NPT_ERROR_EOS
;
176 if (bytes_read
) *bytes_read
= 0;
177 return MapErrno(errno
);
181 /*----------------------------------------------------------------------
182 | NPT_AndroidFileInputStream::GetSize
183 +---------------------------------------------------------------------*/
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
;
195 /*----------------------------------------------------------------------
196 | NPT_AndroidFileInputStream::GetAvailable
197 +---------------------------------------------------------------------*/
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
;
212 /*----------------------------------------------------------------------
213 | NPT_AndroidFileOutputStream
214 +---------------------------------------------------------------------*/
215 class NPT_AndroidFileOutputStream
: public NPT_OutputStream
,
216 private NPT_AndroidFileStream
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
);
234 return NPT_AndroidFileStream::Flush();
238 /*----------------------------------------------------------------------
239 | NPT_AndroidFileOutputStream::Write
240 +---------------------------------------------------------------------*/
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;
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
;
258 if (bytes_written
) *bytes_written
= 0;
259 return MapErrno(errno
);
263 /*----------------------------------------------------------------------
265 +---------------------------------------------------------------------*/
266 class NPT_AndroidFile
: public NPT_FileInterface
269 // constructors and destructor
270 NPT_AndroidFile(NPT_File
& delegator
);
273 // NPT_FileInterface methods
274 NPT_Result
Open(OpenMode mode
);
276 NPT_Result
GetInputStream(NPT_InputStreamReference
& stream
);
277 NPT_Result
GetOutputStream(NPT_OutputStreamReference
& stream
);
281 NPT_File
& m_Delegator
;
283 NPT_AndroidFileReference m_FileReference
;
286 /*----------------------------------------------------------------------
287 | NPT_AndroidFile::NPT_AndroidFile
288 +---------------------------------------------------------------------*/
289 NPT_AndroidFile::NPT_AndroidFile(NPT_File
& delegator
) :
290 m_Delegator(delegator
),
295 /*----------------------------------------------------------------------
296 | NPT_AndroidFile::~NPT_AndroidFile
297 +---------------------------------------------------------------------*/
298 NPT_AndroidFile::~NPT_AndroidFile()
303 /*----------------------------------------------------------------------
304 | NPT_AndroidFile::Open
305 +---------------------------------------------------------------------*/
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
;
317 // check for special names
318 const char* name
= (const char*)m_Delegator
.GetPath();
320 if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_INPUT
)) {
322 } else if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_OUTPUT
)) {
324 } else if (NPT_StringsEqual(name
, NPT_FILE_STANDARD_ERROR
)) {
330 if (mode
& NPT_FILE_OPEN_MODE_WRITE
) {
331 if (mode
& NPT_FILE_OPEN_MODE_READ
) {
332 open_flags
|= O_RDWR
;
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
;
343 if (mode
& NPT_FILE_OPEN_MODE_TRUNCATE
) {
344 open_flags
|= O_TRUNC
;
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
);
362 /*----------------------------------------------------------------------
363 | NPT_AndroidFile::Close
364 +---------------------------------------------------------------------*/
366 NPT_AndroidFile::Close()
368 // release the file reference
369 m_FileReference
= NULL
;
377 /*----------------------------------------------------------------------
378 | NPT_AndroidFile::GetInputStream
379 +---------------------------------------------------------------------*/
381 NPT_AndroidFile::GetInputStream(NPT_InputStreamReference
& stream
)
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
;
395 stream
= new NPT_AndroidFileInputStream(m_FileReference
);
400 /*----------------------------------------------------------------------
401 | NPT_AndroidFile::GetOutputStream
402 +---------------------------------------------------------------------*/
404 NPT_AndroidFile::GetOutputStream(NPT_OutputStreamReference
& stream
)
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
;
418 stream
= new NPT_AndroidFileOutputStream(m_FileReference
);
423 /*----------------------------------------------------------------------
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
)) {
437 /*----------------------------------------------------------------------
438 | NPT_File::operator=
439 +---------------------------------------------------------------------*/
441 NPT_File::operator=(const NPT_File
& file
)
445 m_Path
= file
.m_Path
;
446 m_IsSpecial
= file
.m_IsSpecial
;
447 m_Delegate
= new NPT_AndroidFile(*this);