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>
22 #include "mtp_support.h"
23 #include "mtp_device.h"
24 #include "mtp_media_info.h"
25 #include "mtp_transport.h"
26 #include "mtp_inoti_handler.h"
29 extern mtp_char g_last_deleted[MTP_MAX_PATHNAME_SIZE + 1];
30 static mtp_uint32 g_next_obj_handle = 1;
33 static inline mtp_bool UTIL_CHECK_LIST_NEXT(slist_iterator *iter)
35 return (iter && iter->node_ptr) ? TRUE : FALSE;
38 static void __init_store_info(store_info_t *info)
42 memset(info, 0x00, sizeof(store_info_t));
44 info->store_type = PTP_STORAGETYPE_FIXEDRAM;
45 info->fs_type = PTP_FILESYSTEMTYPE_DCF;
46 info->access = PTP_STORAGEACCESS_RWD;
48 info->capacity = MTP_MAX_STORAGE;
49 info->free_space = MTP_MAX_STORAGE - 1;
50 info->free_space_in_objs = MTP_MAX_STORAGE_IN_OBJTS;
55 static void __init_store_info_params(store_info_t *info,
56 mtp_uint64 capacity, mtp_uint16 store_type, mtp_uint16 fs_type,
57 mtp_uint16 access, mtp_wchar *store_desc, mtp_wchar *label)
59 info->store_type = store_type;
60 info->fs_type = fs_type;
61 info->access = access;
63 info->capacity = capacity;
64 info->free_space = capacity;
65 info->free_space_in_objs = MTP_MAX_STORAGE_IN_OBJTS;
67 _prop_copy_char_to_ptpstring(&(info->store_desc), store_desc, WCHAR_TYPE);
68 _prop_copy_char_to_ptpstring(&(info->vol_label), label, WCHAR_TYPE);
72 void _entity_update_store_info_run_time(store_info_t *info,
75 fs_info_t fs_info = { 0 };
78 ret_if(root_path == NULL);
80 if (FALSE == _util_get_filesystem_info(root_path, &fs_info)) {
81 ERR("_util_get_filesystem_info fail [%s]\n", root_path);
85 info->capacity = fs_info.disk_size;
86 info->free_space = fs_info.avail_size;
91 mtp_bool _entity_get_store_path_by_id(mtp_uint32 store_id, mtp_char *path)
93 char sto_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
96 case MTP_INTERNAL_STORE_ID:
97 _util_get_internal_path(sto_path);
98 g_strlcpy(path, sto_path,
99 MTP_MAX_PATHNAME_SIZE + 1);
101 case MTP_EXTERNAL_STORE_ID:
102 _util_get_external_path(sto_path);
103 g_strlcpy(path, sto_path,
104 MTP_MAX_PATHNAME_SIZE + 1);
107 ERR("No valid match for the store id [0x%x]\n", store_id);
114 mtp_uint32 _entity_get_store_info_size(store_info_t *info)
116 mtp_uint32 size = FIXED_LENGTH_MEMBERS_MTPSTORE_SIZE;
118 size += _prop_size_ptpstring(&(info->store_desc));
119 size += _prop_size_ptpstring(&(info->vol_label));
124 mtp_uint32 _entity_pack_store_info(store_info_t *info, mtp_uchar *buf,
127 mtp_uint32 num_bytes = 0;
129 retv_if(buf == NULL, 0);
131 if (buf_sz < _entity_get_store_info_size(info)) {
132 ERR("Buffer size is less [%u]\n", buf_sz);
135 #ifdef __BIG_ENDIAN__
136 memcpy(&(buf[num_bytes]), &(info->store_type),
137 sizeof(info->StorageType));
138 _util_conv_byte_order(buf, sizeof(info->store_type));
139 num_bytes += sizeof(info->store_type);
141 memcpy(&(buf[num_bytes]), &(info->fs_type), sizeof(info->fs_type));
142 _util_conv_byte_order(buf, sizeof(info->fs_type));
143 num_bytes += sizeof(info->fs_type);
145 memcpy(&(buf[num_bytes]), &(info->access), sizeof(info->access));
146 _util_conv_byte_order(buf, sizeof(info->access));
147 num_bytes += sizeof(info->access);
149 memcpy(&(buf[num_bytes]), &(info->capacity), sizeof(info->capacity));
150 _util_conv_byte_order(buf, sizeof(info->capacity));
151 num_bytes += sizeof(info->capacity);
153 memcpy(&(buf[num_bytes]), &(info->free_space),
154 sizeof(info->free_space));
155 _util_conv_byte_order(buf, sizeof(info->free_space));
156 num_bytes += sizeof(info->free_space);
158 memcpy(&(buf[num_bytes]), &(info->free_space_in_objs),
159 sizeof(info->free_space_in_objs));
160 _util_conv_byte_order(buf, sizeof(info->free_space_in_objs));
161 num_bytes += sizeof(info->free_space_in_objs);
162 #else /*__BIG_ENDIAN__*/
163 memcpy(buf, &(info->store_type), sizeof(mtp_uint16) *3);
164 num_bytes += sizeof(mtp_uint16) * 3;
165 memcpy(&(buf[num_bytes]), &(info->capacity),
166 sizeof(mtp_uint64) * 2 + sizeof(mtp_uint32));
167 num_bytes += sizeof(mtp_uint64) * 2 + sizeof(mtp_uint32);
168 #endif /*__BIG_ENDIAN__*/
169 num_bytes += _prop_pack_ptpstring(&(info->store_desc), buf + num_bytes,
170 _prop_size_ptpstring(&(info->store_desc)));
172 num_bytes += _prop_pack_ptpstring(&(info->vol_label), buf + num_bytes,
173 _prop_size_ptpstring(&(info->vol_label)));
178 mtp_uint32 _entity_get_store_id_by_path(const mtp_char *path_name)
180 mtp_uint32 store_id = 0;
181 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
182 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
184 retv_if(NULL == path_name, FALSE);
186 _util_get_external_path(ext_path);
187 _util_get_internal_path(inter_path);
189 if (!strncmp(path_name, inter_path,
190 strlen(inter_path))) {
191 store_id = MTP_INTERNAL_STORE_ID;
192 } else if (!strncmp(path_name, ext_path,
194 store_id = MTP_EXTERNAL_STORE_ID;
197 DBG_SECURE("Path : %s, store_id : 0x%x\n", path_name, store_id);
202 mtp_bool _entity_init_mtp_store(mtp_store_t *store, mtp_uint32 store_id,
203 mtp_char *store_path)
205 mtp_char temp[MTP_SERIAL_LEN_MAX + 1] = { 0 };
206 mtp_wchar wtemp[MTP_MAX_REG_STRING + 1] = { 0 };
207 mtp_char serial[MTP_MAX_REG_STRING + 1] = { 0 };
208 mtp_wchar wserial[MTP_MAX_REG_STRING + 1] = { 0 };
210 retv_if(store == NULL, FALSE);
212 store->store_id = store_id;
213 store->root_path = g_strdup(store_path);
215 __init_store_info(&(store->store_info));
216 _entity_update_store_info_run_time(&(store->store_info),
219 _device_get_serial(temp, sizeof(temp));
220 g_snprintf(serial, sizeof(serial), "%s-%x", temp, store_id);
221 _util_utf8_to_utf16(wserial, sizeof(wserial) / WCHAR_SIZ, serial);
224 case MTP_INTERNAL_STORE_ID:
225 store->is_hidden = FALSE;
226 _util_utf8_to_utf16(wtemp, sizeof(wtemp) / WCHAR_SIZ,
227 MTP_STORAGE_DESC_INT);
228 __init_store_info_params(&(store->store_info),
229 store->store_info.capacity, PTP_STORAGETYPE_FIXEDRAM,
230 PTP_FILESYSTEMTYPE_HIERARCHICAL, PTP_STORAGEACCESS_RWD,
234 case MTP_EXTERNAL_STORE_ID:
235 store->is_hidden = FALSE;
236 _util_utf8_to_utf16(wtemp, sizeof(wtemp) / WCHAR_SIZ,
237 MTP_STORAGE_DESC_EXT);
238 __init_store_info_params(&(store->store_info),
239 store->store_info.capacity,
240 PTP_STORAGETYPE_REMOVABLERAM,
241 PTP_FILESYSTEMTYPE_HIERARCHICAL,
242 PTP_STORAGEACCESS_RWD, wtemp, wserial);
246 ERR("store initialization Fail");
250 _util_init_list(&(store->obj_list));
255 mtp_obj_t *_entity_add_file_to_store(mtp_store_t *store, mtp_uint32 h_parent,
256 mtp_char *file_path, mtp_char *file_name, dir_entry_t *file_info)
258 mtp_obj_t *obj = NULL;
260 retv_if(NULL == store, NULL);
262 obj = _entity_alloc_mtp_object();
264 ERR("Memory allocation Fail");
268 if (_entity_init_mtp_object_params(obj, store->store_id, h_parent,
269 file_path, file_name, file_info) == FALSE) {
270 ERR("_entity_init_mtp_object_params Fail");
275 _entity_add_object_to_store(store, obj);
279 mtp_obj_t *_entity_add_folder_to_store(mtp_store_t *store, mtp_uint32 h_parent,
280 mtp_char *file_path, mtp_char *file_name, dir_entry_t *file_info)
282 mtp_obj_t *obj = NULL;
284 retv_if(NULL == store, NULL);
286 obj = _entity_alloc_mtp_object();
288 ERR("Memory allocation Fail");
292 if (_entity_init_mtp_object_params(obj, store->store_id, h_parent,
293 file_path, file_name, file_info) == FALSE) {
294 ERR("_entity_init_mtp_object_params Fail");
299 _entity_add_object_to_store(store, obj);
303 mtp_bool _entity_add_object_to_store(mtp_store_t *store, mtp_obj_t *obj)
305 mtp_obj_t *par_obj = NULL;
307 retv_if(obj == NULL, FALSE);
308 retv_if(NULL == store, FALSE);
309 retv_if(obj->obj_info == NULL, FALSE);
311 if (_util_add_node(&(store->obj_list), obj) == FALSE) {
312 ERR("Node add to list Fail");
317 if (PTP_OBJECTHANDLE_ROOT != obj->obj_info->h_parent) {
318 par_obj = _entity_get_object_from_store(store, obj->obj_info->h_parent);
320 _entity_add_reference_child_array(par_obj, obj->obj_handle);
326 mtp_obj_t *_entity_get_object_from_store(mtp_store_t *store, mtp_uint32 handle)
328 mtp_obj_t *obj = NULL;
329 slist_iterator *iter = NULL;
331 retv_if(NULL == store, NULL);
333 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
335 ERR("Iterator init Fail, Store id = [0x%x]\n", store->store_id);
339 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
340 obj = (mtp_obj_t *)_util_get_list_next(iter);
342 if (obj && obj->obj_handle == handle) {
343 _util_deinit_list_iterator(iter);
348 ERR("Object not found in the list handle [%d] in store[0x%x]\n", handle, store->store_id);
349 _util_deinit_list_iterator(iter);
353 mtp_obj_t *_entity_get_last_object_from_store(mtp_store_t *store,
356 mtp_obj_t *obj = NULL;
357 mtp_obj_t *temp_obj = NULL;
358 slist_iterator *iter = NULL;
360 retv_if(NULL == store, NULL);
362 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
364 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
368 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
370 temp_obj = (mtp_obj_t *)_util_get_list_next(iter);
371 if (temp_obj && temp_obj->obj_handle == handle)
375 _util_deinit_list_iterator(iter);
379 mtp_obj_t *_entity_get_object_from_store_by_path(mtp_store_t *store,
382 mtp_obj_t *obj = NULL;
383 slist_iterator *iter = NULL;
385 retv_if(NULL == store, NULL);
387 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
389 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
393 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
394 obj = (mtp_obj_t *)_util_get_list_next(iter);
396 ERR("Object is NULL");
400 if (!g_strcmp0(file_path, obj->file_path)) {
401 _util_deinit_list_iterator(iter);
405 ERR_SECURE("Object [%s] not found in the list\n", file_path);
406 _util_deinit_list_iterator(iter);
411 * _entity_get_objects_from_store
412 * called in case of PTP_OBJECTHANDLE_ALL
413 * fills the obj_array with objects matching the format code
415 mtp_uint32 _entity_get_objects_from_store(mtp_store_t *store,
416 mtp_uint32 obj_handle, mtp_uint32 fmt, ptp_array_t *obj_arr)
418 mtp_obj_t *obj = NULL;
419 slist_iterator *iter = NULL;
421 retv_if(store == NULL, 0);
422 retv_if(obj_arr == NULL, 0);
424 if (obj_handle != PTP_OBJECTHANDLE_ALL) {
425 ERR("Object Handle is not PTP_OBJECTHANDLE_ALL");
429 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
431 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
435 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
437 obj = (mtp_obj_t *)_util_get_list_next(iter);
439 ERR("Object is NULL");
442 if ((fmt == obj->obj_info->obj_fmt) ||
443 (fmt == PTP_FORMATCODE_ALL) ||
444 (fmt == PTP_FORMATCODE_NOTUSED)) {
445 _prop_append_ele_ptparray(obj_arr, obj->obj_handle);
448 _util_deinit_list_iterator(iter);
449 return obj_arr->num_ele;
452 mtp_uint32 _entity_get_objects_from_store_till_depth(mtp_store_t *store,
453 mtp_uint32 obj_handle, mtp_uint32 fmt_code, mtp_uint32 depth,
454 ptp_array_t *obj_arr)
456 retv_if(store == NULL, 0);
457 retv_if(obj_arr == NULL, 0);
459 if (PTP_OBJECTHANDLE_ALL == obj_handle) {
460 _entity_get_objects_from_store(store, obj_handle, fmt_code,
462 DBG("Number of object filled [%u]\n", obj_arr->num_ele);
463 return obj_arr->num_ele;
466 if (PTP_OBJECTHANDLE_ROOT != obj_handle)
467 _prop_append_ele_ptparray(obj_arr, obj_handle);
470 ptp_array_t *child_arr = NULL;
471 mtp_uint32 *ptr = NULL;
474 child_arr = _prop_alloc_ptparray(UINT32_TYPE);
475 if (child_arr == NULL || child_arr->array_entry == NULL)
480 _entity_get_child_handles_with_same_format(store, obj_handle,
481 fmt_code, child_arr);
482 ptr = child_arr->array_entry;
484 for (ii = 0; ii < child_arr->num_ele; ii++) {
485 _entity_get_objects_from_store_till_depth(store,
486 ptr[ii], fmt_code, depth, obj_arr);
488 _prop_destroy_ptparray(child_arr);
491 DBG("Handle[%u] : array count [%u]!!\n", obj_handle,
493 return obj_arr->num_ele;
496 mtp_uint32 _entity_get_objects_from_store_by_format(mtp_store_t *store,
497 mtp_uint32 format, ptp_array_t *obj_arr)
499 mtp_obj_t *obj = NULL;
500 slist_iterator *iter = NULL;
502 retv_if(store == NULL, 0);
503 retv_if(obj_arr == NULL, 0);
505 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
507 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
511 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
513 obj = (mtp_obj_t *)_util_get_list_next(iter);
514 if (obj == NULL || obj->obj_info == NULL)
516 if ((format == PTP_FORMATCODE_NOTUSED) ||
517 (format == obj->obj_info->obj_fmt) ||
518 ((format == PTP_FORMATCODE_ALL) &&
519 (obj->obj_info->obj_fmt !=
520 PTP_FMT_ASSOCIATION))) {
521 _prop_append_ele_ptparray(obj_arr,
522 (mtp_uint32)obj->obj_handle);
527 _util_deinit_list_iterator(iter);
528 return (obj_arr->num_ele);
531 mtp_uint32 _entity_get_num_object_with_same_format(mtp_store_t *store,
534 mtp_uint32 count = 0;
535 mtp_obj_t *obj = NULL;
536 slist_iterator *iter = NULL;
538 retv_if(store == NULL, 0);
540 if (PTP_FORMATCODE_NOTUSED == format)
541 return store->obj_list.nnodes;
543 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
545 ERR("Iterator init Fail, store id = [0x%x]\n", store->store_id);
549 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
551 obj = (mtp_obj_t *)_util_get_list_next(iter);
552 if (obj == NULL || obj->obj_info == NULL)
555 if ((obj->obj_info->obj_fmt == format) ||
556 (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION &&
557 PTP_FORMATCODE_ALL == format)) {
562 _util_deinit_list_iterator(iter);
566 mtp_uint32 _entity_get_num_children(mtp_store_t *store, mtp_uint32 h_parent,
569 mtp_uint32 count = 0;
570 mtp_obj_t *obj = NULL;
571 slist_iterator *iter = NULL;
573 retv_if(store == NULL, 0);
575 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
577 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
581 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
583 obj = (mtp_obj_t *)_util_get_list_next(iter);
584 if (obj == NULL || obj->obj_info == NULL)
587 if ((obj->obj_info->h_parent == h_parent) &&
588 ((format == obj->obj_info->obj_fmt) ||
589 (format == PTP_FORMATCODE_NOTUSED) ||
590 ((format == PTP_FORMATCODE_ALL) &&
591 (obj->obj_info->obj_fmt !=
592 PTP_FMT_ASSOCIATION)))) {
597 _util_deinit_list_iterator(iter);
601 mtp_uint32 _entity_get_child_handles(mtp_store_t *store, mtp_uint32 h_parent,
602 ptp_array_t *child_arr)
604 mtp_obj_t *obj = NULL;
605 slist_iterator *iter = NULL;
606 mtp_obj_t *parent_obj = NULL;
608 retv_if(store == NULL, 0);
609 retv_if(child_arr == NULL, 0);
611 parent_obj = _entity_get_object_from_store(store, h_parent);
613 if (NULL == parent_obj) {
614 ERR("parent object is NULL");
618 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
620 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
624 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
626 obj = (mtp_obj_t *)_util_get_list_next(iter);
627 if (obj == NULL || obj->obj_info == NULL)
630 if (obj->obj_info->h_parent == h_parent)
631 _prop_append_ele_ptparray(child_arr, obj->obj_handle);
634 _util_deinit_list_iterator(iter);
635 return child_arr->num_ele;
638 mtp_uint32 _entity_get_child_handles_with_same_format(mtp_store_t *store,
639 mtp_uint32 h_parent, mtp_uint32 format, ptp_array_t *child_arr)
641 mtp_obj_t *obj = NULL;
642 slist_iterator *iter = NULL;
644 retv_if(store == NULL, 0);
645 retv_if(child_arr == NULL, 0);
647 iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
649 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
653 while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
655 obj = (mtp_obj_t *)_util_get_list_next(iter);
656 if (obj == NULL || obj->obj_info == NULL)
659 if ((obj->obj_info->h_parent == h_parent) &&
660 ((obj->obj_info->obj_fmt == format) ||
661 (format == PTP_FORMATCODE_NOTUSED))) {
663 _prop_append_ele_ptparray(child_arr, obj->obj_handle);
668 _util_deinit_list_iterator(iter);
669 return child_arr->num_ele;
672 mtp_bool _entity_remove_object_mtp_store(mtp_store_t *store, mtp_obj_t *obj,
673 mtp_uint32 format, mtp_uint16 *response, mtp_bool *atleast_one,
677 mtp_bool all_del = TRUE;
678 mtp_uint32 h_parent = 0;
679 obj_info_t *objinfo = NULL;
680 mtp_int32 ret = MTP_ERROR_NONE;
682 retv_if(store == NULL, 0);
684 if (TRUE == _transport_get_cancel_initialization() ||
685 TRUE == _transport_get_usb_discon_state()) {
686 ERR("Delete operation cancelled or USB is disconnected");
687 *response = PTP_RESPONSE_PARTIAL_DELETION;
691 if (NULL == obj || NULL == obj->obj_info || NULL == store) {
692 *response = PTP_RESPONSE_UNDEFINED;
696 objinfo = obj->obj_info;
698 if ((objinfo->obj_fmt != format) && (format != PTP_FORMATCODE_ALL) &&
699 (format != PTP_FORMATCODE_NOTUSED)) {
700 *response = PTP_RESPONSE_UNDEFINED;
704 if ((PTP_FORMATCODE_ALL == format) &&
705 (PTP_FMT_ASSOCIATION == objinfo->obj_fmt)) {
707 *response = PTP_RESPONSE_UNDEFINED;
711 #ifdef MTP_SUPPORT_SET_PROTECTION
712 /* Delete readonly files/folder */
714 objinfo->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
715 #endif /* MTP_SUPPORT_SET_PROTECTION */
717 if (PTP_FMT_ASSOCIATION == objinfo->obj_fmt) {
718 /* If this is an association, delete children first
719 * the reference list contain all the children handle
720 * or find a child each time;
724 ptp_array_t child_arr = { 0 };
725 mtp_obj_t *child_obj = NULL;
727 _prop_init_ptparray(&child_arr, UINT32_TYPE);
728 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
730 if (child_arr.num_ele) {
732 for (i = 0; i < child_arr.num_ele; i++) {
733 mtp_uint32 *ptr32 = child_arr.array_entry;
734 /*check cancel transaction*/
735 if (_transport_get_cancel_initialization() == TRUE ||
736 _transport_get_usb_discon_state() == TRUE) {
737 ERR("child handle. USB is disconnected \
738 format operation is cancelled.");
740 PTP_RESPONSE_PARTIAL_DELETION;
744 child_obj = _entity_get_object_from_store(store,
746 if (NULL == child_obj)
749 if (_entity_remove_object_mtp_store(store, child_obj,
750 format, response, atleast_one,
753 node = _util_delete_node(&(store->obj_list),
757 _entity_dealloc_mtp_obj(child_obj);
760 /*check cancel transaction*/
761 if (TRUE == _transport_get_cancel_initialization() ||
762 TRUE == _transport_get_usb_discon_state()) {
763 ERR("USB is disconnected format\
764 operation is cancelled.");
766 PTP_RESPONSE_PARTIAL_DELETION;
772 _prop_deinit_ptparray(&child_arr);
775 /* Non-Enumerated Folder */
776 mtp_uint32 num_of_deleted_file = 0;
777 mtp_uint32 num_of_file = 0;
779 ret = _util_remove_dir_children_recursive(obj->file_path,
780 &num_of_deleted_file, &num_of_file, read_only);
781 if (MTP_ERROR_GENERAL == ret ||
782 MTP_ERROR_ACCESS_DENIED == ret) {
783 ERR_SECURE("directory children deletion Fail [%s]\n",
785 *response = PTP_RESPONSE_GEN_ERROR;
786 if (MTP_ERROR_ACCESS_DENIED == ret)
788 PTP_RESPONSE_ACCESSDENIED;
791 if (num_of_file == 0)
792 DBG_SECURE("Folder[%s] is empty\n", obj->file_path);
793 else if (num_of_deleted_file == 0) {
794 DBG_SECURE("Folder[%s] contains only read-only files\n",
797 } else if (num_of_deleted_file < num_of_file) {
798 DBG("num of files[%d] is present in folder[%s]\
799 and number of deleted files[%d]\n",
800 num_of_file, obj->file_path,
801 num_of_deleted_file);
806 _util_scan_folder_contents_in_db(obj->file_path);
808 g_snprintf(g_last_deleted,
809 MTP_MAX_PATHNAME_SIZE + 1, "%s",
812 if (rmdir(obj->file_path) < 0) {
813 memset(g_last_deleted, 0,
814 MTP_MAX_PATHNAME_SIZE + 1);
815 *response = PTP_RESPONSE_GEN_ERROR;
818 PTP_RESPONSE_ACCESSDENIED;
822 ERR("all member in this folder is not deleted.");
825 #ifdef MTP_SUPPORT_SET_PROTECTION
826 size = objinfo->file_size;
827 #endif /* MTP_SUPPORT_SET_PROTECTION */
829 if (objinfo->protcn_status ==
830 PTP_PROTECTIONSTATUS_READONLY ||
831 objinfo->protcn_status ==
832 MTP_PROTECTIONSTATUS_READONLY_DATA) {
833 *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
837 /* delete the real file */
838 g_snprintf(g_last_deleted, MTP_MAX_PATHNAME_SIZE + 1,
839 "%s", obj->file_path);
840 if (remove(obj->file_path) < 0) {
841 memset(g_last_deleted, 0,
842 MTP_MAX_PATHNAME_SIZE + 1);
843 *response = PTP_RESPONSE_GEN_ERROR;
845 *response = PTP_RESPONSE_ACCESSDENIED;
850 /* Upate store's available space */
851 store->store_info.free_space += size;
855 *response = PTP_RESPONSE_OK;
856 /* delete references;*/
857 h_parent = objinfo->h_parent;
858 if (h_parent != PTP_OBJECTHANDLE_ROOT) {
859 mtp_obj_t *parent_obj =
860 _entity_get_object_from_store(store, h_parent);
861 if (NULL != parent_obj) {
862 _entity_remove_reference_child_array(parent_obj,
866 } else if (*atleast_one) {
867 *response = PTP_RESPONSE_PARTIAL_DELETION;
870 *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
877 mtp_uint16 _entity_delete_obj_mtp_store(mtp_store_t *store,
878 mtp_uint32 obj_handle, mtp_uint32 fmt, mtp_bool read_only)
881 mtp_obj_t *obj = NULL;
882 mtp_bool all_del = TRUE;
883 mtp_bool atleas_one = FALSE;
885 retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
887 if (PTP_STORAGEACCESS_R == store->store_info.access) {
888 ERR("Read only store");
889 return PTP_RESPONSE_STORE_READONLY;
892 if (PTP_OBJECTHANDLE_ALL == obj_handle) {
893 slist_node_t *node = NULL;
894 node = store->obj_list.start;
895 while (NULL != node) {
896 if (TRUE == _transport_get_cancel_initialization() ||
897 TRUE == _transport_get_usb_discon_state()) {
898 ERR("USB is disconnected format\
899 operation is cancelled.");
900 response = PTP_RESPONSE_GEN_ERROR;
903 /* protect from disconnect USB */
904 if (NULL == store || NULL == node ||
905 NULL == node->value) {
906 response = PTP_RESPONSE_GEN_ERROR;
910 obj = (mtp_obj_t *)node->value;
911 if (_entity_remove_object_mtp_store(store, obj,
912 fmt, &response, &atleas_one, read_only)) {
914 slist_node_t *temp = NULL;
917 temp = _util_delete_node(&(store->obj_list), obj);
919 _util_delete_file_from_db(obj->file_path);
920 _entity_dealloc_mtp_obj(obj);
926 case PTP_RESPONSE_PARTIAL_DELETION:
929 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
930 case PTP_RESPONSE_ACCESSDENIED:
933 case PTP_RESPONSE_UNDEFINED:
940 DBG("object handle is not PTP_OBJECTHANDLE_ALL. [%ld]\n",
942 obj = _entity_get_object_from_store(store, obj_handle);
945 if (_entity_remove_object_mtp_store(store, obj, PTP_FORMATCODE_NOTUSED,
946 &response, &atleas_one, read_only)) {
947 slist_node_t *temp = NULL;
949 temp = _util_delete_node(&(store->obj_list), obj);
951 _util_delete_file_from_db(obj->file_path);
952 _entity_dealloc_mtp_obj(obj);
955 case PTP_RESPONSE_PARTIAL_DELETION:
958 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
959 case PTP_RESPONSE_ACCESSDENIED:
962 case PTP_RESPONSE_UNDEFINED:
972 response = PTP_RESPONSE_OK;
974 response = PTP_RESPONSE_PARTIAL_DELETION;
979 mtp_uint32 _entity_get_object_tree_size(mtp_store_t *store, mtp_obj_t *obj)
984 retv_if(store == NULL, 0);
985 retv_if(obj == NULL, 0);
987 if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
988 size = obj->obj_info->file_size;
990 ptp_array_t child_arr = { 0 };
991 mtp_obj_t *child_obj = NULL;
993 _prop_init_ptparray(&child_arr, UINT32_TYPE);
995 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
997 for (i = 0; i < child_arr.num_ele; i++) {
998 mtp_uint32 *ptr32 = child_arr.array_entry;
999 child_obj = _entity_get_object_from_store(store,
1001 size += _entity_get_object_tree_size(store, child_obj);
1003 _prop_deinit_ptparray(&child_arr);
1009 mtp_bool _entity_check_if_B_parent_of_A(mtp_store_t *store,
1010 mtp_uint32 handleA, mtp_uint32 handleB)
1013 mtp_obj_t *obj = NULL;
1014 ptp_array_t child_arr = {0};
1016 retv_if(store == NULL, FALSE);
1018 _prop_init_ptparray(&child_arr, UINT32_TYPE);
1019 _entity_get_child_handles(store, handleB, &child_arr);
1021 for (i = 0; i < child_arr.num_ele; i++) {
1022 mtp_uint32 *ptr32 = child_arr.array_entry;
1023 if (handleA == ptr32[i]) {
1024 _prop_deinit_ptparray(&child_arr);
1028 obj = _entity_get_object_from_store(store, ptr32[i]);
1029 if (obj == NULL || obj->obj_info == NULL ||
1030 obj->obj_info->obj_fmt ==
1031 PTP_FMT_ASSOCIATION) {
1034 if (_entity_check_if_B_parent_of_A(store, handleA, ptr32[i])) {
1035 _prop_deinit_ptparray(&child_arr);
1039 _prop_deinit_ptparray(&child_arr);
1043 mtp_uint32 _entity_generate_next_obj_handle(void)
1045 return g_next_obj_handle++;
1048 mtp_uint16 _entity_format_store(mtp_store_t *store, mtp_uint32 fs_format)
1050 mtp_uint16 response;
1052 retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
1054 /* Is store ready only? */
1055 if (store->store_info.access == PTP_STORAGEACCESS_R) {
1056 ERR("Read only storage");
1057 return PTP_RESPONSE_STORE_READONLY;
1060 /* Is FilesystemFormat supported? */
1061 if ((fs_format != PTP_FILESYSTEMTYPE_UNDEFINED) &&
1062 (fs_format != PTP_FILESYSTEMTYPE_FLAT) &&
1063 (fs_format != PTP_FILESYSTEMTYPE_HIERARCHICAL) &&
1064 (fs_format != PTP_FILESYSTEMTYPE_DCF)) {
1065 ERR("File system type not supported");
1066 return PTP_RESPONSE_INVALIDPARAM;
1069 /* check cancel transaction */
1070 if (TRUE == _transport_get_cancel_initialization() ||
1071 TRUE == _transport_get_usb_discon_state()) {
1072 ERR("USB is disconnected format operation is cancelled.");
1073 return PTP_RESPONSE_GEN_ERROR;
1076 response = _entity_delete_obj_mtp_store(store, PTP_OBJECTHANDLE_ALL,
1077 PTP_FORMATCODE_NOTUSED, TRUE);
1079 if (PTP_RESPONSE_OK != response) {
1080 ERR("format is not completed [0x%X].\n", response);
1084 return PTP_RESPONSE_OK;
1087 void _entity_destroy_mtp_store(mtp_store_t *store)
1090 slist_node_t *node = NULL;
1091 slist_node_t *next_node = NULL;
1093 ret_if(store == NULL);
1095 for (ii = 0, next_node = store->obj_list.start;
1096 ii < store->obj_list.nnodes; ii++) {
1099 next_node = node->link;
1100 _entity_dealloc_mtp_obj((mtp_obj_t *)node->value);
1104 _util_init_list(&(store->obj_list));
1108 void _entity_store_recursive_enum_folder_objects(mtp_store_t *store,
1112 mtp_char file_name[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1113 mtp_bool status = FALSE;
1114 mtp_obj_t *obj = NULL;
1115 dir_entry_t entry = { { 0 }, 0 };
1116 mtp_char *folder_name;
1117 mtp_uint32 h_parent;
1119 ret_if(NULL == store);
1122 folder_name = store->root_path;
1123 h_parent = PTP_OBJECTHANDLE_ROOT;
1125 folder_name = pobj->file_path;
1126 h_parent = pobj->obj_handle;
1129 if (folder_name == NULL || folder_name[0] != '/') {
1130 ERR("foldername has no root slash!!");
1134 if (FALSE == _util_ifind_first(folder_name, &h_dir, &entry)) {
1135 DBG("No more files");
1140 if (TRUE == _transport_get_usb_discon_state()) {
1141 DBG("USB is disconnected");
1142 if (closedir(h_dir) < 0)
1143 ERR("Close directory Fail");
1148 _util_get_file_name(entry.filename, file_name);
1149 if (0 == strlen(file_name)) {
1150 ERR("szFilename size is 0");
1154 if (file_name[0] == '.') {
1155 DBG_SECURE("Hidden file [%s]\n", entry.filename);
1156 } else if (entry.type == MTP_DIR_TYPE) {
1157 obj = _entity_add_folder_to_store(store, h_parent,
1158 entry.filename, file_name, &entry);
1161 ERR("pObject is NULL");
1165 _entity_store_recursive_enum_folder_objects(store, obj);
1166 } else if (entry.type == MTP_FILE_TYPE) {
1167 _entity_add_file_to_store(store, h_parent,
1168 entry.filename, file_name, &entry);
1170 DBG("UNKNOWN TYPE");
1173 status = (mtp_bool)_util_ifind_next(folder_name, h_dir,
1177 if (closedir(h_dir) < 0)
1178 ERR("close directory fail");
1180 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
1181 _inoti_add_watch_for_fs_events(folder_name);
1182 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
1187 void _entity_list_modified_files(mtp_uint32 minutes)
1192 mtp_char command[FIND_CMD_LEN] = { 0 };
1194 if (TRUE == _device_is_store_mounted(MTP_STORAGE_INTERNAL)) {
1195 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1196 _util_get_internal_path(inter_path);
1198 g_snprintf(command, FIND_CMD_LEN, FIND_CMD,
1199 inter_path, minutes,
1200 MTP_FILES_MODIFIED_FILES);
1201 DBG("find query is [%s]\n", command);
1202 ret = system(command);
1203 if (WIFSIGNALED(ret) &&
1204 (WTERMSIG(ret) == SIGINT ||
1205 WTERMSIG(ret) == SIGQUIT)) {
1210 if (TRUE == _device_is_store_mounted(MTP_STORAGE_EXTERNAL)) {
1211 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1212 _util_get_external_path(ext_path);
1214 g_snprintf(command, FIND_CMD_LEN, FIND_CMD,
1216 MTP_FILES_MODIFIED_FILES);
1217 DBG("find query is [%s]\n", command);
1218 ret = system(command);
1219 if (WIFSIGNALED(ret) &&
1220 (WTERMSIG(ret) == SIGINT ||
1221 WTERMSIG(ret) == SIGQUIT)) {
1230 void _entity_copy_store_data(mtp_store_t *dst, mtp_store_t *src)
1232 dst->store_id = src->store_id;
1233 dst->root_path = src->root_path;
1234 dst->is_hidden = src->is_hidden;
1236 memcpy(&(dst->obj_list), &(src->obj_list), sizeof(slist_t));
1237 _entity_update_store_info_run_time(&(dst->store_info), dst->root_path);
1238 _prop_copy_ptpstring(&(dst->store_info.store_desc), &(src->store_info.store_desc));
1239 _prop_copy_ptpstring(&(dst->store_info.vol_label), &(src->store_info.vol_label));