Add error handling for object copy
[platform/core/connectivity/mtp-responder.git] / src / mtp_cmd_handler_util.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 <unistd.h>
18 #include <glib.h>
19 #include <glib/gprintf.h>
20 #include "mtp_cmd_handler.h"
21 #include "mtp_cmd_handler_util.h"
22 #include "mtp_support.h"
23 #include "mtp_media_info.h"
24 #include "mtp_transport.h"
25
26 /*
27  * GLOBAL AND EXTERN VARIABLES
28  */
29 mtp_bool g_is_full_enum = FALSE;
30 extern mtp_mgr_t g_mtp_mgr;
31 extern obj_interdep_proplist_t interdep_proplist;
32 extern mtp_char g_last_created_dir[MTP_MAX_PATHNAME_SIZE + 1];
33 extern mtp_char g_last_moved[MTP_MAX_PATHNAME_SIZE + 1];
34 extern mtp_char g_last_copied[MTP_MAX_PATHNAME_SIZE + 1];
35 extern mtp_char g_last_deleted[MTP_MAX_PATHNAME_SIZE + 1];
36
37 /*
38  * STATIC VARIABLES
39  */
40 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
41
42 /*
43  * FUNCTIONS
44  */
45
46 /*
47  * This function gets the storage entry.
48  * @param[in]   store_id        Specifies the storage id to get.
49  * @param[in]   info            Points the storage info structure
50  * @return      This function returns MTP_ERROR_NONE on success or
51  *              ERROR_No on failure.
52  */
53 mtp_err_t _hutil_get_storage_entry(mtp_uint32 store_id, store_info_t *info)
54 {
55         mtp_store_t *store = NULL;
56
57         store = _device_get_store(store_id);
58         if (store == NULL) {
59                 ERR("Not able to retrieve store");
60                 return MTP_ERROR_GENERAL;
61         }
62         _entity_update_store_info_run_time(&(store->store_info),
63                         store->root_path);
64
65         _prop_copy_ptpstring(&(info->store_desc), &(store->store_info.store_desc));
66         _prop_copy_ptpstring(&(info->vol_label), &(store->store_info.vol_label));
67         info->access = store->store_info.access;
68         info->fs_type = store->store_info.fs_type;
69         info->free_space = store->store_info.free_space;
70         info->capacity = store->store_info.capacity;
71         info->store_type = store->store_info.store_type;
72         info->free_space_in_objs = store->store_info.free_space_in_objs;
73         return MTP_ERROR_NONE;
74 }
75
76 mtp_err_t _hutil_get_storage_ids(ptp_array_t *store_ids)
77 {
78         mtp_uint32 num_elem = 0;
79         mtp_uint32 num_stores = 0;
80
81         num_elem = _device_get_store_ids(store_ids);
82         num_stores = _device_get_num_stores();
83         if (num_elem == num_stores)
84                 return MTP_ERROR_NONE;
85
86         ERR("get storage id Fail. num_elem[%d], num_stores[%d]\n",
87                         num_elem, num_stores);
88         return MTP_ERROR_GENERAL;
89 }
90
91 /*
92  * This function gets the device property.
93  * @param[in]   prop_id         Specifies the property id to retrieve
94  * @param[in]   dev_prop        Points the device prop structure
95  * @return      This function returns MTP_ERROR_NONE on success,
96  *              or ERROR_NO on failure.
97  */
98 mtp_err_t _hutil_get_device_property(mtp_uint32 prop_id,
99                 device_prop_desc_t* dev_prop)
100 {
101         device_prop_desc_t *prop = NULL;
102
103         prop = _device_get_device_property(prop_id);
104         if (prop == NULL)
105                 return MTP_ERROR_GENERAL;
106
107         memcpy(dev_prop, prop, sizeof(device_prop_desc_t));
108         return MTP_ERROR_NONE;
109 }
110
111 /*
112  * This function sets the device property.
113  * @param[in]   prop_id         Specifies the property id to retrieve.
114  * @param[in]   data            Points the associated data buffer.
115  * @param[in]   data_sz         Specifies the data size of property.
116  * @return      This function returns MTP_ERROR_NONE on success or
117  *              appropriate error on failure.
118  */
119 mtp_err_t _hutil_set_device_property(mtp_uint32 prop_id, void *data,
120                 mtp_uint32 data_sz)
121 {
122         device_prop_desc_t *prop = NULL;
123
124         prop = _device_get_device_property(prop_id);
125         if (prop == NULL)
126                 return MTP_ERROR_GENERAL;
127
128         if (prop->propinfo.get_set == PTP_PROPGETSET_GETONLY)
129                 return MTP_ERROR_ACCESS_DENIED;
130
131         if (FALSE == _prop_set_current_device_prop(prop, data, data_sz))
132                 return MTP_ERROR_INVALID_OBJ_PROP_VALUE;
133
134         return MTP_ERROR_NONE;
135 }
136
137 /*
138  * This function resets the device property.
139  * @param[in]   prop_id         Specifies the property id to retrieve.
140  * @return      This function returns MTP_ERROR_NONE on success,
141  *              appropriate error on failure.
142  */
143 mtp_err_t _hutil_reset_device_entry(mtp_uint32 prop_id)
144 {
145         device_prop_desc_t *prop = NULL;
146         mtp_uint16 ii = 0;
147
148         if (prop_id == 0xFFFFFFFF) {
149
150                 prop = _device_get_ref_prop_list();
151                 if (prop == NULL) {
152                         ERR("property reference is NULL");
153                         return MTP_ERROR_GENERAL;
154                 }
155                 for (ii = 0; ii < NUM_DEVICE_PROPERTIES; ii++)
156                         _prop_reset_device_prop_desc(&prop[ii]);
157         } else {
158                 prop = _device_get_device_property(prop_id);
159                 if (prop == NULL)
160                         return MTP_ERROR_GENERAL;
161
162                 _prop_reset_device_prop_desc(prop);
163         }
164
165         return MTP_ERROR_NONE;
166 }
167
168 /*
169  * This function adds the object entry.
170  * @param[in]   obj_info        Points the objectinfo.
171  * @param[in]   file_name       Points the file name of the object.
172  * @param[out]  new_obj         Points to the new object added.
173  * @return      This function returns MTP_ERROR_NONE on success or
174  *              appropriate error on failure.
175  */
176 mtp_err_t _hutil_add_object_entry(obj_info_t *obj_info, mtp_char *file_name,
177                 mtp_obj_t **new_obj)
178 {
179         mtp_obj_t *obj = NULL;
180         mtp_obj_t *par_obj = NULL;
181         mtp_store_t *store = NULL;
182         mtp_wchar temp_wfname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
183         mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
184         mtp_char new_f_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
185         mtp_int32 i = 0;
186         mtp_int32 error;
187         mtp_bool is_made_by_mtp = FALSE;
188         mtp_wchar w_file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
189
190         if (obj_info->h_parent != PTP_OBJECTHANDLE_ROOT) {
191                 par_obj = _device_get_object_with_handle(obj_info->h_parent);
192                 if (par_obj == NULL) {
193                         ERR("parent is not existed.");
194                         _entity_dealloc_obj_info(obj_info);
195                         return MTP_ERROR_INVALID_OBJECTHANDLE;
196                 }
197
198                 if (par_obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
199                         ERR("parent handle is not association format[0x%x]\
200                                         handle[%d]\n", par_obj->obj_info->obj_fmt,
201                                         par_obj->obj_info->h_parent);
202                         _entity_dealloc_obj_info(obj_info);
203                         return MTP_ERROR_INVALID_PARENT;
204                 }
205         }
206
207         store = _device_get_store(obj_info->store_id);
208         if (store == NULL) {
209                 ERR("store is null");
210                 _entity_dealloc_obj_info(obj_info);
211                 return MTP_ERROR_GENERAL;
212         }
213
214         if (store->store_info.free_space < obj_info->file_size) {
215                 ERR("free space is not enough [%ld] bytes, object size[%ld]\n",
216                                 store->store_info.free_space, obj_info->file_size);
217                 _entity_dealloc_obj_info(obj_info);
218                 return MTP_ERROR_STORE_FULL;
219         }
220
221         obj = _entity_alloc_mtp_object();
222         if (obj == NULL) {
223                 ERR("allocation memory Fail");
224                 _entity_dealloc_obj_info(obj_info);
225                 return MTP_ERROR_GENERAL;
226         }
227
228         memset(obj, 0, sizeof(mtp_obj_t));
229         obj->child_array.type = UINT32_TYPE;
230         obj->obj_handle = _entity_generate_next_obj_handle();
231         obj->obj_info = obj_info;
232
233         /* For PC->MMC read-only file/folder transfer
234          * and for PC->Phone read-only folder transfer
235          * store PTP_PROTECTIONSTATUS_NOPROTECTION in
236          * the field obj_info->ProtectionStatus
237          */
238         if (MTP_EXTERNAL_STORE_ID == obj_info->store_id ||
239                         obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
240                 obj_info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
241         }
242
243         if (strlen(file_name) == 0) {
244                 /* Generate a filename in 8.3 format for this object */
245                 g_snprintf(utf8_temp, MTP_MAX_PATHNAME_SIZE + 1,
246                                 "Tmp_%04u.dat", obj->obj_handle);
247                 _util_utf8_to_utf16(temp_wfname,
248                                 sizeof(temp_wfname) / WCHAR_SIZ, utf8_temp);
249         } else {
250                 _util_utf8_to_utf16(temp_wfname,
251                                 sizeof(temp_wfname) / WCHAR_SIZ, file_name);
252         }
253
254         /* Does this path/filename already exist ? */
255         for (i = 0; ; i++) {
256                 mtp_bool file_exist = FALSE;
257                 mtp_uint32 path_len = 0;
258
259                 /* Get/Generate the Full Path for the new Object; */
260                 if (obj_info->h_parent == PTP_OBJECTHANDLE_ROOT) {
261                         _util_utf16_to_utf8(utf8_temp, sizeof(utf8_temp),
262                                         temp_wfname);
263
264                         if (_util_create_path(new_f_path, sizeof(new_f_path),
265                                                 store->root_path, utf8_temp) == FALSE) {
266                                 _entity_dealloc_mtp_obj(obj);
267                                 return MTP_ERROR_GENERAL;
268                         }
269 #ifdef MTP_SUPPORT_HIDE_WMPINFO_XML
270                         /* WMPInfo.xml and DevLogo.fil.*/
271                         /* find WMPInfo.xml and add file mtp store */
272                         {
273                                 mtp_char wmp_info_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
274                                 mtp_char wmp_hidden_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
275
276                                 if (obj_info->store_id == MTP_INTERNAL_STORE_ID) {
277                                         char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
278                                         _util_get_internal_path(inter_path);
279
280                                         g_snprintf(wmp_hidden_path,
281                                                         MTP_MAX_PATHNAME_SIZE + 1,
282                                                         "%s/%s/%s", MTP_USER_DIRECTORY,
283                                                         MTP_HIDDEN_PHONE,
284                                                         MTP_FILE_NAME_WMPINFO_XML);
285                                         g_snprintf(wmp_info_path,
286                                                         MTP_MAX_PATHNAME_SIZE + 1,
287                                                         "%s/%s", inter_path,
288                                                         MTP_FILE_NAME_WMPINFO_XML);
289                                 } else {
290                                         char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
291                                         _util_get_external_path(ext_path);
292
293                                         g_snprintf(wmp_hidden_path,
294                                                         MTP_MAX_PATHNAME_SIZE + 1,
295                                                         "%s/%s/%s", MTP_USER_DIRECTORY,
296                                                         MTP_HIDDEN_CARD,
297                                                         MTP_FILE_NAME_WMPINFO_XML);
298                                         g_snprintf(wmp_info_path,
299                                                         MTP_MAX_PATHNAME_SIZE + 1,
300                                                         "%s/%s", ext_path,
301                                                         MTP_FILE_NAME_WMPINFO_XML);
302                                 }
303
304                                 if (!strcasecmp(wmp_info_path, new_f_path)) {
305                                         DBG("substitute file[%s]-->[%s]\n",
306                                                         wmp_info_path, wmp_hidden_path);
307
308                                         g_strlcpy(new_f_path, wmp_hidden_path,
309                                                         sizeof(new_f_path));
310
311                                         if (obj_info->store_id ==
312                                                         MTP_INTERNAL_STORE_ID) {
313                                                 obj->obj_handle =
314                                                         MTP_MAX_INT_OBJECT_NUM -
315                                                         MTPSTORE_WMPINFO_PHONE;
316                                         } else {
317                                                 obj->obj_handle =
318                                                         MTP_MAX_INT_OBJECT_NUM -
319                                                         MTPSTORE_WMPINFO_CARD;
320                                         }
321                                 }
322                         }
323 #endif /*MTP_SUPPORT_HIDE_WMPINFO_XML*/
324                 } else {
325                         _util_utf16_to_utf8(utf8_temp, sizeof(utf8_temp),
326                                         temp_wfname);
327                         if (_util_create_path(new_f_path, sizeof(new_f_path),
328                                                 par_obj->file_path, utf8_temp) == FALSE) {
329                                 _entity_dealloc_mtp_obj(obj);
330                                 return MTP_ERROR_GENERAL;
331                         }
332                 }
333
334                 /*
335                  * g_mgr->ftemp_st.filepath was allocated g_strdup("/tmp/.mtptemp.tmp");
336                  * So if we need to change the path we need to allocate sufficient memory
337                  * otherwise memory corruption may happen
338                  */
339
340                 path_len = strlen(store->root_path) + strlen(MTP_TEMP_FILE) + 2;
341                 g_mgr->ftemp_st.filepath = g_realloc(g_mgr->ftemp_st.filepath, path_len);
342                 if (g_mgr->ftemp_st.filepath == NULL) {
343                         ERR("g_realloc Fail");
344                         _entity_dealloc_mtp_obj(obj);
345                         return MTP_ERROR_GENERAL;
346                 }
347
348                 if (_util_create_path(g_mgr->ftemp_st.filepath, path_len,
349                                         store->root_path, MTP_TEMP_FILE) == FALSE) {
350                         ERR("Tempfile fullPath is too long");
351                         _entity_dealloc_mtp_obj(obj);
352                         return MTP_ERROR_GENERAL;
353                 }
354
355                 DBG_SECURE("Temp file path [%s]\n", g_mgr->ftemp_st.filepath);
356
357
358 #ifdef MTP_SUPPORT_ALBUM_ART
359                 if (access(new_f_path, F_OK) == 0) {
360                         file_exist = TRUE;
361                         /* if file is album, overwrite it. */
362                         mtp_char alb_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
363                         mtp_char alb_ext[MTP_MAX_PATHNAME_SIZE + 1] =   { 0 };
364
365                         /* find extension, if album or pla, overwrite that. */
366                         _util_utf16_to_utf8(alb_buf, sizeof(alb_buf), temp_wfname);
367
368                         if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
369                                         (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
370                                          obj_info->association_type !=
371                                          PTP_ASSOCIATIONTYPE_UNDEFINED &&
372                                          obj_info->association_type !=
373                                          PTP_ASSOCIATIONTYPE_FOLDER)) {
374
375                                 _util_get_file_extn(alb_buf, alb_ext);
376                                 if (!strcasecmp(alb_ext, "alb")) {
377                                         if (remove(new_f_path) == 0) {
378                                                 file_exist = FALSE;
379                                                 DBG("[%s] file is found. Delete\
380                                                                 old and make new one\n",
381                                                                 alb_ext);
382                                         } else
383                                                 ERR("[%s] file is found. but \
384                                                                 cannot delete it\n",
385                                                                 alb_ext);
386                                 }
387                         }
388                 }
389 #endif /*MTP_SUPPORT_ALBUM_ART*/
390
391                 if (file_exist == FALSE) {
392                         DBG_SECURE("Found a unique file name for the incoming object\
393                                         [%s]\n", temp_wfname);
394                         break;
395                 }
396
397 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
398                 is_made_by_mtp = obj_info->file_size == 0 &&
399                         obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
400                         obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC;
401 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
402                 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION ||
403                                 is_made_by_mtp) {
404                         *new_obj = _device_get_object_with_path(new_f_path);
405                         if (*new_obj) {
406                                 _entity_dealloc_mtp_obj(obj);
407                                 return MTP_ERROR_NONE;
408                         } else {
409                                 DBG("+ not found object. [%s]\n", new_f_path);
410                                 break;
411                         }
412                 }
413
414                 /* Rename the Filename for this object */
415                 memset(temp_wfname, 0, (MTP_MAX_PATHNAME_SIZE + 1) * 2);
416                 _util_utf8_to_utf16(w_file_name, sizeof(w_file_name) / WCHAR_SIZ,
417                                 file_name);
418                 _util_wchar_swprintf(temp_wfname,
419                                 MTP_MAX_PATHNAME_SIZE + 1, "COPY%d_%s", i, w_file_name);
420         }
421
422         /* Save the full path to this object */
423         _entity_set_object_file_path(obj, new_f_path, CHAR_TYPE);
424
425         /*
426          * Is this an association (or folder)?
427          * Associations are fully qualified by the ObjectInfo Dataset.
428          */
429 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
430         is_made_by_mtp = (obj_info->file_size == 0 &&
431                         obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
432                         obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC);
433 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
434
435         if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION || is_made_by_mtp) {
436                 /* Create the new object */
437                 DBG("[normal] create association file/folder[%s][0x%x]\n",
438                                 new_f_path, obj_info->association_type);
439
440                 if ((obj_info->association_type !=
441                                         PTP_ASSOCIATIONTYPE_UNDEFINED &&
442                                         obj_info->association_type !=
443                                         PTP_ASSOCIATIONTYPE_FOLDER) ||
444                                 is_made_by_mtp) {
445                         FILE* h_abs_file = NULL;
446                         h_abs_file = _util_file_open(new_f_path,
447                                         MTP_FILE_WRITE, &error);
448                         if (h_abs_file == NULL) {
449                                 ERR("create file fail!!");
450                                 _entity_dealloc_mtp_obj(obj);
451                                 return MTP_ERROR_GENERAL;
452                         }
453                         _util_file_close(h_abs_file);
454                 } else {
455                         g_snprintf(g_last_created_dir,
456                                         MTP_MAX_PATHNAME_SIZE + 1, "%s", new_f_path);
457                         if (_util_dir_create(new_f_path, &error) == FALSE) {
458                                 /* We failed to create the folder */
459                                 ERR("create directory Fail");
460                                 memset(g_last_created_dir, 0,
461                                                 sizeof(g_last_created_dir));
462                                 _entity_dealloc_mtp_obj(obj);
463                                 return MTP_ERROR_GENERAL;
464                         }
465                 }
466
467                 _entity_set_object_file_path(obj, new_f_path, CHAR_TYPE);
468                 if (_entity_add_object_to_store(store, obj) == FALSE) {
469                         ERR("_entity_add_object_to_store Fail");
470                         _entity_dealloc_mtp_obj(obj);
471                         return MTP_ERROR_STORE_FULL;
472                 }
473         } else {
474                 /* Reserve space for the object: Object itself, and probably
475                  * some Filesystem-specific overhead
476                  */
477                 store->store_info.free_space -= obj_info->file_size;
478         }
479
480         *new_obj = obj;
481
482         return MTP_ERROR_NONE;
483 }
484
485 /*
486  * This function removes the object entry.
487  * @param[in]   obj_handle      Specifies the object to remove.
488  * @param[in]   format          Specifies the format code.
489  * @return      This function returns MTP_ERROR_NONE on success or
490  *              appropriate error on failure.
491  */
492 mtp_err_t _hutil_remove_object_entry(mtp_uint32 obj_handle, mtp_uint32 format)
493 {
494         mtp_err_t resp = MTP_ERROR_GENERAL;
495         mtp_uint16 ret = 0;
496
497 #ifdef MTP_SUPPORT_SET_PROTECTION
498         /* this will check to see if the protection is set */
499         mtp_obj_t *obj = NULL;
500         if (obj_handle != 0xFFFFFFFF) {
501                 obj = _device_get_object_with_handle(obj_handle);
502                 if (obj != NULL) {
503                         if ((obj->obj_info->protcn_status ==
504                                                 MTP_PROTECTIONSTATUS_READONLY_DATA) ||
505                                         (obj->obj_info->protcn_status ==
506                                          PTP_PROTECTIONSTATUS_READONLY)) {
507                                 ERR("Protection status is [0x%x]\n",
508                                                 obj->obj_info->protcn_status);
509                                 return MTP_ERROR_OBJECT_WRITE_PROTECTED;
510                         }
511                 }
512         }
513 #endif /*MTP_SUPPORT_SET_PROTECTION*/
514
515         ret = _device_delete_object(obj_handle, format);
516         switch (ret) {
517         case PTP_RESPONSE_OK:
518                 resp = MTP_ERROR_NONE;
519                 break;
520         case PTP_RESPONSE_STORE_READONLY:
521                 resp = MTP_ERROR_STORE_READ_ONLY;
522                 break;
523         case PTP_RESPONSE_PARTIAL_DELETION:
524                 resp = MTP_ERROR_PARTIAL_DELETION;
525                 break;
526         case PTP_RESPONSE_OBJ_WRITEPROTECTED:
527                 resp = MTP_ERROR_OBJECT_WRITE_PROTECTED;
528                 break;
529         case PTP_RESPONSE_ACCESSDENIED:
530                 resp = MTP_ERROR_ACCESS_DENIED;
531                 break;
532         case PTP_RESPONSE_INVALID_OBJ_HANDLE:
533                 resp = MTP_ERROR_INVALID_OBJECTHANDLE;
534                 break;
535         default:
536                 break;
537         }
538
539         return resp;
540 }
541
542 /*
543  * This function gets the object entry.
544  * @param[in]   obj_handle      Specifies the object to get.
545  * @param[out]  obj_ptr         Points to object found.
546  * @return      This function returns MTP_ERROR_NONE on success
547  *              or appropriate error on failure.
548  */
549 mtp_err_t _hutil_get_object_entry(mtp_uint32 obj_handle, mtp_obj_t **obj_ptr)
550 {
551         mtp_obj_t *obj = NULL;
552
553         obj = _device_get_object_with_handle(obj_handle);
554         if (NULL == obj || NULL == obj->obj_info)
555                 return MTP_ERROR_GENERAL;
556
557         *obj_ptr = obj;
558         return MTP_ERROR_NONE;
559 }
560
561 mtp_err_t _hutil_copy_object_entries(mtp_uint32 dst_store_id,
562                 mtp_uint32 src_store_id, mtp_uint32 h_parent, mtp_uint32 obj_handle,
563                 mtp_uint32 *new_hobj, mtp_bool keep_handle)
564 {
565         mtp_store_t *dst = NULL;
566         mtp_store_t *src = NULL;
567         mtp_obj_t *obj = NULL;
568         mtp_obj_t *par_obj = NULL;
569         mtp_obj_t *new_obj = NULL;
570         mtp_int32 error = 0;
571         mtp_char fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
572         mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
573         mtp_err_t ret = MTP_ERROR_NONE;
574         mtp_uint32 num_of_deleted_file = 0;
575         mtp_uint32 num_of_file = 0;
576         ptp_array_t child_arr = { 0 };
577         mtp_obj_t *child_obj = NULL;
578         mtp_uint32 ii = 0;
579
580         src = _device_get_store(src_store_id);
581         dst = _device_get_store(dst_store_id);
582         obj = _device_get_object_with_handle(obj_handle);
583
584         if ((src == NULL) || (dst == NULL) || (obj == NULL)) {
585                 ERR("NULL!!");
586                 return MTP_ERROR_GENERAL;
587         }
588
589         if (h_parent > 0)       {
590                 if (keep_handle) {
591                         /* two sam handle can occurs in folder copy case
592                          * (find last appended object in target storage)
593                          */
594                         par_obj = _entity_get_last_object_from_store(dst,
595                                         h_parent);
596                 } else
597                         par_obj = _device_get_object_with_handle(h_parent);
598         } else {
599                 par_obj = NULL;
600         }
601
602         _util_get_file_name(obj->file_path, utf8_temp);
603
604         if (par_obj == NULL) {
605                 /* Parent is the root of this store */
606                 if (_util_create_path(fpath, sizeof(fpath), dst->root_path,
607                                         utf8_temp) == FALSE) {
608                         ERR("new path is too LONG");
609                         return MTP_ERROR_GENERAL;
610                 }
611         } else {
612                 if (_util_create_path(fpath, sizeof(fpath), par_obj->file_path,
613                                         utf8_temp) == FALSE) {
614                         ERR("New path is too LONG!!");
615                         return MTP_ERROR_GENERAL;
616                 }
617         }
618
619         if (!strcasecmp(fpath, obj->file_path)) {
620                 ERR("Identical path of source and destination[%s]\n", fpath);
621                 return MTP_ERROR_GENERAL;
622         }
623
624         new_obj = _entity_alloc_mtp_object();
625         if (new_obj == NULL) {
626                 ERR("_entity_alloc_mtp_object Fail");
627                 return MTP_ERROR_GENERAL;
628         }
629
630         memset(new_obj, 0, sizeof(mtp_obj_t));
631         new_obj->child_array.type = UINT32_TYPE;
632
633         _entity_copy_mtp_object(new_obj, obj);
634         if (new_obj->obj_info == NULL) {
635                 _entity_dealloc_mtp_obj(new_obj);
636                 return MTP_ERROR_GENERAL;
637         }
638
639         new_obj->obj_info->store_id = dst_store_id;
640         _entity_set_object_file_path(new_obj, fpath, CHAR_TYPE);
641
642         if (MTP_EXTERNAL_STORE_ID == new_obj->obj_info->store_id) {
643                 new_obj->obj_info->protcn_status =
644                         PTP_PROTECTIONSTATUS_NOPROTECTION;
645         }
646
647         new_obj->obj_handle = (keep_handle) ? obj->obj_handle :
648                 _entity_generate_next_obj_handle();
649         new_obj->obj_info->h_parent = (par_obj == NULL) ? PTP_OBJECTHANDLE_ROOT :
650                 par_obj->obj_handle;
651
652         if (new_obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
653                 DBG("Non-association type!!");
654                 g_snprintf(g_last_copied, MTP_MAX_PATHNAME_SIZE + 1, "%s",
655                                 new_obj->file_path);
656                 if (_util_file_copy(obj->file_path, new_obj->file_path,
657                                         &error) == FALSE) {
658                         memset(g_last_copied, 0, MTP_MAX_PATHNAME_SIZE + 1);
659                         ERR("Copy file Fail");
660                         _entity_dealloc_mtp_obj(new_obj);
661                         if (EACCES == error)
662                                 return MTP_ERROR_ACCESS_DENIED;
663                         else if (ENOSPC == error)
664                                 return MTP_ERROR_STORE_FULL;
665                         return MTP_ERROR_GENERAL;
666
667                 }
668 #ifdef MTP_SUPPORT_SET_PROTECTION
669                 file_attr_t attr = { 0 };
670                 attr.attribute = MTP_FILE_ATTR_MODE_REG;
671                 if (PTP_PROTECTIONSTATUS_READONLY ==
672                                 new_obj->obj_info->protcn_status) {
673                         if (FALSE == _util_set_file_attrs(new_obj->file_path,
674                                                 attr.attribute | MTP_FILE_ATTR_MODE_READ_ONLY))
675                                 return MTP_ERROR_GENERAL;
676                 }
677 #endif /* MTP_SUPPORT_SET_PROTECTION */
678
679                 /* Update the storeinfo after successfully copy of the object */
680                 dst->store_info.free_space -= obj->obj_info->file_size;
681
682                 /* move case */
683                 if (keep_handle) {
684                         _entity_add_object_to_store(dst, new_obj);
685                         /* Reference Copy */
686                         _prop_copy_ptparray(&(new_obj->child_array),
687                                         &(obj->child_array));
688                 } else {
689                         _entity_add_object_to_store(dst, new_obj);
690                 }
691
692                 *new_hobj = new_obj->obj_handle;
693                 return MTP_ERROR_NONE;
694         }
695
696         DBG("Association type!!");
697         if (access(new_obj->file_path, F_OK) == 0) {
698                 if (TRUE == keep_handle) {
699                         /*generate unique_path*/
700                         mtp_char unique_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
701                         if (FALSE == _util_get_unique_dir_path(new_obj->file_path,
702                                                 unique_fpath, sizeof(unique_fpath))) {
703                                 _entity_dealloc_mtp_obj(new_obj);
704                                 return MTP_ERROR_GENERAL;
705                         }
706                         _entity_set_object_file_path(new_obj, unique_fpath, CHAR_TYPE);
707                         g_snprintf(g_last_created_dir, MTP_MAX_PATHNAME_SIZE + 1,
708                                         "%s", new_obj->file_path);
709                         if (_util_dir_create(new_obj->file_path, &error) == FALSE) {
710                                 memset(g_last_created_dir, 0,
711                                                 MTP_MAX_PATHNAME_SIZE + 1);
712                                 ERR("Creating folder Fail!!");
713                                 _entity_dealloc_mtp_obj(new_obj);
714                                 if (ENOSPC == error)
715                                         return MTP_ERROR_STORE_FULL;
716                                 return MTP_ERROR_GENERAL;
717                         }
718
719                         /* Add the new object to this store's object list */
720                         _entity_add_object_to_store(dst, new_obj);
721                 } else {
722                         DBG("Already existed association type!!");
723                         _entity_dealloc_mtp_obj(new_obj);
724                         new_obj = _entity_get_object_from_store_by_path(dst, fpath);
725                         if (!new_obj) {
726                                 ERR("But object is not registered!!");
727                                 return MTP_ERROR_GENERAL;
728                         }
729                 }
730         } else {
731                 g_snprintf(g_last_created_dir, MTP_MAX_PATHNAME_SIZE + 1,
732                                 "%s", new_obj->file_path);
733                 if (_util_dir_create(new_obj->file_path, &error) == FALSE) {
734                         memset(g_last_created_dir, 0,
735                                         MTP_MAX_PATHNAME_SIZE + 1);
736                         ERR("Creating folder Fail!!");
737                         _entity_dealloc_mtp_obj(new_obj);
738                         if (ENOSPC == error)
739                                 return MTP_ERROR_STORE_FULL;
740                         return MTP_ERROR_GENERAL;
741                 }
742
743                 /* Add the new object to this store's object list */
744                 _entity_add_object_to_store(dst, new_obj);
745         }
746
747         /* Child addition to data structures is not required in Copy
748          * case as on demand enumeration is supported
749          */
750         if (FALSE == keep_handle) {
751                 if (FALSE == _util_copy_dir_children_recursive(obj->file_path,
752                                         new_obj->file_path, &error)) {
753                         ERR_SECURE("Recursive copy Fail  [%s]->[%s]",
754                                         obj->file_path, new_obj->file_path);
755                         ret = MTP_ERROR_GENERAL;
756                         if (EACCES == error)
757                                 ret = MTP_ERROR_ACCESS_DENIED;
758                         else if (ENOSPC == error)
759                                 ret = MTP_ERROR_STORE_FULL;
760                         if (_util_remove_dir_children_recursive(new_obj->file_path,
761                                                 &num_of_deleted_file, &num_of_file,
762                                                 FALSE) == MTP_ERROR_NONE) {
763                                 g_snprintf(g_last_deleted,
764                                                 MTP_MAX_PATHNAME_SIZE + 1,
765                                                 "%s", new_obj->file_path);
766                                 if (rmdir(new_obj->file_path) < 0) {
767                                         memset(g_last_deleted, 0,
768                                                         MTP_MAX_PATHNAME_SIZE + 1);
769                                 }
770                         }
771                         return ret;
772                 }
773
774                 *new_hobj = new_obj->obj_handle;
775
776                 return MTP_ERROR_NONE;
777         }
778
779
780         /* Since this is an association, copy its children as well*/
781         _prop_init_ptparray(&child_arr, UINT32_TYPE);
782         _entity_get_child_handles(src, obj->obj_handle, &child_arr);
783
784         for (ii = 0; ii < child_arr.num_ele; ii++)      {
785                 mtp_uint32 *ptr32 = child_arr.array_entry;
786
787                 child_obj = _entity_get_object_from_store(src, ptr32[ii]);
788                 if (child_obj == NULL)
789                         continue;
790
791                 ret = _hutil_copy_object_entries(dst_store_id, src_store_id,
792                                 new_obj->obj_handle, child_obj->obj_handle,
793                                 new_hobj, keep_handle);
794                 if (ret != MTP_ERROR_NONE) {
795                         ERR("Copy file Fail");
796                         _prop_deinit_ptparray(&child_arr);
797                         return ret;
798                 }
799         }
800
801         /* Recursive copy is required when folder is not enumerated so it may
802          * return 0 child handles
803          */
804         if (!((child_arr.num_ele > 0) ||
805                                 _util_copy_dir_children_recursive(obj->file_path,
806                                         new_obj->file_path, &error))) {
807                 ERR_SECURE("Recursive copy Fail [%d], [%s]->[%s]",
808                                 child_arr.num_ele,
809                                 obj->file_path, new_obj->file_path);
810                 _prop_deinit_ptparray(&child_arr);
811                 if (_util_remove_dir_children_recursive(new_obj->file_path,
812                                         &num_of_deleted_file, &num_of_file, FALSE) ==
813                                 MTP_ERROR_NONE) {
814                         g_snprintf(g_last_deleted, MTP_MAX_PATHNAME_SIZE + 1,
815                                         "%s", new_obj->file_path);
816                         if (rmdir(new_obj->file_path) < 0) {
817                                 memset(g_last_deleted, 0,
818                                                 MTP_MAX_PATHNAME_SIZE + 1);
819                         }
820                 }
821                 if (error == ENOSPC)
822                         return MTP_ERROR_STORE_FULL;
823                 return MTP_ERROR_GENERAL;
824         }
825
826         _prop_deinit_ptparray(&child_arr);
827         *new_hobj = new_obj->obj_handle;
828
829         return MTP_ERROR_NONE;
830 }
831
832 mtp_err_t _hutil_move_object_entry(mtp_uint32 dst_store_id, mtp_uint32 h_parent,
833                 mtp_uint32 obj_handle)
834 {
835         mtp_store_t *src = NULL;
836         mtp_store_t *dst = NULL;
837         mtp_obj_t *obj = NULL;
838         mtp_obj_t *par_obj = NULL;
839         mtp_char str_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
840         mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
841         mtp_uint32 new_handle = 0;
842         mtp_int32 error = 0;
843         mtp_err_t ret = MTP_ERROR_NONE;
844
845         obj = _device_get_object_with_handle(obj_handle);
846         if (NULL == obj) {
847                 ERR("object is [%p]\n", obj);
848                 return MTP_ERROR_INVALID_OBJECTHANDLE;
849         }
850         if (NULL == obj->obj_info) {
851                 ERR("obj_info is [%p]\n", obj->obj_info);
852                 return MTP_ERROR_GENERAL;
853         }
854
855         src = _device_get_store_containing_obj(obj_handle);
856         if (src == NULL) {
857                 ERR("error retrieving source store");
858                 return MTP_ERROR_STORE_NOT_AVAILABLE;
859         }
860
861         if (src->store_info.access == PTP_STORAGEACCESS_R) {
862                 ERR("Store access is read only");
863                 return MTP_ERROR_STORE_READ_ONLY;
864         }
865
866         dst = _device_get_store(dst_store_id);
867         if (dst == NULL) {
868                 ERR("error retrieving destination store");
869                 return MTP_ERROR_STORE_NOT_AVAILABLE;
870         }
871
872         if (dst->store_info.access != PTP_STORAGEACCESS_RWD) {
873                 ERR("Write permission not there on target store");
874                 return MTP_ERROR_STORE_READ_ONLY;
875         }
876
877         /* Get the Parent Object Handle */
878         if (h_parent > 0) {
879                 par_obj = _device_get_object_with_handle(h_parent);
880
881                 if (par_obj == NULL || par_obj->obj_info == NULL) {
882                         ERR("par_obj[%p] or par_obj->obj_info is NULL\n", par_obj);
883                         return MTP_ERROR_INVALID_PARENT;
884                 } else if (PTP_FMT_ASSOCIATION != par_obj->obj_info->obj_fmt) {
885                         ERR("par obj fmt = [0x%x]\n", par_obj->obj_info->obj_fmt);
886                         return MTP_ERROR_INVALID_PARENT;
887                 }
888
889                 if (dst != _device_get_store_containing_obj(h_parent)) {
890                         ERR("parent is not on the destination store");
891                         return MTP_ERROR_INVALID_PARENT;
892                 }
893
894                 /* Parent must not be a descendant of the object to be moved */
895                 if (dst->store_id == src->store_id) {
896                         if (_entity_check_if_B_parent_of_A(dst, h_parent,
897                                                 obj_handle))
898                                 return MTP_ERROR_INVALID_PARAM;
899                 }
900         } else {
901                 par_obj = NULL; /* Parent is the root */
902         }
903
904         /* Check if the source store is the target store */
905         if (dst->store_id == src->store_id) {
906
907                 mtp_obj_t *old_par = NULL;
908                 mtp_char new_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
909                 mtp_char dst_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
910                 mtp_char *parent_path = NULL;
911
912                 DBG("same storage , type[0x%x]\n",
913                                 obj->obj_info->association_type);
914                 _util_get_file_name(obj->file_path, utf8_temp);
915
916                 if (par_obj == NULL)
917                         parent_path = dst->root_path;
918                 else
919                         parent_path = par_obj->file_path;
920
921                 if (_util_create_path(dst_fpath, sizeof(dst_fpath), parent_path,
922                                         utf8_temp) == FALSE) {
923                         ERR("dst path is too LONG!!");
924                         return MTP_ERROR_GENERAL;
925                 }
926
927                 /* Do a real "Move" for the object in the same store: no need to
928                  * check space available
929                  */
930                 g_strlcpy(str_buf, obj->file_path, sizeof(str_buf));
931
932                 if (obj->obj_info != NULL && obj->obj_info->obj_fmt ==
933                                 PTP_FMT_ASSOCIATION) {
934
935                         if (access(dst_fpath, F_OK) == 0) {
936                                 if (FALSE == _util_get_unique_dir_path(dst_fpath,
937                                                         new_fpath, sizeof(new_fpath))) {
938                                         return MTP_ERROR_GENERAL;
939                                 }
940                         } else {
941                                 g_strlcpy(new_fpath, dst_fpath, sizeof(new_fpath));
942                         }
943
944                         g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
945                                         "%s", str_buf);
946                         if (rename(str_buf, new_fpath) < 0) {
947                                 /* Failed to move the object */
948                                 error = errno;
949                                 memset(g_last_moved, 0,
950                                                 MTP_MAX_PATHNAME_SIZE + 1);
951                                 ERR_SECURE("Directory rename fail in same storage\
952                                                 [%s]->[%s]\n", str_buf, new_fpath);
953                                 if (EACCES == error)
954                                         return MTP_ERROR_ACCESS_DENIED;
955                                 else if (ENOSPC == error)
956                                         return MTP_ERROR_STORE_FULL;
957                                 return MTP_ERROR_GENERAL;
958                         }
959
960                         _util_scan_folder_contents_in_db(str_buf);
961                         _entity_set_object_file_path(obj, new_fpath, CHAR_TYPE);
962                         _entity_set_child_object_path(obj, str_buf, new_fpath);
963                         _util_scan_folder_contents_in_db(new_fpath);
964                 } else {
965                         g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
966                                         "%s", str_buf);
967                         if (FALSE == _util_file_move(str_buf, dst_fpath,
968                                                 &error)) {
969                                 /* Failed to move the object */
970                                 memset(g_last_moved, 0,
971                                                 MTP_MAX_PATHNAME_SIZE + 1);
972                                 ERR("move file Fail in same storage\
973                                                 [%s]->[%s]\n", str_buf, dst_fpath);
974                                 if (EACCES == error)
975                                         return MTP_ERROR_ACCESS_DENIED;
976                                 else if (ENOSPC == error)
977                                         return MTP_ERROR_STORE_FULL;
978                                 return MTP_ERROR_GENERAL;
979                         }
980
981                         _util_delete_file_from_db(obj->file_path);
982                         _entity_set_object_file_path(obj, dst_fpath, CHAR_TYPE);
983                         _util_add_file_to_db(obj->file_path);
984                 }
985
986                 if (obj->obj_info->h_parent != PTP_OBJECTHANDLE_ROOT) {
987                         old_par = _entity_get_object_from_store(src,
988                                         obj->obj_info->h_parent);
989                         if (old_par) {
990                                 _entity_remove_reference_child_array(old_par,
991                                                 obj->obj_handle);
992                         }
993                 }
994
995                 if (par_obj != NULL) {
996                         obj->obj_info->h_parent = par_obj->obj_handle;
997                         _entity_add_reference_child_array(par_obj,
998                                         obj->obj_handle);
999                 } else {
1000                         obj->obj_info->h_parent = PTP_OBJECTHANDLE_ROOT;
1001                 }
1002
1003                 return MTP_ERROR_NONE;
1004         } else {
1005                 /* Move is called between two stores */
1006                 /* Calculate the space required for the new object(s) */
1007                 mtp_obj_t *new_obj = NULL;
1008                 DBG("Different storage or a folder, type[0x%x]\n",
1009                                 obj->obj_info->association_type);
1010
1011                 /* Simulate a Move operation: First copy the Object,
1012                  * then remove the old object
1013                  */
1014                 ret = _hutil_copy_object_entries(dst->store_id, src->store_id,
1015                                 (par_obj == NULL) ? 0 : (par_obj->obj_handle),
1016                                 obj->obj_handle, &new_handle, TRUE);
1017                 if (ret != MTP_ERROR_NONE) {
1018                         _entity_delete_obj_mtp_store(dst, obj->obj_handle,
1019                                         PTP_FORMATCODE_NOTUSED, FALSE);
1020                         return ret;
1021                 }
1022
1023                 _entity_delete_obj_mtp_store(src, obj->obj_handle,
1024                                 PTP_FORMATCODE_NOTUSED, FALSE);
1025                 new_obj = _device_get_object_with_handle(new_handle);
1026                 if (NULL == new_obj || NULL == new_obj->obj_info)
1027                         return MTP_ERROR_GENERAL;
1028
1029                 if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1030                         _util_scan_folder_contents_in_db(new_obj->file_path);
1031                 else
1032                         _util_add_file_to_db(new_obj->file_path);
1033
1034                 return MTP_ERROR_NONE;
1035         }
1036         return MTP_ERROR_GENERAL;
1037 }
1038
1039 mtp_err_t _hutil_duplicate_object_entry(mtp_uint32 dst_store_id,
1040                 mtp_uint32 h_parent, mtp_uint32 obj_handle, mtp_uint32 *new_handle)
1041 {
1042         mtp_store_t *src = NULL;
1043         mtp_store_t *dst = NULL;
1044         mtp_obj_t *obj = NULL;
1045         mtp_obj_t *par_obj = NULL;
1046         mtp_obj_t *new_obj = NULL;
1047         mtp_uint32 space_req = 0;
1048         mtp_err_t ret = MTP_ERROR_NONE;
1049
1050         obj = _device_get_object_with_handle(obj_handle);
1051         if (NULL == obj) {
1052                 ERR("Object not found");
1053                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1054         }
1055
1056         src = _device_get_store_containing_obj(obj_handle);
1057         if (NULL == src) {
1058                 ERR("Source store not found");
1059                 return MTP_ERROR_STORE_NOT_AVAILABLE;
1060         }
1061
1062         dst = _device_get_store(dst_store_id);
1063         if (NULL == dst) {
1064                 ERR("Destination store not found");
1065                 return MTP_ERROR_STORE_NOT_AVAILABLE;
1066         }
1067
1068         if (dst->store_info.access != PTP_STORAGEACCESS_RWD) {
1069                 ERR("Store is read only");
1070                 return MTP_ERROR_STORE_READ_ONLY;
1071         }
1072
1073         if (h_parent > 0) {
1074                 par_obj = _device_get_object_with_handle(h_parent);
1075                 if ((par_obj == NULL) || (par_obj->obj_info->obj_fmt !=
1076                                         PTP_FMT_ASSOCIATION))
1077                         return MTP_ERROR_INVALID_PARENT;
1078
1079                 if (dst != _device_get_store_containing_obj(h_parent))
1080                         return MTP_ERROR_INVALID_PARENT;
1081
1082                 if (dst->store_id == src->store_id) {
1083                         if (_entity_check_if_B_parent_of_A(dst, h_parent,
1084                                                 obj_handle))
1085                                 return MTP_ERROR_INVALID_PARENT;
1086                 }
1087         } else
1088                 par_obj = NULL;
1089
1090         space_req = _entity_get_object_tree_size(src, obj);
1091         if (dst->store_info.free_space < space_req) {
1092                 ERR("Insufficient free space");
1093                 return MTP_ERROR_STORE_FULL;
1094         }
1095
1096         if ((ret = _hutil_copy_object_entries(dst_store_id, src->store_id,
1097                                         h_parent, obj_handle, new_handle, FALSE)) != MTP_ERROR_NONE) {
1098                 return ret;
1099         }
1100         /*
1101          * After this command, Initiator will ask get object prop list (0x9805).
1102          * update the media DB.
1103          */
1104         new_obj = _device_get_object_with_handle(*new_handle);
1105         if (NULL == new_obj || NULL == new_obj->obj_info) {
1106                 ERR("new obj or info is NULL");
1107                 return MTP_ERROR_GENERAL;
1108         }
1109
1110         if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1111                 _util_scan_folder_contents_in_db(new_obj->file_path);
1112         else
1113                 _util_add_file_to_db(new_obj->file_path);
1114
1115         return MTP_ERROR_NONE;
1116 }
1117
1118 mtp_err_t _hutil_read_file_data_from_offset(mtp_uint32 obj_handle, off_t offset,
1119                 void *data, mtp_uint32 *data_sz)
1120 {
1121         mtp_obj_t *obj = NULL;
1122         FILE* h_file = NULL;
1123         mtp_int32 error = 0;
1124         mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1];
1125         off_t result = 0;
1126         mtp_uint32 num_bytes;
1127
1128         obj = _device_get_object_with_handle(obj_handle);
1129         if (obj == NULL) {
1130                 ERR("_device_get_object_with_handle returned NULL object");
1131                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1132         }
1133
1134         if (obj->obj_info->protcn_status ==
1135                         MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA) {
1136
1137                 ERR("protection data, NONTRANSFERABLE_OBJECT");
1138                 return MTP_ERROR_GENERAL;
1139         }
1140
1141         g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1142         h_file = _util_file_open(fname, MTP_FILE_READ, &error);
1143         if (h_file == NULL) {
1144                 ERR("file open Fail[%s]\n", fname);
1145                 return MTP_ERROR_GENERAL;
1146         }
1147
1148         result = _util_file_seek(h_file, offset, SEEK_SET);
1149         if (result == FALSE) {
1150                 ERR("file seek Fail [%d]\n", errno);
1151                 _util_file_close(h_file);
1152                 return MTP_ERROR_GENERAL;
1153         }
1154
1155         num_bytes = *data_sz;
1156         _util_file_read(h_file, data, *data_sz, data_sz);
1157
1158         if (num_bytes != *data_sz) {
1159                 ERR("requested[%d] and read[%d] number of bytes do not match\n",
1160                                 *data_sz, num_bytes);
1161                 _util_file_close(h_file);
1162                 return MTP_ERROR_GENERAL;
1163         }
1164
1165         _util_file_close(h_file);
1166         return MTP_ERROR_NONE;
1167 }
1168
1169 mtp_err_t _hutil_write_file_data(mtp_uint32 store_id, mtp_obj_t *obj,
1170                 mtp_char *fpath)
1171 {
1172         mtp_store_t *store;
1173         mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1174 #ifdef MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE
1175         mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1176 #endif /*MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE*/
1177         mtp_int32 error = 0;
1178
1179         retv_if(obj == NULL, MTP_ERROR_INVALID_PARAM);
1180         retv_if(obj->obj_info == NULL, MTP_ERROR_INVALID_PARAM);
1181
1182         store = _device_get_store(store_id);
1183         if (store == NULL) {
1184                 ERR("destination store is not valid");
1185                 return MTP_ERROR_INVALID_OBJECT_INFO;
1186         }
1187
1188         g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1189         if (access(fpath, F_OK) < 0) {
1190                 ERR("temp file does not exist");
1191                 return MTP_ERROR_GENERAL;
1192         }
1193
1194 #ifdef MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE
1195         /* in case of alb extension, does not make real file just skip below */
1196         if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
1197                         (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
1198                          obj_info->association_type != PTP_ASSOCIATIONTYPE_UNDEFINED &&
1199                          obj_info->association_type != PTP_ASSOCIATIONTYPE_FOLDER)) {
1200
1201                 _util_get_file_extn(fname, extn);
1202                 if (strlen(extn) && !strcasecmp(extn, "alb")) {
1203                         DBG("No need to create album file");
1204                         remove(fpath, &error);
1205                         return MTP_ERROR_NONE;
1206                 }
1207         }
1208 #endif /*MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE*/
1209
1210         g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1, "%s", fpath);
1211         if (FALSE == _util_file_move(fpath, fname, &error)) {
1212                 memset(g_last_moved, 0, MTP_MAX_PATHNAME_SIZE + 1);
1213                 ERR("move to real file fail [%s]->[%s] \n", fpath, fname);
1214                 _entity_dealloc_mtp_obj(obj);
1215
1216                 return MTP_ERROR_STORE_FULL;
1217         }
1218
1219 #ifdef MTP_SUPPORT_SET_PROTECTION
1220         if ((obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) ||
1221                         (obj_info->ProtectionStatus ==
1222                          MTP_PROTECTIONSTATUS_READONLY_DATA)) {
1223                 file_attr_t attrs;
1224                 if (_util_get_file_attrs(fname, &attrs) == FALSE) {
1225                         ERR("real file get attributes Fail");
1226                         _entity_dealloc_mtp_obj(obj);
1227                         return MTP_ERROR_GENERAL;
1228                 }
1229                 _util_set_file_attrs(fname, attrs.attribute |
1230                                 MTP_FILE_ATTR_MODE_READ_ONLY);
1231         }
1232 #endif /* MTP_SUPPORT_SET_PROTECTION */
1233
1234         _util_add_file_to_db(obj->file_path);
1235
1236 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1237         if (updatePropertyValuesMtpObject(obj) == FALSE) {
1238                 ERR("update property values mtp obj Fail");
1239                 _entity_dealloc_mtp_obj(obj);
1240                 return MTP_ERROR_GENERAL;
1241         }
1242 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1243
1244         _entity_add_object_to_store(store, obj);
1245
1246         return MTP_ERROR_NONE;
1247 }
1248
1249 mtp_err_t _hutil_get_object_entry_size(mtp_uint32 obj_handle,
1250                 mtp_uint64 *obj_sz)
1251 {
1252         mtp_obj_t *obj = NULL;
1253
1254         obj = _device_get_object_with_handle(obj_handle);
1255         if (obj == NULL) {
1256                 ERR("_device_get_object_with_handle returned Null object");
1257                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1258         }
1259
1260         *obj_sz = obj->obj_info->file_size;
1261         return MTP_ERROR_NONE;
1262 }
1263
1264 #ifdef MTP_SUPPORT_SET_PROTECTION
1265 mtp_err_t _hutil_set_protection(mtp_uint32 obj_handle, mtp_uint16 prot_status)
1266 {
1267         mtp_obj_t *obj = NULL;
1268         mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1269         file_attr_t attrs = { 0 };
1270
1271         obj = _device_get_object_with_handle(obj_handle);
1272         if (obj == NULL)
1273                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1274
1275         if (MTP_EXTERNAL_STORE_ID == obj->obj_info->store_id) {
1276                 ERR("Storage is external");
1277                 return MTP_ERROR_OPERATION_NOT_SUPPORTED;
1278         }
1279
1280         g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1281         obj->obj_info->protcn_status = prot_status;
1282
1283         if (FALSE == _util_get_file_attrs(fname, &attrs)) {
1284                 ERR("Failed to get file[%s] attrs\n", fname);
1285                 return MTP_ERROR_GENERAL;
1286         }
1287
1288         if (MTP_FILE_ATTR_MODE_NONE == attrs.attribute)
1289                 return MTP_ERROR_GENERAL;
1290
1291         if (prot_status == PTP_PROTECTIONSTATUS_READONLY)
1292                 attrs.attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
1293         else
1294                 attrs.attribute &= ~MTP_FILE_ATTR_MODE_READ_ONLY;
1295
1296         if (FALSE == _util_set_file_attrs(fname, attrs.attribute)) {
1297                 ERR("Failed to set file[%s] attrs\n", fname);
1298                 return MTP_ERROR_GENERAL;
1299         }
1300
1301         return MTP_ERROR_NONE;
1302 }
1303 #endif /* MTP_SUPPORT_SET_PROTECTION */
1304
1305 mtp_err_t _hutil_get_num_objects(mtp_uint32 store_id, mtp_uint32 h_parent,
1306                 mtp_uint32 format, mtp_uint32 *num_obj)
1307 {
1308         mtp_store_t *store = NULL;
1309         mtp_obj_t *obj = NULL;
1310         mtp_int32 i = 0;
1311         mtp_uint32 numobj = 0;
1312
1313         *num_obj = 0;
1314         if (store_id != PTP_STORAGEID_ALL) {
1315                 store = _device_get_store(store_id);
1316                 if (store == NULL) {
1317                         ERR("specific store is null");
1318                         return MTP_ERROR_INVALID_STORE;
1319                 }
1320         }
1321
1322         if (!h_parent) {
1323                 if (!format) {
1324                         *num_obj = _device_get_num_objects(store_id);
1325                 } else {
1326                         *num_obj = _device_get_num_objects_with_format(store_id,
1327                                         format);
1328                 }
1329                 return MTP_ERROR_NONE;
1330         }
1331
1332         /* return the number of direct children for a particular association
1333          * (in a single store)
1334          */
1335         if (h_parent == PTP_OBJECTHANDLE_ALL) {
1336
1337                 h_parent = PTP_OBJECTHANDLE_ROOT;
1338                 if (store_id == PTP_STORAGEID_ALL) {
1339                         for (i = (_device_get_num_stores() - 1); i >= 0; i--) {
1340                                 store = _device_get_store_at_index(i);
1341                                 if (store == NULL) {
1342                                         ERR("Store is null");
1343                                         return MTP_ERROR_STORE_NOT_AVAILABLE;
1344                                 }
1345                                 numobj += _entity_get_num_children(store,
1346                                                 h_parent, format);
1347                         }
1348                         *num_obj = numobj;
1349
1350                         return MTP_ERROR_NONE;
1351                 }
1352         } else {
1353                 /* Initiator wants number of children of a particular association */
1354                 obj = _device_get_object_with_handle(h_parent);
1355                 if (obj == NULL) {
1356                         ERR("obj is null");
1357                         return MTP_ERROR_INVALID_OBJECTHANDLE;
1358                 }
1359
1360                 if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
1361                         ERR("format is not association");
1362                         return MTP_ERROR_INVALID_PARENT;
1363                 }
1364
1365                 store = _device_get_store_containing_obj(h_parent);
1366         }
1367
1368         if (store == NULL) {
1369                 ERR("store is null");
1370                 return MTP_ERROR_STORE_NOT_AVAILABLE;
1371         }
1372
1373         *num_obj = _entity_get_num_children(store, h_parent, format);
1374         return MTP_ERROR_NONE;
1375 }
1376
1377 mtp_err_t _hutil_get_object_handles(mtp_uint32 store_id, mtp_uint32 format,
1378                 mtp_uint32 h_parent, ptp_array_t *handle_arr)
1379 {
1380         mtp_store_t *store = NULL;
1381         mtp_int32 i = 0;
1382
1383         if (h_parent == PTP_OBJECTHANDLE_ALL || h_parent == PTP_OBJECTHANDLE_ROOT) {
1384                 for (i = 0; i < _device_get_num_stores(); i++) {
1385                         store = _device_get_store_at_index(i);
1386                         if (store && store->obj_list.nnodes == 0)
1387                                 _entity_store_recursive_enum_folder_objects(store, NULL);
1388                 }
1389                 g_is_full_enum = TRUE;
1390         }
1391
1392         if (store_id == PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ROOT) {
1393                 for (i = 0; i < _device_get_num_stores(); i++) {
1394                         store = _device_get_store_at_index(i);
1395                         _entity_get_objects_from_store_by_format(store, format, handle_arr);
1396                 }
1397                 return MTP_ERROR_NONE;
1398
1399         } else if (store_id == PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ALL) {
1400                 h_parent = PTP_OBJECTHANDLE_ROOT;
1401                 for (i = 0; i < _device_get_num_stores(); i++) {
1402                         store = _device_get_store_at_index(i);
1403                         _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1404                 }
1405                 return MTP_ERROR_NONE;
1406
1407         } else if (store_id != PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ROOT) {
1408                 store = _device_get_store(store_id);
1409                 if (store == NULL) {
1410                         ERR("invalid store id [%d]\n", store_id);
1411                         return MTP_ERROR_INVALID_STORE;
1412                 }
1413
1414                 _entity_get_objects_from_store_by_format(store, format, handle_arr);
1415                 return MTP_ERROR_NONE;
1416
1417         } else if (store_id != PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ALL) {
1418                 h_parent = PTP_OBJECTHANDLE_ROOT;
1419                 store = _device_get_store(store_id);
1420                 if (store == NULL) {
1421                         ERR("invalid store id [%d]\n", store_id);
1422                         return MTP_ERROR_INVALID_STORE;
1423                 }
1424                 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1425                 return MTP_ERROR_NONE;
1426         }
1427
1428         store = _device_get_store(store_id);
1429         if (store == NULL) {
1430                 ERR("invalid store id [%d]\n", store_id);
1431                 return MTP_ERROR_INVALID_STORE;
1432         }
1433
1434         _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1435         return MTP_ERROR_NONE;
1436 }
1437
1438 mtp_err_t _hutil_construct_object_entry(mtp_uint32 store_id,
1439                 mtp_uint32 h_parent, obj_data_t *objdata, mtp_obj_t **obj, void *data,
1440                 mtp_uint32 data_sz)
1441 {
1442         mtp_store_t *store = NULL;
1443         mtp_obj_t *tobj = NULL;
1444         obj_info_t *obj_info = NULL;
1445         mtp_char file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
1446
1447         if (store_id) {
1448                 if (!h_parent)
1449                         h_parent = _device_get_default_parent_handle();
1450                 else if (h_parent == 0xFFFFFFFF)
1451                         h_parent = PTP_OBJECTHANDLE_ROOT;
1452         } else {
1453                 store_id = _device_get_default_store_id();
1454
1455                 if (!store_id) {
1456                         ERR("_device_get_default_store_id Fail");
1457                         return MTP_ERROR_STORE_NOT_AVAILABLE;
1458                 }
1459
1460                 if (h_parent) {
1461                         /* If the second parameter is used,
1462                          * the first must also be used.
1463                          */
1464                         return MTP_ERROR_INVALID_PARAM;
1465                 } else {
1466                         h_parent = _device_get_default_parent_handle();
1467                 }
1468         }
1469
1470         if (objdata != NULL) {
1471                 store = _device_get_store(objdata->store_id);
1472                 if (store != NULL) {
1473                         DBG("check free size instead of re-calculation");
1474                         _entity_update_store_info_run_time(&(store->store_info),
1475                                         (store->root_path));
1476                 }
1477
1478                 /* Delete and invalidate the old obj_info for send object */
1479                 if (objdata->obj != NULL)
1480                         _entity_dealloc_mtp_obj(objdata->obj);
1481         }
1482
1483         store = _device_get_store(store_id);
1484         if (store == NULL) {
1485                 ERR("Store not found");
1486                 return MTP_ERROR_INVALID_STORE;
1487         }
1488
1489         if (store->store_info.access == PTP_STORAGEACCESS_R) {
1490                 ERR("Read only storage");
1491                 return MTP_ERROR_STORE_READ_ONLY;
1492         }
1493
1494         if ((store->store_info.free_space) == 0 ||
1495                         (store->store_info.free_space >
1496                          store->store_info.capacity)) {
1497                 ERR("free space is not enough [%ld:%ld]\n",
1498                                 store->store_info.free_space,
1499                                 store->store_info.capacity);
1500                 return MTP_ERROR_STORE_FULL;
1501         }
1502
1503         obj_info = _entity_alloc_object_info();
1504         if (obj_info == NULL) {
1505                 ERR("_entity_alloc_object_info Fail");
1506                 return MTP_ERROR_GENERAL;
1507         }
1508
1509         if (_entity_parse_raw_obj_info(data, data_sz, obj_info, file_name,
1510                                 sizeof(file_name)) != data_sz) {
1511                 /* wrong object info sent from Host.*/
1512                 ERR("Invalid objet info");
1513                 _entity_dealloc_obj_info(obj_info);
1514                 return MTP_ERROR_INVALID_OBJECT_INFO;
1515         }
1516         obj_info->store_id = store_id;
1517         obj_info->h_parent = h_parent;
1518
1519         switch (_hutil_add_object_entry(obj_info, file_name, &tobj)) {
1520         case MTP_ERROR_NONE:
1521                 *obj = tobj;
1522                 break;
1523
1524         case MTP_ERROR_STORE_FULL:
1525                 return MTP_ERROR_STORE_FULL;
1526
1527         case MTP_ERROR_INVALID_OBJECTHANDLE:
1528                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1529
1530         case MTP_ERROR_INVALID_PARENT:
1531                 return MTP_ERROR_INVALID_PARENT;
1532
1533         default:
1534                 return MTP_ERROR_GENERAL;
1535         }
1536
1537         return MTP_ERROR_NONE;
1538 }
1539
1540 mtp_err_t _hutil_construct_object_entry_prop_list(mtp_uint32 store_id,
1541                 mtp_uint32 h_parent, mtp_uint16 format, mtp_uint64 obj_sz,
1542                 obj_data_t *obj_data, mtp_obj_t **obj_ptr, void *data,
1543                 mtp_int32 data_sz, mtp_uint32 *err_idx)
1544 {
1545         mtp_uint32 index = 0;
1546         mtp_store_t *store = NULL;
1547         mtp_obj_t *obj = NULL;
1548         obj_prop_desc_t *prop_desc = NULL;
1549         obj_prop_val_t *prop_val = NULL;
1550         mtp_uint32 num_elem = 0;
1551         mtp_int32 quad_sz = 0;
1552         mtp_uint32 obj_handle = 0;
1553         mtp_uint16 prop_code = 0;
1554         mtp_uint16 data_type = 0;
1555         obj_info_t *obj_info = NULL;
1556         mtp_uchar *temp = NULL;
1557         mtp_int32 bytes_left = data_sz;
1558         mtp_err_t resp = 0;
1559
1560 #ifdef MTP_SUPPORT_ALBUM_ART
1561         mtp_uint16 albumFormat = 0;
1562         mtp_char alb_extn[MTP_MAX_EXTENSION_LENGTH + 1] = { 0 };
1563         mtp_char *alb_buf = NULL;
1564         mtp_uint32 alb_sz = 0;
1565         FILE* h_temp = NULL;
1566         mtp_int32 error = 0;
1567 #endif /*MTP_SUPPORT_ALBUM_ART*/
1568         mtp_char file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
1569
1570         if (obj_data != NULL && obj_data->obj != NULL) {
1571                 store = _device_get_store(obj_data->store_id);
1572                 if (store != NULL) {
1573                         DBG("check free size instead of re-calculation");
1574                         _entity_update_store_info_run_time(&(store->store_info),
1575                                         (store->root_path));
1576                 }
1577                 _entity_dealloc_mtp_obj(obj_data->obj);
1578         }
1579
1580         store = _device_get_store(store_id);
1581         if (store == NULL) {
1582                 ERR("Could not get the store");
1583                 return MTP_ERROR_INVALID_STORE;
1584         }
1585
1586         if (store->store_info.access == PTP_STORAGEACCESS_R) {
1587                 ERR("Only read access allowed on store");
1588                 return MTP_ERROR_STORE_READ_ONLY;
1589         }
1590
1591         if ((store->store_info.free_space) == 0 ||
1592                         (store->store_info.free_space > store->store_info.capacity)) {
1593                 ERR("free space is not enough [%ld bytes]\n",
1594                                 store->store_info.free_space);
1595                 return MTP_ERROR_STORE_FULL;
1596         }
1597
1598         if (store->store_info.free_space <= obj_sz) {
1599                 ERR("free space is not enough [%ld bytes]\n",
1600                                 store->store_info.free_space);
1601                 return MTP_ERROR_STORE_FULL;
1602         }
1603
1604         obj_info = _entity_alloc_object_info();
1605         if (obj_info == NULL) {
1606                 ERR("_entity_alloc_object_info Fail");
1607                 return MTP_ERROR_GENERAL;
1608         }
1609
1610         obj_info->obj_fmt = format;
1611         if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1612                 obj_info->association_type = PTP_ASSOCIATIONTYPE_FOLDER;
1613
1614         obj_info->file_size = obj_sz;
1615
1616         /* Prop value quadruple: Object Handle, PropertyCode, DataType
1617          * and DTS Prop Value (assume a byte value)
1618          */
1619         temp = (mtp_uchar *) data;
1620         bytes_left = data_sz;
1621         quad_sz = sizeof(mtp_uint32) + sizeof(mtp_uint16) + sizeof(mtp_uint16) +
1622                 sizeof(mtp_char);
1623         memcpy(&num_elem, temp, sizeof(mtp_uint32));
1624 #ifdef __BIG_ENDIAN__
1625         _util_conv_byte_order(&num_elem, sizeof(mtp_uint32));
1626 #endif
1627         temp += sizeof(mtp_uint32);
1628         bytes_left -= sizeof(mtp_uint32);
1629
1630         /* frequent disconnect/connect make bluscreen since below process
1631          * is not finished
1632          */
1633         for (index = 0; index < num_elem; index++) {
1634                 if (MTP_PHONE_USB_DISCONNECTED == _util_get_local_usb_status() ||
1635                                 TRUE == _transport_get_usb_discon_state()) {
1636                         /* seems usb is disconnected, stop */
1637                         _entity_dealloc_obj_info(obj_info);
1638                         resp = MTP_ERROR_GENERAL;
1639                         goto ERROR_EXIT;
1640                 }
1641
1642                 *err_idx = index;
1643                 if (bytes_left < quad_sz) {
1644                         /* seems invalid dataset received: Stops parsing */
1645                         _entity_dealloc_obj_info(obj_info);
1646                         resp = MTP_ERROR_INVALID_DATASET;
1647                         goto ERROR_EXIT;
1648                 }
1649
1650                 /* Get ObjectHandle & validate */
1651                 memcpy(&obj_handle, temp, sizeof(mtp_uint32));
1652 #ifdef __BIG_ENDIAN__
1653                 _util_conv_byte_order(&obj_handle, sizeof(mtp_uint32));
1654 #endif /* __BIG_ENDIAN__ */
1655                 temp += sizeof(mtp_uint32);
1656                 bytes_left -= sizeof(mtp_uint32);
1657                 if (obj_handle != 0x00000000) {
1658                         _entity_dealloc_obj_info(obj_info);
1659                         resp = MTP_ERROR_INVALID_OBJECTHANDLE;
1660                         goto ERROR_EXIT;
1661                 }
1662
1663                 /* Get PropCode & Validate */
1664                 memcpy(&prop_code, temp, sizeof(mtp_uint16));
1665 #ifdef __BIG_ENDIAN__
1666                 _util_conv_byte_order(&prop_code, sizeof(mtp_uint16));
1667 #endif /* __BIG_ENDIAN__ */
1668                 temp += sizeof(mtp_uint16);
1669                 bytes_left -= sizeof(mtp_uint16);
1670                 prop_desc = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1671                 if (prop_desc == NULL) {
1672                         _entity_dealloc_obj_info(obj_info);
1673                         ERR("property may be unsupported!!");
1674                         resp = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1675                         goto ERROR_EXIT;
1676                 }
1677
1678                 /* Verify that properties already present in parameters
1679                  * don't get repeated in the list
1680                  */
1681                 if ((prop_code == MTP_OBJ_PROPERTYCODE_STORAGEID) ||
1682                                 (prop_code == MTP_OBJ_PROPERTYCODE_PARENT) ||
1683                                 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFORMAT) ||
1684                                 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTSIZE)) {
1685                         _entity_dealloc_obj_info(obj_info);
1686                         resp = MTP_ERROR_INVALID_DATASET;
1687                         goto ERROR_EXIT;
1688                 }
1689
1690                 /* Get DataType */
1691                 memcpy(&data_type, temp, sizeof(mtp_uint16));
1692 #ifdef __BIG_ENDIAN__
1693                 _util_conv_byte_order(&data_type, sizeof(mtp_uint16));
1694 #endif /* __BIG_ENDIAN__ */
1695                 temp += sizeof(mtp_uint16);
1696                 bytes_left -= sizeof(mtp_uint16);
1697                 if (data_type != prop_desc->propinfo.data_type) {
1698                         _entity_dealloc_obj_info(obj_info);
1699                         resp = MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1700                         goto ERROR_EXIT;
1701                 }
1702
1703                 /* Acquire object information related data. */
1704                 prop_val = _prop_alloc_obj_propval(prop_desc);
1705                 if (prop_val == NULL)
1706                         continue;
1707
1708                 _prop_set_current_array_val(prop_val, temp, bytes_left);
1709                 switch (prop_code) {
1710                 case MTP_OBJ_PROPERTYCODE_WIDTH:
1711                         // TODO: find mechanism to save (integer)
1712                         break;
1713                 case MTP_OBJ_PROPERTYCODE_TRACK:
1714                         // TODO: find mechanism to save (integer)
1715                         break;
1716                 case MTP_OBJ_PROPERTYCODE_GENRE:
1717                         // TODO: find mechanism to save (string)
1718                         break;
1719                 case MTP_OBJ_PROPERTYCODE_HEIGHT:
1720                         // TODO: find mechanism to save (integer)
1721                         break;
1722                 case MTP_OBJ_PROPERTYCODE_ARTIST:
1723                         // TODO: find mechanism to save (string)
1724                         break;
1725                 case MTP_OBJ_PROPERTYCODE_DURATION:
1726                         // TODO: find mechanism to save (integer)
1727                         break;
1728                 case MTP_OBJ_PROPERTYCODE_COMPOSER:
1729                         // TODO: find mechanism to save (string)
1730                         break;
1731                 case MTP_OBJ_PROPERTYCODE_ALBUMNAME:
1732                         // TODO: find mechanism to save (string)
1733                         break;
1734                 case MTP_OBJ_PROPERTYCODE_SAMPLERATE:
1735                         // TODO: find mechanism to save (integer)
1736                         break;
1737                 case MTP_OBJ_PROPERTYCODE_DATECREATED:
1738                         // TODO: find mechanism to save (string)
1739                         break;
1740                 case MTP_OBJ_PROPERTYCODE_DATEMODIFIED:
1741                         // TODO: find mechanism to save (string)
1742                         break;
1743                 case MTP_OBJ_PROPERTYCODE_AUDIOBITRATE:
1744                         // TODO: find mechanism to save (integer)
1745                         break;
1746                 case MTP_OBJ_PROPERTYCODE_VIDEOBITRATE:
1747                         // TODO: find mechanism to save (integer)
1748                         break;
1749                 case  MTP_OBJ_PROPERTYCODE_OBJECTFILENAME:
1750                         /* empty metadata folder problem
1751                          * emtpy file name
1752                          */
1753                         if (prop_val->current_val.str->num_chars == 0) {
1754                                 g_strlcpy(file_name, MTP_UNKNOWN_METADATA, sizeof(file_name));
1755                         } else {
1756                                 _util_utf16_to_utf8(file_name, sizeof(file_name),
1757                                                 prop_val->current_val.str->str);
1758                         }
1759                         break;
1760
1761                 case MTP_OBJ_PROPERTYCODE_PROTECTIONSTATUS:
1762 #ifdef MTP_SUPPORT_SET_PROTECTION
1763                         memcpy(&obj_info->protcn_status, prop_val->current_val.integer,
1764                                         sizeof(mtp_uint16));
1765 #else /* MTP_SUPPORT_SET_PROTECTION */
1766                         obj_info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
1767 #endif /*MTP_SUPPORT_SET_PROTECTION*/
1768                         break;
1769
1770                 case MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE:
1771                         memcpy(&obj_info->association_type, prop_val->current_val.integer,
1772                                         sizeof(mtp_uint16));
1773                         break;
1774
1775                 case MTP_OBJ_PROPERTYCODE_NUMBEROFCHANNELS:
1776                         // TODO: find mechanism to save (integer)
1777                         break;
1778                 case MTP_OBJ_PROPERTYCODE_FRAMESPER1KSECONDS:
1779                         // TODO: find mechanism to save (integer)
1780                         break;
1781 #ifdef MTP_SUPPORT_ALBUM_ART
1782                 case MTP_OBJ_PROPERTYCODE_SAMPLEDATA:
1783                         /* save sample data(album cover data) with
1784                          * sample format, otherwise no extension
1785                          * update db with sample data path
1786                          * there is no case that this position is called
1787                          * again but prevent detect this
1788                          */
1789                         g_free(alb_buf);
1790                         alb_buf = NULL;
1791                         alb_buf = g_malloc(sizeof(mtp_uchar) *
1792                                         (prop_val->current_val.array->num_ele) + 1);
1793                         alb_sz = prop_val->current_val.array->num_ele;
1794                         if (alb_buf != NULL) {
1795                                 memset(alb_buf, 0,
1796                                                 sizeof(mtp_uchar) * alb_sz + 1);
1797                                 if (alb_sz > 0)
1798                                         memcpy(alb_buf,
1799                                                         (prop_val->current_val.array->array_entry),
1800                                                         sizeof(mtp_uchar) * alb_sz);
1801                         } else {
1802                                 ERR("album art test mem allocation Fail");
1803                                 _prop_destroy_obj_propval(prop_val);
1804                                 _entity_dealloc_obj_info(obj_info);
1805                                 return MTP_ERROR_GENERAL;
1806                         }
1807                         break;
1808
1809                 case MTP_OBJ_PROPERTYCODE_SAMPLEFORMAT:
1810                         /* if is_albumart is turned on, Move file with
1811                          * new extension. And update db with data path
1812                          */
1813                         memcpy(&albumFormat, prop_val->current_val.integer,
1814                                         sizeof(mtp_uint16));
1815                         switch (albumFormat) {
1816                         case PTP_FMT_IMG_EXIF:
1817                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "jpg");
1818                                 break;
1819                         case PTP_FMT_IMG_GIF:
1820                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "gif");
1821                                 break;
1822                         case PTP_FMT_IMG_PNG:
1823                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "png");
1824                                 break;
1825                         case MTP_FMT_WMA:
1826                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "wma");
1827                                 break;
1828                         case PTP_FMT_MPEG:
1829                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "mpg");
1830                                 break;
1831                         default:
1832                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "dat");
1833                                 break;
1834                         }
1835
1836                         ERR("sampleformatl![0x%x], extension[%s]\n", prop_code, alb_extn);
1837                         break;
1838                 case MTP_OBJ_PROPERTYCODE_SAMPLESIZE:
1839                 case MTP_OBJ_PROPERTYCODE_SAMPLEHEIGHT:
1840                 case MTP_OBJ_PROPERTYCODE_SAMPLEWIDTH:
1841                 case MTP_OBJ_PROPERTYCODE_SAMPLEDURATION:
1842                         DBG("Sample data is not supported [0x%x]\n", prop_code);
1843                         break;
1844 #endif /*MTP_SUPPORT_ALBUM_ART*/
1845
1846                 default:
1847                         DBG("Unsupported Property [0x%x]\n", prop_code);
1848                         break;
1849                 }
1850
1851                 temp += _prop_size_obj_propval(prop_val);
1852                 bytes_left -= _prop_size_obj_propval(prop_val);
1853                 _prop_destroy_obj_propval(prop_val);
1854         }
1855
1856         obj_info->store_id = store_id;
1857         obj_info->h_parent = h_parent;
1858
1859         if ((resp = _hutil_add_object_entry(obj_info, file_name, &obj)) !=
1860                         MTP_ERROR_NONE) {
1861                 goto ERROR_EXIT;
1862         }
1863
1864 #ifdef MTP_SUPPORT_ALBUM_ART
1865         mtp_char full_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1866         mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1867
1868         g_strlcpy(full_path, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1869
1870         /* in case of album, if there is album data, fill it in this file */
1871         if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
1872                         (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
1873                          obj_info->association_type != PTP_ASSOCIATIONTYPE_UNDEFINED &&
1874                          obj_info->association_type != PTP_ASSOCIATIONTYPE_FOLDER)) {
1875
1876                 _util_get_file_extn(full_path, extn);
1877                 if (!strcasecmp(extn, "alb")) {
1878                         /* check db whether it contains sample form
1879                          * save sample data(album cover data) with
1880                          * sample format, otherwise no extension
1881                          */
1882                         if (alb_buf != NULL) {
1883                                 /* file write */
1884                                 h_temp = _util_file_open(full_path,
1885                                                 MTP_FILE_WRITE, &error);
1886                                 if (h_temp != NULL) {
1887                                         _util_file_write(h_temp, alb_buf,
1888                                                         sizeof(mtp_uchar) *alb_sz);
1889                                         _util_file_close(h_temp);
1890                                 } else {
1891                                         ERR("open album file Fail!!");
1892                                 }
1893                         } else {
1894                                 ERR("no album art data");
1895                         }
1896                 }
1897         }
1898
1899         g_free(alb_buf);
1900 #endif /* MTP_SUPPORT_ALBUM_ART */
1901         *obj_ptr = obj;
1902
1903         return MTP_ERROR_NONE;
1904
1905 ERROR_EXIT:
1906 #ifdef MTP_SUPPORT_ALBUM_ART
1907         g_free(alb_buf);
1908 #endif /* MTP_SUPPORT_ALBUM_ART */
1909         if (obj_info != NULL)
1910                 _entity_dealloc_obj_info(obj_info);
1911
1912         return resp;
1913 }
1914
1915 mtp_err_t _hutil_get_object_prop_value(mtp_uint32 obj_handle,
1916                 mtp_uint32 prop_code, obj_prop_val_t *prop_val, mtp_obj_t **obj)
1917 {
1918         obj_prop_val_t *tprop = NULL;
1919         mtp_obj_t *tobj = NULL;
1920
1921         tobj = _device_get_object_with_handle(obj_handle);
1922         if (NULL == tobj) {
1923                 ERR("requested handle does not exist[0x%x]\n", obj_handle);
1924                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1925         }
1926
1927         tprop = _prop_get_prop_val(tobj, prop_code);
1928         if (tprop != NULL) {
1929                 memcpy(prop_val, tprop, sizeof(obj_prop_val_t));
1930                 *obj = tobj;
1931                 return MTP_ERROR_NONE;
1932         }
1933
1934         ERR("can not get the prop value for propcode [0x%x]\n", prop_code);
1935         return MTP_ERROR_GENERAL;
1936 }
1937
1938 mtp_err_t _hutil_update_object_property(mtp_uint32 obj_handle,
1939                 mtp_uint32 prop_code, mtp_uint16 *data_type, void *buf,
1940                 mtp_uint32 buf_sz, mtp_uint32 *prop_sz)
1941 {
1942         mtp_int32 error = 0;
1943         mtp_uint32 p_size = 0;
1944         mtp_obj_t *obj = NULL;
1945         obj_info_t *obj_info = NULL;
1946         obj_prop_desc_t *prp_dev = NULL;
1947         mtp_char temp_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1948         mtp_char orig_pfpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1949         mtp_wchar mov_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1950         mtp_char orig_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1951         mtp_char dest_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1952
1953         retv_if(NULL == buf, MTP_ERROR_INVALID_PARAM);
1954
1955         obj = _device_get_object_with_handle(obj_handle);
1956         if ((NULL == obj) || (NULL == obj->obj_info)) {
1957                 ERR("Object not found");
1958                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1959         }
1960
1961         obj_info = obj->obj_info;
1962         /* Avoid to rename file/folder during file operating by phone side. */
1963         if (_util_is_file_opened(obj->file_path) == TRUE) {
1964                 ERR_SECURE("Object [%s] is already opened\n", obj->file_path);
1965                 return MTP_ERROR_GENERAL;
1966         }
1967
1968         prp_dev = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1969         if (prp_dev == NULL) {
1970                 ERR("_prop_get_obj_prop_desc Fail");
1971                 return MTP_ERROR_INVALID_OBJ_PROP_CODE;
1972         }
1973
1974 #ifdef MTP_SUPPORT_SET_PROTECTION
1975         if (obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) {
1976                 ERR("protection is PTP_PROTECTIONSTATUS_READONLY");
1977                 return MTP_ERROR_ACCESS_DENIED;
1978         }
1979 #endif /* MTP_SUPPORT_SET_PROTECTION */
1980
1981         if (prp_dev->propinfo.get_set == PTP_PROPGETSET_GETONLY) {
1982                 ERR("property type is GETONLY");
1983                 return MTP_ERROR_ACCESS_DENIED;
1984         }
1985
1986         if (data_type != NULL && *data_type != prp_dev->propinfo.data_type) {
1987                 ERR("Not matched data type [%d][%d]\n",
1988                                 *data_type, prp_dev->propinfo.data_type);
1989                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1990         }
1991
1992         /* Set up needed object info fields */
1993         if (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFILENAME) {
1994                 ptp_string_t fname = { 0 };
1995
1996                 _prop_init_ptpstring(&fname);
1997                 _prop_parse_rawstring(&fname, buf, buf_sz);
1998
1999                 _util_utf16_to_utf8(temp_buf, sizeof(temp_buf),
2000                                 fname.str);
2001                 g_strlcpy(orig_fpath, obj->file_path,
2002                                 MTP_MAX_PATHNAME_SIZE + 1);
2003                 _util_get_parent_path(orig_fpath, orig_pfpath);
2004
2005                 if (_util_create_path(dest_fpath, sizeof(dest_fpath),
2006                                         orig_pfpath, temp_buf) == FALSE) {
2007                         ERR("Path is too long");
2008                         return MTP_ERROR_ACCESS_DENIED;
2009                 }
2010                 _util_utf8_to_utf16(mov_fpath,
2011                                 sizeof(mov_fpath) / WCHAR_SIZ, dest_fpath);
2012
2013                 /* when changed name is different */
2014                 if (strcasecmp(orig_fpath, dest_fpath)) {
2015                         /* Extension change is not permitted */
2016                         mtp_char orig_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2017                         mtp_char dest_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2018
2019                         _util_get_file_extn(orig_fpath, orig_extn);
2020                         _util_get_file_extn(dest_fpath, dest_extn);
2021
2022                         if (strcasecmp(orig_extn, dest_extn)) {
2023                                 ERR("file extension is different with original\
2024                                                 one [%s]:[%s]\n", orig_extn, dest_extn);
2025                                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2026                         }
2027
2028                         /* FILE RENAME */
2029                         if (_entity_check_child_obj_path(obj, orig_fpath,
2030                                                 dest_fpath) == FALSE) {
2031                                 ERR("_entity_check_child_obj_path FALSE. ");
2032                                 return MTP_ERROR_GENERAL;
2033                         }
2034                         g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
2035                                         "%s", orig_fpath);
2036                         if (FALSE == _util_file_move(orig_fpath, dest_fpath,
2037                                                 &error)) {
2038                                 if (EACCES == error)
2039                                         return MTP_ERROR_ACCESS_DENIED;
2040                                 return MTP_ERROR_GENERAL;
2041                         }
2042
2043                         if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
2044                                 _util_scan_folder_contents_in_db(orig_fpath);
2045                                 _util_scan_folder_contents_in_db(dest_fpath);
2046                         } else {
2047                                 _util_delete_file_from_db(orig_fpath);
2048                                 _util_add_file_to_db(dest_fpath);
2049
2050                         }
2051
2052                         /* Finally assign new handle and update full path */
2053                         _entity_set_object_file_path(obj, dest_fpath,
2054                                         CHAR_TYPE);
2055
2056                         /* FILE RENAME */
2057                         if (_entity_set_child_object_path(obj, orig_fpath,
2058                                                 dest_fpath) == FALSE) {
2059                                 ERR("failed to set the full path!!");
2060                                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2061                         }
2062
2063                         DBG("File moved to [%s]\n", dest_fpath);
2064                 } else {
2065                         ERR_SECURE("changed name is same with original one. [%s]\n",
2066                                         dest_fpath);
2067                 }
2068                 p_size = _prop_size_ptpstring(&fname);
2069         } else if (prop_code == MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE) {
2070                 memcpy(&obj_info->association_type, buf, sizeof(mtp_uint16));
2071                 p_size = sizeof(mtp_uint16);
2072         } else {
2073                 ERR("Propert [0x%x] is GETONLY\n", prop_code);
2074         }
2075
2076         if (prop_sz != NULL)
2077                 *prop_sz = p_size;
2078
2079         return MTP_ERROR_NONE;
2080 }
2081
2082 mtp_err_t _hutil_get_prop_desc(mtp_uint32 format, mtp_uint32 prop_code,
2083                 void *data)
2084 {
2085         obj_prop_desc_t *prop = NULL;
2086
2087         prop = _prop_get_obj_prop_desc(format, prop_code);
2088         if (prop == NULL) {
2089                 ERR("pProperty is NULL");
2090                 return MTP_ERROR_GENERAL;
2091         }
2092
2093         memcpy(data, prop, sizeof(obj_prop_desc_t));
2094         return MTP_ERROR_NONE;
2095 }
2096
2097 mtp_err_t _hutil_get_object_prop_supported(mtp_uint32 format,
2098                 ptp_array_t     *prop_arr)
2099 {
2100         _prop_get_supp_obj_props(format, prop_arr);
2101         return MTP_ERROR_NONE;
2102 }
2103
2104 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2105 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2106                 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2107                 obj_proplist_t *prop_list)
2108 #else /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2109 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2110                 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2111                 obj_proplist_t *prop_list, ptp_array_t *obj_arr)
2112 #endif /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2113 {
2114 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2115         ptp_array_t obj_arr = { 0 };
2116 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2117         mtp_obj_t *obj = NULL;
2118         mtp_uint32 i = 0;
2119         mtp_uint32 ii = 0;
2120         mtp_store_t *store = NULL;
2121
2122         if ((obj_handle != PTP_OBJECTHANDLE_UNDEFINED) &&
2123                         (obj_handle != PTP_OBJECTHANDLE_ALL)) {
2124                 /* Is this object handle valid? */
2125                 store = _device_get_store_containing_obj(obj_handle);
2126                 if (store == NULL) {
2127                         ERR("invalid object handle");
2128                         return MTP_ERROR_INVALID_OBJECTHANDLE;
2129                 }
2130         }
2131
2132         if (prop_code == PTP_PROPERTY_UNDEFINED) {
2133                 /* PropGroupCode should be used if Property code
2134                  * is not specified.
2135                  * */
2136                 if (group_code == 0x0) {
2137                         ERR("PropGroupCode is zero");
2138                         return MTP_ERROR_INVALID_PARAM;
2139                 }
2140         }
2141
2142         if (!(obj_handle == PTP_OBJECTHANDLE_ALL ||
2143                                 obj_handle == PTP_OBJECTHANDLE_UNDEFINED) &&
2144                         !(format == PTP_FORMATCODE_NOTUSED ||
2145                                 format == PTP_FORMATCODE_ALL)) {
2146                 ERR("both object handle and format code is specified!\
2147                                 return nospecification by format");
2148                 return MTP_ERROR_NO_SPEC_BY_FORMAT;
2149         }
2150
2151         _util_init_list(&(prop_list->prop_quad_list));
2152         _prop_init_ptparray(obj_arr, UINT32_TYPE);
2153
2154         if (store != NULL) {
2155                 _entity_get_objects_from_store_till_depth(store, obj_handle,
2156                                 format, depth, obj_arr);
2157         } else {
2158                 for (ii = 0; ii < _device_get_num_stores(); ii++) {
2159                         store = _device_get_store_at_index(ii);
2160                         _entity_get_objects_from_store_till_depth(store,
2161                                         obj_handle, format, depth, obj_arr);
2162                 }
2163         }
2164
2165         if (obj_arr->num_ele != 0) {
2166                 mtp_uint32 *obj_handles = obj_arr->array_entry;
2167
2168                 for (i = 0; i < obj_arr->num_ele; i++) {
2169                         obj = _entity_get_object_from_store(store, obj_handles[i]);
2170                         if (!obj)
2171                                 continue;
2172
2173                         if (_prop_get_obj_proplist(obj, prop_code, group_code,
2174                                                 prop_list) == FALSE) {
2175                                 ERR("Fail to create Proplist");
2176 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2177                                 _prop_deinit_ptparray(&obj_arr);
2178 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2179                                 return MTP_ERROR_GENERAL;
2180                         }
2181                 }
2182         }
2183
2184 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2185         prop_deinit_ptparray(&obj_arr);
2186 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2187
2188         return MTP_ERROR_NONE;
2189 }
2190
2191 mtp_err_t _hutil_remove_object_reference(mtp_uint32 obj_handle,
2192                 mtp_uint32 ref_handle)
2193 {
2194         mtp_obj_t *obj = NULL;
2195
2196         obj = _device_get_object_with_handle(obj_handle);
2197         if (obj == NULL) {
2198                 ERR("No object for handle[%d]\n", obj_handle);
2199                 return MTP_ERROR_NONE;
2200         }
2201
2202         if (_entity_remove_reference_child_array(obj, ref_handle) == FALSE)
2203                 ERR("_entity_remove_reference_child_array Fail");
2204
2205         return MTP_ERROR_NONE;
2206 }
2207
2208 mtp_err_t _hutil_add_object_references_enhanced(mtp_uint32 obj_handle,
2209                 mtp_uchar *buffer, mtp_uint32 buf_sz)
2210 {
2211         mtp_obj_t *obj = NULL;
2212
2213         obj = _device_get_object_with_handle(obj_handle);
2214         if (obj == NULL) {
2215                 DBG("No object for handle[0x%x]\n", obj_handle);
2216                 return MTP_ERROR_NONE;
2217         }
2218
2219         if (_entity_set_reference_child_array(obj, buffer, buf_sz) == FALSE) {
2220                 ERR("_entity_set_reference_child_array Fail");
2221                 return MTP_ERROR_GENERAL;
2222         }
2223
2224         return MTP_ERROR_NONE;
2225 }
2226
2227 mtp_err_t _hutil_get_object_references(mtp_uint32 obj_handle,
2228                 ptp_array_t *parray, mtp_uint32 *num_ele)
2229 {
2230         mtp_obj_t *obj = NULL;
2231         mtp_obj_t *ref_obj = NULL;
2232         mtp_uint16 idx = 0;
2233         mtp_uint32 *ref_ptr = NULL;
2234         ptp_array_t ref_arr = { 0 };
2235
2236         obj = _device_get_object_with_handle(obj_handle);
2237         if (NULL == obj || NULL == obj->obj_info) {
2238                 *num_ele = 0;
2239                 return MTP_ERROR_INVALID_OBJECTHANDLE;
2240         }
2241
2242         if (parray == NULL) {
2243                 *num_ele = 0;
2244                 return MTP_ERROR_GENERAL;
2245         }
2246
2247         if (obj->child_array.num_ele == 0) {
2248                 *num_ele = 0;
2249                 return MTP_ERROR_NONE;
2250         }
2251
2252         _prop_init_ptparray(&ref_arr, obj->child_array.type);
2253         _prop_copy_ptparray(&ref_arr, &(obj->child_array));
2254         ref_ptr = (mtp_uint32 *)(ref_arr.array_entry);
2255
2256         for (idx = 0; idx < ref_arr.num_ele; idx++) {
2257                 ref_obj = _device_get_object_with_handle(ref_ptr[idx]);
2258                 if (ref_obj == NULL)
2259                         _entity_remove_reference_child_array(obj, ref_ptr[idx]);
2260         }
2261
2262         *num_ele = obj->child_array.num_ele;
2263         if (*num_ele) {
2264                 _prop_init_ptparray(parray, obj->child_array.type);
2265                 _prop_grow_ptparray(parray, *num_ele);
2266                 _prop_copy_ptparray(parray, &(obj->child_array));
2267         }
2268
2269         _prop_deinit_ptparray(&ref_arr);
2270         return MTP_ERROR_NONE;
2271 }
2272
2273 mtp_err_t _hutil_get_number_of_objects(mtp_uint32 store_id, mtp_uint32 *num_obj)
2274 {
2275         *num_obj = _device_get_num_objects(store_id);
2276         return MTP_ERROR_NONE;
2277 }
2278
2279 mtp_err_t _hutil_get_interdep_prop_config_list_size(mtp_uint32 *list_sz,
2280                 mtp_uint32 format)
2281 {
2282         *list_sz = _prop_get_size_interdep_proplist(&interdep_proplist,
2283                         format);
2284         return MTP_ERROR_NONE;
2285 }
2286
2287 mtp_err_t _hutil_get_interdep_prop_config_list_data(void *data,
2288                 mtp_uint32 list_sz, mtp_uint32 format)
2289 {
2290         if (list_sz == _prop_pack_interdep_proplist(&interdep_proplist,
2291                                 format, data, list_sz)) {
2292                 return MTP_ERROR_NONE;
2293         }
2294
2295         ERR("packet and requested size do not match");
2296         return MTP_ERROR_GENERAL;
2297 }
2298
2299 mtp_err_t _hutil_get_playback_skip(mtp_int32 skip_param)
2300 {
2301         mtp_int32 idx = 0;
2302         mtp_obj_t *obj = NULL;
2303         mtp_uint32 new_idx = 0;
2304         mtp_uint32 new_hobj = 0;
2305         mtp_uint32 obj_handle = 0;
2306         mtp_obj_t *par_obj = NULL;
2307         obj_info_t *obj_info = NULL;
2308         ptp_array_t *ref_arr = NULL;
2309         device_prop_desc_t *dev_prop = NULL;
2310
2311         retv_if(skip_param == 0, MTP_ERROR_INVALID_PARAM);
2312
2313         if (_device_get_playback_obj(&obj_handle) == FALSE) {
2314                 ERR("_device_get_playback_obj Fail");
2315                 return MTP_ERROR_GENERAL;
2316         }
2317
2318         if (obj_handle == 0x0)
2319                 return MTP_ERROR_NONE;
2320
2321         obj = _device_get_object_with_handle(obj_handle);
2322         if (obj == NULL || obj->obj_info == NULL) {
2323                 ERR("obj or obj_info is NULL");
2324                 return MTP_ERROR_GENERAL;
2325         }
2326
2327         obj_info = obj->obj_info;
2328         if ((obj_info->obj_fmt == PTP_FMT_WAVE) ||
2329                         (obj_info->obj_fmt == PTP_FMT_MP3) ||
2330                         (obj_info->obj_fmt == MTP_FMT_WMA) ||
2331                         (obj_info->obj_fmt == MTP_FMT_WMV) ||
2332                         (obj_info->obj_fmt == MTP_FMT_UNDEFINED_AUDIO)) {
2333                 par_obj = _device_get_object_with_handle(obj_info->h_parent);
2334                 if (!par_obj) {
2335                         ERR("parent not found in obj_list");
2336                         return MTP_ERROR_GENERAL;
2337                 }
2338                 ref_arr = _entity_get_reference_child_array(par_obj);
2339                 idx = _prop_find_ele_ptparray(ref_arr, obj_handle);
2340                 if (idx != ELEMENT_NOT_FOUND) {
2341                         if (((long long)idx + (long long)skip_param) > UINT_MAX)
2342                                 new_idx = ref_arr->num_ele - 1;
2343                         else if ((idx + skip_param) >= ref_arr->num_ele)
2344                                 new_idx = 0;
2345                         else
2346                                 new_idx = idx + skip_param;
2347
2348                         if (_prop_get_ele_ptparray(ref_arr, new_idx,
2349                                                 (void *)(&new_hobj)) == TRUE) {
2350                                 dev_prop = _device_get_device_property(
2351                                                 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2352                                 if (dev_prop == NULL) {
2353                                         ERR("dev_prop is null");
2354                                         return MTP_ERROR_GENERAL;
2355                                 }
2356                                 _prop_set_current_integer(dev_prop, 0xFFFFFFFF);
2357                                 _device_set_playback_obj(new_hobj);
2358                         }
2359                 }
2360         } else if ((obj_info->obj_fmt == MTP_FMT_ABSTRACT_AUDIO_ALBUM) ||
2361                         (obj_info->obj_fmt == MTP_FMT_ABSTRACT_VIDEO_ALBUM)) {
2362                 dev_prop = _device_get_device_property(
2363                                 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2364                 if (dev_prop == NULL) {
2365                         ERR("dev_prop is null");
2366                         return MTP_ERROR_GENERAL;
2367                 }
2368                 memcpy(&idx, dev_prop->current_val.integer, sizeof(mtp_uint32));
2369                 ref_arr = _entity_get_reference_child_array(obj);
2370                 if (((long long)idx + (long long)skip_param) > UINT_MAX)
2371                         new_idx = ref_arr->num_ele - 1;
2372                 else if ((idx + skip_param) >= ref_arr->num_ele)
2373                         new_idx = 0;
2374                 else
2375                         new_idx = idx + skip_param;
2376
2377                 _prop_set_current_integer(dev_prop, new_idx);
2378                 return MTP_ERROR_NONE;
2379         }
2380
2381         return MTP_ERROR_GENERAL;
2382 }
2383
2384 mtp_err_t _hutil_format_storage(mtp_uint32 store_id, mtp_uint32 fs_format)
2385 {
2386         mtp_err_t error = MTP_ERROR_GENERAL;
2387         mtp_store_t *store = NULL;
2388
2389         store = _device_get_store(store_id);
2390         if (store == NULL) {
2391                 ERR("Store is NULL");
2392                 return error;
2393         }
2394
2395         error = _entity_format_store(store, fs_format);
2396         if (error == PTP_RESPONSE_OK)
2397                 return MTP_ERROR_NONE;
2398
2399         ERR("Format store Fail");
2400         return error;
2401 }
2402
2403 mtp_uint32 _hutil_get_storage_info_size(store_info_t *store_info)
2404 {
2405         mtp_uint32 size = 0;
2406
2407         size += sizeof(store_info->access);
2408         size += sizeof(store_info->fs_type);
2409         size += sizeof(store_info->free_space);
2410         size += sizeof(store_info->free_space_in_objs);
2411         size += sizeof(store_info->capacity);
2412         size += sizeof(store_info->store_type);
2413         size += _prop_size_ptpstring(&(store_info->store_desc));
2414         size += _prop_size_ptpstring(&(store_info->vol_label));
2415
2416         return size;
2417 }