2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <sys/types.h>
21 #include <system_info.h>
23 #include "mtp_support.h"
24 #include "mtp_device.h"
25 #include "mtp_media_info.h"
26 #include "mtp_transport.h"
27 #include "mtp_inoti_handler.h"
30 extern mtp_char g_last_deleted[MTP_MAX_PATHNAME_SIZE + 1];
31 static mtp_uint32 g_next_obj_handle = 1;
34 static inline mtp_bool UTIL_CHECK_LIST_NEXT(slist_iterator *iter)
36 return (iter && iter->node_ptr) ? TRUE : FALSE;
39 static void __init_store_info(store_info_t *info)
43 memset(info, 0x00, sizeof(store_info_t));
45 info->store_type = PTP_STORAGETYPE_FIXEDRAM;
46 info->fs_type = PTP_FILESYSTEMTYPE_DCF;
47 info->access = PTP_STORAGEACCESS_RWD;
49 info->capacity = MTP_MAX_STORAGE;
50 info->free_space = MTP_MAX_STORAGE - 1;
51 info->free_space_in_objs = MTP_MAX_STORAGE_IN_OBJTS;
56 static void __init_store_info_params(store_info_t *info,
57 mtp_uint64 capacity, mtp_uint16 store_type, mtp_uint16 fs_type,
58 mtp_uint16 access, mtp_wchar *store_desc, mtp_wchar *label)
60 info->store_type = store_type;
61 info->fs_type = fs_type;
62 info->access = access;
64 info->capacity = capacity;
65 info->free_space = capacity;
66 info->free_space_in_objs = MTP_MAX_STORAGE_IN_OBJTS;
68 _prop_copy_char_to_ptpstring(&(info->store_desc), store_desc, WCHAR_TYPE);
69 _prop_copy_char_to_ptpstring(&(info->vol_label), label, WCHAR_TYPE);
73 void _entity_update_store_info_run_time(store_info_t *info,
76 fs_info_t fs_info = { 0 };
79 ret_if(root_path == NULL);
81 if (FALSE == _util_get_filesystem_info(root_path, &fs_info)) {
82 ERR("_util_get_filesystem_info fail [%s]\n", root_path);
86 info->capacity = fs_info.disk_size;
87 info->free_space = fs_info.avail_size;
93 mtp_bool _entity_get_store_path_by_id(mtp_uint32 store_id, mtp_char *path)
95 char sto_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
98 case MTP_INTERNAL_STORE_ID:
99 _util_get_internal_path(sto_path);
100 g_strlcpy(path, sto_path,
101 MTP_MAX_PATHNAME_SIZE + 1);
103 case MTP_EXTERNAL_STORE_ID:
104 _util_get_external_path(sto_path);
105 g_strlcpy(path, sto_path,
106 MTP_MAX_PATHNAME_SIZE + 1);
109 ERR("No valid match for the store id [0x%x]\n", store_id);
116 mtp_uint32 _entity_get_store_info_size(store_info_t *info)
118 mtp_uint32 size = FIXED_LENGTH_MEMBERS_MTPSTORE_SIZE;
120 size += _prop_size_ptpstring(&(info->store_desc));
121 size += _prop_size_ptpstring(&(info->vol_label));
126 mtp_uint32 _entity_pack_store_info(store_info_t *info, mtp_uchar *buf,
129 mtp_uint32 num_bytes = 0;
131 retv_if(buf == NULL, 0);
133 if (buf_sz < _entity_get_store_info_size(info)) {
134 ERR("Buffer size is less [%u]\n", buf_sz);
137 #ifdef __BIG_ENDIAN__
138 memcpy(&(buf[num_bytes]), &(info->store_type),
139 sizeof(info->StorageType));
140 _util_conv_byte_order(buf, sizeof(info->store_type));
141 num_bytes += sizeof(info->store_type);
143 memcpy(&(buf[num_bytes]), &(info->fs_type), sizeof(info->fs_type));
144 _util_conv_byte_order(buf, sizeof(info->fs_type));
145 num_bytes += sizeof(info->fs_type);
147 memcpy(&(buf[num_bytes]), &(info->access), sizeof(info->access));
148 _util_conv_byte_order(buf, sizeof(info->access));
149 num_bytes += sizeof(info->access);
151 memcpy(&(buf[num_bytes]), &(info->capacity), sizeof(info->capacity));
152 _util_conv_byte_order(buf, sizeof(info->capacity));
153 num_bytes += sizeof(info->capacity);
155 memcpy(&(buf[num_bytes]), &(info->free_space),
156 sizeof(info->free_space));
157 _util_conv_byte_order(buf, sizeof(info->free_space));
158 num_bytes += sizeof(info->free_space);
160 memcpy(&(buf[num_bytes]), &(info->free_space_in_objs),
161 sizeof(info->free_space_in_objs));
162 _util_conv_byte_order(buf, sizeof(info->free_space_in_objs));
163 num_bytes += sizeof(info->free_space_in_objs);
164 #else /*__BIG_ENDIAN__*/
165 memcpy(buf, &(info->store_type), sizeof(mtp_uint16) *3);
166 num_bytes += sizeof(mtp_uint16) * 3;
167 memcpy(&(buf[num_bytes]), &(info->capacity),
168 sizeof(mtp_uint64) * 2 + sizeof(mtp_uint32));
169 num_bytes += sizeof(mtp_uint64) * 2 + sizeof(mtp_uint32);
170 #endif /*__BIG_ENDIAN__*/
171 num_bytes += _prop_pack_ptpstring(&(info->store_desc), buf + num_bytes,
172 _prop_size_ptpstring(&(info->store_desc)));
174 num_bytes += _prop_pack_ptpstring(&(info->vol_label), buf + num_bytes,
175 _prop_size_ptpstring(&(info->vol_label)));
180 mtp_uint32 _entity_get_store_id_by_path(const mtp_char *path_name)
182 mtp_uint32 store_id = 0;
183 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
184 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
186 retv_if(NULL == path_name, FALSE);
188 _util_get_external_path(ext_path);
189 _util_get_internal_path(inter_path);
191 if (!strncmp(path_name, inter_path,
192 strlen(inter_path))) {
193 store_id = MTP_INTERNAL_STORE_ID;
194 } else if (!strncmp(path_name, ext_path,
196 store_id = MTP_EXTERNAL_STORE_ID;
199 DBG_SECURE("Path : %s, store_id : 0x%x\n", path_name, store_id);
205 mtp_bool _entity_init_mtp_store(mtp_store_t *store, mtp_uint32 store_id,
206 mtp_char *store_path)
208 mtp_char temp[MTP_SERIAL_LEN_MAX + 1] = { 0 };
209 mtp_wchar wtemp[MTP_MAX_REG_STRING + 1] = { 0 };
210 mtp_char serial[MTP_MAX_REG_STRING + 1] = { 0 };
211 mtp_wchar wserial[MTP_MAX_REG_STRING + 1] = { 0 };
212 char *profile = NULL;
213 char *storage_desc = NULL;
215 retv_if(store == NULL, FALSE);
217 store->store_id = store_id;
218 store->root_path = g_strdup(store_path);
220 __init_store_info(&(store->store_info));
221 _entity_update_store_info_run_time(&(store->store_info),
224 _device_get_serial(temp, sizeof(temp));
225 g_snprintf(serial, sizeof(serial), "%s-%x", temp, store_id);
226 _util_utf8_to_utf16(wserial, sizeof(wserial) / WCHAR_SIZ, serial);
229 case MTP_INTERNAL_STORE_ID:
230 store->is_hidden = FALSE;
232 system_info_get_platform_string("http://tizen.org/feature/profile", &profile);
233 if (profile != NULL) {
234 if (g_strcmp0(profile, "mobile") == 0) {
235 storage_desc = g_strdup("Phone");
236 } else if (g_strcmp0(profile, "wearable") == 0) {
237 storage_desc = g_strdup("Watch");
241 if (storage_desc == NULL)
242 storage_desc = g_strdup("Common");
244 _util_utf8_to_utf16(wtemp, sizeof(wtemp) / WCHAR_SIZ,
246 __init_store_info_params(&(store->store_info),
247 store->store_info.capacity, PTP_STORAGETYPE_FIXEDRAM,
248 PTP_FILESYSTEMTYPE_HIERARCHICAL, PTP_STORAGEACCESS_RWD,
251 if (storage_desc != NULL)
252 g_free(storage_desc);
258 case MTP_EXTERNAL_STORE_ID:
259 /* LCOV_EXCL_START */
260 store->is_hidden = FALSE;
261 _util_utf8_to_utf16(wtemp, sizeof(wtemp) / WCHAR_SIZ,
262 MTP_STORAGE_DESC_EXT);
263 __init_store_info_params(&(store->store_info),
264 store->store_info.capacity,
265 PTP_STORAGETYPE_REMOVABLERAM,
266 PTP_FILESYSTEMTYPE_HIERARCHICAL,
267 PTP_STORAGEACCESS_RWD, wtemp, wserial);
271 ERR("store initialization Fail");
275 _util_init_list(&(store->obj_list));
280 mtp_obj_t *_entity_add_file_to_store(mtp_store_t *store, mtp_uint32 h_parent,
281 mtp_char *file_path, mtp_char *file_name, dir_entry_t *file_info)
283 mtp_obj_t *obj = NULL;
285 retv_if(NULL == store, NULL);
287 obj = _entity_alloc_mtp_object();
289 ERR("Memory allocation Fail");
293 if (_entity_init_mtp_object_params(obj, store->store_id, h_parent,
294 file_path, file_name, file_info) == FALSE) {
295 /* LCOV_EXCL_START */
296 ERR("_entity_init_mtp_object_params Fail");
302 _entity_add_object_to_store(store, obj);
306 mtp_obj_t *_entity_add_folder_to_store(mtp_store_t *store, mtp_uint32 h_parent,
307 mtp_char *file_path, mtp_char *file_name, dir_entry_t *file_info)
309 mtp_obj_t *obj = NULL;
311 retv_if(NULL == store, NULL);
313 obj = _entity_alloc_mtp_object();
315 ERR("Memory allocation Fail");
319 if (_entity_init_mtp_object_params(obj, store->store_id, h_parent,
320 file_path, file_name, file_info) == FALSE) {
321 /* LCOV_EXCL_START */
322 ERR("_entity_init_mtp_object_params Fail");
329 _entity_add_object_to_store(store, obj);
333 mtp_bool _entity_add_object_to_store(mtp_store_t *store, mtp_obj_t *obj)
335 mtp_obj_t *par_obj = NULL;
337 retv_if(obj == NULL, FALSE);
338 retv_if(NULL == store, FALSE);
339 retv_if(obj->obj_info == NULL, FALSE);
341 if (_util_add_node(&(store->obj_list), obj) == FALSE) {
342 ERR("Node add to list Fail");
347 if (PTP_OBJECTHANDLE_ROOT != obj->obj_info->h_parent) {
348 par_obj = _entity_get_object_from_store(store, obj->obj_info->h_parent);
350 _entity_add_reference_child_array(par_obj, obj->obj_handle);
356 mtp_obj_t *_entity_get_object_from_store(mtp_store_t *store, mtp_uint32 handle)
358 mtp_obj_t *obj = NULL;
359 slist_iterator *iter = NULL;
361 retv_if(NULL == store, NULL);
363 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
365 ERR("Iterator init Fail, Store id = [0x%x]\n", store->store_id);
369 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
370 obj = (mtp_obj_t *)_util_get_list_next(iter);
372 if (obj && obj->obj_handle == handle) {
373 _util_deinit_list_iterator(iter);
378 ERR("Object not found in the list handle [%d] in store[0x%x]\n", handle, store->store_id);
379 _util_deinit_list_iterator(iter);
383 /* LCOV_EXCL_START */
384 mtp_obj_t *_entity_get_last_object_from_store(mtp_store_t *store,
387 mtp_obj_t *obj = NULL;
388 mtp_obj_t *temp_obj = NULL;
389 slist_iterator *iter = NULL;
391 retv_if(NULL == store, NULL);
393 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
395 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
399 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
401 temp_obj = (mtp_obj_t *)_util_get_list_next(iter);
402 if (temp_obj && temp_obj->obj_handle == handle)
406 _util_deinit_list_iterator(iter);
410 mtp_obj_t *_entity_get_object_from_store_by_path(mtp_store_t *store,
411 const mtp_char *file_path)
413 mtp_obj_t *obj = NULL;
414 slist_iterator *iter = NULL;
416 retv_if(NULL == store, NULL);
418 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
420 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
424 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
425 obj = (mtp_obj_t *)_util_get_list_next(iter);
427 ERR("Object is NULL");
431 if (!g_strcmp0(file_path, obj->file_path)) {
432 _util_deinit_list_iterator(iter);
436 ERR_SECURE("Object [%s] not found in the list\n", file_path);
437 _util_deinit_list_iterator(iter);
442 * _entity_get_objects_from_store
443 * called in case of PTP_OBJECTHANDLE_ALL
444 * fills the obj_array with objects matching the format code
446 mtp_uint32 _entity_get_objects_from_store(mtp_store_t *store,
447 mtp_uint32 obj_handle, mtp_uint32 fmt, ptp_array_t *obj_arr)
449 mtp_obj_t *obj = NULL;
450 slist_iterator *iter = NULL;
452 retv_if(store == NULL, 0);
453 retv_if(obj_arr == NULL, 0);
455 if (obj_handle != PTP_OBJECTHANDLE_ALL) {
456 ERR("Object Handle is not PTP_OBJECTHANDLE_ALL");
460 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
462 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
466 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
468 obj = (mtp_obj_t *)_util_get_list_next(iter);
470 ERR("Object is NULL");
473 if ((fmt == obj->obj_info->obj_fmt) ||
474 (fmt == PTP_FORMATCODE_ALL) ||
475 (fmt == PTP_FORMATCODE_NOTUSED)) {
476 _prop_append_ele_ptparray(obj_arr, obj->obj_handle);
479 _util_deinit_list_iterator(iter);
480 return obj_arr->num_ele;
483 mtp_uint32 _entity_get_objects_from_store_till_depth(mtp_store_t *store,
484 mtp_uint32 obj_handle, mtp_uint32 fmt_code, mtp_uint32 depth,
485 ptp_array_t *obj_arr)
487 retv_if(store == NULL, 0);
488 retv_if(obj_arr == NULL, 0);
490 if (PTP_OBJECTHANDLE_ALL == obj_handle) {
491 _entity_get_objects_from_store(store, obj_handle, fmt_code,
493 DBG("Number of object filled [%u]\n", obj_arr->num_ele);
494 return obj_arr->num_ele;
497 if (PTP_OBJECTHANDLE_ROOT != obj_handle)
498 _prop_append_ele_ptparray(obj_arr, obj_handle);
501 ptp_array_t *child_arr = NULL;
502 mtp_uint32 *ptr = NULL;
505 child_arr = _prop_alloc_ptparray(UINT32_TYPE);
506 if (child_arr == NULL) {
509 if (child_arr->array_entry == NULL) {
510 _prop_destroy_ptparray(child_arr);
516 _entity_get_child_handles_with_same_format(store, obj_handle,
517 fmt_code, child_arr);
518 ptr = child_arr->array_entry;
520 for (ii = 0; ii < child_arr->num_ele; ii++) {
521 _entity_get_objects_from_store_till_depth(store,
522 ptr[ii], fmt_code, depth, obj_arr);
524 _prop_destroy_ptparray(child_arr);
527 DBG("Handle[%u] : array count [%u]!!\n", obj_handle,
529 return obj_arr->num_ele;
532 mtp_uint32 _entity_get_objects_from_store_by_format(mtp_store_t *store,
533 mtp_uint32 format, ptp_array_t *obj_arr)
535 mtp_obj_t *obj = NULL;
536 slist_iterator *iter = NULL;
538 retv_if(store == NULL, 0);
539 retv_if(obj_arr == NULL, 0);
541 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
543 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
547 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
549 obj = (mtp_obj_t *)_util_get_list_next(iter);
550 if (obj == NULL || obj->obj_info == NULL)
552 if ((format == PTP_FORMATCODE_NOTUSED) ||
553 (format == obj->obj_info->obj_fmt) ||
554 ((format == PTP_FORMATCODE_ALL) &&
555 (obj->obj_info->obj_fmt !=
556 PTP_FMT_ASSOCIATION))) {
557 _prop_append_ele_ptparray(obj_arr,
558 (mtp_uint32)obj->obj_handle);
563 _util_deinit_list_iterator(iter);
564 return (obj_arr->num_ele);
567 mtp_uint32 _entity_get_num_object_with_same_format(mtp_store_t *store,
570 mtp_uint32 count = 0;
571 mtp_obj_t *obj = NULL;
572 slist_iterator *iter = NULL;
574 retv_if(store == NULL, 0);
576 if (PTP_FORMATCODE_NOTUSED == format)
577 return store->obj_list.nnodes;
579 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
581 ERR("Iterator init Fail, store id = [0x%x]\n", store->store_id);
585 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
587 obj = (mtp_obj_t *)_util_get_list_next(iter);
588 if (obj == NULL || obj->obj_info == NULL)
591 if ((obj->obj_info->obj_fmt == format) ||
592 (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION &&
593 PTP_FORMATCODE_ALL == format)) {
598 _util_deinit_list_iterator(iter);
602 mtp_uint32 _entity_get_num_children(mtp_store_t *store, mtp_uint32 h_parent,
605 mtp_uint32 count = 0;
606 mtp_obj_t *obj = NULL;
607 slist_iterator *iter = NULL;
609 retv_if(store == NULL, 0);
611 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
613 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
617 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
619 obj = (mtp_obj_t *)_util_get_list_next(iter);
620 if (obj == NULL || obj->obj_info == NULL)
623 if ((obj->obj_info->h_parent == h_parent) &&
624 ((format == obj->obj_info->obj_fmt) ||
625 (format == PTP_FORMATCODE_NOTUSED) ||
626 ((format == PTP_FORMATCODE_ALL) &&
627 (obj->obj_info->obj_fmt !=
628 PTP_FMT_ASSOCIATION)))) {
633 _util_deinit_list_iterator(iter);
637 mtp_uint32 _entity_get_child_handles(mtp_store_t *store, mtp_uint32 h_parent,
638 ptp_array_t *child_arr)
640 mtp_obj_t *obj = NULL;
641 slist_iterator *iter = NULL;
642 mtp_obj_t *parent_obj = NULL;
644 retv_if(store == NULL, 0);
645 retv_if(child_arr == NULL, 0);
647 parent_obj = _entity_get_object_from_store(store, h_parent);
649 if (NULL == parent_obj) {
650 ERR("parent object is NULL");
654 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
656 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
660 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
662 obj = (mtp_obj_t *)_util_get_list_next(iter);
663 if (obj == NULL || obj->obj_info == NULL)
666 if (obj->obj_info->h_parent == h_parent)
667 _prop_append_ele_ptparray(child_arr, obj->obj_handle);
670 _util_deinit_list_iterator(iter);
671 return child_arr->num_ele;
674 mtp_uint32 _entity_get_child_handles_with_same_format(mtp_store_t *store,
675 mtp_uint32 h_parent, mtp_uint32 format, ptp_array_t *child_arr)
677 mtp_obj_t *obj = NULL;
678 slist_iterator *iter = NULL;
680 retv_if(store == NULL, 0);
681 retv_if(child_arr == NULL, 0);
683 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
685 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
689 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
691 obj = (mtp_obj_t *)_util_get_list_next(iter);
692 if (obj == NULL || obj->obj_info == NULL)
695 if ((obj->obj_info->h_parent == h_parent) &&
696 ((obj->obj_info->obj_fmt == format) ||
697 (format == PTP_FORMATCODE_NOTUSED))) {
699 _prop_append_ele_ptparray(child_arr, obj->obj_handle);
704 _util_deinit_list_iterator(iter);
705 return child_arr->num_ele;
708 mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj,
709 mtp_uint32 format, mtp_uint16 *response, mtp_bool *atleast_one,
713 mtp_bool all_del = TRUE;
714 mtp_uint32 h_parent = 0;
715 obj_info_t *objinfo = NULL;
716 mtp_int32 ret = MTP_ERROR_NONE;
718 retv_if(store == NULL, 0);
720 if (TRUE == _transport_get_cancel_initialization() ||
721 TRUE == _transport_get_usb_discon_state()) {
722 ERR("Delete operation cancelled or USB is disconnected");
723 *response = PTP_RESPONSE_PARTIAL_DELETION;
727 if (NULL == obj || NULL == obj->obj_info || NULL == store) {
728 *response = PTP_RESPONSE_UNDEFINED;
732 objinfo = obj->obj_info;
734 if ((objinfo->obj_fmt != format) && (format != PTP_FORMATCODE_ALL) &&
735 (format != PTP_FORMATCODE_NOTUSED)) {
736 *response = PTP_RESPONSE_UNDEFINED;
740 if ((PTP_FORMATCODE_ALL == format) &&
741 (PTP_FMT_ASSOCIATION == objinfo->obj_fmt)) {
743 *response = PTP_RESPONSE_UNDEFINED;
747 #ifdef MTP_SUPPORT_SET_PROTECTION
748 /* Delete readonly files/folder */
750 objinfo->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
751 #endif /* MTP_SUPPORT_SET_PROTECTION */
753 if (PTP_FMT_ASSOCIATION == objinfo->obj_fmt) {
754 /* If this is an association, delete children first
755 * the reference list contain all the children handle
756 * or find a child each time;
760 ptp_array_t child_arr = { 0 };
761 mtp_obj_t *child_obj = NULL;
763 _prop_init_ptparray(&child_arr, UINT32_TYPE);
764 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
766 if (child_arr.num_ele) {
768 for (i = 0; i < child_arr.num_ele; i++) {
769 mtp_uint32 *ptr32 = child_arr.array_entry;
770 /*check cancel transaction*/
771 if (_transport_get_cancel_initialization() == TRUE ||
772 _transport_get_usb_discon_state() == TRUE) {
773 ERR("child handle. USB is disconnected \
774 format operation is cancelled.");
776 PTP_RESPONSE_PARTIAL_DELETION;
777 _prop_deinit_ptparray(&child_arr);
781 child_obj = _entity_get_object_from_store(store,
783 if (NULL == child_obj)
786 if (_entity_remove_object_mtp_store(store, child_obj,
787 format, response, atleast_one,
790 node = _util_delete_node(&(store->obj_list),
794 _entity_dealloc_mtp_obj(child_obj);
797 /*check cancel transaction*/
798 if (TRUE == _transport_get_cancel_initialization() ||
799 TRUE == _transport_get_usb_discon_state()) {
800 ERR("USB is disconnected format\
801 operation is cancelled.");
803 PTP_RESPONSE_PARTIAL_DELETION;
804 _prop_deinit_ptparray(&child_arr);
811 /* Non-Enumerated Folder */
812 mtp_uint32 num_of_deleted_file = 0;
813 mtp_uint32 num_of_file = 0;
815 ret = _util_remove_dir_children_recursive(obj->file_path,
816 &num_of_deleted_file, &num_of_file, read_only);
817 if (MTP_ERROR_GENERAL == ret ||
818 MTP_ERROR_ACCESS_DENIED == ret) {
819 ERR_SECURE("directory children deletion Fail [%s]\n",
821 *response = PTP_RESPONSE_GEN_ERROR;
822 if (MTP_ERROR_ACCESS_DENIED == ret)
824 PTP_RESPONSE_ACCESSDENIED;
825 _prop_deinit_ptparray(&child_arr);
828 if (num_of_file == 0)
829 DBG_SECURE("Folder[%s] is empty\n", obj->file_path);
830 else if (num_of_deleted_file == 0) {
831 DBG_SECURE("Folder[%s] contains only read-only files\n",
834 } else if (num_of_deleted_file < num_of_file) {
835 DBG("num of files[%d] is present in folder[%s]\
836 and number of deleted files[%d]\n",
837 num_of_file, obj->file_path,
838 num_of_deleted_file);
843 _prop_deinit_ptparray(&child_arr);
845 _util_scan_folder_contents_in_db(obj->file_path);
847 g_snprintf(g_last_deleted,
848 MTP_MAX_PATHNAME_SIZE + 1, "%s",
851 if (rmdir(obj->file_path) < 0) {
852 memset(g_last_deleted, 0,
853 MTP_MAX_PATHNAME_SIZE + 1);
854 *response = PTP_RESPONSE_GEN_ERROR;
857 PTP_RESPONSE_ACCESSDENIED;
861 ERR("all member in this folder is not deleted.");
864 #ifdef MTP_SUPPORT_SET_PROTECTION
865 size = objinfo->file_size;
866 #endif /* MTP_SUPPORT_SET_PROTECTION */
868 if (objinfo->protcn_status ==
869 PTP_PROTECTIONSTATUS_READONLY ||
870 objinfo->protcn_status ==
871 MTP_PROTECTIONSTATUS_READONLY_DATA) {
872 *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
876 /* delete the real file */
877 g_snprintf(g_last_deleted, MTP_MAX_PATHNAME_SIZE + 1,
878 "%s", obj->file_path);
879 if (remove(obj->file_path) < 0) {
880 memset(g_last_deleted, 0,
881 MTP_MAX_PATHNAME_SIZE + 1);
882 *response = PTP_RESPONSE_GEN_ERROR;
884 *response = PTP_RESPONSE_ACCESSDENIED;
889 /* Upate store's available space */
890 store->store_info.free_space += size;
894 *response = PTP_RESPONSE_OK;
895 /* delete references;*/
896 h_parent = objinfo->h_parent;
897 if (h_parent != PTP_OBJECTHANDLE_ROOT) {
898 mtp_obj_t *parent_obj =
899 _entity_get_object_from_store(store, h_parent);
900 if (NULL != parent_obj) {
901 _entity_remove_reference_child_array(parent_obj,
905 } else if (*atleast_one) {
906 *response = PTP_RESPONSE_PARTIAL_DELETION;
909 *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
916 mtp_uint16 _entity_delete_obj_mtp_store(mtp_store_t *store,
917 mtp_uint32 obj_handle, mtp_uint32 fmt, mtp_bool read_only)
920 mtp_obj_t *obj = NULL;
921 mtp_bool all_del = TRUE;
922 mtp_bool atleas_one = FALSE;
924 retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
926 if (PTP_STORAGEACCESS_R == store->store_info.access) {
927 ERR("Read only store");
928 return PTP_RESPONSE_STORE_READONLY;
931 if (PTP_OBJECTHANDLE_ALL == obj_handle) {
932 slist_node_t *node = NULL;
933 node = store->obj_list.start;
934 while (NULL != node) {
935 if (TRUE == _transport_get_cancel_initialization() ||
936 TRUE == _transport_get_usb_discon_state()) {
937 ERR("USB is disconnected format\
938 operation is cancelled.");
939 response = PTP_RESPONSE_GEN_ERROR;
942 /* protect from disconnect USB */
943 if (NULL == store || NULL == node ||
944 NULL == node->value) {
945 response = PTP_RESPONSE_GEN_ERROR;
949 obj = (mtp_obj_t *)node->value;
950 if (_entity_remove_object_mtp_store(store, obj,
951 fmt, &response, &atleas_one, read_only)) {
953 slist_node_t *temp = NULL;
956 temp = _util_delete_node(&(store->obj_list), obj);
958 _util_delete_file_from_db(obj->file_path);
959 _entity_dealloc_mtp_obj(obj);
965 case PTP_RESPONSE_PARTIAL_DELETION:
968 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
969 case PTP_RESPONSE_ACCESSDENIED:
972 case PTP_RESPONSE_UNDEFINED:
979 DBG("object handle is not PTP_OBJECTHANDLE_ALL. [%u]\n",
981 obj = _entity_get_object_from_store(store, obj_handle);
984 if (_entity_remove_object_mtp_store(store, obj, PTP_FORMATCODE_NOTUSED,
985 &response, &atleas_one, read_only)) {
986 slist_node_t *temp = NULL;
988 temp = _util_delete_node(&(store->obj_list), obj);
990 _util_delete_file_from_db(obj->file_path);
991 _entity_dealloc_mtp_obj(obj);
994 case PTP_RESPONSE_PARTIAL_DELETION:
997 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
998 case PTP_RESPONSE_ACCESSDENIED:
1001 case PTP_RESPONSE_UNDEFINED:
1011 response = PTP_RESPONSE_OK;
1012 else if (atleas_one)
1013 response = PTP_RESPONSE_PARTIAL_DELETION;
1018 mtp_uint32 _entity_get_object_tree_size(mtp_store_t *store, mtp_obj_t *obj)
1021 mtp_uint64 size = 0;
1023 retv_if(store == NULL, 0);
1024 retv_if(obj == NULL, 0);
1026 if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
1027 size = obj->obj_info->file_size;
1029 ptp_array_t child_arr = { 0 };
1030 mtp_obj_t *child_obj = NULL;
1032 _prop_init_ptparray(&child_arr, UINT32_TYPE);
1034 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
1036 for (i = 0; i < child_arr.num_ele; i++) {
1037 mtp_uint32 *ptr32 = child_arr.array_entry;
1038 child_obj = _entity_get_object_from_store(store,
1040 size += _entity_get_object_tree_size(store, child_obj);
1042 _prop_deinit_ptparray(&child_arr);
1048 mtp_bool _entity_check_if_B_parent_of_A(mtp_store_t *store,
1049 mtp_uint32 handleA, mtp_uint32 handleB)
1052 mtp_obj_t *obj = NULL;
1053 ptp_array_t child_arr = {0};
1055 retv_if(store == NULL, FALSE);
1057 _prop_init_ptparray(&child_arr, UINT32_TYPE);
1058 _entity_get_child_handles(store, handleB, &child_arr);
1060 for (i = 0; i < child_arr.num_ele; i++) {
1061 mtp_uint32 *ptr32 = child_arr.array_entry;
1062 if (handleA == ptr32[i]) {
1063 _prop_deinit_ptparray(&child_arr);
1067 obj = _entity_get_object_from_store(store, ptr32[i]);
1068 if (obj == NULL || obj->obj_info == NULL ||
1069 obj->obj_info->obj_fmt ==
1070 PTP_FMT_ASSOCIATION) {
1073 if (_entity_check_if_B_parent_of_A(store, handleA, ptr32[i])) {
1074 _prop_deinit_ptparray(&child_arr);
1078 _prop_deinit_ptparray(&child_arr);
1081 /* LCOV_EXCL_STOP */
1083 mtp_uint32 _entity_generate_next_obj_handle(void)
1085 return g_next_obj_handle++;
1088 /* LCOV_EXCL_START */
1089 mtp_uint16 _entity_format_store(mtp_store_t *store, mtp_uint32 fs_format)
1091 mtp_uint16 response;
1093 retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
1095 /* Is store ready only? */
1096 if (store->store_info.access == PTP_STORAGEACCESS_R) {
1097 ERR("Read only storage");
1098 return PTP_RESPONSE_STORE_READONLY;
1101 /* Is FilesystemFormat supported? */
1102 if ((fs_format != PTP_FILESYSTEMTYPE_UNDEFINED) &&
1103 (fs_format != PTP_FILESYSTEMTYPE_FLAT) &&
1104 (fs_format != PTP_FILESYSTEMTYPE_HIERARCHICAL) &&
1105 (fs_format != PTP_FILESYSTEMTYPE_DCF)) {
1106 ERR("File system type not supported");
1107 return PTP_RESPONSE_INVALIDPARAM;
1110 /* check cancel transaction */
1111 if (TRUE == _transport_get_cancel_initialization() ||
1112 TRUE == _transport_get_usb_discon_state()) {
1113 ERR("USB is disconnected format operation is cancelled.");
1114 return PTP_RESPONSE_GEN_ERROR;
1117 response = _entity_delete_obj_mtp_store(store, PTP_OBJECTHANDLE_ALL,
1118 PTP_FORMATCODE_NOTUSED, TRUE);
1120 if (PTP_RESPONSE_OK != response) {
1121 ERR("format is not completed [0x%X].\n", response);
1125 return PTP_RESPONSE_OK;
1128 void _entity_destroy_mtp_store(mtp_store_t *store)
1131 slist_node_t *node = NULL;
1132 slist_node_t *next_node = NULL;
1134 ret_if(store == NULL);
1136 for (ii = 0, next_node = store->obj_list.start;
1137 ii < store->obj_list.nnodes; ii++) {
1140 next_node = node->link;
1141 _entity_dealloc_mtp_obj((mtp_obj_t *)node->value);
1145 _util_init_list(&(store->obj_list));
1148 /* LCOV_EXCL_STOP */
1150 void _entity_store_recursive_enum_folder_objects(mtp_store_t *store,
1154 mtp_char file_name[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1155 mtp_bool status = FALSE;
1156 mtp_obj_t *obj = NULL;
1157 dir_entry_t entry = { { 0 }, 0 };
1158 mtp_char *folder_name;
1159 mtp_uint32 h_parent;
1161 ret_if(NULL == store);
1164 folder_name = store->root_path;
1165 h_parent = PTP_OBJECTHANDLE_ROOT;
1167 folder_name = pobj->file_path;
1168 h_parent = pobj->obj_handle;
1171 if (folder_name == NULL || folder_name[0] != '/') {
1172 ERR("foldername has no root slash!!");
1176 if (FALSE == _util_ifind_first(folder_name, &h_dir, &entry)) {
1177 DBG("No more files");
1182 if (TRUE == _transport_get_usb_discon_state()) {
1183 /* LCOV_EXCL_START */
1184 DBG("USB is disconnected");
1185 if (closedir(h_dir) < 0)
1186 ERR("Close directory Fail");
1189 /* LCOV_EXCL_STOP */
1192 _util_get_file_name(entry.filename, file_name);
1193 if (0 == strlen(file_name)) {
1194 ERR("szFilename size is 0");
1198 if (file_name[0] == '.') {
1199 DBG_SECURE("Hidden file [%s]\n", entry.filename);
1200 } else if (entry.type == MTP_DIR_TYPE) {
1201 obj = _entity_add_folder_to_store(store, h_parent,
1202 entry.filename, file_name, &entry);
1205 ERR("pObject is NULL");
1209 _entity_store_recursive_enum_folder_objects(store, obj);
1210 } else if (entry.type == MTP_FILE_TYPE) {
1211 _entity_add_file_to_store(store, h_parent,
1212 entry.filename, file_name, &entry);
1214 DBG("UNKNOWN TYPE");
1217 status = (mtp_bool)_util_ifind_next(folder_name, h_dir,
1221 if (closedir(h_dir) < 0)
1222 ERR("close directory fail");
1224 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
1225 _inoti_add_watch_for_fs_events(folder_name);
1226 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
1231 /* LCOV_EXCL_START */
1232 void _entity_list_modified_files(mtp_uint32 minutes)
1237 mtp_char command[FIND_CMD_LEN] = { 0 };
1239 if (TRUE == _device_is_store_mounted(MTP_STORAGE_INTERNAL)) {
1240 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1241 _util_get_internal_path(inter_path);
1243 g_snprintf(command, FIND_CMD_LEN, FIND_CMD,
1244 inter_path, minutes,
1245 MTP_FILES_MODIFIED_FILES);
1246 DBG("find query is [%s]\n", command);
1247 ret = _util_system_cmd_wait(command);
1249 if (WIFSIGNALED(ret) &&
1250 (WTERMSIG(ret) == SIGINT ||
1251 WTERMSIG(ret) == SIGQUIT)) {
1256 if (TRUE == _device_is_store_mounted(MTP_STORAGE_EXTERNAL)) {
1257 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1258 _util_get_external_path(ext_path);
1260 g_snprintf(command, FIND_CMD_LEN, FIND_CMD,
1262 MTP_FILES_MODIFIED_FILES);
1263 DBG("find query is [%s]\n", command);
1264 ret = _util_system_cmd_wait(command);
1266 if (WIFSIGNALED(ret) &&
1267 (WTERMSIG(ret) == SIGINT ||
1268 WTERMSIG(ret) == SIGQUIT)) {
1277 void _entity_copy_store_data(mtp_store_t *dst, mtp_store_t *src)
1279 dst->store_id = src->store_id;
1280 dst->root_path = src->root_path;
1281 dst->is_hidden = src->is_hidden;
1283 memcpy(&(dst->obj_list), &(src->obj_list), sizeof(slist_t));
1284 _entity_update_store_info_run_time(&(dst->store_info), dst->root_path);
1285 _prop_copy_ptpstring(&(dst->store_info.store_desc), &(src->store_info.store_desc));
1286 _prop_copy_ptpstring(&(dst->store_info.vol_label), &(src->store_info.vol_label));
1290 /* LCOV_EXCL_STOP */