Loss some precision while cast from 8 byte long to double
[platform/core/multimedia/media-server.git] / src / common / media-common-utils.c
1 /*
2  * Media Server
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.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 #include <sys/types.h>
23 #include <fcntl.h>
24 #include <vconf.h>
25 #include <sys/statvfs.h>
26 #include <sys/stat.h>
27
28 #ifdef _USE_TVPD_MODE
29 #include <sys/prctl.h>
30 #endif
31 #include <system_info.h>
32 #include <device/power.h>
33
34 #ifndef _USE_DEVICED_DBUS
35 #include <usb-device.h>
36 #endif
37
38 #include "media-util.h"
39 #include "media-server-ipc.h"
40 #include "media-common-dbg.h"
41 #include "media-common-system.h"
42 #include "media-common-utils.h"
43
44 bool ms_config_get_int(const char *key, int *value)
45 {
46         int err;
47
48         if (!key || !value) {
49                 MS_DBG_ERR("Arguments key or value is NULL");
50                 return false;
51         }
52
53         err = vconf_get_int(key, value);
54         if (err == VCONF_OK)
55                 return true;
56
57         MS_DBG_ERR("Error code: %d", err);
58
59         return false;
60 }
61
62 bool ms_config_set_int(const char *key, int value)
63 {
64         int err;
65
66         if (!key) {
67                 MS_DBG_ERR("Arguments key is NULL");
68                 return false;
69         }
70
71         err = vconf_set_int(key, value);
72         if (err == VCONF_OK)
73                 return true;
74
75         MS_DBG_ERR("Error code: %d", err);
76
77         return false;
78 }
79
80 bool ms_config_get_str(const char *key, char **value)
81 {
82         char *res = NULL;
83
84         if (key == NULL || value == NULL) {
85                 MS_DBG_ERR("Arguments key or value is NULL");
86                 return false;
87         }
88
89         res = vconf_get_str(key);
90         if (MS_STRING_VALID(res)) {
91                 *value = g_strdup(res);
92                 MS_SAFE_FREE(res);
93                 return true;
94         }
95
96         return false;
97 }
98
99 int ms_get_remain_space(uint64_t *free_space)
100 {
101         int ret = MS_MEDIA_ERR_NONE;
102         const char *path = "/opt";
103         struct statvfs s;
104
105         ret = statvfs(path, &s);
106         if (ret != 0) {
107                 MS_DBG_ERR("statvfs failed[%d]", ret);
108                 MS_DBG_STRERROR();
109                 return MS_MEDIA_ERR_INTERNAL;
110         }
111
112         /* f_bsize:unsigned long, f_bavail:fsblkcnt_t(unsigned long) */
113         *free_space = (uint64_t)s.f_bsize * (uint64_t)s.f_bavail;
114
115         return MS_MEDIA_ERR_NONE;
116 }
117
118 #ifdef _USE_TVPD_MODE
119 bool ms_is_support_pvr(void)
120 {
121         bool bSupportPVR = false;
122         if (system_info_get_custom_bool("com.samsung/featureconf/pvr.pvr_support", &bSupportPVR) != SYSTEM_INFO_ERROR_NONE) {
123                 MS_DBG_ERR("Get PVR Support failed");
124                 return false;
125         }
126
127         MS_DBG("PVR Support : [%d]", bSupportPVR);
128
129         return bSupportPVR;
130 }
131 #endif
132
133 bool ms_is_valid_symlink(const char *path)
134 {
135 #ifdef _USE_TVPD_MODE
136         return false;
137 #else
138         g_autofree char *real_path = realpath(path, NULL);
139
140         if (!real_path)
141                 return false;
142
143         return (g_strcmp0(real_path, MEDIA_SHARE_PATH) == 0);
144 #endif
145 }
146
147 int ms_check_file_path(const char *file_path, uid_t uid)
148 {
149         ms_user_storage_type_e storage_type = -1;
150         int ret = MS_MEDIA_ERR_NONE;
151
152         if (!MS_STRING_VALID(file_path)) {
153                 MS_DBG_ERR("Invalid path");
154                 return MS_MEDIA_ERR_INVALID_PARAMETER;
155         }
156
157         ret = ms_user_get_storage_type(uid, file_path, &storage_type);
158         MS_DBG_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
159
160         if (!g_file_test(file_path, G_FILE_TEST_IS_REGULAR)) {
161                 MS_DBG_SERR("g_file_test fail [%s]", file_path);
162                 return MS_MEDIA_ERR_INVALID_PARAMETER;
163         }
164
165         return MS_MEDIA_ERR_NONE;
166 }
167
168 int ms_check_ignore_dir(const char *full_path, uid_t uid)
169 {
170         int ret = MS_MEDIA_ERR_NONE;
171         char *dir_path = NULL;
172         char *next = NULL;
173         int next_pos = 0;
174
175         ret = ms_check_file_path(full_path, uid);
176         MS_DBG_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret);
177
178         if (MS_STRING_VALID(MEDIA_ROOT_PATH_USB) && !strncmp(full_path, MEDIA_ROOT_PATH_USB, strlen(MEDIA_ROOT_PATH_USB))) {
179                 next_pos = strlen(MEDIA_ROOT_PATH_USB) + 1;
180         } else {
181                 ret = ms_user_get_internal_root_path(uid, &dir_path);
182                 MS_DBG_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "ms_user_get_internal_root_path() fail");
183
184                 next_pos = strlen(dir_path);
185                 g_free(dir_path);
186                 dir_path = NULL;
187         }
188
189         while ((next = strstr(full_path + next_pos, "/"))) {
190                 next_pos = (next - full_path);
191                 dir_path = g_strndup(full_path, next_pos);
192                 next_pos++;
193
194                 ret = ms_check_scan_ignore(dir_path, uid);
195                 g_free(dir_path);
196                 if (ret != MS_MEDIA_ERR_NONE)
197                         break;
198         }
199
200         return ret;
201 }
202
203 int ms_check_scan_ignore(char * path, uid_t uid)
204 {
205         int ret = MS_MEDIA_ERR_NONE;
206         const char *ignore_file = ".scan_ignore";
207         char *tmp_path = NULL;
208         char *org_path = NULL;
209         char ignore_path[MS_FILE_PATH_LEN_MAX] = {0, };
210
211 #ifndef _USE_TVPD_MODE
212         char replace[MS_FILE_PATH_LEN_MAX] = {0, };
213         char *mediashared = NULL;
214 #endif
215
216         /* Check for symbolic link */
217         tmp_path = realpath(path, NULL);
218         /* Get trimmed path */
219         org_path = g_canonicalize_filename(path, NULL);
220
221 #ifdef _USE_TVPD_MODE
222         if (g_strcmp0(tmp_path, org_path) != 0) {
223                 MS_SAFE_FREE(tmp_path);
224                 g_free(org_path);
225                 MS_DBG_ERR("symbolic link(directory)");
226                 return MS_MEDIA_ERR_INVALID_PARAMETER;
227         }
228 #else
229         if (g_str_has_prefix(tmp_path, MEDIA_SHARE_PATH)) {
230                 ms_user_get_mediashared_path(uid, &mediashared);
231                 snprintf(replace, MS_FILE_PATH_LEN_MAX, "%s%s", mediashared, tmp_path + strlen(MEDIA_SHARE_PATH));
232                 MS_SAFE_FREE(mediashared);
233                 if (g_strcmp0(replace, org_path) != 0) {
234                         MS_SAFE_FREE(tmp_path);
235                         g_free(org_path);
236                         MS_DBG_ERR("symbolic link(directory)");
237                         return MS_MEDIA_ERR_INVALID_PARAMETER;
238                 }
239         } else {
240                 if (g_strcmp0(tmp_path, org_path) != 0) {
241                         MS_SAFE_FREE(tmp_path);
242                         g_free(org_path);
243                         MS_DBG_ERR("symbolic link(directory)");
244                         return MS_MEDIA_ERR_INVALID_PARAMETER;
245                 }
246         }
247 #endif
248         MS_SAFE_FREE(tmp_path);
249         g_free(org_path);
250
251         if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
252                 snprintf(ignore_path, sizeof(ignore_path), "%s/%s", path, ignore_file);
253
254                 if (g_file_test(ignore_path, G_FILE_TEST_EXISTS)) {
255                         MS_DBG_WARN("scan ignore file exist [%s]", ignore_path);
256                         return MS_MEDIA_ERR_INVALID_PARAMETER;
257                 }
258         } else {
259                 MS_DBG_ERR("g_file_test fails[%s]", path);
260                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
261
262                 if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
263                         MS_DBG_ERR("Fail to get USB path");
264                         return ret;
265                 }
266
267                 if (strstr(path, MEDIA_ROOT_PATH_USB) != NULL) {
268                         /*if the directory does not exist, check the device is unmounted*/
269                         if (!ms_storage_mount_status(path)) {
270                                 MS_DBG_ERR("Device is unmounted[%s]", path);
271                                 return MS_MEDIA_ERR_USB_UNMOUNTED;
272                         }
273                 }
274         }
275
276         return ret;
277 }
278
279 #ifndef _USE_DEVICED_DBUS
280
281 typedef struct storage_result {
282         char *storage_path;
283         bool result;
284 } storage_result_s;
285
286 static void __ms_check_mount_status(usb_device_h usb_device, void *user_data)
287 {
288         storage_result_s *data = (storage_result_s *)user_data;
289         char *mount_path = NULL;
290
291         mount_path = usb_device_get_mountpath(usb_device);
292         if (!mount_path)
293                 return;
294
295         MS_DBG_SWARN("mount_path [%s]", mount_path);
296         data->result = (g_strcmp0(mount_path, data->storage_path) == 0);
297 }
298 #endif
299
300 bool ms_storage_mount_status(const char *start_path)
301 {
302         bool ret = false;
303 #ifndef _USE_DEVICED_DBUS
304         storage_result_s res = {0, };
305         char *remain_path = NULL;
306         int remain_len = 0;
307
308         remain_path = strstr(start_path + strlen(MEDIA_ROOT_PATH_USB) + 1, "/");
309         if (remain_path != NULL)
310                 remain_len = strlen(remain_path);
311
312         res.storage_path = g_strndup(start_path, strlen(start_path) - remain_len);
313
314         MS_DBG_SWARN("storage_path [%s]", res.storage_path);
315
316         usb_mass_storage_foreach(__ms_check_mount_status, &res);
317         g_free(res.storage_path);
318         ret = res.result;
319
320         if (ret)
321                 MS_DBG_SWARN("start path is mounted [%s]", start_path);
322 #endif
323         return ret;
324 }
325
326 int ms_set_db_status(ms_db_status_type_t status, ms_user_storage_type_e storage_type)
327 {
328         int ret = MS_MEDIA_ERR_NONE;
329
330         if (status == MS_DB_UPDATING) {
331                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING))
332                                 goto ERROR;
333
334                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
335                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADING))
336                                 goto ERROR;
337                 }
338         } else {
339                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATED))
340                                 goto ERROR;
341
342                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
343                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADED))
344                                 goto ERROR;
345                 }
346         }
347
348         ret = ms_set_power_mode(status);
349         if (ret != MS_MEDIA_ERR_NONE)
350                 MS_DBG_ERR("ms_set_power_mode fail");
351
352         return ret;
353 ERROR:
354         MS_DBG_ERR("ms_config_set_int failed");
355         return MS_MEDIA_ERR_INTERNAL;
356 }
357
358 int ms_set_power_mode(ms_db_status_type_t status)
359 {
360         int res = MS_MEDIA_ERR_NONE;
361         int err;
362
363         switch (status) {
364         case MS_DB_UPDATING:
365                 err = device_power_request_lock(POWER_LOCK_CPU, 0);
366                 if (err != 0)
367                         res = MS_MEDIA_ERR_INTERNAL;
368                 break;
369         case MS_DB_UPDATED:
370                 err = device_power_release_lock(POWER_LOCK_CPU);
371                 if (err != 0)
372                         res = MS_MEDIA_ERR_INTERNAL;
373                 break;
374         default:
375                 MS_DBG_ERR("Unacceptable type : %d", status);
376                 break;
377         }
378
379         return res;
380 }
381
382 void ms_trim_dir_path(char *dir_path)
383 {
384         /* need implementation */
385         /* if dir_path is not NULL terminated, this function will occure crash */
386         int len = strlen(dir_path);
387
388         if (dir_path[len -1] == '/')
389                 dir_path[len -1] = '\0';
390 }
391
392 int ms_check_size_mediadb(uid_t uid, uint64_t *db_size)
393 {
394         int ret = MS_MEDIA_ERR_NONE;
395         char *db_path = NULL;
396         struct stat buf;
397
398         ret = ms_user_get_media_db_path(uid, &db_path);
399
400         if (stat(db_path, &buf) == 0) {
401                 *db_size = (uint64_t)buf.st_size;
402         } else {
403                 MS_DBG_STRERROR("stat failed");
404                 ret = MS_MEDIA_ERR_INTERNAL;
405         }
406
407         g_free(db_path);
408
409         return ret;
410 }
411
412 #ifdef _USE_TVPD_MODE
413 #define PROC_OOM_SCORE_ADJ_PATH         "/proc/%d/oom_score_adj"
414 #define VIP_OOM_SCORE_ADJ                       (-1000)
415 #define PROC_NAME_MAX 1024
416 #define PROC_BUF_MAX 64
417
418 static int ms_get_cmdline_from_proc(pid_t pid, char *cmdline)
419 {
420         char buf[PROC_BUF_MAX];
421         char cmdline_buf[PROC_NAME_MAX];
422         char *filename;
423         FILE *fp;
424
425         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
426         fp = fopen(buf, "r");
427         if (fp == NULL)
428                 return MS_MEDIA_ERR_INTERNAL;
429
430         if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
431                 fclose(fp);
432                 return MS_MEDIA_ERR_INTERNAL;
433         }
434         fclose(fp);
435
436         filename = strrchr(cmdline_buf, '/');
437         if (filename == NULL)
438                 filename = cmdline_buf;
439         else
440                 filename = filename + 1;
441
442         SAFE_STRLCPY(cmdline, filename, PROC_NAME_MAX);
443
444         return MS_MEDIA_ERR_NONE;
445 }
446
447 int ms_set_vip_process(void)
448 {
449         char buf[100] = {0};
450         int id = 0;
451         static pid_t pid = 0;
452         static char process_name[PROC_NAME_MAX] = {0};
453         static char *appid = NULL;
454
455         /* Get Pid */
456         pid = getpid();
457         if (ms_get_cmdline_from_proc(pid, process_name)) {
458                 MS_DBG_ERR("%s: Read process name failed pid[%d]", __func__, pid);
459                 return MS_MEDIA_ERR_INTERNAL;
460         }
461         appid = process_name;
462
463         MS_DBG("Process name[%s]:Pid[%d]", appid, pid);
464
465         if (prctl(PR_GET_DUMPABLE) == 0)
466                 prctl(PR_SET_DUMPABLE, 1);
467
468         snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
469         id = open(buf, O_WRONLY, 0777);
470         if (id < 0) {
471                 MS_DBG_ERR("fopen %s failed errno:%d", buf, errno);
472                 return MS_MEDIA_ERR_INTERNAL;
473         }
474         snprintf(buf, sizeof(buf), "%d", VIP_OOM_SCORE_ADJ);
475         if (write(id, buf, strlen(buf)) < 0) {
476                 MS_DBG_ERR("write() failed errno=%d", errno);
477                 close(id);
478                 return MS_MEDIA_ERR_INTERNAL;
479         }
480         close(id);
481         return MS_MEDIA_ERR_NONE;
482 }
483 #endif