2447693f3c693d0d8026975babc79c3cd4643b41
[platform/core/connectivity/mtp-responder.git] / src / entity / mtp_object.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 <string.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <glib.h>
22 #include "mtp_fs.h"
23 #include "mtp_support.h"
24 #include "mtp_util.h"
25 #include "mtp_device.h"
26
27
28 extern mtp_bool g_is_full_enum;
29
30
31 /* LCOV_EXCL_START */
32 mtp_bool _entity_get_file_times(mtp_obj_t *obj, ptp_time_string_t *create_tm,
33                 ptp_time_string_t *modify_tm)
34 {
35         file_attr_t attrs = {0};
36         system_time_t local_time = {0};
37         struct tm new_time = {0};
38
39         if (FALSE == _util_get_file_attrs(obj->file_path, &attrs)) {
40                 ERR("_util_get_file_attrs Fail");
41                 return FALSE;
42         }
43
44         if (NULL != localtime_r((time_t*)&attrs.ctime, &new_time)) {
45                 local_time.year = new_time.tm_year + 1900;
46                 local_time.month = new_time.tm_mon + 1;
47                 local_time.day = new_time.tm_mday;
48                 local_time.hour = new_time.tm_hour;
49                 local_time.minute = new_time.tm_min;
50                 local_time.second = new_time.tm_sec;
51                 local_time.day_of_week = 0;
52                 local_time.millisecond = 0;
53         } else {
54                 ERR("localtime_r returned NULL");
55                 _util_print_error();
56                 return FALSE;
57         }
58         _prop_copy_time_to_ptptimestring(create_tm, &local_time);
59
60         if (NULL != localtime_r((time_t*)&attrs.mtime, &new_time)) {
61                 local_time.year = new_time.tm_year + 1900;
62                 local_time.month = new_time.tm_mon + 1;
63                 local_time.day = new_time.tm_mday;
64                 local_time.hour = new_time.tm_hour;
65                 local_time.minute = new_time.tm_min;
66                 local_time.second = new_time.tm_sec;
67                 local_time.day_of_week = 0;
68                 local_time.millisecond = 0;
69         } else {
70                 ERR("localtime_r returned NULL");
71                 _util_print_error();
72                 return FALSE;
73         }
74         _prop_copy_time_to_ptptimestring(modify_tm, &local_time);
75
76         return TRUE;
77 }
78 /* LCOV_EXCL_STOP */
79
80 obj_info_t *_entity_alloc_object_info(void)
81 {
82         obj_info_t *info = NULL;
83
84         info = (obj_info_t *)g_malloc(sizeof(obj_info_t));
85         if (NULL == info) {
86                 ERR("Memory allocation Fail");
87                 return NULL;
88         }
89
90         _entity_init_object_info(info);
91
92         return info;
93 }
94
95 void _entity_init_object_info(obj_info_t *info)
96 {
97         ret_if(info == NULL);
98
99         memset(info, 0, sizeof(obj_info_t));
100 }
101
102 /* LCOV_EXCL_START */
103 mtp_uint32 _entity_get_object_info_size(mtp_obj_t *obj, ptp_string_t *file_name)
104 {
105         int ret;
106         ptp_string_t keywords;
107         mtp_wchar wtemp[2] = { 0 };
108         ptp_time_string_t create_time_str = {0};
109         ptp_time_string_t modify_time_str = {0};
110         mtp_uint32 size = FIXED_LENGTH_MEMBERS_SIZE;
111
112         retv_if(obj == NULL, 0);
113
114         ret = _entity_get_file_times(obj, &create_time_str, &modify_time_str);
115         if (FALSE == ret) {
116                 ERR("_entity_get_file_times() Fail");
117                 return 0;
118         }
119
120         _prop_copy_char_to_ptpstring(&keywords, wtemp, WCHAR_TYPE);
121
122         size += _prop_size_ptpstring(file_name);
123         size += _prop_size_ptptimestring(&create_time_str);
124         size += _prop_size_ptptimestring(&modify_time_str);
125         size += _prop_size_ptpstring(&keywords);
126
127         return (size);
128 }
129 /* LCOV_EXCL_STOP */
130
131 void _entity_init_object_info_params(obj_info_t *info, mtp_uint32 store_id,
132                 mtp_uint32 parent_handle, mtp_char *file_name, dir_entry_t *dir)
133 {
134         mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
135
136         _entity_init_object_info(info);
137
138         info->store_id = store_id;
139         info->h_parent = parent_handle;
140
141         _util_get_file_extn(file_name, extn);
142
143         if (dir->attrs.attribute == MTP_FILE_ATTR_INVALID) {
144                 ERR("File attribute invalid");
145                 return;
146         }
147 #ifndef MTP_SUPPORT_SET_PROTECTION
148         info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
149 #else /* MTP_SUPPORT_SET_PROTECTION */
150         info->protcn_status = (dir->attrs.attribute &
151                         MTP_FILE_ATTR_MODE_READ_ONLY) ?
152                 PTP_PROTECTIONSTATUS_READONLY :
153                 PTP_PROTECTIONSTATUS_NOPROTECTION;
154 #endif /* MTP_SUPPORT_SET_PROTECTION */
155
156         if (dir->attrs.attribute & MTP_FILE_ATTR_MODE_DIR) {
157                 info->obj_fmt = PTP_FMT_ASSOCIATION;
158                 info->association_type = PTP_ASSOCIATIONTYPE_FOLDER;
159                 return;
160         }
161
162         info->file_size = dir->attrs.fsize;
163         info->obj_fmt = _util_get_fmtcode(extn);
164
165         return;
166 }
167
168 mtp_uint32 _entity_parse_raw_obj_info(mtp_uchar *buf, mtp_uint32 buf_sz,
169                 obj_info_t *info, mtp_char *file_name, mtp_uint16 fname_len)
170 {
171         mtp_uchar *temp = buf;
172         ptp_string_t str = {0};
173         mtp_uint32 bytes_parsed = 0;
174
175         retv_if(buf == NULL, 0);
176         retvm_if(buf_sz < FIXED_LENGTH_MEMBERS_SIZE, 0, "buf_sz[%d] is less", buf_sz);
177
178         /* LCOV_EXCL_START */
179         /* Copy Obj Props from store_id till file_size */
180         memcpy(&(info->store_id), temp, (sizeof(mtp_uint16) * 2 + sizeof(mtp_uint32) * 2));
181         temp += (sizeof(mtp_uint16) * 2 + sizeof(mtp_uint32) * 2);
182
183         /* Skip ObjProp:thumb format .No need to store ,the prop has
184          * a default value.
185          */
186         temp += sizeof(mtp_uint16);
187
188         memcpy(&(info->thumb_file_size), temp, sizeof(mtp_uint32));
189         temp += sizeof(mtp_uint32);
190
191         /* Skip ObjProps:ThumbPixWidth,ThumbPixHeight,ImagePixWidth,
192          * ImagePixHeight,ImageBitDepth.No need to store,they have default value
193          */
194         temp += sizeof(mtp_uint32) * 5;
195
196         memcpy(&(info->h_parent), temp, sizeof(mtp_uint32));
197         temp += sizeof(mtp_uint32);
198
199         memcpy(&(info->association_type), temp, sizeof(mtp_uint16));
200         temp += sizeof(mtp_uint16);
201
202         /* Skip ObjProps:association_desc, sequence_desc */
203         temp += sizeof(mtp_uint32) * 2;
204
205 #ifdef __BIG_ENDIAN__
206         /* Byte swap the structure elements if needed.
207          * This works since the data elements will have the same size,
208          * the only difference is the byte order.
209          */
210         _util_conv_byte_order(&(info->store_id), sizeof(info->store_id));
211         _util_conv_byte_order(&(info->obj_fmt), sizeof(info->obj_fmt));
212         _util_conv_byte_order(&(info->protcn_status),
213                         sizeof(info->protcn_status));
214         _util_conv_byte_order(&(info->file_size), sizeof(info->file_size));
215         _util_conv_byte_order(&(info->thumb_file_size),
216                         sizeof(info->thumb_file_size));
217         _util_conv_byte_order(&(info->h_parent), sizeof(info->h_parent));
218         _util_conv_byte_order(&(info->association_type),
219                         sizeof(info->association_type));
220 #endif /*__BIG_ENDIAN__*/
221
222         ptp_string_t fname = { 0 };
223         bytes_parsed = _prop_parse_rawstring(&fname, temp, buf_sz);
224         temp += bytes_parsed;
225
226         _util_utf16_to_utf8(file_name, fname_len, fname.str);
227
228         /* Skip ObjProps: datecreated/datemodified/keywords.
229          * The values are retrieved using stat.
230          */
231         memcpy(&(str.num_chars), temp, sizeof(mtp_uchar));
232         temp += _prop_size_ptpstring(&str);
233
234         memcpy(&(str.num_chars), temp, sizeof(mtp_uchar));
235         temp += _prop_size_ptpstring(&str);
236
237         memcpy(&(str.num_chars), temp, sizeof(mtp_uchar));
238         temp += _prop_size_ptpstring(&str);
239
240         return (mtp_uint32)(temp - buf);
241 }
242
243 void _entity_copy_obj_info(obj_info_t *dst, obj_info_t *src)
244 {
245         memcpy(&(dst->store_id), &(src->store_id), (2 * sizeof(mtp_uint16) +
246                                 sizeof(mtp_uint32) + sizeof(mtp_uint64)));
247
248         /* Copy Object Props:thumb_file_size,h_parent, association_type */
249         memcpy(&(dst->thumb_file_size), &(src->thumb_file_size),
250                         (2 * sizeof(mtp_uint32) + sizeof(mtp_uint16)));
251
252         return;
253 }
254
255 mtp_uint32 _entity_pack_obj_info(mtp_obj_t *obj, ptp_string_t *file_name,
256                 mtp_uchar *buf, mtp_uint32 buf_sz)
257 {
258         int ret;
259         mtp_uint32 num_bytes = 0;
260         mtp_uint32 objSize = 0;
261         mtp_uint16 thumb_fmt = 0;
262         mtp_uint32 thumb_width = 0;
263         mtp_uint32 thumb_height = 0;
264         obj_info_t *info = obj->obj_info;
265         ptp_time_string_t create_time_str = { 0 };
266         ptp_time_string_t modify_time_str = { 0 };
267         ptp_string_t keywords;
268         mtp_wchar wtemp[2] = { 0 };
269
270         retv_if(buf == NULL, 0);
271         retv_if(obj == NULL, 0);
272
273         ret = _entity_get_file_times(obj, &create_time_str, &modify_time_str);
274         if (FALSE == ret) {
275                 ERR("_entity_get_file_times() Fail");
276                 return 0;
277         }
278
279         _prop_copy_char_to_ptpstring(&keywords, wtemp, WCHAR_TYPE);
280
281         if (buf_sz < _entity_get_object_info_size(obj, file_name)) {
282                 ERR("Buffer size is less than object info size");
283                 return 0;
284         }
285
286         /* As per Spec ObjectCompressedSize field in ObjectInfo dataset is
287          * 4 bytes. In case file size greater than 4Gb, value 0xFFFFFFFF is sent
288          */
289         objSize = (info->file_size >= MTP_FILESIZE_4GB) ?
290                 0xFFFFFFFF : (mtp_uint32)info->file_size;
291
292 #ifdef __BIG_ENDIAN__
293         memcpy(&(buf[num_bytes]), &(info->store_id), sizeof(mtp_uint32));
294         _util_conv_byte_order(buf, sizeof(mtp_uint32));
295         num_bytes += sizeof(mtp_uint32);
296
297         memcpy(&(buf[num_bytes]), &(info->obj_fmt), sizeof(mtp_uint16));
298         _util_conv_byte_order(buf, sizeof(mtp_uint16));
299         num_bytes += sizeof(mtp_uint16);
300
301         memcpy(&(buf[num_bytes]), &(info->protcn_status), sizeof(mtp_uint16));
302         _util_conv_byte_order(buf, sizeof(mtp_uint16));
303         num_bytes += sizeof(mtp_uint16);
304
305         memcpy(&(buf[num_bytes]), &objSize, sizeof(mtp_uint32));
306         _util_conv_byte_order(buf, sizeof(mtp_uint32));
307         num_bytes += sizeof(mtp_uint32);
308
309         /* Thumb format has a constant value of 2 bytes */
310         memset(&(buf[num_bytes]), &thumb_fmt, sizeof(mtp_uint16));
311         _util_conv_byte_order(buf, sizeof(mtp_uint16));
312         num_bytes += sizeof(mtp_uint16);
313
314         memcpy(&(buf[num_bytes]), &(info->thumb_file_size), sizeof(mtp_uint32));
315         _util_conv_byte_order(buf, sizeof(mtp_uint32));
316         num_bytes += sizeof(mtp_uint32);
317
318         memcpy(&(buf[num_bytes]), &thumb_width, sizeof(mtp_uint32));
319         _util_conv_byte_order(buf, sizeof(mtp_uint32));
320         num_bytes += sizeof(mtp_uint32);
321
322         memcpy(&(buf[num_bytes]), &thumb_height, sizeof(mtp_uint32));
323         _util_conv_byte_order(buf, sizeof(mtp_uint32));
324         num_bytes += sizeof(mtp_uint32);
325
326         /* ObjProps:image_width, image_height, image_bit_depth values
327          * currently are always 0 for any type of FILE/FOLDER
328          */
329         memset(&(buf[num_bytes]), 0, sizeof(mtp_uint32) * 3);
330         _util_conv_byte_order(buf, sizeof(mtp_uint32) * 3);
331         num_bytes += (sizeof(mtp_uint32) * 3);
332
333         memcpy(&(buf[num_bytes]), &(info->h_parent), sizeof(mtp_uint32));
334         _util_conv_byte_order(buf, sizeof(mtp_uint32));
335         num_bytes += sizeof(mtp_uint32);
336
337         memcpy(&(buf[num_bytes]),
338                         &(info->association_type), sizeof(mtp_uint16));
339         _util_conv_byte_order(buf, sizeof(mtp_uint16));
340         num_bytes += sizeof(mtp_uint16);
341
342         /* ObjProps:association desc,sequence number values are always 0 */
343         memset(&(buf[num_bytes]), 0, sizeof(mtp_uint32) * 2);
344         _util_conv_byte_order(buf, sizeof(mtp_uint32) * 2);
345         num_bytes += (sizeof(mtp_uint32) * 2);
346
347 #else /* __BIG_ENDIAN__ */
348
349         /* ObjProps:store_id, obj_format, protection status */
350         memcpy(buf, &(info->store_id),
351                         (sizeof(mtp_uint32) + sizeof(mtp_uint16) * 2));
352         num_bytes += (sizeof(mtp_uint32) + sizeof(mtp_uint16) * 2);
353
354         memcpy(&buf[num_bytes], &objSize, sizeof(mtp_uint32));
355         num_bytes += sizeof(mtp_uint32);
356
357         /* ObjProp:thumb format */
358         memcpy(&buf[num_bytes], &thumb_fmt, sizeof(mtp_uint16));
359         num_bytes += sizeof(mtp_uint16);
360
361         /* ObjProp: thumb file size */
362         memcpy(&buf[num_bytes], &(info->thumb_file_size), sizeof(mtp_uint32));
363         num_bytes += sizeof(mtp_uint32);
364
365         /* ObjProp:thumb_width */
366         memcpy(&buf[num_bytes], &thumb_width, sizeof(mtp_uint32));
367         num_bytes += sizeof(mtp_uint32);
368
369         /* ObjProp:thumb_height */
370         memcpy(&buf[num_bytes], &thumb_height, sizeof(mtp_uint32));
371         num_bytes += sizeof(mtp_uint32);
372
373         /* ObjProp:image_width, image_height,
374          * image_bit_depth values currently are always 0
375          */
376         memset(&(buf[num_bytes]), 0, sizeof(mtp_uint32) * 3);
377         num_bytes +=  (sizeof(mtp_uint32) * 3);
378
379         /* ObjProp:parent_handle */
380         memcpy(&buf[num_bytes], &(info->h_parent), sizeof(mtp_uint32));
381         num_bytes += sizeof(mtp_uint32);
382
383         /* ObjProp:association_type */
384         memcpy(&buf[num_bytes], &(info->association_type), sizeof(mtp_uint16));
385         num_bytes += sizeof(mtp_uint16);
386
387         /* ObjProp:association_desc,sequence Number values are always 0 */
388         memset(&buf[num_bytes], 0, sizeof(mtp_uint32) * 2);
389         num_bytes += sizeof(mtp_uint32) * 2;
390 #endif /* __BIG_ENDIAN__ */
391
392         num_bytes += _prop_pack_ptpstring(file_name, buf + num_bytes,
393                         _prop_size_ptpstring(file_name));
394
395         num_bytes += _prop_pack_ptptimestring(&create_time_str,
396                         buf + num_bytes,
397                         _prop_size_ptptimestring(&create_time_str));
398
399         num_bytes += _prop_pack_ptptimestring(&modify_time_str,
400                         buf + num_bytes,
401                         _prop_size_ptptimestring(&modify_time_str));
402
403         num_bytes += _prop_pack_ptpstring(&keywords,
404                         buf + num_bytes,
405                         _prop_size_ptpstring(&keywords));
406
407         DBG("number of bytes for objectinfo :[%d]\n", num_bytes);
408         return num_bytes;
409 }
410
411 void _entity_dealloc_obj_info(obj_info_t *info)
412 {
413         g_free(info);
414         info = NULL;
415         return;
416 }
417 /* LCOV_EXCL_STOP */
418
419 mtp_obj_t *_entity_alloc_mtp_object(void)
420 {
421         return ((mtp_obj_t *)g_malloc(sizeof(mtp_obj_t)));
422 }
423
424 mtp_bool _entity_init_mtp_object_params(
425                 mtp_obj_t *obj,
426                 mtp_uint32 store_id,
427                 mtp_uint32 h_parent,
428                 mtp_char *file_path,
429                 mtp_char *file_name,
430                 dir_entry_t *file_info)
431 {
432         retv_if(obj == NULL, FALSE);
433
434         obj->obj_handle = 0;
435         obj->obj_info = NULL;
436         obj->file_path = NULL;
437         obj->obj_handle = _entity_generate_next_obj_handle();
438         _entity_set_object_file_path(obj, file_path, CHAR_TYPE);
439         obj->obj_info = _entity_alloc_object_info();
440
441         if (NULL == obj->obj_info) {
442                 g_free(obj->file_path);
443                 obj->file_path = NULL;
444                 return FALSE;
445         }
446         _entity_init_object_info_params(obj->obj_info, store_id, h_parent,
447                         file_name, file_info);
448
449         _util_init_list(&(obj->propval_list));
450         memset(&(obj->child_array), 0, sizeof(ptp_array_t));
451         obj->child_array.type = UINT32_TYPE;
452
453         return TRUE;
454 }
455
456 mtp_bool _entity_set_object_file_path(mtp_obj_t *obj, void *file_path,
457                 char_mode_t char_type)
458 {
459         mtp_char temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
460
461         if (char_type == WCHAR_TYPE) {
462                 _util_utf16_to_utf8(temp, sizeof(temp), (mtp_wchar *)file_path);
463                 g_free(obj->file_path);
464                 obj->file_path = g_strdup(temp);
465         } else {
466                 g_free(obj->file_path);
467                 obj->file_path = g_strdup((char *)file_path);
468         }
469         return TRUE;
470 }
471
472 /* LCOV_EXCL_START */
473 mtp_bool _entity_check_child_obj_path(mtp_obj_t *obj,
474                 mtp_char *src_path, mtp_char *dest_path)
475 {
476         mtp_uint16 idx = 0;
477         mtp_char *ptr = NULL;
478         mtp_obj_t *child_obj = NULL;
479         ptp_array_t child_arr = { 0 };
480         mtp_store_t *src_store = NULL;
481         mtp_char dest_chld_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
482         mtp_char temp_chld_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
483         mtp_wchar dest_chld_wpath[MTP_MAX_PATHNAME_SIZE * 2 + 1] = { 0 };
484         mtp_wchar temp_chld_wpath[MTP_MAX_PATHNAME_SIZE * 2 + 1] = { 0 };
485
486         retv_if(obj == NULL, FALSE);
487
488         if (strlen(dest_path) > MTP_MAX_PATHNAME_SIZE - 1) {
489                 ERR("dest_path is too long[%zu]\n", strlen(dest_path));
490                 return FALSE;
491         }
492
493         if (strlen(src_path) > MTP_MAX_PATHNAME_SIZE - 1) {
494                 ERR("src_path is too long[%zu]\n", strlen(src_path));
495                 return FALSE;
496         }
497
498         src_store = _device_get_store_containing_obj(obj->obj_handle);
499         if (NULL == src_store) {
500                 ERR("Object not present in store");
501                 return FALSE;
502         }
503
504         _prop_init_ptparray(&child_arr, UINT32_TYPE);
505         _entity_get_child_handles(src_store, obj->obj_handle, &child_arr);
506
507         DBG("obj_handle[%d], src_path[%s], dest_path[%s], num elements[%u]\n",
508                         obj->obj_handle, src_path, dest_path, child_arr.num_ele);
509
510         for (idx = 0; idx < child_arr.num_ele; idx++) {
511                 mtp_uint32 *ptr32 = child_arr.array_entry;
512
513                 child_obj = _entity_get_object_from_store(src_store, ptr32[idx]);
514                 if (NULL == child_obj)
515                         continue;
516
517                 if (_util_is_file_opened(child_obj->file_path) == TRUE) {
518                         ERR_SECURE("File [%s] is already opened\n",
519                                         child_obj->file_path);
520                         _prop_deinit_ptparray(&child_arr);
521                         return FALSE;
522                 }
523
524                 g_strlcpy(temp_chld_path, child_obj->file_path,
525                                 MTP_MAX_PATHNAME_SIZE + 1);
526                 _util_utf8_to_utf16(temp_chld_wpath,
527                                 sizeof(temp_chld_wpath) / WCHAR_SIZ, temp_chld_path);
528                 if (_util_wchar_len(temp_chld_wpath) >
529                                 MTP_MAX_PATHNAME_SIZE - 1) {
530                         ERR("Child Object Full Path is too long[%zu]\n",
531                                         strlen(child_obj->file_path));
532                         _prop_deinit_ptparray(&child_arr);
533                         return FALSE;
534                 }
535
536                 ptr = strstr(child_obj->file_path, src_path);
537                 if (NULL == ptr)
538                         continue;
539
540                 _util_utf8_to_utf16(dest_chld_wpath,
541                                 sizeof(dest_chld_wpath) / WCHAR_SIZ, src_path);
542
543                 if (_util_wchar_len(dest_chld_wpath) <
544                                 MTP_MAX_PATHNAME_SIZE - 1) {
545                         g_strlcpy(dest_chld_path, dest_path,
546                                         MTP_MAX_PATHNAME_SIZE + 1);
547                 } else {
548                         ERR("dest_chld_wpath is too long[%zu]\n",
549                                         strlen(dest_path));
550                         _prop_deinit_ptparray(&child_arr);
551                         return FALSE;
552                 }
553
554                 ptr += strlen(src_path);
555                 if ((strlen(dest_chld_path) + strlen(ptr)) <
556                                 MTP_MAX_PATHNAME_SIZE) {
557                         g_strlcat(dest_chld_path, ptr,
558                                         MTP_MAX_PATHNAME_SIZE + 1);
559                 } else {
560                         ERR("dest_chld_path + ptr is too long[%zu]\n",
561                                         (strlen(ptr) + strlen(ptr)));
562                         _prop_deinit_ptparray(&child_arr);
563                         return FALSE;
564                 }
565                 DBG("dest_chld_path[%s], ptr[%s]\n", dest_chld_path, ptr);
566
567                 if (_entity_check_child_obj_path(child_obj,
568                                         temp_chld_path, dest_chld_path) == FALSE) {
569                         ERR("set full path Fail");
570                         _prop_deinit_ptparray(&child_arr);
571                         return FALSE;
572                 }
573         }
574
575         _prop_deinit_ptparray(&child_arr);
576         return TRUE;
577 }
578
579 mtp_bool _entity_set_child_object_path(mtp_obj_t *obj, mtp_char *src_path,
580                 mtp_char *dest_path)
581 {
582         mtp_uint16 idx = 0;
583         mtp_char *ptr = NULL;
584         ptp_array_t child_arr = {0};
585         mtp_obj_t *child_obj = NULL;
586         mtp_store_t *src_store = NULL;
587         mtp_uint32 *child_handle_arr = NULL;
588         mtp_char dest_child_path[MTP_MAX_PATHNAME_SIZE + 1] = {0};
589         mtp_char temp_child_path[MTP_MAX_PATHNAME_SIZE + 1] = {0};
590
591         retv_if(NULL == obj, FALSE);
592         retv_if(NULL == src_path, FALSE);
593         retv_if(NULL == dest_path, FALSE);
594
595         src_store = _device_get_store_containing_obj(obj->obj_handle);
596         if (NULL == src_store) {
597                 ERR("Object not present in store");
598                 return FALSE;
599         }
600
601         _prop_init_ptparray(&child_arr, UINT32_TYPE);
602         _entity_get_child_handles(src_store, obj->obj_handle, &child_arr);
603         DBG("Object handle[%u], src_path[%s], dest_path[%s], Numchild[%u]\n",
604                         obj->obj_handle, src_path, dest_path, child_arr.num_ele);
605
606         for (idx = 0; idx < child_arr.num_ele; idx++) {
607                 child_handle_arr = child_arr.array_entry;
608                 child_obj = _entity_get_object_from_store(src_store, child_handle_arr[idx]);
609                 if (NULL == child_obj)
610                         continue;
611                 DBG_SECURE("obj_handle[%u], full path[%s]\n", child_obj->obj_handle,
612                                 child_obj->file_path);
613                 g_strlcpy(temp_child_path, child_obj->file_path,
614                                 sizeof(temp_child_path));
615
616                 ptr = strstr(child_obj->file_path, src_path);
617                 if (NULL == ptr)
618                         continue;
619
620                 g_strlcpy(dest_child_path, dest_path, sizeof(dest_child_path));
621
622                 ptr += strlen(src_path);
623                 if (g_strlcat(dest_child_path, ptr, sizeof(dest_child_path)) >=
624                                 sizeof(dest_child_path)) {
625                         ERR("g_strlcat truncation occured,failed to create\
626                                         dest_child_path");
627                         _entity_remove_reference_child_array(obj,
628                                         child_obj->obj_handle);
629                         _entity_dealloc_mtp_obj(child_obj);
630                         continue;
631                 }
632                 _util_delete_file_from_db(child_obj->file_path);
633
634                 _entity_set_object_file_path(child_obj, dest_child_path, CHAR_TYPE);
635
636                 if (child_obj->obj_info == NULL) {
637                         ERR("obj_info is NULL");
638                         continue;
639                 }
640
641                 if ((child_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)) {
642                         if (_entity_set_child_object_path(child_obj, temp_child_path,
643                                                 dest_child_path) == FALSE) {
644                                 ERR("Fail to set the full path!!");
645                                 _entity_remove_reference_child_array(obj,
646                                                 child_obj->obj_handle);
647                                 _entity_dealloc_mtp_obj(child_obj);
648                                 continue;
649                         }
650                 }
651         }
652
653         _prop_deinit_ptparray(&child_arr);
654         return TRUE;
655 }
656 /* LCOV_EXCL_STOP */
657
658 mtp_bool _entity_add_reference_child_array(mtp_obj_t *obj, mtp_uint32 handle)
659 {
660         if (_prop_find_ele_ptparray(&(obj->child_array), handle) ==
661                         ELEMENT_NOT_FOUND) {
662                 return (_prop_append_ele_ptparray(&(obj->child_array), handle));
663         }
664
665         return TRUE;
666 }
667
668 /* LCOV_EXCL_START */
669 ptp_array_t *_entity_get_reference_child_array(mtp_obj_t *obj)
670 {
671         return &(obj->child_array);
672 }
673
674 mtp_bool _entity_set_reference_child_array(mtp_obj_t *obj, mtp_uchar *buf,
675                 mtp_uint32 buf_sz)
676 {
677         mtp_uint32 i = 0;
678         mtp_uint32 no_ref = 0;
679         mtp_uint32 ref_handle = 0;
680
681         retv_if(NULL == buf, FALSE);
682
683         /*Retrieve the number of references*/
684         no_ref = buf_sz;
685
686         /*Clean up the reference array*/
687         _entity_remove_reference_child_array(obj, PTP_OBJECTHANDLE_ALL);
688
689         /* Grow the array to accommodate all references*/
690         if (_prop_grow_ptparray(&(obj->child_array), no_ref) == FALSE) {
691                 ERR("grow ptp Array Fail");
692                 return FALSE;
693         }
694
695         ref_handle = 0;
696         for (i = 0; i < no_ref; i++) {
697                 memcpy(&ref_handle, buf, sizeof(mtp_uint32));
698                 buf += sizeof(mtp_uint32);
699                 _prop_append_ele_ptparray(&(obj->child_array), ref_handle);
700         }
701
702         return TRUE;
703 }
704
705 void _entity_copy_mtp_object(mtp_obj_t *dst, mtp_obj_t *src)
706 {
707         /*Copy same information*/
708         dst->obj_info = _entity_alloc_object_info();
709         if (dst->obj_info == NULL) {
710                 ERR("Object info allocation Fail.");
711                 return;
712         }
713         _entity_copy_obj_info(dst->obj_info, src->obj_info);
714         dst->obj_handle = 0;
715         dst->file_path = NULL;
716
717 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
718         _prop_update_property_values_list(dst);
719 #endif /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
720         return;
721 }
722
723 mtp_bool _entity_remove_reference_child_array(mtp_obj_t *obj, mtp_uint32 handle)
724 {
725         if (handle == PTP_OBJECTHANDLE_ALL) {
726                 _prop_deinit_ptparray(&(obj->child_array));
727                 return TRUE;
728         }
729         return _prop_rem_elem_ptparray(&(obj->child_array), handle);
730 }
731
732 void _entity_dealloc_mtp_obj(mtp_obj_t *obj)
733 {
734         mtp_uint16 ii = 0;
735         slist_node_t *node = NULL;
736         slist_node_t *next_node = NULL;
737
738         ret_if(NULL == obj);
739
740         if (obj->obj_info) {
741                 _entity_dealloc_obj_info(obj->obj_info);
742                 obj->obj_info = NULL;
743         }
744
745         _entity_remove_reference_child_array(obj, PTP_OBJECTHANDLE_ALL);
746
747         for (ii = 0, next_node = obj->propval_list.start;
748                         ii < obj->propval_list.nnodes; ii++) {
749                 node = next_node;
750                 next_node = node->link;
751                 _prop_destroy_obj_propval((obj_prop_val_t *)node->value);
752                 g_free(node);
753         }
754
755         g_free(obj->file_path);
756         g_free(obj);
757         obj = NULL;
758         return;
759 }
760 /* LCOV_EXCL_STOP */