Sync code with Tizen 3.0 branch
[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         obj_info = _entity_alloc_object_info();
1599         if (obj_info == NULL) {
1600                 ERR("_entity_alloc_object_info Fail");
1601                 return MTP_ERROR_GENERAL;
1602         }
1603
1604         obj_info->obj_fmt = format;
1605         if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1606                 obj_info->association_type = PTP_ASSOCIATIONTYPE_FOLDER;
1607
1608         obj_info->file_size = obj_sz;
1609
1610         /* Prop value quadruple: Object Handle, PropertyCode, DataType
1611          * and DTS Prop Value (assume a byte value)
1612          */
1613         temp = (mtp_uchar *) data;
1614         bytes_left = data_sz;
1615         quad_sz = sizeof(mtp_uint32) + sizeof(mtp_uint16) + sizeof(mtp_uint16) +
1616                 sizeof(mtp_char);
1617         memcpy(&num_elem, temp, sizeof(mtp_uint32));
1618 #ifdef __BIG_ENDIAN__
1619         _util_conv_byte_order(&num_elem, sizeof(mtp_uint32));
1620 #endif
1621         temp += sizeof(mtp_uint32);
1622         bytes_left -= sizeof(mtp_uint32);
1623
1624         /* frequent disconnect/connect make bluscreen since below process
1625          * is not finished
1626          */
1627         for (index = 0; index < num_elem; index++) {
1628                 if (MTP_PHONE_USB_DISCONNECTED == _util_get_local_usb_status() ||
1629                                 TRUE == _transport_get_usb_discon_state()) {
1630                         /* seems usb is disconnected, stop */
1631                         _entity_dealloc_obj_info(obj_info);
1632                         resp = MTP_ERROR_GENERAL;
1633                         goto ERROR_EXIT;
1634                 }
1635
1636                 *err_idx = index;
1637                 if (bytes_left < quad_sz) {
1638                         /* seems invalid dataset received: Stops parsing */
1639                         _entity_dealloc_obj_info(obj_info);
1640                         resp = MTP_ERROR_INVALID_DATASET;
1641                         goto ERROR_EXIT;
1642                 }
1643
1644                 /* Get ObjectHandle & validate */
1645                 memcpy(&obj_handle, temp, sizeof(mtp_uint32));
1646 #ifdef __BIG_ENDIAN__
1647                 _util_conv_byte_order(&obj_handle, sizeof(mtp_uint32));
1648 #endif /* __BIG_ENDIAN__ */
1649                 temp += sizeof(mtp_uint32);
1650                 bytes_left -= sizeof(mtp_uint32);
1651                 if (obj_handle != 0x00000000) {
1652                         _entity_dealloc_obj_info(obj_info);
1653                         resp = MTP_ERROR_INVALID_OBJECTHANDLE;
1654                         goto ERROR_EXIT;
1655                 }
1656
1657                 /* Get PropCode & Validate */
1658                 memcpy(&prop_code, temp, sizeof(mtp_uint16));
1659 #ifdef __BIG_ENDIAN__
1660                 _util_conv_byte_order(&prop_code, sizeof(mtp_uint16));
1661 #endif /* __BIG_ENDIAN__ */
1662                 temp += sizeof(mtp_uint16);
1663                 bytes_left -= sizeof(mtp_uint16);
1664                 prop_desc = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1665                 if (prop_desc == NULL) {
1666                         _entity_dealloc_obj_info(obj_info);
1667                         ERR("property may be unsupported!!");
1668                         resp = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1669                         goto ERROR_EXIT;
1670                 }
1671
1672                 /* Verify that properties already present in parameters
1673                  * don't get repeated in the list
1674                  */
1675                 if ((prop_code == MTP_OBJ_PROPERTYCODE_STORAGEID) ||
1676                                 (prop_code == MTP_OBJ_PROPERTYCODE_PARENT) ||
1677                                 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFORMAT) ||
1678                                 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTSIZE)) {
1679                         _entity_dealloc_obj_info(obj_info);
1680                         resp = MTP_ERROR_INVALID_DATASET;
1681                         goto ERROR_EXIT;
1682                 }
1683
1684                 /* Get DataType */
1685                 memcpy(&data_type, temp, sizeof(mtp_uint16));
1686 #ifdef __BIG_ENDIAN__
1687                 _util_conv_byte_order(&data_type, sizeof(mtp_uint16));
1688 #endif /* __BIG_ENDIAN__ */
1689                 temp += sizeof(mtp_uint16);
1690                 bytes_left -= sizeof(mtp_uint16);
1691                 if (data_type != prop_desc->propinfo.data_type) {
1692                         _entity_dealloc_obj_info(obj_info);
1693                         resp = MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1694                         goto ERROR_EXIT;
1695                 }
1696
1697                 /* Acquire object information related data. */
1698                 prop_val = _prop_alloc_obj_propval(prop_desc);
1699                 if (prop_val == NULL)
1700                         continue;
1701
1702                 _prop_set_current_array_val(prop_val, temp, bytes_left);
1703                 switch (prop_code) {
1704                 case MTP_OBJ_PROPERTYCODE_WIDTH:
1705                         // TODO: find mechanism to save (integer)
1706                         break;
1707                 case MTP_OBJ_PROPERTYCODE_TRACK:
1708                         // TODO: find mechanism to save (integer)
1709                         break;
1710                 case MTP_OBJ_PROPERTYCODE_GENRE:
1711                         // TODO: find mechanism to save (string)
1712                         break;
1713                 case MTP_OBJ_PROPERTYCODE_HEIGHT:
1714                         // TODO: find mechanism to save (integer)
1715                         break;
1716                 case MTP_OBJ_PROPERTYCODE_ARTIST:
1717                         // TODO: find mechanism to save (string)
1718                         break;
1719                 case MTP_OBJ_PROPERTYCODE_DURATION:
1720                         // TODO: find mechanism to save (integer)
1721                         break;
1722                 case MTP_OBJ_PROPERTYCODE_COMPOSER:
1723                         // TODO: find mechanism to save (string)
1724                         break;
1725                 case MTP_OBJ_PROPERTYCODE_ALBUMNAME:
1726                         // TODO: find mechanism to save (string)
1727                         break;
1728                 case MTP_OBJ_PROPERTYCODE_SAMPLERATE:
1729                         // TODO: find mechanism to save (integer)
1730                         break;
1731                 case MTP_OBJ_PROPERTYCODE_DATECREATED:
1732                         // TODO: find mechanism to save (string)
1733                         break;
1734                 case MTP_OBJ_PROPERTYCODE_DATEMODIFIED:
1735                         // TODO: find mechanism to save (string)
1736                         break;
1737                 case MTP_OBJ_PROPERTYCODE_AUDIOBITRATE:
1738                         // TODO: find mechanism to save (integer)
1739                         break;
1740                 case MTP_OBJ_PROPERTYCODE_VIDEOBITRATE:
1741                         // TODO: find mechanism to save (integer)
1742                         break;
1743                 case  MTP_OBJ_PROPERTYCODE_OBJECTFILENAME:
1744                         /* empty metadata folder problem
1745                          * emtpy file name
1746                          */
1747                         if (prop_val->current_val.str->num_chars == 0) {
1748                                 g_strlcpy(file_name, MTP_UNKNOWN_METADATA, sizeof(file_name));
1749                         } else {
1750                                 _util_utf16_to_utf8(file_name, sizeof(file_name),
1751                                                 prop_val->current_val.str->str);
1752                         }
1753                         break;
1754
1755                 case MTP_OBJ_PROPERTYCODE_PROTECTIONSTATUS:
1756 #ifdef MTP_SUPPORT_SET_PROTECTION
1757                         memcpy(&obj_info->protcn_status, prop_val->current_val.integer,
1758                                         sizeof(mtp_uint16));
1759 #else /* MTP_SUPPORT_SET_PROTECTION */
1760                         obj_info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
1761 #endif /*MTP_SUPPORT_SET_PROTECTION*/
1762                         break;
1763
1764                 case MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE:
1765                         memcpy(&obj_info->association_type, prop_val->current_val.integer,
1766                                         sizeof(mtp_uint16));
1767                         break;
1768
1769                 case MTP_OBJ_PROPERTYCODE_NUMBEROFCHANNELS:
1770                         // TODO: find mechanism to save (integer)
1771                         break;
1772                 case MTP_OBJ_PROPERTYCODE_FRAMESPER1KSECONDS:
1773                         // TODO: find mechanism to save (integer)
1774                         break;
1775 #ifdef MTP_SUPPORT_ALBUM_ART
1776                 case MTP_OBJ_PROPERTYCODE_SAMPLEDATA:
1777                         /* save sample data(album cover data) with
1778                          * sample format, otherwise no extension
1779                          * update db with sample data path
1780                          * there is no case that this position is called
1781                          * again but prevent detect this
1782                          */
1783                         g_free(alb_buf);
1784                         alb_buf = NULL;
1785                         alb_buf = g_malloc(sizeof(mtp_uchar) *
1786                                         (prop_val->current_val.array->num_ele) + 1);
1787                         alb_sz = prop_val->current_val.array->num_ele;
1788                         if (alb_buf != NULL) {
1789                                 memset(alb_buf, 0,
1790                                                 sizeof(mtp_uchar) * alb_sz + 1);
1791                                 if (alb_sz > 0)
1792                                         memcpy(alb_buf,
1793                                                         (prop_val->current_val.array->array_entry),
1794                                                         sizeof(mtp_uchar) * alb_sz);
1795                         } else {
1796                                 ERR("album art test mem allocation Fail");
1797                                 _prop_destroy_obj_propval(prop_val);
1798                                 _entity_dealloc_obj_info(obj_info);
1799                                 return MTP_ERROR_GENERAL;
1800                         }
1801                         break;
1802
1803                 case MTP_OBJ_PROPERTYCODE_SAMPLEFORMAT:
1804                         /* if is_albumart is turned on, Move file with
1805                          * new extension. And update db with data path
1806                          */
1807                         memcpy(&albumFormat, prop_val->current_val.integer,
1808                                         sizeof(mtp_uint16));
1809                         switch (albumFormat) {
1810                         case PTP_FMT_IMG_EXIF:
1811                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "jpg");
1812                                 break;
1813                         case PTP_FMT_IMG_GIF:
1814                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "gif");
1815                                 break;
1816                         case PTP_FMT_IMG_PNG:
1817                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "png");
1818                                 break;
1819                         case MTP_FMT_WMA:
1820                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "wma");
1821                                 break;
1822                         case PTP_FMT_MPEG:
1823                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "mpg");
1824                                 break;
1825                         default:
1826                                 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "dat");
1827                                 break;
1828                         }
1829
1830                         ERR("sampleformatl![0x%x], extension[%s]\n", prop_code, alb_extn);
1831                         break;
1832                 case MTP_OBJ_PROPERTYCODE_SAMPLESIZE:
1833                 case MTP_OBJ_PROPERTYCODE_SAMPLEHEIGHT:
1834                 case MTP_OBJ_PROPERTYCODE_SAMPLEWIDTH:
1835                 case MTP_OBJ_PROPERTYCODE_SAMPLEDURATION:
1836                         DBG("Sample data is not supported [0x%x]\n", prop_code);
1837                         break;
1838 #endif /*MTP_SUPPORT_ALBUM_ART*/
1839
1840                 default:
1841                         DBG("Unsupported Property [0x%x]\n", prop_code);
1842                         break;
1843                 }
1844
1845                 temp += _prop_size_obj_propval(prop_val);
1846                 bytes_left -= _prop_size_obj_propval(prop_val);
1847                 _prop_destroy_obj_propval(prop_val);
1848         }
1849
1850         obj_info->store_id = store_id;
1851         obj_info->h_parent = h_parent;
1852
1853         if ((resp = _hutil_add_object_entry(obj_info, file_name, &obj)) !=
1854                         MTP_ERROR_NONE) {
1855                 goto ERROR_EXIT;
1856         }
1857
1858 #ifdef MTP_SUPPORT_ALBUM_ART
1859         mtp_char full_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1860         mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1861
1862         g_strlcpy(full_path, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1863
1864         /* in case of album, if there is album data, fill it in this file */
1865         if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
1866                         (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
1867                          obj_info->association_type != PTP_ASSOCIATIONTYPE_UNDEFINED &&
1868                          obj_info->association_type != PTP_ASSOCIATIONTYPE_FOLDER)) {
1869
1870                 _util_get_file_extn(full_path, extn);
1871                 if (!strcasecmp(extn, "alb")) {
1872                         /* check db whether it contains sample form
1873                          * save sample data(album cover data) with
1874                          * sample format, otherwise no extension
1875                          */
1876                         if (alb_buf != NULL) {
1877                                 /* file write */
1878                                 h_temp = _util_file_open(full_path,
1879                                                 MTP_FILE_WRITE, &error);
1880                                 if (h_temp != NULL) {
1881                                         _util_file_write(h_temp, alb_buf,
1882                                                         sizeof(mtp_uchar) *alb_sz);
1883                                         _util_file_close(h_temp);
1884                                 } else {
1885                                         ERR("open album file Fail!!");
1886                                 }
1887                         } else {
1888                                 ERR("no album art data");
1889                         }
1890                 }
1891         }
1892
1893         g_free(alb_buf);
1894 #endif /* MTP_SUPPORT_ALBUM_ART */
1895         *obj_ptr = obj;
1896         return MTP_ERROR_NONE;
1897
1898 ERROR_EXIT:
1899 #ifdef MTP_SUPPORT_ALBUM_ART
1900         g_free(alb_buf);
1901 #endif /* MTP_SUPPORT_ALBUM_ART */
1902         return resp;
1903 }
1904
1905 mtp_err_t _hutil_get_object_prop_value(mtp_uint32 obj_handle,
1906                 mtp_uint32 prop_code, obj_prop_val_t *prop_val, mtp_obj_t **obj)
1907 {
1908         obj_prop_val_t *tprop = NULL;
1909         mtp_obj_t *tobj = NULL;
1910
1911         tobj = _device_get_object_with_handle(obj_handle);
1912         if (NULL == tobj) {
1913                 ERR("requested handle does not exist[0x%x]\n", obj_handle);
1914                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1915         }
1916
1917         tprop = _prop_get_prop_val(tobj, prop_code);
1918         if (tprop != NULL) {
1919                 memcpy(prop_val, tprop, sizeof(obj_prop_val_t));
1920                 *obj = tobj;
1921                 return MTP_ERROR_NONE;
1922         }
1923
1924         ERR("can not get the prop value for propcode [0x%x]\n", prop_code);
1925         return MTP_ERROR_GENERAL;
1926 }
1927
1928 mtp_err_t _hutil_update_object_property(mtp_uint32 obj_handle,
1929                 mtp_uint32 prop_code, mtp_uint16 *data_type, void *buf,
1930                 mtp_uint32 buf_sz, mtp_uint32 *prop_sz)
1931 {
1932         mtp_int32 error = 0;
1933         mtp_uint32 p_size = 0;
1934         mtp_obj_t *obj = NULL;
1935         obj_info_t *obj_info = NULL;
1936         obj_prop_desc_t *prp_dev = NULL;
1937         mtp_char temp_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1938         mtp_char orig_pfpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1939         mtp_wchar mov_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1940         mtp_char orig_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1941         mtp_char dest_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1942
1943         retv_if(NULL == buf, MTP_ERROR_INVALID_PARAM);
1944
1945         obj = _device_get_object_with_handle(obj_handle);
1946         if ((NULL == obj) || (NULL == obj->obj_info)) {
1947                 ERR("Object not found");
1948                 return MTP_ERROR_INVALID_OBJECTHANDLE;
1949         }
1950
1951         obj_info = obj->obj_info;
1952         /* Avoid to rename file/folder during file operating by phone side. */
1953         if (_util_is_file_opened(obj->file_path) == TRUE) {
1954                 ERR_SECURE("Object [%s] is already opened\n", obj->file_path);
1955                 return MTP_ERROR_GENERAL;
1956         }
1957
1958         prp_dev = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1959         if (prp_dev == NULL) {
1960                 ERR("_prop_get_obj_prop_desc Fail");
1961                 return MTP_ERROR_INVALID_OBJ_PROP_CODE;
1962         }
1963
1964 #ifdef MTP_SUPPORT_SET_PROTECTION
1965         if (obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) {
1966                 ERR("protection is PTP_PROTECTIONSTATUS_READONLY");
1967                 return MTP_ERROR_ACCESS_DENIED;
1968         }
1969 #endif /* MTP_SUPPORT_SET_PROTECTION */
1970
1971         if (prp_dev->propinfo.get_set == PTP_PROPGETSET_GETONLY) {
1972                 ERR("property type is GETONLY");
1973                 return MTP_ERROR_ACCESS_DENIED;
1974         }
1975
1976         if (data_type != NULL && *data_type != prp_dev->propinfo.data_type) {
1977                 ERR("Not matched data type [%d][%d]\n",
1978                                 *data_type, prp_dev->propinfo.data_type);
1979                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1980         }
1981
1982         /* Set up needed object info fields */
1983         if (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFILENAME) {
1984                 ptp_string_t fname = { 0 };
1985
1986                 _prop_init_ptpstring(&fname);
1987                 _prop_parse_rawstring(&fname, buf, buf_sz);
1988
1989                 _util_utf16_to_utf8(temp_buf, sizeof(temp_buf),
1990                                 fname.str);
1991                 g_strlcpy(orig_fpath, obj->file_path,
1992                                 MTP_MAX_PATHNAME_SIZE + 1);
1993                 _util_get_parent_path(orig_fpath, orig_pfpath);
1994
1995                 if (_util_create_path(dest_fpath, sizeof(dest_fpath),
1996                                         orig_pfpath, temp_buf) == FALSE) {
1997                         ERR("Path is too long");
1998                         return MTP_ERROR_ACCESS_DENIED;
1999                 }
2000                 _util_utf8_to_utf16(mov_fpath,
2001                                 sizeof(mov_fpath) / WCHAR_SIZ, dest_fpath);
2002
2003                 /* when changed name is different */
2004                 if (strcasecmp(orig_fpath, dest_fpath)) {
2005                         /* Extension change is not permitted */
2006                         mtp_char orig_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2007                         mtp_char dest_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2008
2009                         _util_get_file_extn(orig_fpath, orig_extn);
2010                         _util_get_file_extn(dest_fpath, dest_extn);
2011
2012                         if (strcasecmp(orig_extn, dest_extn)) {
2013                                 ERR("file extension is different with original\
2014                                                 one [%s]:[%s]\n", orig_extn, dest_extn);
2015                                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2016                         }
2017
2018                         /* FILE RENAME */
2019                         if (_entity_check_child_obj_path(obj, orig_fpath,
2020                                                 dest_fpath) == FALSE) {
2021                                 ERR("_entity_check_child_obj_path FALSE. ");
2022                                 return MTP_ERROR_GENERAL;
2023                         }
2024                         g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
2025                                         "%s", orig_fpath);
2026                         if (FALSE == _util_file_move(orig_fpath, dest_fpath,
2027                                                 &error)) {
2028                                 if (EACCES == error)
2029                                         return MTP_ERROR_ACCESS_DENIED;
2030                                 return MTP_ERROR_GENERAL;
2031                         }
2032
2033                         if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
2034                                 _util_scan_folder_contents_in_db(orig_fpath);
2035                                 _util_scan_folder_contents_in_db(dest_fpath);
2036                         } else {
2037                                 _util_delete_file_from_db(orig_fpath);
2038                                 _util_add_file_to_db(dest_fpath);
2039
2040                         }
2041
2042                         /* Finally assign new handle and update full path */
2043                         _entity_set_object_file_path(obj, dest_fpath,
2044                                         CHAR_TYPE);
2045
2046                         /* FILE RENAME */
2047                         if (_entity_set_child_object_path(obj, orig_fpath,
2048                                                 dest_fpath) == FALSE) {
2049                                 ERR("failed to set the full path!!");
2050                                 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2051                         }
2052
2053                         DBG("File moved to [%s]\n", dest_fpath);
2054                 } else {
2055                         ERR_SECURE("changed name is same with original one. [%s]\n",
2056                                         dest_fpath);
2057                 }
2058                 p_size = _prop_size_ptpstring(&fname);
2059         } else if (prop_code == MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE) {
2060                 memcpy(&obj_info->association_type, buf, sizeof(mtp_uint16));
2061                 p_size = sizeof(mtp_uint16);
2062         } else {
2063                 ERR("Propert [0x%x] is GETONLY\n", prop_code);
2064         }
2065
2066         if (prop_sz != NULL)
2067                 *prop_sz = p_size;
2068
2069         return MTP_ERROR_NONE;
2070 }
2071
2072 mtp_err_t _hutil_get_prop_desc(mtp_uint32 format, mtp_uint32 prop_code,
2073                 void *data)
2074 {
2075         obj_prop_desc_t *prop = NULL;
2076
2077         prop = _prop_get_obj_prop_desc(format, prop_code);
2078         if (prop == NULL) {
2079                 ERR("pProperty is NULL");
2080                 return MTP_ERROR_GENERAL;
2081         }
2082
2083         memcpy(data, prop, sizeof(obj_prop_desc_t));
2084         return MTP_ERROR_NONE;
2085 }
2086
2087 mtp_err_t _hutil_get_object_prop_supported(mtp_uint32 format,
2088                 ptp_array_t     *prop_arr)
2089 {
2090         _prop_get_supp_obj_props(format, prop_arr);
2091         return MTP_ERROR_NONE;
2092 }
2093
2094 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2095 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2096                 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2097                 obj_proplist_t *prop_list)
2098 #else /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2099 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2100                 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2101                 obj_proplist_t *prop_list, ptp_array_t *obj_arr)
2102 #endif /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2103 {
2104 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2105         ptp_array_t obj_arr = { 0 };
2106 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2107         mtp_obj_t *obj = NULL;
2108         mtp_uint32 i = 0;
2109         mtp_uint32 ii = 0;
2110         mtp_store_t *store = NULL;
2111
2112         if ((obj_handle != PTP_OBJECTHANDLE_UNDEFINED) &&
2113                         (obj_handle != PTP_OBJECTHANDLE_ALL)) {
2114                 /* Is this object handle valid? */
2115                 store = _device_get_store_containing_obj(obj_handle);
2116                 if (store == NULL) {
2117                         ERR("invalid object handle");
2118                         return MTP_ERROR_INVALID_OBJECTHANDLE;
2119                 }
2120         }
2121
2122         if (prop_code == PTP_PROPERTY_UNDEFINED) {
2123                 /* PropGroupCode should be used if Property code
2124                  * is not specified.
2125                  * */
2126                 if (group_code == 0x0) {
2127                         ERR("PropGroupCode is zero");
2128                         return MTP_ERROR_INVALID_PARAM;
2129                 }
2130         }
2131
2132         if (!(obj_handle == PTP_OBJECTHANDLE_ALL ||
2133                                 obj_handle == PTP_OBJECTHANDLE_UNDEFINED) &&
2134                         !(format == PTP_FORMATCODE_NOTUSED ||
2135                                 format == PTP_FORMATCODE_ALL)) {
2136                 ERR("both object handle and format code is specified!\
2137                                 return nospecification by format");
2138                 return MTP_ERROR_NO_SPEC_BY_FORMAT;
2139         }
2140
2141         _util_init_list(&(prop_list->prop_quad_list));
2142         _prop_init_ptparray(obj_arr, UINT32_TYPE);
2143
2144         if (store != NULL) {
2145                 _entity_get_objects_from_store_till_depth(store, obj_handle,
2146                                 format, depth, obj_arr);
2147         } else {
2148                 for (ii = 0; ii < _device_get_num_stores(); ii++) {
2149                         store = _device_get_store_at_index(ii);
2150                         _entity_get_objects_from_store_till_depth(store,
2151                                         obj_handle, format, depth, obj_arr);
2152                 }
2153         }
2154
2155         if (obj_arr->num_ele != 0) {
2156                 mtp_uint32 *obj_handles = obj_arr->array_entry;
2157
2158                 for (i = 0; i < obj_arr->num_ele; i++) {
2159                         obj = _entity_get_object_from_store(store, obj_handles[i]);
2160                         if (!obj)
2161                                 continue;
2162
2163                         if (_prop_get_obj_proplist(obj, prop_code, group_code,
2164                                                 prop_list) == FALSE) {
2165                                 ERR("Fail to create Proplist");
2166 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2167                                 _prop_deinit_ptparray(&obj_arr);
2168 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2169                                 return MTP_ERROR_GENERAL;
2170                         }
2171                 }
2172         }
2173
2174 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2175         prop_deinit_ptparray(&obj_arr);
2176 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2177
2178         return MTP_ERROR_NONE;
2179 }
2180
2181 mtp_err_t _hutil_remove_object_reference(mtp_uint32 obj_handle,
2182                 mtp_uint32 ref_handle)
2183 {
2184         mtp_obj_t *obj = NULL;
2185
2186         obj = _device_get_object_with_handle(obj_handle);
2187         if (obj == NULL) {
2188                 ERR("No object for handle[%d]\n", obj_handle);
2189                 return MTP_ERROR_NONE;
2190         }
2191
2192         if (_entity_remove_reference_child_array(obj, ref_handle) == FALSE)
2193                 ERR("_entity_remove_reference_child_array Fail");
2194
2195         return MTP_ERROR_NONE;
2196 }
2197
2198 mtp_err_t _hutil_add_object_references_enhanced(mtp_uint32 obj_handle,
2199                 mtp_uchar *buffer, mtp_uint32 buf_sz)
2200 {
2201         mtp_obj_t *obj = NULL;
2202
2203         obj = _device_get_object_with_handle(obj_handle);
2204         if (obj == NULL) {
2205                 DBG("No object for handle[0x%x]\n", obj_handle);
2206                 return MTP_ERROR_NONE;
2207         }
2208
2209         if (_entity_set_reference_child_array(obj, buffer, buf_sz) == FALSE) {
2210                 ERR("_entity_set_reference_child_array Fail");
2211                 return MTP_ERROR_GENERAL;
2212         }
2213
2214         return MTP_ERROR_NONE;
2215 }
2216
2217 mtp_err_t _hutil_get_object_references(mtp_uint32 obj_handle,
2218                 ptp_array_t *parray, mtp_uint32 *num_ele)
2219 {
2220         mtp_obj_t *obj = NULL;
2221         mtp_obj_t *ref_obj = NULL;
2222         mtp_uint16 idx = 0;
2223         mtp_uint32 *ref_ptr = NULL;
2224         ptp_array_t ref_arr = { 0 };
2225
2226         obj = _device_get_object_with_handle(obj_handle);
2227         if (NULL == obj || NULL == obj->obj_info) {
2228                 *num_ele = 0;
2229                 return MTP_ERROR_INVALID_OBJECTHANDLE;
2230         }
2231
2232         if (parray == NULL) {
2233                 *num_ele = 0;
2234                 return MTP_ERROR_GENERAL;
2235         }
2236
2237         if (obj->child_array.num_ele == 0) {
2238                 *num_ele = 0;
2239                 return MTP_ERROR_NONE;
2240         }
2241
2242         _prop_init_ptparray(&ref_arr, obj->child_array.type);
2243         _prop_copy_ptparray(&ref_arr, &(obj->child_array));
2244         ref_ptr = (mtp_uint32 *)(ref_arr.array_entry);
2245
2246         for (idx = 0; idx < ref_arr.num_ele; idx++) {
2247                 ref_obj = _device_get_object_with_handle(ref_ptr[idx]);
2248                 if (ref_obj == NULL)
2249                         _entity_remove_reference_child_array(obj, ref_ptr[idx]);
2250         }
2251
2252         *num_ele = obj->child_array.num_ele;
2253         if (*num_ele) {
2254                 _prop_init_ptparray(parray, obj->child_array.type);
2255                 _prop_grow_ptparray(parray, *num_ele);
2256                 _prop_copy_ptparray(parray, &(obj->child_array));
2257         }
2258
2259         _prop_deinit_ptparray(&ref_arr);
2260         return MTP_ERROR_NONE;
2261 }
2262
2263 mtp_err_t _hutil_get_number_of_objects(mtp_uint32 store_id, mtp_uint32 *num_obj)
2264 {
2265         *num_obj = _device_get_num_objects(store_id);
2266         return MTP_ERROR_NONE;
2267 }
2268
2269 mtp_err_t _hutil_get_interdep_prop_config_list_size(mtp_uint32 *list_sz,
2270                 mtp_uint32 format)
2271 {
2272         *list_sz = _prop_get_size_interdep_proplist(&interdep_proplist,
2273                         format);
2274         return MTP_ERROR_NONE;
2275 }
2276
2277 mtp_err_t _hutil_get_interdep_prop_config_list_data(void *data,
2278                 mtp_uint32 list_sz, mtp_uint32 format)
2279 {
2280         if (list_sz == _prop_pack_interdep_proplist(&interdep_proplist,
2281                                 format, data, list_sz)) {
2282                 return MTP_ERROR_NONE;
2283         }
2284
2285         ERR("packet and requested size do not match");
2286         return MTP_ERROR_GENERAL;
2287 }
2288
2289 mtp_err_t _hutil_get_playback_skip(mtp_int32 skip_param)
2290 {
2291         mtp_int32 idx = 0;
2292         mtp_obj_t *obj = NULL;
2293         mtp_uint32 new_idx = 0;
2294         mtp_uint32 new_hobj = 0;
2295         mtp_uint32 obj_handle = 0;
2296         mtp_obj_t *par_obj = NULL;
2297         obj_info_t *obj_info = NULL;
2298         ptp_array_t *ref_arr = NULL;
2299         device_prop_desc_t *dev_prop = NULL;
2300
2301         retv_if(skip_param == 0, MTP_ERROR_INVALID_PARAM);
2302
2303         if (_device_get_playback_obj(&obj_handle) == FALSE) {
2304                 ERR("_device_get_playback_obj Fail");
2305                 return MTP_ERROR_GENERAL;
2306         }
2307
2308         if (obj_handle == 0x0)
2309                 return MTP_ERROR_NONE;
2310
2311         obj = _device_get_object_with_handle(obj_handle);
2312         if (obj == NULL || obj->obj_info == NULL) {
2313                 ERR("obj or obj_info is NULL");
2314                 return MTP_ERROR_GENERAL;
2315         }
2316
2317         obj_info = obj->obj_info;
2318         if ((obj_info->obj_fmt == PTP_FMT_WAVE) ||
2319                         (obj_info->obj_fmt == PTP_FMT_MP3) ||
2320                         (obj_info->obj_fmt == MTP_FMT_WMA) ||
2321                         (obj_info->obj_fmt == MTP_FMT_WMV) ||
2322                         (obj_info->obj_fmt == MTP_FMT_UNDEFINED_AUDIO)) {
2323                 par_obj = _device_get_object_with_handle(obj_info->h_parent);
2324                 if (!par_obj) {
2325                         ERR("parent not found in obj_list");
2326                         return MTP_ERROR_GENERAL;
2327                 }
2328                 ref_arr = _entity_get_reference_child_array(par_obj);
2329                 idx = _prop_find_ele_ptparray(ref_arr, obj_handle);
2330                 if (idx != ELEMENT_NOT_FOUND) {
2331                         if (((long long)idx + (long long)skip_param) > UINT_MAX)
2332                                 new_idx = ref_arr->num_ele - 1;
2333                         else if ((idx + skip_param) >= ref_arr->num_ele)
2334                                 new_idx = 0;
2335                         else
2336                                 new_idx = idx + skip_param;
2337
2338                         if (_prop_get_ele_ptparray(ref_arr, new_idx,
2339                                                 (void *)(&new_hobj)) == TRUE) {
2340                                 dev_prop = _device_get_device_property(
2341                                                 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2342                                 if (dev_prop == NULL) {
2343                                         ERR("dev_prop is null");
2344                                         return MTP_ERROR_GENERAL;
2345                                 }
2346                                 _prop_set_current_integer(dev_prop, 0xFFFFFFFF);
2347                                 _device_set_playback_obj(new_hobj);
2348                         }
2349                 }
2350         } else if ((obj_info->obj_fmt == MTP_FMT_ABSTRACT_AUDIO_ALBUM) ||
2351                         (obj_info->obj_fmt == MTP_FMT_ABSTRACT_VIDEO_ALBUM)) {
2352                 dev_prop = _device_get_device_property(
2353                                 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2354                 if (dev_prop == NULL) {
2355                         ERR("dev_prop is null");
2356                         return MTP_ERROR_GENERAL;
2357                 }
2358                 memcpy(&idx, dev_prop->current_val.integer, sizeof(mtp_uint32));
2359                 ref_arr = _entity_get_reference_child_array(obj);
2360                 if (((long long)idx + (long long)skip_param) > UINT_MAX)
2361                         new_idx = ref_arr->num_ele - 1;
2362                 else if ((idx + skip_param) >= ref_arr->num_ele)
2363                         new_idx = 0;
2364                 else
2365                         new_idx = idx + skip_param;
2366
2367                 _prop_set_current_integer(dev_prop, new_idx);
2368                 return MTP_ERROR_NONE;
2369         }
2370
2371         return MTP_ERROR_GENERAL;
2372 }
2373
2374 mtp_err_t _hutil_format_storage(mtp_uint32 store_id, mtp_uint32 fs_format)
2375 {
2376         mtp_err_t error = MTP_ERROR_GENERAL;
2377         mtp_store_t *store = NULL;
2378
2379         store = _device_get_store(store_id);
2380         if (store == NULL) {
2381                 ERR("Store is NULL");
2382                 return error;
2383         }
2384
2385         error = _entity_format_store(store, fs_format);
2386         if (error == PTP_RESPONSE_OK)
2387                 return MTP_ERROR_NONE;
2388
2389         ERR("Format store Fail");
2390         return error;
2391 }
2392
2393 mtp_uint32 _hutil_get_storage_info_size(store_info_t *store_info)
2394 {
2395         mtp_uint32 size = 0;
2396
2397         size += sizeof(store_info->access);
2398         size += sizeof(store_info->fs_type);
2399         size += sizeof(store_info->free_space);
2400         size += sizeof(store_info->free_space_in_objs);
2401         size += sizeof(store_info->capacity);
2402         size += sizeof(store_info->store_type);
2403         size += _prop_size_ptpstring(&(store_info->store_desc));
2404         size += _prop_size_ptpstring(&(store_info->vol_label));
2405
2406         return size;
2407 }