Use FMS(Feature Management System) key instead of system key
[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 _SET_VIP_PROCESS
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 int ms_strappend(char *res, const int size, const char *pattern, const char *str1, const char *str2)
45 {
46         int len = 0;
47         int real_size = size - 1;
48
49         if (!res || !pattern || !str1 || !str2)
50                 return MS_MEDIA_ERR_INVALID_PARAMETER;
51
52         if (real_size < (int)(strlen(str1) + strlen(str2)))
53                 return MS_MEDIA_ERR_INVALID_PARAMETER;
54
55         len = snprintf(res, real_size, pattern, str1, str2);
56         if (len < 0)
57                 return MS_MEDIA_ERR_INVALID_PARAMETER;
58
59         res[len] = '\0';
60
61         return MS_MEDIA_ERR_NONE;
62 }
63
64 bool ms_config_get_int(const char *key, int *value)
65 {
66         int err;
67
68         if (!key || !value) {
69                 MS_DBG_ERR("Arguments key or value is NULL");
70                 return false;
71         }
72
73         err = vconf_get_int(key, value);
74         if (err == VCONF_OK)
75                 return true;
76
77         MS_DBG_ERR("Error code: %d", err);
78
79         return false;
80 }
81
82 bool ms_config_set_int(const char *key, int value)
83 {
84         int err;
85
86         if (!key) {
87                 MS_DBG_ERR("Arguments key is NULL");
88                 return false;
89         }
90
91         err = vconf_set_int(key, value);
92         if (err == VCONF_OK)
93                 return true;
94
95         MS_DBG_ERR("Error code: %d", err);
96
97         return false;
98 }
99
100 bool ms_config_get_str(const char *key, char **value)
101 {
102         char *res = NULL;
103
104         if (key == NULL || value == NULL) {
105                 MS_DBG_ERR("Arguments key or value is NULL");
106                 return false;
107         }
108
109         res = vconf_get_str(key);
110         if (MS_STRING_VALID(res)) {
111                 *value = g_strdup(res);
112                 MS_SAFE_FREE(res);
113                 return true;
114         }
115
116         return false;
117 }
118
119 int ms_get_remain_space(double *free_space)
120 {
121         int ret = MS_MEDIA_ERR_NONE;
122         const char *path = "/opt";
123         struct statvfs s;
124
125         ret = statvfs(path, &s);
126         if (ret != 0) {
127                 MS_DBG_ERR("statvfs failed[%d]", ret);
128                 MS_DBG_STRERROR();
129                 return MS_MEDIA_ERR_INTERNAL;
130         }
131
132         /* f_bsize:unsigned long, f_bavail:fsblkcnt_t(unsigned long) */
133         *free_space = (double)(s.f_bsize * s.f_bavail);
134
135         return MS_MEDIA_ERR_NONE;
136 }
137
138 #ifdef _USE_RECORDED_CONTENT
139 bool ms_is_support_pvr(void)
140 {
141         bool bSupportPVR = false;
142         if (system_info_get_custom_bool("com.samsung/featureconf/pvr.pvr_support", &bSupportPVR) != SYSTEM_INFO_ERROR_NONE) {
143                 MS_DBG_ERR("Get PVR Support failed");
144                 return false;
145         }
146
147         MS_DBG("PVR Support : [%d]", bSupportPVR);
148
149         return bSupportPVR;
150 }
151 #endif
152
153 #ifdef _USE_SENIOR_MODE
154 bool ms_is_support_senior_mode(void)
155 {
156         bool bSupportSeniorMode = false;
157
158         if (system_info_get_value_bool(SYSTEM_INFO_KEY_GET_SENIOR_MODE_SUPPORTED, &bSupportSeniorMode) != SYSTEM_INFO_ERROR_NONE) {
159                 MS_DBG_ERR("Get senior mode support failed");
160                 return false;
161         }
162
163         MS_DBG("Senior mode support : [%d]", bSupportSeniorMode);
164
165         return bSupportSeniorMode;
166 }
167 #endif
168
169 int ms_check_file_path(const char *file_path, uid_t uid)
170 {
171         ms_user_storage_type_e storage_type = -1;
172         int ret = MS_MEDIA_ERR_NONE;
173
174         if (!MS_STRING_VALID(file_path)) {
175                 MS_DBG_ERR("Invalid path");
176                 return MS_MEDIA_ERR_INVALID_PARAMETER;
177         }
178
179         ret = ms_user_get_storage_type(uid, file_path, &storage_type);
180         MS_DBG_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
181
182         if (!g_file_test(file_path, G_FILE_TEST_IS_REGULAR)) {
183                 MS_DBG_SERR("g_file_test fail [%s]", file_path);
184                 return MS_MEDIA_ERR_INVALID_PARAMETER;
185         }
186
187         return MS_MEDIA_ERR_NONE;
188 }
189
190 int ms_check_ignore_dir(const char *full_path, uid_t uid)
191 {
192         int ret = MS_MEDIA_ERR_NONE;
193         char *dir_path = NULL;
194         char *leaf_path = NULL;
195         char *usr_path = NULL;
196
197         ret = ms_check_file_path(full_path, uid);
198         if (ret != MS_MEDIA_ERR_NONE) {
199                 MS_DBG_ERR("invalid path : %s", full_path);
200                 return MS_MEDIA_ERR_INVALID_PARAMETER;
201         }
202
203         dir_path = g_path_get_dirname(full_path);
204         if (dir_path == NULL || strcmp(dir_path, ".") == 0) {
205                 MS_DBG_ERR("getting directory path is failed : %s", full_path);
206                 g_free(dir_path);
207                 return MS_MEDIA_ERR_INVALID_PARAMETER;
208         }
209
210         ret = ms_user_get_internal_root_path(uid, &usr_path);
211         if (ret != MS_MEDIA_ERR_NONE) {
212                 MS_DBG_ERR("ms_user_get_internal_root_path() fail");
213                 g_free(dir_path);
214                 return MS_MEDIA_ERR_INTERNAL;
215         }
216
217         while (1) {
218                 if (ms_check_scan_ignore(dir_path, uid) != MS_MEDIA_ERR_NONE) {
219                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
220                         break;
221                 }
222
223 #ifdef _USE_SENIOR_MODE
224                 if (ms_is_support_senior_mode()) {
225                         if (strcmp(dir_path, MEDIA_ROOT_PATH_SENIOR_MODE) == 0)
226                                 break;
227                 }
228 #endif
229                 if (strcmp(dir_path, usr_path) == 0)
230                         break;
231                 else if (MS_STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && (strncmp(dir_path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0))
232                         break;
233                 else if (MS_STRING_VALID(MEDIA_ROOT_PATH_USB) && (strncmp(dir_path, MEDIA_ROOT_PATH_USB, strlen(MEDIA_ROOT_PATH_USB)) == 0))
234                         break;
235                 else if (MS_STRING_VALID(MEDIA_ROOT_PATH_DISC) && (strncmp(dir_path, MEDIA_ROOT_PATH_DISC, strlen(MEDIA_ROOT_PATH_DISC)) == 0))
236                         break;
237
238                 leaf_path = strrchr(dir_path, '/');
239                 if (leaf_path != NULL) {
240                                 int seek_len = leaf_path -dir_path;
241                                 dir_path[seek_len] = '\0';
242                 } else {
243                         MS_DBG_ERR("Fail to find leaf path");
244                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
245                         break;
246                 }
247         }
248
249         g_free(dir_path);
250         g_free(usr_path);
251
252         return ret;
253 }
254
255 static void __ms_trim_path(const char *input_path, char **output_path)
256 {
257         char buf[4096] = {0, };
258         char tmp[4096] = {0, };
259         char *pos = NULL;
260
261         SAFE_STRLCPY(buf, input_path, sizeof(buf));
262
263         while ((pos = strstr(buf, "//")) != NULL) {
264                 memset(tmp, 0, sizeof(tmp));
265                 SAFE_STRLCPY(tmp, buf, pos - buf + 1);
266                 SAFE_STRLCAT(tmp, pos + 1, sizeof(tmp));
267
268                 memset(buf, 0, sizeof(buf));
269                 SAFE_STRLCPY(buf, tmp, sizeof(buf));
270         }
271
272         if (g_str_has_suffix(buf, "/"))
273                 *output_path = g_strndup(buf, strlen(buf) - 1);
274         else
275                 *output_path = g_strdup(buf);
276 }
277
278 int ms_check_scan_ignore(char * path, uid_t uid)
279 {
280         int ret = MS_MEDIA_ERR_NONE;
281         const char *ignore_file = ".scan_ignore";
282         char *tmp_path = NULL;
283         char *org_path = NULL;
284         char ignore_path[MS_FILE_PATH_LEN_MAX] = {0, };
285
286 #ifndef _USE_TVPD_MODE
287         char replace[MS_FILE_PATH_LEN_MAX] = {0, };
288         char *mediashared = NULL;
289 #endif
290
291         /* Check for symbolic link */
292         tmp_path = realpath(path, NULL);
293         /* Get trimmed path */
294         __ms_trim_path(path, &org_path);
295
296 #ifdef _USE_TVPD_MODE
297         if (g_strcmp0(tmp_path, org_path) != 0) {
298                 MS_SAFE_FREE(tmp_path);
299                 g_free(org_path);
300                 MS_DBG_ERR("symbolic link(directory)");
301                 return MS_MEDIA_ERR_INVALID_PARAMETER;
302         }
303 #else
304         if (g_str_has_prefix(tmp_path, MEDIA_SHARE_PATH)) {
305                 ms_user_get_mediashared_path(uid, &mediashared);
306                 snprintf(replace, MS_FILE_PATH_LEN_MAX, "%s%s", mediashared, tmp_path + strlen(MEDIA_SHARE_PATH));
307                 MS_SAFE_FREE(mediashared);
308                 if (g_strcmp0(replace, org_path) != 0) {
309                         MS_SAFE_FREE(tmp_path);
310                         g_free(org_path);
311                         MS_DBG_ERR("symbolic link(directory)");
312                         return MS_MEDIA_ERR_INVALID_PARAMETER;
313                 }
314         } else {
315                 if (g_strcmp0(tmp_path, org_path) != 0) {
316                         MS_SAFE_FREE(tmp_path);
317                         g_free(org_path);
318                         MS_DBG_ERR("symbolic link(directory)");
319                         return MS_MEDIA_ERR_INVALID_PARAMETER;
320                 }
321         }
322 #endif
323         MS_SAFE_FREE(tmp_path);
324         g_free(org_path);
325
326         if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
327                 snprintf(ignore_path, sizeof(ignore_path), "%s/%s", path, ignore_file);
328
329                 if (g_file_test(ignore_path, G_FILE_TEST_EXISTS)) {
330                         MS_DBG_WARN("scan ignore file exist [%s]", ignore_path);
331                         return MS_MEDIA_ERR_INVALID_PARAMETER;
332                 }
333         } else {
334                 MS_DBG_ERR("g_file_test fails[%s]", path);
335                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
336
337                 if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
338                         MS_DBG_ERR("Fail to get USB path");
339                         return ret;
340                 }
341
342                 if (strstr(path, MEDIA_ROOT_PATH_USB) != NULL) {
343                         /*if the directory does not exist, check the device is unmounted*/
344                         if (!ms_storage_mount_status(path)) {
345                                 MS_DBG_ERR("Device is unmounted[%s]", path);
346                                 return MS_MEDIA_ERR_USB_UNMOUNTED;
347                         }
348                 }
349         }
350
351         return ret;
352 }
353
354 bool ms_storage_mount_status(const char* start_path)
355 {
356         bool ret = false;
357 #ifndef _USE_DEVICED_DBUS
358         int count = 0;
359         int err = 0;
360         usb_device_list_h list;
361         usb_device_h device;
362         char *mount_path = NULL;
363
364         char *storage_path = NULL;
365         char *remain_path = NULL;
366         int remain_len = 0;
367
368         remain_path = strstr(start_path+strlen(MEDIA_ROOT_PATH_USB) +1, "/");
369         if (remain_path != NULL)
370                 remain_len = strlen(remain_path);
371
372         storage_path = g_strndup(start_path, strlen(start_path) - remain_len);
373
374         MS_DBG_SWARN("storage_path [%s]", storage_path);
375
376         err = usb_device_get_device_list(USB_MASS_STORAGE, &list);
377         if (err == 0) {
378                 count = usb_device_list_get_count(list);
379                 if (count > 0) {
380                         err = usb_device_list_get_first(list, &device);
381                         if (err != USB_ERROR_LIST_FAILED_TO_GET && device != NULL) {
382                                 mount_path = usb_device_get_mountpath(device);
383                                 if (mount_path != NULL) {
384                                         MS_DBG_SWARN("mount_path [%s]", mount_path);
385                                         if (strlen(mount_path) == strlen(storage_path)) {
386                                                 if (strncmp(mount_path, storage_path, strlen(mount_path)) == 0) {
387                                                         MS_DBG_SWARN("start path is mounted [%s]", start_path);
388                                                         ret = true;
389                                                 }
390                                         }
391                                 }
392                         }
393
394                         if (ret != true) {
395                                 while (usb_device_list_get_next(list, &device) == 0) {
396                                         if (device != NULL) {
397                                                 mount_path = usb_device_get_mountpath(device);
398                                                 if (mount_path != NULL) {
399                                                         MS_DBG_SWARN("mount_path [%s]", mount_path);
400                                                         if (strlen(mount_path) == strlen(storage_path)) {
401                                                                 if (strncmp(mount_path, storage_path, strlen(mount_path)) == 0) {
402                                                                         MS_DBG_SWARN("start path is mounted [%s]", start_path);
403                                                                         ret = true;
404                                                                         break;
405                                                                 }
406                                                         }
407                                                 }
408                                         }
409                                 }
410                         }
411                 }
412
413                 usb_device_free_device_list(list);
414         } else {
415                 MS_DBG_ERR("usb_device_get_device_list falied [%d]", err);
416         }
417
418         g_free(storage_path);
419 #endif
420         return ret;
421 }
422
423 int ms_set_db_status(ms_db_status_type_t status, ms_user_storage_type_e storage_type)
424 {
425         int ret = MS_MEDIA_ERR_NONE;
426
427         if (status == MS_DB_UPDATING) {
428                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING))
429                                 goto ERROR;
430
431                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
432                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADING))
433                                 goto ERROR;
434                 }
435         } else {
436                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATED))
437                                 goto ERROR;
438
439                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
440                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADED))
441                                 goto ERROR;
442                 }
443         }
444
445         ret = ms_set_power_mode(status);
446         if (ret != MS_MEDIA_ERR_NONE)
447                 MS_DBG_ERR("ms_set_power_mode fail");
448
449         return ret;
450 ERROR:
451         MS_DBG_ERR("ms_config_set_int failed");
452         return MS_MEDIA_ERR_INTERNAL;
453 }
454
455 int ms_set_power_mode(ms_db_status_type_t status)
456 {
457         int res = MS_MEDIA_ERR_NONE;
458         int err;
459
460         switch (status) {
461         case MS_DB_UPDATING:
462                 err = device_power_request_lock(POWER_LOCK_CPU, 0);
463                 if (err != 0)
464                         res = MS_MEDIA_ERR_INTERNAL;
465                 break;
466         case MS_DB_UPDATED:
467                 err = device_power_release_lock(POWER_LOCK_CPU);
468                 if (err != 0)
469                         res = MS_MEDIA_ERR_INTERNAL;
470                 break;
471         default:
472                 MS_DBG_ERR("Unacceptable type : %d", status);
473                 break;
474         }
475
476         return res;
477 }
478
479 void ms_trim_dir_path(char *dir_path)
480 {
481         /* need implementation */
482         /* if dir_path is not NULL terminated, this function will occure crash */
483         int len = strlen(dir_path);
484
485         if (dir_path[len -1] == '/')
486                 dir_path[len -1] = '\0';
487 }
488
489 int ms_check_size_mediadb(uid_t uid, double *db_size)
490 {
491         int ret = MS_MEDIA_ERR_NONE;
492         char *db_path = NULL;
493         struct stat buf;
494
495         ret = ms_user_get_media_db_path(uid, &db_path);
496
497         if (stat(db_path, &buf) == 0) {
498                 *db_size = buf.st_size;
499         } else {
500                 MS_DBG_STRERROR("stat failed");
501                 ret = MS_MEDIA_ERR_INTERNAL;
502         }
503
504         g_free(db_path);
505
506         return ret;
507 }
508
509 #ifdef _SET_VIP_PROCESS
510 #define PROC_OOM_SCORE_ADJ_PATH         "/proc/%d/oom_score_adj"
511 #define VIP_OOM_SCORE_ADJ                       (-1000)
512 #define PROC_NAME_MAX 1024
513 #define PROC_BUF_MAX 64
514
515 static int ms_get_cmdline_from_proc(pid_t pid, char *cmdline)
516 {
517         char buf[PROC_BUF_MAX];
518         char cmdline_buf[PROC_NAME_MAX];
519         char *filename;
520         FILE *fp;
521
522         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
523         fp = fopen(buf, "r");
524         if (fp == NULL)
525                 return MS_MEDIA_ERR_INTERNAL;
526
527         if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
528                 fclose(fp);
529                 return MS_MEDIA_ERR_INTERNAL;
530         }
531         fclose(fp);
532
533         filename = strrchr(cmdline_buf, '/');
534         if (filename == NULL)
535                 filename = cmdline_buf;
536         else
537                 filename = filename + 1;
538
539         SAFE_STRLCPY(cmdline, filename, PROC_NAME_MAX);
540
541         return MS_MEDIA_ERR_NONE;
542 }
543
544 int ms_set_vip_process(void)
545 {
546         char buf[100] = {0};
547         int id = 0;
548         static pid_t pid = 0;
549         static char process_name[PROC_NAME_MAX] = {0};
550         static char *appid = NULL;
551
552         /* Get Pid */
553         pid = getpid();
554         if (ms_get_cmdline_from_proc(pid, process_name)) {
555                 MS_DBG_ERR("%s: Read process name failed pid[%d]", __func__, pid);
556                 return MS_MEDIA_ERR_INTERNAL;
557         }
558         appid = process_name;
559
560         MS_DBG("Process name[%s]:Pid[%d]", appid, pid);
561
562         if (prctl(PR_GET_DUMPABLE) == 0)
563                 prctl(PR_SET_DUMPABLE, 1);
564
565         snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
566         id = open(buf, O_WRONLY, 0777);
567         if (id < 0) {
568                 MS_DBG_ERR("fopen %s failed errno:%d", buf, errno);
569                 return MS_MEDIA_ERR_INTERNAL;
570         }
571         snprintf(buf, sizeof(buf), "%d", VIP_OOM_SCORE_ADJ);
572         if (write(id, buf, strlen(buf)) < 0) {
573                 MS_DBG_ERR("write() failed errno=%d", errno);
574                 close(id);
575                 return MS_MEDIA_ERR_INTERNAL;
576         }
577         close(id);
578         return MS_MEDIA_ERR_NONE;
579 }
580 #endif