1 /*****************************************************************
2 |
3 | AP4 - Android File Byte Stream implementation
4 |
5 | Copyright 2002-2016 Axiomatic Systems, LLC
6 |
7 |
8 | This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 | Unless you have obtained Bento4 under a difference license,
11 | this version of Bento4 is Bento4|GPL.
12 | Bento4|GPL is free software; you can redistribute it and/or modify
13 | it under the terms of the GNU General Public License as published by
14 | the Free Software Foundation; either version 2, or (at your option)
15 | any later version.
16 |
17 | Bento4|GPL is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have received a copy of the GNU General Public License
23 | along with Bento4|GPL; see the file COPYING. If not, write to the
24 | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 | 02111-1307, USA.
26 |
27 ****************************************************************/
28
29 /*----------------------------------------------------------------------
30 | includes
31 +---------------------------------------------------------------------*/
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38
39 #include "Ap4FileByteStream.h"
40
41 /*----------------------------------------------------------------------
42 | AP4_AndroidFileByteStream
43 +---------------------------------------------------------------------*/
44 class AP4_AndroidFileByteStream: public AP4_ByteStream
45 {
46 public:
47 // class methods
48 static AP4_Result Create(AP4_FileByteStream* delegator,
49 const char* name,
50 AP4_FileByteStream::Mode mode,
51 AP4_ByteStream*& stream);
52
53 // methods
54 AP4_AndroidFileByteStream(AP4_FileByteStream* delegator,
55 int fd,
56 AP4_LargeSize size);
57
58 ~AP4_AndroidFileByteStream();
59
60 // AP4_ByteStream methods
61 AP4_Result ReadPartial(void* buffer,
62 AP4_Size bytesToRead,
63 AP4_Size& bytesRead);
64 AP4_Result WritePartial(const void* buffer,
65 AP4_Size bytesToWrite,
66 AP4_Size& bytesWritten);
67 AP4_Result Seek(AP4_Position position);
68 AP4_Result Tell(AP4_Position& position);
69 AP4_Result GetSize(AP4_LargeSize& size);
70 AP4_Result Flush();
71
72 // AP4_Referenceable methods
73 void AddReference();
74 void Release();
75
76 private:
77 // members
78 AP4_ByteStream* m_Delegator;
79 AP4_Cardinal m_ReferenceCount;
80 int m_FD;
81 AP4_Position m_Position;
82 AP4_LargeSize m_Size;
83 };
84
85 /*----------------------------------------------------------------------
86 | AP4_AndroidFileByteStream::Create
87 +---------------------------------------------------------------------*/
88 AP4_Result
Create(AP4_FileByteStream * delegator,const char * name,AP4_FileByteStream::Mode mode,AP4_ByteStream * & stream)89 AP4_AndroidFileByteStream::Create(AP4_FileByteStream* delegator,
90 const char* name,
91 AP4_FileByteStream::Mode mode,
92 AP4_ByteStream*& stream)
93 {
94 // default value
95 stream = NULL;
96
97 // check arguments
98 if (name == NULL) return AP4_ERROR_INVALID_PARAMETERS;
99
100 // open the file
101 int fd = 0;
102 AP4_Position size = 0;
103 if (!strcmp(name, "-stdin")) {
104 fd = STDIN_FILENO;
105 } else if (!strcmp(name, "-stdout")) {
106 fd = STDOUT_FILENO;
107 } else if (!strcmp(name, "-stderr")) {
108 fd = STDERR_FILENO;
109 } else {
110 int open_flags = 0;
111 int create_perm = 0;
112 switch (mode) {
113 case AP4_FileByteStream::STREAM_MODE_READ:
114 open_flags = O_RDONLY;
115 break;
116
117 case AP4_FileByteStream::STREAM_MODE_WRITE:
118 open_flags = O_RDWR | O_CREAT | O_TRUNC;
119 break;
120
121 case AP4_FileByteStream::STREAM_MODE_READ_WRITE:
122 open_flags = O_RDWR;
123 break;
124
125 default:
126 return AP4_ERROR_INVALID_PARAMETERS;
127 }
128
129 fd = open(name, open_flags, create_perm);
130 if (fd < 0) {
131 if (errno == ENOENT) {
132 return AP4_ERROR_NO_SUCH_FILE;
133 } else if (errno == EACCES) {
134 return AP4_ERROR_PERMISSION_DENIED;
135 } else {
136 return AP4_ERROR_CANNOT_OPEN_FILE;
137 }
138 }
139
140 // get the size
141 struct stat info;
142 if (stat(name, &info) == 0) {
143 size = info.st_size;
144 }
145 }
146
147 stream = new AP4_AndroidFileByteStream(delegator, fd, size);
148 return AP4_SUCCESS;
149 }
150
151 /*----------------------------------------------------------------------
152 | AP4_AndroidFileByteStream::AP4_AndroidFileByteStream
153 +---------------------------------------------------------------------*/
AP4_AndroidFileByteStream(AP4_FileByteStream * delegator,int fd,AP4_LargeSize size)154 AP4_AndroidFileByteStream::AP4_AndroidFileByteStream(AP4_FileByteStream* delegator,
155 int fd,
156 AP4_LargeSize size) :
157 m_Delegator(delegator),
158 m_ReferenceCount(1),
159 m_FD(fd),
160 m_Position(0),
161 m_Size(size)
162 {
163 }
164
165 /*----------------------------------------------------------------------
166 | AP4_AndroidFileByteStream::~AP4_AndroidFileByteStream
167 +---------------------------------------------------------------------*/
~AP4_AndroidFileByteStream()168 AP4_AndroidFileByteStream::~AP4_AndroidFileByteStream()
169 {
170 if (m_FD && m_FD != STDERR_FILENO && m_FD != STDOUT_FILENO && m_FD != STDERR_FILENO) {
171 close(m_FD);
172 }
173 }
174
175 /*----------------------------------------------------------------------
176 | AP4_AndroidFileByteStream::AddReference
177 +---------------------------------------------------------------------*/
178 void
AddReference()179 AP4_AndroidFileByteStream::AddReference()
180 {
181 m_ReferenceCount++;
182 }
183
184 /*----------------------------------------------------------------------
185 | AP4_AndroidFileByteStream::Release
186 +---------------------------------------------------------------------*/
187 void
Release()188 AP4_AndroidFileByteStream::Release()
189 {
190 if (--m_ReferenceCount == 0) {
191 if (m_Delegator) {
192 delete m_Delegator;
193 } else {
194 delete this;
195 }
196 }
197 }
198
199 /*----------------------------------------------------------------------
200 | AP4_AndroidFileByteStream::ReadPartial
201 +---------------------------------------------------------------------*/
202 AP4_Result
ReadPartial(void * buffer,AP4_Size bytes_to_read,AP4_Size & bytes_read)203 AP4_AndroidFileByteStream::ReadPartial(void* buffer,
204 AP4_Size bytes_to_read,
205 AP4_Size& bytes_read)
206 {
207 ssize_t nb_read = read(m_FD, buffer, bytes_to_read);
208
209 if (nb_read > 0) {
210 bytes_read = (AP4_Size)nb_read;
211 m_Position += nb_read;
212 return AP4_SUCCESS;
213 } else if (nb_read == 0) {
214 bytes_read = 0;
215 return AP4_ERROR_EOS;
216 } else {
217 bytes_read = 0;
218 return AP4_ERROR_READ_FAILED;
219 }
220 }
221
222 /*----------------------------------------------------------------------
223 | AP4_AndroidFileByteStream::WritePartial
224 +---------------------------------------------------------------------*/
225 AP4_Result
WritePartial(const void * buffer,AP4_Size bytes_to_write,AP4_Size & bytes_written)226 AP4_AndroidFileByteStream::WritePartial(const void* buffer,
227 AP4_Size bytes_to_write,
228 AP4_Size& bytes_written)
229 {
230 if (bytes_to_write == 0) {
231 bytes_written = 0;
232 return AP4_SUCCESS;
233 }
234 ssize_t nb_written = write(m_FD, buffer, bytes_to_write);
235
236 if (nb_written > 0) {
237 bytes_written = (AP4_Size)nb_written;
238 m_Position += nb_written;
239 return AP4_SUCCESS;
240 } else {
241 bytes_written = 0;
242 return AP4_ERROR_WRITE_FAILED;
243 }
244 }
245
246 /*----------------------------------------------------------------------
247 | AP4_AndroidFileByteStream::Seek
248 +---------------------------------------------------------------------*/
249 AP4_Result
Seek(AP4_Position position)250 AP4_AndroidFileByteStream::Seek(AP4_Position position)
251 {
252 // shortcut
253 if (position == m_Position) return AP4_SUCCESS;
254
255 off64_t result = lseek64(m_FD, position, SEEK_SET);
256 if (result >= 0) {
257 m_Position = position;
258 return AP4_SUCCESS;
259 } else {
260 return AP4_FAILURE;
261 }
262 }
263
264 /*----------------------------------------------------------------------
265 | AP4_AndroidFileByteStream::Tell
266 +---------------------------------------------------------------------*/
267 AP4_Result
Tell(AP4_Position & position)268 AP4_AndroidFileByteStream::Tell(AP4_Position& position)
269 {
270 position = m_Position;
271 return AP4_SUCCESS;
272 }
273
274 /*----------------------------------------------------------------------
275 | AP4_AndroidFileByteStream::GetSize
276 +---------------------------------------------------------------------*/
277 AP4_Result
GetSize(AP4_LargeSize & size)278 AP4_AndroidFileByteStream::GetSize(AP4_LargeSize& size)
279 {
280 size = m_Size;
281 return AP4_SUCCESS;
282 }
283
284 /*----------------------------------------------------------------------
285 | AP4_AndroidFileByteStream::Flush
286 +---------------------------------------------------------------------*/
287 AP4_Result
Flush()288 AP4_AndroidFileByteStream::Flush()
289 {
290 return AP4_SUCCESS;
291 }
292
293 /*----------------------------------------------------------------------
294 | AP4_FileByteStream::Create
295 +---------------------------------------------------------------------*/
296 AP4_Result
Create(const char * name,AP4_FileByteStream::Mode mode,AP4_ByteStream * & stream)297 AP4_FileByteStream::Create(const char* name,
298 AP4_FileByteStream::Mode mode,
299 AP4_ByteStream*& stream)
300 {
301 return AP4_AndroidFileByteStream::Create(NULL, name, mode, stream);
302 }
303
304 #if !defined(AP4_CONFIG_NO_EXCEPTIONS)
305 /*----------------------------------------------------------------------
306 | AP4_FileByteStream::AP4_FileByteStream
307 +---------------------------------------------------------------------*/
AP4_FileByteStream(const char * name,AP4_FileByteStream::Mode mode)308 AP4_FileByteStream::AP4_FileByteStream(const char* name,
309 AP4_FileByteStream::Mode mode)
310 {
311 AP4_ByteStream* stream = NULL;
312 AP4_Result result = AP4_AndroidFileByteStream::Create(this, name, mode, stream);
313 if (AP4_FAILED(result)) throw AP4_Exception(result);
314
315 m_Delegate = stream;
316 }
317 #endif
318
319
320
321
322
323
324
325
326
327
328
329