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