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