Use g_snprintf() instead of ms_strappend()
[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(double *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 = (double)(s.f_bsize * 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 int ms_check_file_path(const char *file_path, uid_t uid)
134 {
135         ms_user_storage_type_e storage_type = -1;
136         int ret = MS_MEDIA_ERR_NONE;
137
138         if (!MS_STRING_VALID(file_path)) {
139                 MS_DBG_ERR("Invalid path");
140                 return MS_MEDIA_ERR_INVALID_PARAMETER;
141         }
142
143         ret = ms_user_get_storage_type(uid, file_path, &storage_type);
144         MS_DBG_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
145
146         if (!g_file_test(file_path, G_FILE_TEST_IS_REGULAR)) {
147                 MS_DBG_SERR("g_file_test fail [%s]", file_path);
148                 return MS_MEDIA_ERR_INVALID_PARAMETER;
149         }
150
151         return MS_MEDIA_ERR_NONE;
152 }
153
154 int ms_check_ignore_dir(const char *full_path, uid_t uid)
155 {
156         int ret = MS_MEDIA_ERR_NONE;
157         char *dir_path = NULL;
158         char *leaf_path = NULL;
159         char *usr_path = NULL;
160
161         ret = ms_check_file_path(full_path, uid);
162         if (ret != MS_MEDIA_ERR_NONE) {
163                 MS_DBG_ERR("invalid path : %s", full_path);
164                 return MS_MEDIA_ERR_INVALID_PARAMETER;
165         }
166
167         dir_path = g_path_get_dirname(full_path);
168         if (dir_path == NULL || strcmp(dir_path, ".") == 0) {
169                 MS_DBG_ERR("getting directory path is failed : %s", full_path);
170                 g_free(dir_path);
171                 return MS_MEDIA_ERR_INVALID_PARAMETER;
172         }
173
174         ret = ms_user_get_internal_root_path(uid, &usr_path);
175         if (ret != MS_MEDIA_ERR_NONE) {
176                 MS_DBG_ERR("ms_user_get_internal_root_path() fail");
177                 g_free(dir_path);
178                 return MS_MEDIA_ERR_INTERNAL;
179         }
180
181         while (1) {
182                 if (ms_check_scan_ignore(dir_path, uid) != MS_MEDIA_ERR_NONE) {
183                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
184                         break;
185                 }
186
187                 if (strcmp(dir_path, usr_path) == 0)
188                         break;
189                 else if (MS_STRING_VALID(MEDIA_ROOT_PATH_SDCARD) && (strncmp(dir_path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0))
190                         break;
191                 else if (MS_STRING_VALID(MEDIA_ROOT_PATH_USB) && (strncmp(dir_path, MEDIA_ROOT_PATH_USB, strlen(MEDIA_ROOT_PATH_USB)) == 0))
192                         break;
193
194                 leaf_path = strrchr(dir_path, '/');
195                 if (leaf_path != NULL) {
196                                 int seek_len = leaf_path -dir_path;
197                                 dir_path[seek_len] = '\0';
198                 } else {
199                         MS_DBG_ERR("Fail to find leaf path");
200                         ret = MS_MEDIA_ERR_INVALID_PARAMETER;
201                         break;
202                 }
203         }
204
205         g_free(dir_path);
206         g_free(usr_path);
207
208         return ret;
209 }
210
211 static void __ms_trim_path(const char *input_path, char **output_path)
212 {
213         char buf[4096] = {0, };
214         char tmp[4096] = {0, };
215         char *pos = NULL;
216
217         SAFE_STRLCPY(buf, input_path, sizeof(buf));
218
219         while ((pos = strstr(buf, "//")) != NULL) {
220                 memset(tmp, 0, sizeof(tmp));
221                 SAFE_STRLCPY(tmp, buf, pos - buf + 1);
222                 SAFE_STRLCAT(tmp, pos + 1, sizeof(tmp));
223
224                 memset(buf, 0, sizeof(buf));
225                 SAFE_STRLCPY(buf, tmp, sizeof(buf));
226         }
227
228         if (g_str_has_suffix(buf, "/"))
229                 *output_path = g_strndup(buf, strlen(buf) - 1);
230         else
231                 *output_path = g_strdup(buf);
232 }
233
234 int ms_check_scan_ignore(char * path, uid_t uid)
235 {
236         int ret = MS_MEDIA_ERR_NONE;
237         const char *ignore_file = ".scan_ignore";
238         char *tmp_path = NULL;
239         char *org_path = NULL;
240         char ignore_path[MS_FILE_PATH_LEN_MAX] = {0, };
241
242 #ifndef _USE_TVPD_MODE
243         char replace[MS_FILE_PATH_LEN_MAX] = {0, };
244         char *mediashared = NULL;
245 #endif
246
247         /* Check for symbolic link */
248         tmp_path = realpath(path, NULL);
249         /* Get trimmed path */
250         __ms_trim_path(path, &org_path);
251
252 #ifdef _USE_TVPD_MODE
253         if (g_strcmp0(tmp_path, org_path) != 0) {
254                 MS_SAFE_FREE(tmp_path);
255                 g_free(org_path);
256                 MS_DBG_ERR("symbolic link(directory)");
257                 return MS_MEDIA_ERR_INVALID_PARAMETER;
258         }
259 #else
260         if (g_str_has_prefix(tmp_path, MEDIA_SHARE_PATH)) {
261                 ms_user_get_mediashared_path(uid, &mediashared);
262                 snprintf(replace, MS_FILE_PATH_LEN_MAX, "%s%s", mediashared, tmp_path + strlen(MEDIA_SHARE_PATH));
263                 MS_SAFE_FREE(mediashared);
264                 if (g_strcmp0(replace, org_path) != 0) {
265                         MS_SAFE_FREE(tmp_path);
266                         g_free(org_path);
267                         MS_DBG_ERR("symbolic link(directory)");
268                         return MS_MEDIA_ERR_INVALID_PARAMETER;
269                 }
270         } else {
271                 if (g_strcmp0(tmp_path, org_path) != 0) {
272                         MS_SAFE_FREE(tmp_path);
273                         g_free(org_path);
274                         MS_DBG_ERR("symbolic link(directory)");
275                         return MS_MEDIA_ERR_INVALID_PARAMETER;
276                 }
277         }
278 #endif
279         MS_SAFE_FREE(tmp_path);
280         g_free(org_path);
281
282         if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
283                 snprintf(ignore_path, sizeof(ignore_path), "%s/%s", path, ignore_file);
284
285                 if (g_file_test(ignore_path, G_FILE_TEST_EXISTS)) {
286                         MS_DBG_WARN("scan ignore file exist [%s]", ignore_path);
287                         return MS_MEDIA_ERR_INVALID_PARAMETER;
288                 }
289         } else {
290                 MS_DBG_ERR("g_file_test fails[%s]", path);
291                 ret = MS_MEDIA_ERR_INVALID_PARAMETER;
292
293                 if (!MS_STRING_VALID(MEDIA_ROOT_PATH_USB)) {
294                         MS_DBG_ERR("Fail to get USB path");
295                         return ret;
296                 }
297
298                 if (strstr(path, MEDIA_ROOT_PATH_USB) != NULL) {
299                         /*if the directory does not exist, check the device is unmounted*/
300                         if (!ms_storage_mount_status(path)) {
301                                 MS_DBG_ERR("Device is unmounted[%s]", path);
302                                 return MS_MEDIA_ERR_USB_UNMOUNTED;
303                         }
304                 }
305         }
306
307         return ret;
308 }
309
310 bool ms_storage_mount_status(const char* start_path)
311 {
312         bool ret = false;
313 #ifndef _USE_DEVICED_DBUS
314         int count = 0;
315         int err = 0;
316         usb_device_list_h list;
317         usb_device_h device;
318         char *mount_path = NULL;
319
320         char *storage_path = NULL;
321         char *remain_path = NULL;
322         int remain_len = 0;
323
324         remain_path = strstr(start_path+strlen(MEDIA_ROOT_PATH_USB) +1, "/");
325         if (remain_path != NULL)
326                 remain_len = strlen(remain_path);
327
328         storage_path = g_strndup(start_path, strlen(start_path) - remain_len);
329
330         MS_DBG_SWARN("storage_path [%s]", storage_path);
331
332         err = usb_device_get_device_list(USB_MASS_STORAGE, &list);
333         if (err == 0) {
334                 count = usb_device_list_get_count(list);
335                 if (count > 0) {
336                         err = usb_device_list_get_first(list, &device);
337                         if (err != USB_ERROR_LIST_FAILED_TO_GET && device != NULL) {
338                                 mount_path = usb_device_get_mountpath(device);
339                                 if (mount_path != NULL) {
340                                         MS_DBG_SWARN("mount_path [%s]", mount_path);
341                                         if (strlen(mount_path) == strlen(storage_path)) {
342                                                 if (strncmp(mount_path, storage_path, strlen(mount_path)) == 0) {
343                                                         MS_DBG_SWARN("start path is mounted [%s]", start_path);
344                                                         ret = true;
345                                                 }
346                                         }
347                                 }
348                         }
349
350                         if (ret != true) {
351                                 while (usb_device_list_get_next(list, &device) == 0) {
352                                         if (device != NULL) {
353                                                 mount_path = usb_device_get_mountpath(device);
354                                                 if (mount_path != NULL) {
355                                                         MS_DBG_SWARN("mount_path [%s]", mount_path);
356                                                         if (strlen(mount_path) == strlen(storage_path)) {
357                                                                 if (strncmp(mount_path, storage_path, strlen(mount_path)) == 0) {
358                                                                         MS_DBG_SWARN("start path is mounted [%s]", start_path);
359                                                                         ret = true;
360                                                                         break;
361                                                                 }
362                                                         }
363                                                 }
364                                         }
365                                 }
366                         }
367                 }
368
369                 usb_device_free_device_list(list);
370         } else {
371                 MS_DBG_ERR("usb_device_get_device_list falied [%d]", err);
372         }
373
374         g_free(storage_path);
375 #endif
376         return ret;
377 }
378
379 int ms_set_db_status(ms_db_status_type_t status, ms_user_storage_type_e storage_type)
380 {
381         int ret = MS_MEDIA_ERR_NONE;
382
383         if (status == MS_DB_UPDATING) {
384                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING))
385                                 goto ERROR;
386
387                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
388                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADING))
389                                 goto ERROR;
390                 }
391         } else {
392                 if (!ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATED))
393                                 goto ERROR;
394
395                 if (storage_type == MS_USER_STORAGE_EXTERNAL) {
396                         if (!ms_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADED))
397                                 goto ERROR;
398                 }
399         }
400
401         ret = ms_set_power_mode(status);
402         if (ret != MS_MEDIA_ERR_NONE)
403                 MS_DBG_ERR("ms_set_power_mode fail");
404
405         return ret;
406 ERROR:
407         MS_DBG_ERR("ms_config_set_int failed");
408         return MS_MEDIA_ERR_INTERNAL;
409 }
410
411 int ms_set_power_mode(ms_db_status_type_t status)
412 {
413         int res = MS_MEDIA_ERR_NONE;
414         int err;
415
416         switch (status) {
417         case MS_DB_UPDATING:
418                 err = device_power_request_lock(POWER_LOCK_CPU, 0);
419                 if (err != 0)
420                         res = MS_MEDIA_ERR_INTERNAL;
421                 break;
422         case MS_DB_UPDATED:
423                 err = device_power_release_lock(POWER_LOCK_CPU);
424                 if (err != 0)
425                         res = MS_MEDIA_ERR_INTERNAL;
426                 break;
427         default:
428                 MS_DBG_ERR("Unacceptable type : %d", status);
429                 break;
430         }
431
432         return res;
433 }
434
435 void ms_trim_dir_path(char *dir_path)
436 {
437         /* need implementation */
438         /* if dir_path is not NULL terminated, this function will occure crash */
439         int len = strlen(dir_path);
440
441         if (dir_path[len -1] == '/')
442                 dir_path[len -1] = '\0';
443 }
444
445 int ms_check_size_mediadb(uid_t uid, double *db_size)
446 {
447         int ret = MS_MEDIA_ERR_NONE;
448         char *db_path = NULL;
449         struct stat buf;
450
451         ret = ms_user_get_media_db_path(uid, &db_path);
452
453         if (stat(db_path, &buf) == 0) {
454                 *db_size = buf.st_size;
455         } else {
456                 MS_DBG_STRERROR("stat failed");
457                 ret = MS_MEDIA_ERR_INTERNAL;
458         }
459
460         g_free(db_path);
461
462         return ret;
463 }
464
465 #ifdef _USE_TVPD_MODE
466 #define PROC_OOM_SCORE_ADJ_PATH         "/proc/%d/oom_score_adj"
467 #define VIP_OOM_SCORE_ADJ                       (-1000)
468 #define PROC_NAME_MAX 1024
469 #define PROC_BUF_MAX 64
470
471 static int ms_get_cmdline_from_proc(pid_t pid, char *cmdline)
472 {
473         char buf[PROC_BUF_MAX];
474         char cmdline_buf[PROC_NAME_MAX];
475         char *filename;
476         FILE *fp;
477
478         snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
479         fp = fopen(buf, "r");
480         if (fp == NULL)
481                 return MS_MEDIA_ERR_INTERNAL;
482
483         if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) {
484                 fclose(fp);
485                 return MS_MEDIA_ERR_INTERNAL;
486         }
487         fclose(fp);
488
489         filename = strrchr(cmdline_buf, '/');
490         if (filename == NULL)
491                 filename = cmdline_buf;
492         else
493                 filename = filename + 1;
494
495         SAFE_STRLCPY(cmdline, filename, PROC_NAME_MAX);
496
497         return MS_MEDIA_ERR_NONE;
498 }
499
500 int ms_set_vip_process(void)
501 {
502         char buf[100] = {0};
503         int id = 0;
504         static pid_t pid = 0;
505         static char process_name[PROC_NAME_MAX] = {0};
506         static char *appid = NULL;
507
508         /* Get Pid */
509         pid = getpid();
510         if (ms_get_cmdline_from_proc(pid, process_name)) {
511                 MS_DBG_ERR("%s: Read process name failed pid[%d]", __func__, pid);
512                 return MS_MEDIA_ERR_INTERNAL;
513         }
514         appid = process_name;
515
516         MS_DBG("Process name[%s]:Pid[%d]", appid, pid);
517
518         if (prctl(PR_GET_DUMPABLE) == 0)
519                 prctl(PR_SET_DUMPABLE, 1);
520
521         snprintf(buf, sizeof(buf), PROC_OOM_SCORE_ADJ_PATH, pid);
522         id = open(buf, O_WRONLY, 0777);
523         if (id < 0) {
524                 MS_DBG_ERR("fopen %s failed errno:%d", buf, errno);
525                 return MS_MEDIA_ERR_INTERNAL;
526         }
527         snprintf(buf, sizeof(buf), "%d", VIP_OOM_SCORE_ADJ);
528         if (write(id, buf, strlen(buf)) < 0) {
529                 MS_DBG_ERR("write() failed errno=%d", errno);
530                 close(id);
531                 return MS_MEDIA_ERR_INTERNAL;
532         }
533         close(id);
534         return MS_MEDIA_ERR_NONE;
535 }
536 #endif