Tizen 2.0 Release
[profile/ivi/avsystem.git] / avsys-common.c
1 /*
2  * avsystem
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jonghyuk Choi <jhchoi.choi@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 #include "avsys-common.h"
23 #include "avsys-debug.h"
24 #include "avsys-error.h"
25
26 #include <stdio.h>
27 #include <memory.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <pwd.h>
32 #include <sys/ipc.h>
33 #include <sys/shm.h>
34 #include <time.h>
35
36 #define RETRY_EINTR
37 #include <fcntl.h>
38 #include <semaphore.h>
39
40 void * avsys_malloc(size_t size)
41 {
42         char *allocated;
43         allocated = (char*) malloc(size + 12);
44
45         if(!allocated) {
46                 return NULL;
47         }
48         memset(allocated, 0, size+8);
49         memcpy(allocated, AVSYS_MAGIC_START, 4);
50         (*(int*)(allocated+4)) = size;
51         memcpy(allocated+size+8, AVSYS_MAGIC_END, 4);
52
53         return (void*)(allocated + 8);
54 }
55
56 void avsys_free(void *ptr)
57 {
58         char *allocated = (char*)ptr;
59         if(allocated) {
60                 if(avsys_mem_check(allocated)) {
61                         free(allocated-8);
62                 }
63         }
64 }
65
66 int avsys_create_shm(const avsys_shm_param_t* param)
67 {
68         int shmid = -1;
69         int *segptr = NULL;
70         key_t key;
71
72         if (!param) {
73                 return AVSYS_STATE_ERR_NULL_POINTER;
74         }
75         if (param->size < 1 || param->key_path == NULL || access(param->key_path, R_OK) != 0) {
76                 return AVSYS_STATE_ERR_INVALID_VALUE;
77         }
78
79         key = ftok(param->key_path, param->key_prefix);
80
81         if ((shmid = shmget(key, param->size, IPC_CREAT|IPC_EXCL|0666)) == -1) {
82                 if (errno == EEXIST) {
83                         avsys_error(AVAUDIO,"Already initialized.\n");
84                         if ((shmid = shmget(key, param->size, 0)) == -1) {
85                                 avsys_error(AVAUDIO, "Initialization fail.\n");
86                         } else {
87                                 segptr = shmat(shmid, 0, 0);
88                                 avsys_assert_r(segptr != NULL);
89                         }
90                 } else {
91                         if(errno == EACCES)
92                                 avsys_error_r(AVAUDIO, "Require ROOT permission.\n");
93                         else if(errno == ENOMEM)
94                                 avsys_critical_r(AVAUDIO, "System memory is empty.\n");
95                         else if(errno == ENOSPC)
96                                 avsys_critical_r(AVAUDIO, "Resource is empty.\n");
97                 }
98         } else {
99                 shmctl(shmid, SHM_LOCK, 0);
100                 segptr = shmat(shmid, 0, 0);
101                 avsys_assert_r(segptr != NULL);
102                 memset((void*)segptr, 0, param->size);
103         }
104
105         if (shmid != -1) {
106                 return AVSYS_STATE_SUCCESS;
107         } else {
108                 return AVSYS_STATE_ERR_INTERNAL;
109         }
110 }
111
112 int avsys_remove_shm(const avsys_shm_param_t* param)
113 {
114         int shmid = -1;
115         key_t key;
116
117         if (!param) {
118                 return AVSYS_STATE_ERR_NULL_POINTER;
119         }
120         if (param->size < 1 || param->key_path == NULL || access(param->key_path, R_OK) != 0) {
121                 return AVSYS_STATE_ERR_INVALID_VALUE;
122         }
123
124         key = ftok(param->key_path, param->key_prefix);
125
126         if ((shmid = shmget(key, param->size, 0)) == -1) {
127                 if(errno == ENOENT)
128                         avsys_error_r(AVAUDIO, "Not initialized.\n");
129                 else if(errno == EACCES)
130                         avsys_error_r(AVAUDIO, "Require ROOT permission.\n");
131                 else if(errno == ENOSPC)
132                         avsys_critical_r(AVAUDIO, "Resource is empty.\n");
133         } else {
134                 avsys_assert_r(shmctl(shmid, IPC_RMID, 0) == 0);
135         }
136
137         if (shmid != -1) {
138                 return AVSYS_STATE_SUCCESS;
139         } else {
140                 return AVSYS_STATE_ERR_INTERNAL;
141         }
142 }
143
144 void* avsys_get_shm(const avsys_shm_param_t* param)
145 {
146         int shmid = -1;
147         void *ptr = NULL;
148         key_t key;
149
150         if (!param) {
151                 return NULL;
152         }
153         if (param->size < 1 || param->key_path == NULL || access(param->key_path, R_OK) != 0) {
154                 return NULL;
155         }
156
157         key = ftok(param->key_path, param->key_prefix);
158
159         if ((shmid = shmget(key, param->size, 0)) == -1) {
160                 if(errno == ENOENT)
161                         avsys_error_r(AVAUDIO, "Not initialized.\n");
162                 else if(errno == EACCES)
163                         avsys_error_r(AVAUDIO, "Require ROOT permission.\n");
164                 else if(errno == ENOSPC)
165                         avsys_critical_r(AVAUDIO, "Resource is empty.\n");
166                 return NULL;
167         }
168
169         ptr = shmat(shmid, 0, 0);
170         if(ptr == (void*)-1) {
171                 if(errno == EACCES)
172                         avsys_error_r(AVAUDIO,"no permission\n");
173                 else if(errno == EINVAL)
174                         avsys_error_r(AVAUDIO,"invalid shmid\n");
175                 else if(errno == ENOMEM)
176                         avsys_error_r(AVAUDIO,"can not allocate memory\n");
177                 else
178                         avsys_error_r(AVAUDIO,"shmat() failed %d\n", errno);
179                 ptr = NULL;
180         }
181         return ptr;
182 }
183
184 int avsys_create_sync(const avsys_sync_param_t *param)
185 {
186         sem_t *sem = NULL;
187         sem = sem_open(param->key_path, O_CREAT, 0666, 1);
188         if (sem == SEM_FAILED) {
189                 switch(errno)
190                 {
191                 case EACCES:
192                         avsys_error(AVAUDIO,
193                                         "The semaphore already exist, but caller does not have permission %s\n",param->key_path);
194                         break;
195                 case ENOMEM:
196                         avsys_error(AVAUDIO,"Insufficient memory in %s (%d)\n",__func__,__LINE__);
197                         break;
198                 case ENFILE:
199                         avsys_error(AVAUDIO,"Too many open files in system %s (%d)\n",__func__,__LINE__);
200                         break;
201                 default:
202                         avsys_critical(AVAUDIO, "Semaphore create fail! (name:%s, errno %d)\n", param->key_path, errno);
203                         break;
204                 }
205                 return AVSYS_STATE_ERR_INTERNAL;
206         }
207         return AVSYS_STATE_SUCCESS;
208 }
209
210 int avsys_remove_sync(const avsys_sync_param_t *param)
211 {
212         int err = 0;
213
214         err = sem_unlink(param->key_path);
215         if (err == -1) {
216                 avsys_critical(AVAUDIO, "Semaphore destroy Fail! (name:%s, errno %d)\n", param->key_path, errno);
217                 return AVSYS_STATE_ERR_INTERNAL;
218         }
219
220         return AVSYS_STATE_SUCCESS;
221 }
222
223 int avsys_lock_sync(const avsys_sync_param_t *param)
224 {
225         sem_t *sem = NULL;
226         int ret;
227         int err = AVSYS_STATE_SUCCESS;
228         struct timespec wait_time;
229
230         sem = sem_open(param->key_path, O_CREAT, 0666, 1);
231         if (sem == SEM_FAILED) {
232                 avsys_critical(AVAUDIO, "Semaphore open Fail! (name:%s, errno %d)\n", param->key_path, errno);
233                 return AVSYS_STATE_ERR_INTERNAL;
234         }
235 retry_lock:
236         wait_time.tv_sec = (long int)(time(NULL)) + LOCK_TIMEOUT_SEC;
237         wait_time.tv_nsec = 0;
238         ret = sem_timedwait(sem, &wait_time);
239         if(ret == -1) {
240                 switch(errno)
241                 {
242                 case EINTR:
243                         avsys_critical(AVAUDIO, "Lock RETRY LOCK\n");
244                         goto retry_lock;
245                         break;
246                 case EINVAL:
247                         avsys_critical(AVAUDIO, "Invalid semaphore\n");
248                         err = AVSYS_STATE_ERR_INTERNAL;
249                         break;
250                 case EAGAIN:
251                         avsys_critical(AVAUDIO, "EAGAIN\n");
252                         err = AVSYS_STATE_ERR_INTERNAL;
253                         break;
254                 case ETIMEDOUT:
255                         avsys_critical(AVAUDIO, "sem_wait leached %d seconds timeout.\n", LOCK_TIMEOUT_SEC);
256                         {
257                                 /* Recovery of sem_wait lock....in abnormal condition */
258                                 int sem_value = -1;
259                                 if (0 == sem_getvalue(sem, &sem_value)) {
260                                         avsys_critical(AVAUDIO,"%s sem value is %d\n",param->key_path, sem_value);
261                                         if (sem_value == 0) {
262                                                 ret = sem_post(sem);
263                                                 if (ret == -1) {
264                                                         avsys_critical(AVAUDIO,"sem_post error %s : %d\n", param->key_path, sem_value);
265                                                 } else {
266                                                         avsys_critical_r(AVAUDIO,"lock recovery success...try lock again\n");
267                                                         goto retry_lock;
268                                                 }
269                                         } else {
270                                                 avsys_critical(AVAUDIO,"sem value is not 0. but failed sem_timedwait so retry.. : %s\n",param->key_path);
271                                                 usleep(5);
272                                                 goto retry_lock;
273                                         }
274                                 } else {
275                                         avsys_critical(AVAUDIO,"sem_getvalue failed : %s\n",param->key_path);
276                                 }
277                         }
278                         err = AVSYS_STATE_ERR_INTERNAL;
279                         break;
280                 }
281         }
282         sem_close(sem);
283         return err;
284 }
285
286 int avsys_unlock_sync(const avsys_sync_param_t *param)
287 {
288         sem_t *sem = NULL;
289         int ret;
290         int err = AVSYS_STATE_SUCCESS;
291
292         sem = sem_open(param->key_path, O_CREAT, 0666, 1);
293         if (sem == SEM_FAILED) {
294                 avsys_critical(AVAUDIO, "Semaphore open Fail! (name:%s, errno %d)\n", param->key_path, errno);
295                 return AVSYS_STATE_ERR_INTERNAL;
296         }
297
298         ret = sem_post(sem);
299         if (ret == -1) {
300                 avsys_critical(AVAUDIO, "UNLOCK FAIL\n");
301                 err = AVSYS_STATE_ERR_INTERNAL;
302         }
303
304         sem_close(sem);
305         return err;
306 }
307
308 int avsys_check_root_privilege()
309 {
310         uid_t uid;
311         uid = getuid();
312         if(0 != uid) {
313                 /* code from man page */
314                 struct passwd pwd;
315                 struct passwd *result;
316                 char *buf;
317                 size_t bufsize;
318                 int s = 0;
319
320                 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
321                 if (bufsize == -1)                /* Value was indeterminate */
322                    bufsize = 16384;             /* Should be more than enough */
323
324                 buf = malloc(bufsize);
325                 if (buf == NULL) {
326                    perror("malloc");
327                 } else {
328                         s= getpwuid_r (uid, &pwd, buf, bufsize, &result);
329                         if (result == NULL) {
330                                 if (s == 0)
331                                    printf("Not found\n");
332                                 else {
333                                    errno = s;
334                                    perror("getpwnam_r");
335                                 }
336                         } else {
337                                 avsys_error_r(AVAUDIO,"super user privilege check failed (%s)\n", pwd.pw_name);
338                         }
339                         free (buf);
340                 }
341                 return AVSYS_STATE_ERR_PRIVILEGE;
342         }
343         return AVSYS_STATE_SUCCESS;
344 }
345
346 int avsys_dump_sync (const avsys_sync_param_t *param)
347 {
348         int err = AVSYS_STATE_SUCCESS;
349
350         sem_t *sem = NULL;
351         int ret;
352         int sem_value = -1;
353
354         sem = sem_open(param->key_path, O_CREAT, 0666, 1);
355         if (sem == SEM_FAILED) {
356                 avsys_critical(AVAUDIO, "Semaphore open Fail! (name:%s, errno %d)\n", param->key_path, errno);
357                 return AVSYS_STATE_ERR_INTERNAL;
358         }
359
360         if(0 == sem_getvalue(sem, &sem_value)) {
361                 fprintf (stdout, " * [%d] sem value for [%s]\n", sem_value, param->key_path);
362         } else {
363                 avsys_critical(AVAUDIO,"sem_getvalue failed : %s\n",param->key_path);
364         }
365
366         sem_close(sem);
367         return err;
368 }