Tizen 2.1 base
[framework/multimedia/media-server.git] / common / scanner / media-scanner-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 /**
23  * This file defines api utilities of contents manager engines.
24  *
25  * @file                media-server-utils.c
26  * @author      Yong Yeon Kim(yy9875.kim@samsung.com)
27  * @version     1.0
28  * @brief       This file implements main database operation.
29  */
30
31 #include <dirent.h>
32 #include <malloc.h>
33 #include <vconf.h>
34
35 #include "media-util.h"
36 #include "media-scanner-dbg.h"
37 #include "media-scanner-utils.h"
38 #include "media-scanner-drm.h"
39
40 #ifdef FMS_PERF
41 #include <sys/time.h>
42 #define MILLION 1000000L
43 struct timeval g_mmc_start_time;
44 struct timeval g_mmc_end_time;
45 #endif
46
47 #define MMC_INFO_SIZE 256
48
49 extern int mmc_state;
50 extern GAsyncQueue *storage_queue;
51 extern GAsyncQueue *scan_queue;
52
53
54
55 #ifdef FMS_PERF
56 void
57 msc_check_start_time(struct timeval *start_time)
58 {
59         gettimeofday(start_time, NULL);
60 }
61
62 void
63 msc_check_end_time(struct timeval *end_time)
64 {
65         gettimeofday(end_time, NULL);
66 }
67
68 void
69 msc_check_time_diff(struct timeval *start_time, struct timeval *end_time)
70 {
71         struct timeval time;
72         long difftime;
73
74         time.tv_sec = end_time->tv_sec - start_time->tv_sec;
75         time.tv_usec = end_time->tv_usec - start_time->tv_usec;
76         difftime = MILLION * time.tv_sec + time.tv_usec;
77         MSC_DBG_INFO("The function_to_time took %ld microseconds or %f seconds.",
78                difftime, difftime / (double)MILLION);
79 }
80 #endif
81
82 bool
83 msc_is_mmc_inserted(void)
84 {
85         int data = -1;
86         msc_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &data);
87         if (data != VCONFKEY_SYSMAN_MMC_MOUNTED) {
88                 return false;
89         } else {
90                 return true;
91         }
92 }
93
94 int
95 _msc_update_mmc_info(const char *cid)
96 {
97         bool res;
98
99         if (cid == NULL) {
100                 MSC_DBG_ERR("Parameters are invalid");
101                 return MS_MEDIA_ERR_INVALID_PARAMETER;
102         }
103
104         res = msc_config_set_str(MS_MMC_INFO_KEY, cid);
105         if (!res) {
106                 MSC_DBG_ERR("fail to get MS_MMC_INFO_KEY");
107                 return MS_MEDIA_ERR_VCONF_SET_FAIL;
108         }
109
110         return MS_MEDIA_ERR_NONE;
111 }
112
113 static int
114 _msc_get_contents(const char *filename, char *buf)
115 {
116         FILE *fp;
117
118         fp = fopen(filename, "rt");
119         if (fp == NULL) {
120                 MSC_DBG_ERR("fp is NULL. file name : %s", filename);
121                 return MS_MEDIA_ERR_FILE_OPEN_FAIL;
122         }
123
124         if (fgets(buf, 255, fp) == NULL)
125                 MSC_DBG_ERR("fgets failed");
126
127         fclose(fp);
128
129         return MS_MEDIA_ERR_NONE;
130 }
131
132 /*need optimize*/
133 int
134 _msc_get_mmc_info(char *cid)
135 {
136         int i;
137         int j;
138         int len;
139         int err = -1;
140         bool getdata = false;
141         bool bHasColon = false;
142         char path[MS_FILE_PATH_LEN_MAX] = { 0 };
143         char mmcpath[MS_FILE_PATH_LEN_MAX] = { 0 };
144
145         DIR *dp;
146         struct dirent ent;
147         struct dirent *res = NULL;
148
149         /* mmcblk0 and mmcblk1 is reserved for movinand */
150         for (j = 1; j < 3; j++) {
151                 len = snprintf(mmcpath, MS_FILE_PATH_LEN_MAX, "/sys/class/mmc_host/mmc%d/", j);
152                 if (len < 0) {
153                         MSC_DBG_ERR("FAIL : snprintf");
154                         return MS_MEDIA_ERR_INTERNAL;
155                 }
156                 else {
157                         mmcpath[len] = '\0';
158                 }
159
160                 dp = opendir(mmcpath);
161                 if (dp == NULL) {
162                         MSC_DBG_ERR("dp is NULL");
163                         return MS_MEDIA_ERR_DIR_OPEN_FAIL;
164                 }
165
166                 while (!readdir_r(dp, &ent, &res)) {
167                          /*end of read dir*/
168                         if (res == NULL)
169                                 break;
170
171                         bHasColon = false;
172                         if (ent.d_name[0] == '.')
173                                 continue;
174
175                         if (ent.d_type == DT_DIR) {
176                                 /*ent->d_name is including ':' */
177                                 for (i = 0; i < strlen(ent.d_name); i++) {
178                                         if (ent.d_name[i] == ':') {
179                                                 bHasColon = true;
180                                                 break;
181                                         }
182                                 }
183
184                                 if (bHasColon) {
185                                         /*check serial */
186                                         err = msc_strappend(path, sizeof(path), "%s%s/cid", mmcpath, ent.d_name);
187                                         if (err < 0) {
188                                                 MSC_DBG_ERR("ms_strappend error : %d", err);
189                                                 continue;
190                                         }
191
192                                         if (_msc_get_contents(path, cid) != MS_MEDIA_ERR_NONE)
193                                                 break;
194                                         else
195                                                 getdata = true;
196                                 }
197                         }
198                 }
199                 closedir(dp);
200
201                 if (getdata == true) {
202                         break;
203                 }
204         }
205
206         return MS_MEDIA_ERR_NONE;
207 }
208
209 int
210 msc_update_mmc_info(void)
211 {
212         int err;
213         char cid[MMC_INFO_SIZE] = { 0 };
214
215         err = _msc_get_mmc_info(cid);
216
217         err = _msc_update_mmc_info(cid);
218
219         /*Active flush */
220         if (!malloc_trim(0))
221                 MSC_DBG_ERR("malloc_trim is failed");
222
223         return err;
224 }
225
226 bool
227 _msc_check_mmc_info(const char *cid)
228 {
229         char pre_mmc_info[MMC_INFO_SIZE] = { 0 };
230         bool res = false;
231
232         if (cid == NULL) {
233                 MSC_DBG_ERR("Parameters are invalid");
234                 return false;
235         }
236
237         res = msc_config_get_str(MS_MMC_INFO_KEY, pre_mmc_info);
238         if (!res) {
239                 MSC_DBG_ERR("fail to get MS_MMC_INFO_KEY");
240                 return false;
241         }
242
243         MSC_DBG_INFO("Last MMC info     = %s", pre_mmc_info);
244         MSC_DBG_INFO("Current MMC info = %s", cid);
245
246         if (strcmp(pre_mmc_info, cid) == 0) {
247                 return true;
248         }
249
250         return false;
251 }
252
253
254 ms_dir_scan_type_t
255 msc_get_mmc_state(void)
256 {
257         char cid[MMC_INFO_SIZE] = { 0 };
258         ms_dir_scan_type_t ret = MS_SCAN_ALL;
259
260         /*get new info */
261         _msc_get_mmc_info(cid);
262
263         /*check it's same mmc */
264         if (_msc_check_mmc_info(cid)) {
265                 ret = MS_SCAN_PART;
266         }
267
268         return ret;
269 }
270
271 void
272 msc_mmc_vconf_cb(void *data)
273 {
274         int status = 0;
275         ms_comm_msg_s *scan_msg;
276         ms_dir_scan_type_t scan_type = MS_SCAN_PART;
277
278         if (!msc_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status)) {
279                 MSC_DBG_ERR("Get VCONFKEY_SYSMAN_MMC_STATUS failed.");
280         }
281
282         MSC_DBG_INFO("VCONFKEY_SYSMAN_MMC_STATUS :%d", status);
283
284         mmc_state = status;
285
286         MS_MALLOC(scan_msg, sizeof(ms_comm_msg_s));
287
288         if (mmc_state == VCONFKEY_SYSMAN_MMC_REMOVED ||
289                 mmc_state == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED) {
290
291                 if (!msc_drm_extract_ext_memory())
292                         MSC_DBG_ERR("ms_drm_extract_ext_memory failed");
293
294                 scan_type = MS_SCAN_INVALID;
295         } else if (mmc_state == VCONFKEY_SYSMAN_MMC_MOUNTED) {
296
297                 if (!msc_drm_insert_ext_memory())
298                         MSC_DBG_ERR("ms_drm_insert_ext_memory failed");
299
300                 scan_type = msc_get_mmc_state();
301         }
302
303         switch (scan_type) {
304                 case MS_SCAN_ALL:
305                         scan_msg->msg_type = MS_MSG_STORAGE_ALL;
306                         break;
307                 case MS_SCAN_PART:
308                         scan_msg->msg_type = MS_MSG_STORAGE_PARTIAL;
309                         break;
310                 case MS_SCAN_INVALID:
311                         scan_msg->msg_type = MS_MSG_STORAGE_INVALID;
312                         break;
313         }
314
315         scan_msg->pid = 0;
316         scan_msg->msg_size = strlen(MEDIA_ROOT_PATH_SDCARD);
317         msc_strcopy(scan_msg->msg, scan_msg->msg_size+1, "%s", MEDIA_ROOT_PATH_SDCARD);
318
319         MSC_DBG_INFO("ms_get_mmc_state is %d", scan_msg->msg_type);
320
321         g_async_queue_push(storage_queue, GINT_TO_POINTER(scan_msg));
322
323         return;
324 }
325
326 /*CAUTION : Before using this function, Have to allocate static memory of ret_path*/
327 /*And the array length does not over MS_FILE_PATH_LEN_MAX*/
328 /*for example : char path[MS_FILE_PATH_LEN_MAX] = {0};*/
329 int
330 msc_get_full_path_from_node(ms_dir_scan_info * const node, char *ret_path, int depth)
331 {
332         int i = 0;
333         int path_length = 0;
334         int length = 0;
335         ms_dir_scan_info *cur_node;
336         char **path_array;
337
338         if (depth < 0) {
339                 MSC_DBG_ERR("depth < 0");
340                 return MS_MEDIA_ERR_INVALID_PATH;
341         }
342
343         MS_MALLOC(path_array, sizeof(char*) * (depth + 1));
344
345         cur_node = node;
346
347         while (1) {
348                 path_array[i] = cur_node->name;
349                 if (cur_node->parent == NULL)
350                         break;
351
352                 cur_node = cur_node->parent;
353                 i++;
354         }
355
356         for(i = depth ; i >= 0 ; i --) {
357                 length = strlen(path_array[i]);
358
359                 if (path_length + length > MS_FILE_PATH_LEN_MAX) {
360                         MSC_DBG_ERR("This is invalid path, %s, %d", node->name, depth);
361                         MS_SAFE_FREE(path_array);
362                         return MS_MEDIA_ERR_INVALID_PATH;
363                 }
364
365                 strncpy(ret_path+path_length, path_array[i], length);
366                 path_length += length;
367
368                 ret_path[path_length] = '/';
369                 path_length ++;
370         }
371
372         ret_path[-- path_length] = '\0';
373
374         MS_SAFE_FREE(path_array);
375
376         return MS_MEDIA_ERR_NONE;
377 }
378
379 ms_storage_type_t
380 msc_get_storage_type_by_full(const char *path)
381 {
382         if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) {
383                 return MS_STORAGE_INTERNAL;
384         } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) {
385                 return MS_STORAGE_EXTERNAL;
386         } else
387                 return MS_MEDIA_ERR_INVALID_PATH;
388 }
389
390 int
391 msc_strappend(char *res, const int size, const char *pattern,
392              const char *str1, const char *str2)
393 {
394         int len = 0;
395         int real_size = size - 1;
396
397         if (!res ||!pattern || !str1 ||!str2 )
398                 return MS_MEDIA_ERR_INVALID_PARAMETER;
399
400         if (real_size < (strlen(str1) + strlen(str2)))
401                 return MS_MEDIA_ERR_INVALID_PARAMETER;
402
403         len = snprintf(res, real_size, pattern, str1, str2);
404         if (len < 0) {
405                 return MS_MEDIA_ERR_INVALID_PARAMETER;
406         }
407
408         res[len] = '\0';
409
410         return MS_MEDIA_ERR_NONE;
411 }
412
413 int
414 msc_strcopy(char *res, const int size, const char *pattern, const char *str1)
415 {
416         int len = 0;
417         int real_size = size;
418
419         if (!res || !pattern || !str1)
420                 return MS_MEDIA_ERR_INVALID_PARAMETER;
421
422         if (real_size < strlen(str1))
423                 return MS_MEDIA_ERR_INVALID_PARAMETER;
424
425         len = snprintf(res, real_size, pattern, str1);
426         if (len < 0) {
427                 return MS_MEDIA_ERR_INVALID_PARAMETER;
428         }
429
430         res[len] = '\0';
431
432         return MS_MEDIA_ERR_NONE;
433 }
434
435 bool
436 msc_config_get_int(const char *key, int *value)
437 {
438         int err;
439
440         if (!key || !value) {
441                 MSC_DBG_ERR("Arguments key or value is NULL");
442                 return false;
443         }
444
445         err = vconf_get_int(key, value);
446         if (err == 0)
447                 return true;
448         else if (err == -1)
449                 return false;
450         else
451                 MSC_DBG_ERR("Unexpected error code: %d", err);
452
453         return false;
454 }
455
456 bool
457 msc_config_set_int(const char *key, int value)
458 {
459         int err;
460
461         if (!key) {
462                 MSC_DBG_ERR("Arguments key is NULL");
463                 return false;
464         }
465
466         err = vconf_set_int(key, value);
467         if (err == 0)
468                 return true;
469         else if (err == -1)
470                 return false;
471         else
472                 MSC_DBG_ERR("Unexpected error code: %d", err);
473
474         return false;
475 }
476
477 bool
478 msc_config_get_str(const char *key, char *value)
479 {
480         char *res;
481         if (!key || !value) {
482                 MSC_DBG_ERR("Arguments key or value is NULL");
483                 return false;
484         }
485
486         res = vconf_get_str(key);
487         if (res) {
488                 strncpy(value, res, strlen(res) + 1);
489                 return true;
490         }
491
492         return false;
493 }
494
495 bool
496 msc_config_set_str(const char *key, const char *value)
497 {
498         int err;
499
500         if (!key || !value) {
501                 MSC_DBG_ERR("Arguments key or value is NULL");
502                 return false;
503         }
504
505         err = vconf_set_str(key, value);
506         if (err == 0)
507                 return true;
508         else
509                 MSC_DBG_ERR("fail to vconf_set_str %d", err);
510
511         return false;
512 }
513