Fix coverity issue (INTEGER_OVERFLOW)
[platform/core/multimedia/libmm-fileinfo.git] / utils / mm_file_util_io_mmap.c
1 /*
2  * libmm-fileinfo
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Haejeong Kim <backto.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 #include "mm_file_debug.h"
34 #include "mm_file_utils.h"
35
36
37 typedef struct {
38         int fd;
39         unsigned char *ptr;
40         long long size;
41         long long offset;
42         int     state;
43 } MMFMMapIOHandle;
44
45 static int mmf_mmap_open(MMFileIOHandle *handle, const char *filename, int flags)
46 {
47         MMFMMapIOHandle *mmapHandle = NULL;
48         struct stat finfo = {0, };
49         int access = O_RDONLY;
50
51         if (!handle || !filename || !handle->iofunc || !handle->iofunc->handleName) {
52                 debug_error(DEBUG, "invalid param\n");
53                 return MMFILE_UTIL_FAIL;
54         }
55
56         filename += strlen(handle->iofunc->handleName) + 3; /* :// */
57
58         mmapHandle = g_new0(MMFMMapIOHandle, 1);
59
60 #ifdef O_BINARY
61         access |= O_BINARY;
62 #endif
63
64         mmapHandle->fd = open(filename, access);
65         if (mmapHandle->fd < 0) {
66                 debug_error(DEBUG, "error: open error: %s\n", filename);
67                 goto exception;
68         }
69
70         if (fstat(mmapHandle->fd, &finfo) == -1) {
71                 debug_error(DEBUG, "error: fstat\n");
72                 goto exception;
73         }
74
75         if (!S_ISREG(finfo.st_mode)) {
76                 debug_error(DEBUG, "error: it is not regular file\n");
77                 goto exception;
78         }
79
80         mmapHandle->size = finfo.st_size;
81         mmapHandle->offset = 0;
82         mmapHandle->state = 0;
83
84         /*mmapHandle->ptr = mmap64(0, mmapHandle->size, PROT_READ, MAP_SHARED, mmapHandle->fd, 0); */
85         mmapHandle->ptr = mmap(0, mmapHandle->size, PROT_READ, MAP_SHARED, mmapHandle->fd, 0);
86
87         if (mmapHandle->ptr == (void *)-1) {
88                 debug_error(DEBUG, "error: mmap\n");
89                 mmapHandle->ptr = NULL;
90                 goto exception;
91         }
92
93         handle->privateData = (void *) mmapHandle;
94
95         return MMFILE_UTIL_SUCCESS;
96
97 exception:
98         if (mmapHandle->ptr) {
99                 munmap(mmapHandle->ptr, mmapHandle->size);
100         }
101
102         if (mmapHandle->fd > 2) {
103                 close(mmapHandle->fd);
104         }
105
106         mmfile_free(mmapHandle);
107         handle->privateData = NULL;
108
109         return MMFILE_UTIL_FAIL;
110 }
111
112 static int mmf_mmap_read(MMFileIOHandle *h, unsigned char *buf, int size)
113 {
114         MMFMMapIOHandle *mmapHandle = NULL;
115         const unsigned char *c = NULL;
116         int len = 0;
117
118         if (!h || !h->privateData || !buf || size <= 0) {
119                 debug_error(DEBUG, "invalid para\n");
120                 return MMFILE_UTIL_FAIL;
121         }
122
123         mmapHandle = h->privateData;
124
125         c = mmapHandle->ptr + mmapHandle->offset;
126
127         if (mmapHandle->state != EOF) {
128                 len = size;
129                 if (len + mmapHandle->offset > mmapHandle->size) {
130                         len = mmapHandle->size - mmapHandle->offset;
131                 }
132         } else {
133                 return 0;
134         }
135
136         memcpy(buf, c, len);
137
138         mmapHandle->offset += len;
139
140         if (mmapHandle->offset == mmapHandle->size) {
141                 mmapHandle->state = EOF;
142         }
143
144         return len;
145 }
146
147 static int mmf_mmap_write(MMFileIOHandle *h, unsigned char *buf, int size)
148 {
149         MMFMMapIOHandle *mmapHandle = NULL;
150         unsigned char *c = NULL;
151         int len = 0;
152
153         if (!h || !h->privateData || !buf) {
154                 debug_error(DEBUG, "invalid para\n");
155                 return MMFILE_UTIL_FAIL;
156         }
157
158         mmapHandle = h->privateData;
159
160         c = mmapHandle->ptr + mmapHandle->offset;
161
162         if (mmapHandle->state != EOF) {
163                 len = size;
164                 if (len + mmapHandle->offset > mmapHandle->size) {
165                         len = mmapHandle->size - mmapHandle->offset;
166                 }
167         } else {
168                 return 0;
169         }
170
171         memcpy(c, buf, len);
172
173         mmapHandle->offset += len;
174
175         if (mmapHandle->offset == mmapHandle->size) {
176                 mmapHandle->state = EOF;
177         }
178
179         return len;
180 }
181
182
183 static int64_t mmf_mmap_seek(MMFileIOHandle *h, int64_t pos, int whence)
184 {
185         MMFMMapIOHandle *mmapHandle = NULL;
186         long tmp_offset = 0;
187
188         if (!h || !h->privateData) {
189                 debug_error(DEBUG, "invalid para\n");
190                 return MMFILE_UTIL_FAIL;
191         }
192
193         mmapHandle = h->privateData;
194
195         switch (whence) {
196         case SEEK_SET:
197                 tmp_offset = 0 + pos;
198                 break;
199         case SEEK_CUR:
200                 tmp_offset = mmapHandle->offset + pos;
201                 break;
202         case SEEK_END:
203                 tmp_offset = mmapHandle->size + pos;
204                 break;
205         default:
206                 return MMFILE_UTIL_FAIL;
207         }
208
209         /*check validation*/
210         if (tmp_offset < 0) {
211                 debug_error(DEBUG, "invalid file offset\n");
212                 return MMFILE_UTIL_FAIL;
213         }
214
215         /*set */
216         mmapHandle->state = (tmp_offset >= mmapHandle->size) ? EOF : !EOF;
217         mmapHandle->offset = tmp_offset;
218
219         return mmapHandle->offset;
220 }
221
222
223 static long long mmf_mmap_tell(MMFileIOHandle *h)
224 {
225         MMFMMapIOHandle *mmapHandle = NULL;
226
227         if (!h || !h->privateData) {
228                 debug_error(DEBUG, "invalid para\n");
229                 return MMFILE_UTIL_FAIL;
230         }
231
232         mmapHandle = h->privateData;
233
234         return mmapHandle->offset;
235 }
236
237 static int mmf_mmap_close(MMFileIOHandle *h)
238 {
239         MMFMMapIOHandle *mmapHandle = NULL;
240
241         if (!h || !h->privateData) {
242                 debug_error(DEBUG, "invalid para\n");
243                 return MMFILE_UTIL_FAIL;
244         }
245
246         mmapHandle = h->privateData;
247
248         if (mmapHandle) {
249                 if (mmapHandle->ptr) {
250                         munmap(mmapHandle->ptr, mmapHandle->size);
251                 }
252
253                 if (mmapHandle->fd > 2) {
254                         close(mmapHandle->fd);
255                 }
256
257                 mmfile_free(mmapHandle);
258         }
259
260         h->privateData = NULL;
261
262         return MMFILE_UTIL_SUCCESS;
263 }
264
265
266 MMFileIOFunc mmfile_mmap_io_handler = {
267         "mmap",
268         mmf_mmap_open,
269         mmf_mmap_read,
270         mmf_mmap_write,
271         mmf_mmap_seek,
272         mmf_mmap_tell,
273         mmf_mmap_close,
274         NULL
275 };