4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <sys/syscall.h>
24 #include "media-util-dbg.h"
25 #include "media-util-register.h"
26 #include "media-util-err.h"
27 #include "media-util-user.h"
28 #include "media-util-ipc.h"
30 static GMutex scan_req_mutex;
32 typedef struct media_scan_data {
34 scan_complete_cb user_callback;
41 static GSList *req_list;
43 static int __check_dir_path(const char *dir_path, uid_t uid)
45 MSAPI_RETVM_IF(!ms_user_is_valid_path(uid, dir_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
47 /* dir_path can be a deleted path. */
48 if (g_file_test(dir_path, G_FILE_TEST_EXISTS)) {
49 /* Check only exist */
50 MSAPI_RETVM_IF(!g_file_test(dir_path, G_FILE_TEST_IS_DIR), MS_MEDIA_ERR_INVALID_PARAMETER, "Not a directory");
53 return MS_MEDIA_ERR_NONE;
56 static gint __find_req_item(gconstpointer data, gconstpointer compare)
58 return g_strcmp0(((media_scan_data *)data)->req_path, (const char *)compare);
61 /* receive message from media-server[function : ms_receive_message_from_scanner] */
62 static gboolean __read_socket(GIOChannel *channel, GIOCondition condition, gpointer data)
64 ms_comm_msg_s recv_msg = {0, };
65 media_request_result_s req_result = {0, };
67 media_scan_data *req_data = NULL;
70 sockfd = g_io_channel_unix_get_fd(channel);
72 MSAPI_DBG("sock fd is invalid!");
73 return G_SOURCE_REMOVE;
76 if (read(sockfd, &recv_msg, sizeof(ms_comm_msg_s)) < 0) {
77 MSAPI_DBG_STRERROR("recv failed");
78 return G_SOURCE_REMOVE;
81 MSAPI_RETVM_IF(strlen(recv_msg.msg) == 0 || strlen(recv_msg.msg) >= MAX_MSG_SIZE, G_SOURCE_REMOVE, "Invalid msg");
83 switch (recv_msg.msg_type) {
84 case MS_MSG_SCANNER_RESULT:
85 req_result.request_type = MEDIA_DIRECTORY_SCAN;
87 case MS_MSG_SCANNER_BULK_RESULT:
88 req_result.request_type = MEDIA_FILES_REGISTER;
90 case MS_MSG_SCANNER_COMPLETE:
91 req_result.request_type = MEDIA_REQUEST_SCAN_COMPLETE;
93 case MS_MSG_SCANNER_PARTIAL:
94 req_result.request_type = MEDIA_REQUEST_SCAN_PARTIAL;
96 case MS_MSG_RECURSIVE_START:
97 req_result.request_type = MEDIA_RECURSIVE_START;
99 case MS_MSG_EXTRACTOR_COMPLETE:
100 req_result.request_type = MEDIA_REQUEST_EXTRACT_COMPLETE;
103 MSAPI_DBG("Invalid msg_type[%d]", recv_msg.msg_type);
104 return G_SOURCE_REMOVE;
108 MSAPI_DBG_SLOG("complete_path :%s", recv_msg.msg);
109 MSAPI_DBG("pid[%d] result[%d] request_type[%d]", recv_msg.pid, recv_msg.result, req_result.request_type);
112 g_mutex_lock(&scan_req_mutex);
114 found = g_slist_find_custom(req_list, recv_msg.msg, __find_req_item);
116 g_mutex_unlock(&scan_req_mutex);
117 MSAPI_DBG("Not in scan queue :%s", recv_msg.msg);
118 return G_SOURCE_REMOVE;
121 req_data = (media_scan_data *)found->data;
123 req_result.complete_path = recv_msg.msg;
124 req_result.pid = recv_msg.pid;
125 req_result.result = recv_msg.result;
127 if (recv_msg.msg_type != MS_MSG_SCANNER_COMPLETE &&
128 recv_msg.msg_type != MS_MSG_SCANNER_PARTIAL &&
129 recv_msg.msg_type != MS_MSG_RECURSIVE_START) {
131 (req_data->user_callback)(&req_result, req_data->user_data);
132 g_free(req_data->req_path);
134 req_list = g_slist_delete_link(req_list, found);
136 g_mutex_unlock(&scan_req_mutex);
138 MSAPI_DBG("REMOVE OK");
140 return G_SOURCE_REMOVE;
143 /*call user define function. Scanner V2 case only*/
144 (req_data->user_callback)(&req_result, req_data->user_data);
145 g_mutex_unlock(&scan_req_mutex);
147 return G_SOURCE_CONTINUE;
150 static void __add_request(media_scan_data *scan_data)
153 g_mutex_lock(&scan_req_mutex);
155 req_list = g_slist_append(req_list, scan_data);
157 g_mutex_unlock(&scan_req_mutex);
160 static int __remove_request(const char *req_path)
162 media_scan_data *req_data = NULL;
163 media_request_result_s req_result;
164 GSList *found = NULL;
167 g_mutex_lock(&scan_req_mutex);
169 found = g_slist_find_custom(req_list, req_path, __find_req_item);
171 MSAPI_DBG("Not in scan queue :%s", req_path);
172 g_mutex_unlock(&scan_req_mutex);
173 return MS_MEDIA_ERR_INVALID_PARAMETER;
176 req_data = (media_scan_data *)found->data;
179 req_result.result = MS_MEDIA_ERR_NONE;
180 req_result.complete_path = (char *)req_path;
181 req_result.request_type = MEDIA_FILES_REGISTER;
183 /*call user define function*/
184 MSAPI_DBG("Call Cancel Callback");
185 (req_data->user_callback)(&req_result, req_data->user_data);
187 g_source_remove(req_data->source_id);
189 g_free(req_data->req_path);
191 req_list = g_slist_delete_link(req_list, found);
193 MSAPI_DBG("CANCEL OK");
195 g_mutex_unlock(&scan_req_mutex);
197 return MS_MEDIA_ERR_NONE;
200 static void __attach_callback(const char *req_path, int *sockfd, scan_complete_cb user_callback, void *user_data)
202 GIOChannel *channel = NULL;
203 media_scan_data *data = NULL;
206 data = g_new0(media_scan_data, 1);
207 /* Create new channel to watch socket */
208 channel = g_io_channel_unix_new(*sockfd);
209 g_io_channel_set_close_on_unref(channel, TRUE);
210 source_id = g_io_add_watch(channel, G_IO_IN, __read_socket, NULL);
211 g_io_channel_unref(channel);
213 data->user_callback = user_callback;
214 data->user_data = user_data;
215 data->req_path = g_strdup(req_path);
216 data->channel = channel;
217 data->source_id = source_id;
222 static int __media_db_request_update_async(ms_msg_type_e msg_type,
223 const char *storage_id,
225 scan_complete_cb user_callback,
229 int ret = MS_MEDIA_ERR_NONE;
231 ms_comm_msg_s send_msg = { 0, };
232 g_autofree gchar *request_path = NULL;
234 MSAPI_RETVM_IF(!path || strlen(path) == 0, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
236 request_path = g_canonicalize_filename(path, NULL);
237 MSAPI_DBG_SLOG("trimmed path[%s]", request_path);
239 send_msg.msg_type = msg_type;
240 send_msg.pid = syscall(__NR_getpid);
242 if (g_strlcpy(send_msg.msg, request_path, sizeof(send_msg.msg)) >= MAX_MSG_SIZE) {
243 MSAPI_DBG_ERR("path exceeds MAX_MSG_SIZE");
244 return MS_MEDIA_ERR_INVALID_PARAMETER;
246 if (g_strlcpy(send_msg.storage_id, storage_id, sizeof(send_msg.storage_id)) >= MS_UUID_SIZE) {
247 MSAPI_DBG_ERR("storage_id exceeds MS_UUID_SIZE");
248 return MS_MEDIA_ERR_INVALID_PARAMETER;
252 ret = ms_ipc_create_client_socket(0, &sockfd);
253 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "ms_ipc_create_client_socket failed[%d]", ret);
255 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
256 if (ret != MS_MEDIA_ERR_NONE) {
257 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
262 __attach_callback(request_path, &sockfd, user_callback, user_data);
267 static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *path)
269 int ret = MS_MEDIA_ERR_NONE;
271 ms_comm_msg_s send_msg = { 0, };
272 g_autofree gchar *request_path = NULL;
274 MSAPI_RETVM_IF(!path || strlen(path) == 0, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
276 request_path = g_canonicalize_filename(path, NULL);
277 MSAPI_DBG("REQUEST CANCEL DIRECTORY SCANNING[%s]", request_path);
279 send_msg.msg_type = msg_type;
280 send_msg.pid = syscall(__NR_getpid);
281 if (g_strlcpy(send_msg.msg, request_path, sizeof(send_msg.msg)) >= MAX_MSG_SIZE) {
282 MSAPI_DBG_ERR("path exceeds MAX_MSG_SIZE");
283 return MS_MEDIA_ERR_INVALID_PARAMETER;
287 ret = ms_ipc_create_client_socket(0, &sockfd);
288 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "ms_ipc_create_client_socket failed[%d]", ret);
290 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
292 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "ms_ipc_send_msg_to_server_tcp failed[%d]", ret);
294 return __remove_request(request_path);
297 int media_directory_scanning_async(const char *directory_path,
298 const char *storage_id,
300 scan_complete_cb user_callback,
304 int ret = MS_MEDIA_ERR_NONE;
306 ret = __check_dir_path(directory_path, uid);
307 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
310 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, storage_id, directory_path, user_callback, user_data, uid);
312 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, storage_id, directory_path, user_callback, user_data, uid);
317 int media_directory_scanning_cancel(const char *directory_path, uid_t uid)
319 return __media_db_request_update_cancel(MS_MSG_DIRECTORY_SCANNING_CANCEL, directory_path);
322 int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data, uid_t uid)
324 return __media_db_request_update_async(MS_MSG_BULK_INSERT, NULL, list_path, user_callback, user_data, uid);