b778cc773f7360d738fc7bed0f615474d52d10b2
[platform/core/connectivity/mtp-responder.git] / src / entity / mtp_store.c
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <glib.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <system_info.h>
22 #include "mtp_util.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"
28
29
30 extern mtp_char g_last_deleted[MTP_MAX_PATHNAME_SIZE + 1];
31 static mtp_uint32 g_next_obj_handle = 1;
32
33
34 static inline mtp_bool UTIL_CHECK_LIST_NEXT(slist_iterator *iter)
35 {
36         return (iter && iter->node_ptr) ? TRUE : FALSE;
37 }
38
39 static void __init_store_info(store_info_t *info)
40 {
41         ret_if(info == NULL);
42
43         memset(info, 0x00, sizeof(store_info_t));
44
45         info->store_type = PTP_STORAGETYPE_FIXEDRAM;
46         info->fs_type = PTP_FILESYSTEMTYPE_DCF;
47         info->access = PTP_STORAGEACCESS_RWD;
48
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;
52
53         return;
54 }
55
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)
59 {
60         info->store_type = store_type;
61         info->fs_type = fs_type;
62         info->access = access;
63
64         info->capacity = capacity;
65         info->free_space = capacity;
66         info->free_space_in_objs = MTP_MAX_STORAGE_IN_OBJTS;
67
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);
70         return;
71 }
72
73 void _entity_update_store_info_run_time(store_info_t *info,
74                 mtp_char *root_path)
75 {
76         fs_info_t fs_info = { 0 };
77
78         ret_if(info == NULL);
79         ret_if(root_path == NULL);
80
81         if (FALSE == _util_get_filesystem_info(root_path, &fs_info)) {
82                 ERR("_util_get_filesystem_info fail [%s]\n", root_path);
83                 return;
84         }
85
86         info->capacity = fs_info.disk_size;
87         info->free_space = fs_info.avail_size;
88
89         return;
90 }
91
92 /* LCOV_EXCL_START */
93 mtp_bool _entity_get_store_path_by_id(mtp_uint32 store_id, mtp_char *path)
94 {
95         char sto_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
96
97         switch (store_id) {
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);
102                 break;
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);
107                 break;
108         default:
109                 ERR("No valid match for the store id [0x%x]\n", store_id);
110                 return FALSE;
111
112         }
113         return TRUE;
114 }
115
116 mtp_uint32 _entity_get_store_info_size(store_info_t *info)
117 {
118         mtp_uint32 size = FIXED_LENGTH_MEMBERS_MTPSTORE_SIZE;
119
120         size += _prop_size_ptpstring(&(info->store_desc));
121         size += _prop_size_ptpstring(&(info->vol_label));
122
123         return (size);
124 }
125
126 mtp_uint32 _entity_pack_store_info(store_info_t *info, mtp_uchar *buf,
127                 mtp_uint32 buf_sz)
128 {
129         mtp_uint32 num_bytes = 0;
130
131         retv_if(buf == NULL, 0);
132
133         if (buf_sz < _entity_get_store_info_size(info)) {
134                 ERR("Buffer size is less [%u]\n", buf_sz);
135                 return 0;
136         }
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);
142
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);
146
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);
150
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);
154
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);
159
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)));
173
174         num_bytes += _prop_pack_ptpstring(&(info->vol_label), buf + num_bytes,
175                         _prop_size_ptpstring(&(info->vol_label)));
176
177         return num_bytes;
178 }
179
180 mtp_uint32 _entity_get_store_id_by_path(const mtp_char *path_name)
181 {
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 };
185
186         retv_if(NULL == path_name, FALSE);
187
188         _util_get_external_path(ext_path);
189         _util_get_internal_path(inter_path);
190
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,
195                                 strlen(ext_path))) {
196                 store_id = MTP_EXTERNAL_STORE_ID;
197         }
198
199         DBG_SECURE("Path : %s, store_id : 0x%x\n", path_name, store_id);
200
201         return store_id;
202 }
203 /* LCOV_EXCL_STOP */
204
205 mtp_bool _entity_init_mtp_store(mtp_store_t *store, mtp_uint32 store_id,
206                 mtp_char *store_path)
207 {
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;
214
215         retv_if(store == NULL, FALSE);
216
217         store->store_id = store_id;
218         store->root_path = g_strdup(store_path);
219
220         __init_store_info(&(store->store_info));
221         _entity_update_store_info_run_time(&(store->store_info),
222                         store->root_path);
223
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);
227
228         switch (store_id) {
229         case MTP_INTERNAL_STORE_ID:
230                 store->is_hidden = FALSE;
231
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");
238                         }
239                 }
240
241                 if (storage_desc == NULL)
242                         storage_desc = g_strdup("Common");
243
244                 _util_utf8_to_utf16(wtemp, sizeof(wtemp) / WCHAR_SIZ,
245                                 storage_desc);
246                 __init_store_info_params(&(store->store_info),
247                                 store->store_info.capacity, PTP_STORAGETYPE_FIXEDRAM,
248                                 PTP_FILESYSTEMTYPE_HIERARCHICAL, PTP_STORAGEACCESS_RWD,
249                                 wtemp, wserial);
250
251                 if (storage_desc != NULL)
252                         g_free(storage_desc);
253
254                 if (profile != NULL)
255                         g_free(profile);
256                 break;
257
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);
268                 break;
269
270         default:
271                 ERR("store initialization Fail");
272                 return FALSE;
273         }
274         /* LCOV_EXCL_STOP */
275         _util_init_list(&(store->obj_list));
276
277         return TRUE;
278 }
279
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)
282 {
283         mtp_obj_t *obj = NULL;
284
285         retv_if(NULL == store, NULL);
286
287         obj = _entity_alloc_mtp_object();
288         if (NULL == obj) {
289                 ERR("Memory allocation Fail");
290                 return NULL;
291         }
292
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");
297                 g_free(obj);
298                 return NULL;
299                 /* LCOV_EXCL_STOP */
300         }
301
302         _entity_add_object_to_store(store, obj);
303         return obj;
304 }
305
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)
308 {
309         mtp_obj_t *obj = NULL;
310
311         retv_if(NULL == store, NULL);
312
313         obj = _entity_alloc_mtp_object();
314         if (NULL == obj) {
315                 ERR("Memory allocation Fail");
316                 return NULL;
317         }
318
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");
323                 g_free(obj);
324                 return NULL;
325                 /* LCOV_EXCL_STOP */
326
327         }
328
329         _entity_add_object_to_store(store, obj);
330         return obj;
331 }
332
333 mtp_bool _entity_add_object_to_store(mtp_store_t *store, mtp_obj_t *obj)
334 {
335         mtp_obj_t *par_obj = NULL;
336
337         retv_if(obj == NULL, FALSE);
338         retv_if(NULL == store, FALSE);
339         retv_if(obj->obj_info == NULL, FALSE);
340
341         if (_util_add_node(&(store->obj_list), obj) == FALSE) {
342                 ERR("Node add to list Fail");
343                 return FALSE;
344         }
345
346         /* references */
347         if (PTP_OBJECTHANDLE_ROOT != obj->obj_info->h_parent) {
348                 par_obj = _entity_get_object_from_store(store, obj->obj_info->h_parent);
349                 if (NULL != par_obj)
350                         _entity_add_reference_child_array(par_obj, obj->obj_handle);
351         }
352
353         return TRUE;
354 }
355
356 mtp_obj_t *_entity_get_object_from_store(mtp_store_t *store, mtp_uint32 handle)
357 {
358         mtp_obj_t *obj = NULL;
359         slist_iterator *iter = NULL;
360
361         retv_if(NULL == store, NULL);
362
363         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
364         if (iter == NULL) {
365                 ERR("Iterator init Fail, Store id = [0x%x]\n", store->store_id);
366                 return NULL;
367         }
368
369         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
370                 obj = (mtp_obj_t *)_util_get_list_next(iter);
371
372                 if (obj && obj->obj_handle == handle) {
373                         _util_deinit_list_iterator(iter);
374                         return obj;
375                 }
376         }
377
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);
380         return NULL;
381 }
382
383 /* LCOV_EXCL_START */
384 mtp_obj_t *_entity_get_last_object_from_store(mtp_store_t *store,
385                 mtp_uint32 handle)
386 {
387         mtp_obj_t *obj = NULL;
388         mtp_obj_t *temp_obj = NULL;
389         slist_iterator *iter = NULL;
390
391         retv_if(NULL == store, NULL);
392
393         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
394         if (iter == NULL) {
395                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
396                 return NULL;
397         }
398
399         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
400
401                 temp_obj = (mtp_obj_t *)_util_get_list_next(iter);
402                 if (temp_obj && temp_obj->obj_handle == handle)
403                         obj = temp_obj;
404         }
405
406         _util_deinit_list_iterator(iter);
407         return obj;
408 }
409
410 mtp_obj_t *_entity_get_object_from_store_by_path(mtp_store_t *store,
411                 const mtp_char *file_path)
412 {
413         mtp_obj_t *obj = NULL;
414         slist_iterator *iter = NULL;
415
416         retv_if(NULL == store, NULL);
417
418         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
419         if (iter == NULL) {
420                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
421                 return NULL;
422         }
423
424         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
425                 obj = (mtp_obj_t *)_util_get_list_next(iter);
426                 if (obj == NULL) {
427                         ERR("Object is NULL");
428                         continue;
429                 }
430
431                 if (!g_strcmp0(file_path, obj->file_path)) {
432                         _util_deinit_list_iterator(iter);
433                         return obj;
434                 }
435         }
436         ERR_SECURE("Object [%s] not found in the list\n", file_path);
437         _util_deinit_list_iterator(iter);
438         return NULL;
439 }
440
441 /*
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
445  */
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)
448 {
449         mtp_obj_t *obj = NULL;
450         slist_iterator *iter = NULL;
451
452         retv_if(store == NULL, 0);
453         retv_if(obj_arr == NULL, 0);
454
455         if (obj_handle != PTP_OBJECTHANDLE_ALL) {
456                 ERR("Object Handle is not PTP_OBJECTHANDLE_ALL");
457                 return 0;
458         }
459
460         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
461         if (iter == NULL) {
462                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
463                 return 0;
464         }
465
466         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
467
468                 obj = (mtp_obj_t *)_util_get_list_next(iter);
469                 if (obj == NULL) {
470                         ERR("Object is NULL");
471                         continue;
472                 }
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);
477                 }
478         }
479         _util_deinit_list_iterator(iter);
480         return obj_arr->num_ele;
481 }
482
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)
486 {
487         retv_if(store == NULL, 0);
488         retv_if(obj_arr == NULL, 0);
489
490         if (PTP_OBJECTHANDLE_ALL == obj_handle) {
491                 _entity_get_objects_from_store(store, obj_handle, fmt_code,
492                                 obj_arr);
493                 DBG("Number of object filled [%u]\n", obj_arr->num_ele);
494                 return obj_arr->num_ele;
495         }
496
497         if (PTP_OBJECTHANDLE_ROOT != obj_handle)
498                 _prop_append_ele_ptparray(obj_arr, obj_handle);
499
500         if (depth > 0) {
501                 ptp_array_t *child_arr = NULL;
502                 mtp_uint32 *ptr = NULL;
503                 mtp_uint32 ii = 0;
504
505                 child_arr = _prop_alloc_ptparray(UINT32_TYPE);
506                 if (child_arr == NULL) {
507                         return 0;
508                 }
509                 if (child_arr->array_entry == NULL) {
510                         _prop_destroy_ptparray(child_arr);
511                         return 0;
512                 }
513
514                 depth--;
515
516                 _entity_get_child_handles_with_same_format(store, obj_handle,
517                                 fmt_code, child_arr);
518                 ptr = child_arr->array_entry;
519
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);
523                 }
524                 _prop_destroy_ptparray(child_arr);
525         }
526
527         DBG("Handle[%u] : array count [%u]!!\n", obj_handle,
528                         obj_arr->num_ele);
529         return obj_arr->num_ele;
530 }
531
532 mtp_uint32 _entity_get_objects_from_store_by_format(mtp_store_t *store,
533                 mtp_uint32 format, ptp_array_t *obj_arr)
534 {
535         mtp_obj_t *obj = NULL;
536         slist_iterator *iter = NULL;
537
538         retv_if(store == NULL, 0);
539         retv_if(obj_arr == NULL, 0);
540
541         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
542         if (iter == NULL) {
543                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
544                 return 0;
545         }
546
547         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
548
549                 obj = (mtp_obj_t *)_util_get_list_next(iter);
550                 if (obj == NULL || obj->obj_info == NULL)
551                         continue;
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);
559                 }
560
561         }
562
563         _util_deinit_list_iterator(iter);
564         return (obj_arr->num_ele);
565 }
566
567 mtp_uint32 _entity_get_num_object_with_same_format(mtp_store_t *store,
568                 mtp_uint32 format)
569 {
570         mtp_uint32 count = 0;
571         mtp_obj_t *obj = NULL;
572         slist_iterator *iter = NULL;
573
574         retv_if(store == NULL, 0);
575
576         if (PTP_FORMATCODE_NOTUSED == format)
577                 return store->obj_list.nnodes;
578
579         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
580         if (iter == NULL) {
581                 ERR("Iterator init Fail, store id = [0x%x]\n", store->store_id);
582                 return 0;
583         }
584
585         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
586
587                 obj = (mtp_obj_t *)_util_get_list_next(iter);
588                 if (obj == NULL || obj->obj_info == NULL)
589                         continue;
590
591                 if ((obj->obj_info->obj_fmt == format) ||
592                                 (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION &&
593                                  PTP_FORMATCODE_ALL == format)) {
594                         count++;
595                 }
596         }
597
598         _util_deinit_list_iterator(iter);
599         return count;
600 }
601
602 mtp_uint32 _entity_get_num_children(mtp_store_t *store, mtp_uint32 h_parent,
603                 mtp_uint32 format)
604 {
605         mtp_uint32 count = 0;
606         mtp_obj_t *obj = NULL;
607         slist_iterator *iter = NULL;
608
609         retv_if(store == NULL, 0);
610
611         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
612         if (iter == NULL) {
613                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
614                 return 0;
615         }
616
617         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
618
619                 obj = (mtp_obj_t *)_util_get_list_next(iter);
620                 if (obj == NULL || obj->obj_info == NULL)
621                         continue;
622
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)))) {
629                         count++;
630                 }
631         }
632
633         _util_deinit_list_iterator(iter);
634         return count;
635 }
636
637 mtp_uint32 _entity_get_child_handles(mtp_store_t *store, mtp_uint32 h_parent,
638                 ptp_array_t *child_arr)
639 {
640         mtp_obj_t *obj = NULL;
641         slist_iterator *iter = NULL;
642         mtp_obj_t *parent_obj = NULL;
643
644         retv_if(store == NULL, 0);
645         retv_if(child_arr == NULL, 0);
646
647         parent_obj = _entity_get_object_from_store(store, h_parent);
648
649         if (NULL == parent_obj) {
650                 ERR("parent object is NULL");
651                 return FALSE;
652         }
653
654         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
655         if (iter == NULL) {
656                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
657                 return 0;
658         }
659
660         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
661
662                 obj = (mtp_obj_t *)_util_get_list_next(iter);
663                 if (obj == NULL || obj->obj_info == NULL)
664                         continue;
665
666                 if (obj->obj_info->h_parent == h_parent)
667                         _prop_append_ele_ptparray(child_arr, obj->obj_handle);
668         }
669
670         _util_deinit_list_iterator(iter);
671         return child_arr->num_ele;
672 }
673
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)
676 {
677         mtp_obj_t *obj = NULL;
678         slist_iterator *iter = NULL;
679
680         retv_if(store == NULL, 0);
681         retv_if(child_arr == NULL, 0);
682
683         iter = (slist_iterator *)_util_init_list_iterator(&(store->obj_list));
684         if (iter == NULL) {
685                 ERR("Iterator init Fail Store id = [0x%x]\n", store->store_id);
686                 return 0;
687         }
688
689         while (UTIL_CHECK_LIST_NEXT(iter) == TRUE) {
690
691                 obj = (mtp_obj_t *)_util_get_list_next(iter);
692                 if (obj == NULL || obj->obj_info == NULL)
693                         continue;
694
695                 if ((obj->obj_info->h_parent == h_parent) &&
696                                 ((obj->obj_info->obj_fmt == format) ||
697                                  (format == PTP_FORMATCODE_NOTUSED))) {
698
699                         _prop_append_ele_ptparray(child_arr, obj->obj_handle);
700                 }
701
702         }
703
704         _util_deinit_list_iterator(iter);
705         return child_arr->num_ele;
706 }
707
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,
710                 mtp_bool read_only)
711 {
712         mtp_uint64 size = 0;
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;
717
718         retv_if(store == NULL, 0);
719
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;
724                 return FALSE;
725         }
726
727         if (NULL == obj || NULL == obj->obj_info || NULL == store) {
728                 *response = PTP_RESPONSE_UNDEFINED;
729                 return FALSE;
730         }
731
732         objinfo = obj->obj_info;
733
734         if ((objinfo->obj_fmt != format) && (format != PTP_FORMATCODE_ALL) &&
735                         (format != PTP_FORMATCODE_NOTUSED)) {
736                 *response = PTP_RESPONSE_UNDEFINED;
737                 return FALSE;
738         }
739
740         if ((PTP_FORMATCODE_ALL == format) &&
741                         (PTP_FMT_ASSOCIATION == objinfo->obj_fmt)) {
742
743                 *response = PTP_RESPONSE_UNDEFINED;
744                 return FALSE;
745         }
746
747 #ifdef MTP_SUPPORT_SET_PROTECTION
748         /* Delete readonly files/folder */
749         if (!read_only)
750                 objinfo->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
751 #endif /* MTP_SUPPORT_SET_PROTECTION */
752
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;
757                  */
758
759                 mtp_uint32 i = 0;
760                 ptp_array_t child_arr = { 0 };
761                 mtp_obj_t *child_obj = NULL;
762
763                 _prop_init_ptparray(&child_arr, UINT32_TYPE);
764                 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
765
766                 if (child_arr.num_ele) {
767
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.");
775                                         *response =
776                                                 PTP_RESPONSE_PARTIAL_DELETION;
777                                         _prop_deinit_ptparray(&child_arr);
778                                         return FALSE;
779                                 }
780
781                                 child_obj = _entity_get_object_from_store(store,
782                                                 ptr32[i]);
783                                 if (NULL == child_obj)
784                                         continue;
785
786                                 if (_entity_remove_object_mtp_store(store, child_obj,
787                                                         format, response, atleast_one,
788                                                         read_only)) {
789                                         slist_node_t *node;
790                                         node = _util_delete_node(&(store->obj_list),
791                                                         child_obj);
792                                         g_free(node);
793                                         *atleast_one = TRUE;
794                                         _entity_dealloc_mtp_obj(child_obj);
795                                 } else {
796                                         all_del = FALSE;
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.");
802                                                 *response =
803                                                         PTP_RESPONSE_PARTIAL_DELETION;
804                                                 _prop_deinit_ptparray(&child_arr);
805                                                 return FALSE;
806                                         }
807                                 }
808
809                         }
810                 } else {
811                         /* Non-Enumerated Folder */
812                         mtp_uint32 num_of_deleted_file = 0;
813                         mtp_uint32 num_of_file = 0;
814
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",
820                                                 obj->file_path);
821                                 *response = PTP_RESPONSE_GEN_ERROR;
822                                 if (MTP_ERROR_ACCESS_DENIED == ret)
823                                         *response =
824                                                 PTP_RESPONSE_ACCESSDENIED;
825                                 _prop_deinit_ptparray(&child_arr);
826                                 return FALSE;
827                         }
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",
832                                                 obj->file_path);
833                                 all_del = FALSE;
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);
839                                 *atleast_one = TRUE;
840                                 all_del = FALSE;
841                         }
842                 }
843                 _prop_deinit_ptparray(&child_arr);
844
845                 _util_scan_folder_contents_in_db(obj->file_path);
846                 if (all_del) {
847                         g_snprintf(g_last_deleted,
848                                         MTP_MAX_PATHNAME_SIZE + 1, "%s",
849                                         obj->file_path);
850
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;
855                                 if (EACCES == errno)
856                                         *response =
857                                                 PTP_RESPONSE_ACCESSDENIED;
858                                 return FALSE;
859                         }
860                 } else {
861                         ERR("all member in this folder is not deleted.");
862                 }
863         } else {
864 #ifdef MTP_SUPPORT_SET_PROTECTION
865                 size = objinfo->file_size;
866 #endif /* MTP_SUPPORT_SET_PROTECTION */
867
868                 if (objinfo->protcn_status ==
869                                 PTP_PROTECTIONSTATUS_READONLY ||
870                                 objinfo->protcn_status ==
871                                 MTP_PROTECTIONSTATUS_READONLY_DATA) {
872                         *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
873                         return FALSE;
874                 }
875
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;
883                         if (EACCES == errno)
884                                 *response = PTP_RESPONSE_ACCESSDENIED;
885                         return FALSE;
886                 }
887                 *atleast_one = TRUE;
888
889                 /* Upate store's available space */
890                 store->store_info.free_space += size;
891         }
892
893         if (all_del) {
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,
902                                                 obj->obj_handle);
903                         }
904                 }
905         } else if (*atleast_one) {
906                 *response = PTP_RESPONSE_PARTIAL_DELETION;
907                 return FALSE;
908         } else {
909                 *response = PTP_RESPONSE_OBJ_WRITEPROTECTED;
910                 return FALSE;
911         }
912
913         return TRUE;
914 }
915
916 mtp_uint16 _entity_delete_obj_mtp_store(mtp_store_t *store,
917                 mtp_uint32 obj_handle, mtp_uint32 fmt, mtp_bool read_only)
918 {
919         mtp_uint16 response;
920         mtp_obj_t *obj = NULL;
921         mtp_bool all_del = TRUE;
922         mtp_bool atleas_one = FALSE;
923
924         retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
925
926         if (PTP_STORAGEACCESS_R == store->store_info.access) {
927                 ERR("Read only store");
928                 return PTP_RESPONSE_STORE_READONLY;
929         }
930
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;
940                                 return response;
941                         }
942                         /* protect from disconnect USB */
943                         if (NULL == store || NULL == node ||
944                                         NULL == node->value) {
945                                 response = PTP_RESPONSE_GEN_ERROR;
946                                 return response;
947                         }
948
949                         obj = (mtp_obj_t *)node->value;
950                         if (_entity_remove_object_mtp_store(store, obj,
951                                                 fmt, &response, &atleas_one, read_only)) {
952
953                                 slist_node_t *temp = NULL;
954
955                                 node = node->link;
956                                 temp = _util_delete_node(&(store->obj_list), obj);
957                                 g_free(temp);
958                                 _util_delete_file_from_db(obj->file_path);
959                                 _entity_dealloc_mtp_obj(obj);
960                         } else {
961                                 node = node->link;
962                         }
963
964                         switch (response) {
965                         case PTP_RESPONSE_PARTIAL_DELETION:
966                                 all_del = FALSE;
967                                 break;
968                         case PTP_RESPONSE_OBJ_WRITEPROTECTED:
969                         case PTP_RESPONSE_ACCESSDENIED:
970                                 all_del = FALSE;
971                                 break;
972                         case PTP_RESPONSE_UNDEFINED:
973                         default:
974                                 break;
975                         }
976
977                 }
978         } else {
979                 DBG("object handle is not PTP_OBJECTHANDLE_ALL. [%u]\n",
980                                 obj_handle);
981                 obj = _entity_get_object_from_store(store, obj_handle);
982
983                 if (NULL != obj) {
984                         if (_entity_remove_object_mtp_store(store, obj, PTP_FORMATCODE_NOTUSED,
985                                                 &response, &atleas_one, read_only)) {
986                                 slist_node_t *temp = NULL;
987
988                                 temp = _util_delete_node(&(store->obj_list), obj);
989                                 g_free(temp);
990                                 _util_delete_file_from_db(obj->file_path);
991                                 _entity_dealloc_mtp_obj(obj);
992                         } else {
993                                 switch (response) {
994                                 case PTP_RESPONSE_PARTIAL_DELETION:
995                                         all_del = FALSE;
996                                         break;
997                                 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
998                                 case PTP_RESPONSE_ACCESSDENIED:
999                                         all_del = FALSE;
1000                                         break;
1001                                 case PTP_RESPONSE_UNDEFINED:
1002                                 default:
1003                                         /* do nothing */
1004                                         break;
1005                                 }
1006                         }
1007                 }
1008         }
1009
1010         if (all_del)
1011                 response = PTP_RESPONSE_OK;
1012         else if (atleas_one)
1013                 response = PTP_RESPONSE_PARTIAL_DELETION;
1014
1015         return response;
1016 }
1017
1018 mtp_uint32 _entity_get_object_tree_size(mtp_store_t *store, mtp_obj_t *obj)
1019 {
1020         mtp_uint32 i = 0;
1021         mtp_uint64 size = 0;
1022
1023         retv_if(store == NULL, 0);
1024         retv_if(obj == NULL, 0);
1025
1026         if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
1027                 size = obj->obj_info->file_size;
1028         } else {
1029                 ptp_array_t child_arr = { 0 };
1030                 mtp_obj_t *child_obj = NULL;
1031
1032                 _prop_init_ptparray(&child_arr, UINT32_TYPE);
1033
1034                 _entity_get_child_handles(store, obj->obj_handle, &child_arr);
1035
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,
1039                                         ptr32[i]);
1040                         size += _entity_get_object_tree_size(store, child_obj);
1041                 }
1042                 _prop_deinit_ptparray(&child_arr);
1043         }
1044
1045         return size;
1046 }
1047
1048 mtp_bool _entity_check_if_B_parent_of_A(mtp_store_t *store,
1049                 mtp_uint32 handleA, mtp_uint32 handleB)
1050 {
1051         mtp_uint32 i = 0;
1052         mtp_obj_t *obj = NULL;
1053         ptp_array_t child_arr = {0};
1054
1055         retv_if(store == NULL, FALSE);
1056
1057         _prop_init_ptparray(&child_arr, UINT32_TYPE);
1058         _entity_get_child_handles(store, handleB, &child_arr);
1059
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);
1064                         return TRUE;
1065                 }
1066
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) {
1071                         continue;
1072                 }
1073                 if (_entity_check_if_B_parent_of_A(store, handleA, ptr32[i])) {
1074                         _prop_deinit_ptparray(&child_arr);
1075                         return TRUE;
1076                 }
1077         }
1078         _prop_deinit_ptparray(&child_arr);
1079         return FALSE;
1080 }
1081 /* LCOV_EXCL_STOP */
1082
1083 mtp_uint32 _entity_generate_next_obj_handle(void)
1084 {
1085         return g_next_obj_handle++;
1086 }
1087
1088 /* LCOV_EXCL_START */
1089 mtp_uint16 _entity_format_store(mtp_store_t *store, mtp_uint32 fs_format)
1090 {
1091         mtp_uint16 response;
1092
1093         retv_if(store == NULL, PTP_RESPONSE_GEN_ERROR);
1094
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;
1099         }
1100
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;
1108         }
1109
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;
1115         }
1116
1117         response = _entity_delete_obj_mtp_store(store, PTP_OBJECTHANDLE_ALL,
1118                         PTP_FORMATCODE_NOTUSED, TRUE);
1119
1120         if (PTP_RESPONSE_OK != response) {
1121                 ERR("format is not completed [0x%X].\n", response);
1122                 return response;
1123         }
1124
1125         return PTP_RESPONSE_OK;
1126 }
1127
1128 void _entity_destroy_mtp_store(mtp_store_t *store)
1129 {
1130         mtp_uint32 ii = 0;
1131         slist_node_t *node = NULL;
1132         slist_node_t *next_node = NULL;
1133
1134         ret_if(store == NULL);
1135
1136         for (ii = 0, next_node = store->obj_list.start;
1137                         ii < store->obj_list.nnodes; ii++) {
1138
1139                 node = next_node;
1140                 next_node = node->link;
1141                 _entity_dealloc_mtp_obj((mtp_obj_t *)node->value);
1142                 g_free(node);
1143         }
1144
1145         _util_init_list(&(store->obj_list));
1146         return;
1147 }
1148 /* LCOV_EXCL_STOP */
1149
1150 void _entity_store_recursive_enum_folder_objects(mtp_store_t *store,
1151                 mtp_obj_t *pobj)
1152 {
1153         DIR *h_dir = 0;
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;
1160
1161         ret_if(NULL == store);
1162
1163         if (!pobj) {
1164                 folder_name = store->root_path;
1165                 h_parent = PTP_OBJECTHANDLE_ROOT;
1166         } else {
1167                 folder_name = pobj->file_path;
1168                 h_parent = pobj->obj_handle;
1169         }
1170
1171         if (folder_name == NULL || folder_name[0] != '/') {
1172                 ERR("foldername has no root slash!!");
1173                 return;
1174         }
1175
1176         if (FALSE == _util_ifind_first(folder_name, &h_dir, &entry)) {
1177                 DBG("No more files");
1178                 return;
1179         }
1180
1181         do {
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");
1187
1188                         return;
1189                         /* LCOV_EXCL_STOP */
1190                 }
1191
1192                 _util_get_file_name(entry.filename, file_name);
1193                 if (0 == strlen(file_name)) {
1194                         ERR("szFilename size is 0");
1195                         goto NEXT;
1196                 }
1197
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);
1203
1204                         if (NULL == obj) {
1205                                 ERR("pObject is NULL");
1206                                 goto NEXT;
1207                         }
1208
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);
1213                 } else {
1214                         DBG("UNKNOWN TYPE");
1215                 }
1216 NEXT:
1217                 status = (mtp_bool)_util_ifind_next(folder_name, h_dir,
1218                                 &entry);
1219         } while (status);
1220
1221         if (closedir(h_dir) < 0)
1222                 ERR("close directory fail");
1223
1224 #ifdef MTP_SUPPORT_OBJECTADDDELETE_EVENT
1225         _inoti_add_watch_for_fs_events(folder_name);
1226 #endif /*MTP_SUPPORT_OBJECTADDDELETE_EVENT*/
1227
1228         return;
1229 }
1230
1231 /* LCOV_EXCL_START */
1232 void _entity_list_modified_files(mtp_uint32 minutes)
1233 {
1234         if (minutes == 0)
1235                 return;
1236         mtp_int32 ret;
1237         mtp_char command[FIND_CMD_LEN] = { 0 };
1238
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);
1242
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);
1248
1249                 if (WIFSIGNALED(ret) &&
1250                                 (WTERMSIG(ret) == SIGINT ||
1251                                  WTERMSIG(ret) == SIGQUIT)) {
1252                         ERR("SYSTEM Fail");
1253                         return;
1254                 }
1255         }
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);
1259
1260                 g_snprintf(command, FIND_CMD_LEN, FIND_CMD,
1261                                 ext_path, minutes,
1262                                 MTP_FILES_MODIFIED_FILES);
1263                 DBG("find query is [%s]\n", command);
1264                 ret = _util_system_cmd_wait(command);
1265
1266                 if (WIFSIGNALED(ret) &&
1267                                 (WTERMSIG(ret) == SIGINT ||
1268                                  WTERMSIG(ret) == SIGQUIT)) {
1269                         ERR("SYSTEM Fail");
1270                         return;
1271                 }
1272         }
1273
1274         return;
1275 }
1276
1277 void _entity_copy_store_data(mtp_store_t *dst, mtp_store_t *src)
1278 {
1279         dst->store_id = src->store_id;
1280         dst->root_path = src->root_path;
1281         dst->is_hidden = src->is_hidden;
1282
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));
1287
1288         return;
1289 }
1290 /* LCOV_EXCL_STOP */