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