2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
27 * GLOBAL AND EXTERN VARIABLES
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];
40 static mtp_mgr_t *g_mgr = &g_mtp_mgr;
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.
53 mtp_err_t _hutil_get_storage_entry(mtp_uint32 store_id, store_info_t *info)
55 mtp_store_t *store = NULL;
57 store = _device_get_store(store_id);
59 ERR("Not able to retrieve store");
60 return MTP_ERROR_GENERAL;
63 _entity_update_store_info_run_time(&(store->store_info),
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;
78 mtp_err_t _hutil_get_storage_ids(ptp_array_t *store_ids)
80 mtp_uint32 num_elem = 0;
81 mtp_uint32 num_stores = 0;
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;
88 ERR("get storage id Fail. num_elem[%d], num_stores[%d]\n",
89 num_elem, num_stores);
90 return MTP_ERROR_GENERAL;
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.
100 mtp_err_t _hutil_get_device_property(mtp_uint32 prop_id,
101 device_prop_desc_t* dev_prop)
103 device_prop_desc_t *prop = NULL;
105 prop = _device_get_device_property(prop_id);
107 return MTP_ERROR_GENERAL;
109 memcpy(dev_prop, prop, sizeof(device_prop_desc_t));
110 return MTP_ERROR_NONE;
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.
121 mtp_err_t _hutil_set_device_property(mtp_uint32 prop_id, void *data,
124 device_prop_desc_t *prop = NULL;
126 prop = _device_get_device_property(prop_id);
128 return MTP_ERROR_GENERAL;
129 /* LCOV_EXCL_START */
130 if (prop->propinfo.get_set == PTP_PROPGETSET_GETONLY)
131 return MTP_ERROR_ACCESS_DENIED;
133 if (FALSE == _prop_set_current_device_prop(prop, data, data_sz))
134 return MTP_ERROR_INVALID_OBJ_PROP_VALUE;
136 return MTP_ERROR_NONE;
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.
146 mtp_err_t _hutil_reset_device_entry(mtp_uint32 prop_id)
148 device_prop_desc_t *prop = NULL;
151 if (prop_id == 0xFFFFFFFF) {
152 /* LCOV_EXCL_START */
153 prop = _device_get_ref_prop_list();
155 ERR("property reference is NULL");
156 return MTP_ERROR_GENERAL;
158 for (ii = 0; ii < NUM_DEVICE_PROPERTIES; ii++)
159 _prop_reset_device_prop_desc(&prop[ii]);
162 prop = _device_get_device_property(prop_id);
164 return MTP_ERROR_GENERAL;
166 _prop_reset_device_prop_desc(prop);
169 return MTP_ERROR_NONE;
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.
180 mtp_err_t _hutil_add_object_entry(obj_info_t *obj_info, mtp_char *file_name,
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 };
191 mtp_bool is_made_by_mtp = FALSE;
192 mtp_wchar w_file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
194 if (obj_info == NULL)
195 return MTP_ERROR_INVALID_PARAM;
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;
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;
216 store = _device_get_store(obj_info->store_id);
218 ERR("store is null");
219 _entity_dealloc_obj_info(obj_info);
220 return MTP_ERROR_GENERAL;
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;
230 obj = _entity_alloc_mtp_object();
232 ERR("allocation memory Fail");
233 _entity_dealloc_obj_info(obj_info);
234 return MTP_ERROR_GENERAL;
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;
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
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;
252 if (file_name == NULL) {
253 _entity_dealloc_obj_info(obj_info);
254 _entity_dealloc_mtp_obj(obj);
255 return MTP_ERROR_INVALID_PARAM;
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);
264 _util_utf8_to_utf16(temp_wfname,
265 sizeof(temp_wfname) / WCHAR_SIZ, file_name);
268 /* Does this path/filename already exist ? */
270 mtp_bool file_exist = FALSE;
271 mtp_uint32 path_len = 0;
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),
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;
284 #ifdef MTP_SUPPORT_HIDE_WMPINFO_XML
285 /* WMPInfo.xml and DevLogo.fil.*/
286 /* find WMPInfo.xml and add file mtp store */
288 mtp_char wmp_info_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
289 mtp_char wmp_hidden_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
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);
295 g_snprintf(wmp_hidden_path,
296 MTP_MAX_PATHNAME_SIZE + 1,
297 "%s/%s/%s", MTP_USER_DIRECTORY,
299 MTP_FILE_NAME_WMPINFO_XML);
300 g_snprintf(wmp_info_path,
301 MTP_MAX_PATHNAME_SIZE + 1,
303 MTP_FILE_NAME_WMPINFO_XML);
305 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
306 _util_get_external_path(ext_path);
308 g_snprintf(wmp_hidden_path,
309 MTP_MAX_PATHNAME_SIZE + 1,
310 "%s/%s/%s", MTP_USER_DIRECTORY,
312 MTP_FILE_NAME_WMPINFO_XML);
313 g_snprintf(wmp_info_path,
314 MTP_MAX_PATHNAME_SIZE + 1,
316 MTP_FILE_NAME_WMPINFO_XML);
319 if (!strcasecmp(wmp_info_path, new_f_path)) {
320 DBG("substitute file[%s]-->[%s]\n",
321 wmp_info_path, wmp_hidden_path);
323 g_strlcpy(new_f_path, wmp_hidden_path,
326 if (obj_info->store_id ==
327 MTP_INTERNAL_STORE_ID) {
329 MTP_MAX_INT_OBJECT_NUM -
330 MTPSTORE_WMPINFO_PHONE;
333 MTP_MAX_INT_OBJECT_NUM -
334 MTPSTORE_WMPINFO_CARD;
338 #endif /*MTP_SUPPORT_HIDE_WMPINFO_XML*/
340 _util_utf16_to_utf8(utf8_temp, sizeof(utf8_temp),
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;
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
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;
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;
370 DBG_SECURE("Temp file path [%s]\n", g_mgr->ftemp_st.filepath);
373 #ifdef MTP_SUPPORT_ALBUM_ART
374 if (access(new_f_path, F_OK) == 0) {
375 /* LCOV_EXCL_START */
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 };
381 /* find extension, if album or pla, overwrite that. */
382 _util_utf16_to_utf8(alb_buf, sizeof(alb_buf), temp_wfname);
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)) {
391 _util_get_file_extn(alb_buf, alb_ext);
392 if (!strcasecmp(alb_ext, "alb")) {
393 if (remove(new_f_path) == 0) {
395 DBG("[%s] file is found. Delete\
396 old and make new one\n",
399 ERR("[%s] file is found. but \
406 #endif /*MTP_SUPPORT_ALBUM_ART*/
408 if (file_exist == FALSE) {
409 DBG_SECURE("Found a unique file name for the incoming object\
410 [0x%p]\n", temp_wfname);
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;
425 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION ||
427 *new_obj = _device_get_object_with_path(new_f_path);
429 _entity_dealloc_mtp_obj(obj);
430 return MTP_ERROR_NONE;
432 DBG("+ not found object. [%s]\n", new_f_path);
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,
441 _util_wchar_swprintf(temp_wfname,
442 MTP_MAX_PATHNAME_SIZE + 1, "COPY%d_%s", i, w_file_name);
445 /* Save the full path to this object */
446 _entity_set_object_file_path(obj, new_f_path, CHAR_TYPE);
449 * Is this an association (or folder)?
450 * Associations are fully qualified by the ObjectInfo Dataset.
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*/
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);
464 if ((obj_info->association_type !=
465 PTP_ASSOCIATIONTYPE_UNDEFINED &&
466 obj_info->association_type !=
467 PTP_ASSOCIATIONTYPE_FOLDER) ||
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;
477 _util_file_close(h_abs_file);
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;
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;
499 /* Reserve space for the object: Object itself, and probably
500 * some Filesystem-specific overhead
502 store->store_info.free_space -= obj_info->file_size;
507 return MTP_ERROR_NONE;
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.
517 mtp_err_t _hutil_remove_object_entry(mtp_uint32 obj_handle, mtp_uint32 format)
519 mtp_err_t resp = MTP_ERROR_GENERAL;
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);
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;
538 #endif /*MTP_SUPPORT_SET_PROTECTION*/
540 ret = _device_delete_object(obj_handle, format);
542 case PTP_RESPONSE_OK:
543 resp = MTP_ERROR_NONE;
545 case PTP_RESPONSE_STORE_READONLY:
546 resp = MTP_ERROR_STORE_READ_ONLY;
548 case PTP_RESPONSE_PARTIAL_DELETION:
549 resp = MTP_ERROR_PARTIAL_DELETION;
551 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
552 resp = MTP_ERROR_OBJECT_WRITE_PROTECTED;
554 case PTP_RESPONSE_ACCESSDENIED:
555 resp = MTP_ERROR_ACCESS_DENIED;
557 case PTP_RESPONSE_INVALID_OBJ_HANDLE:
558 resp = MTP_ERROR_INVALID_OBJECTHANDLE;
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.
574 mtp_err_t _hutil_get_object_entry(mtp_uint32 obj_handle, mtp_obj_t **obj_ptr)
576 mtp_obj_t *obj = NULL;
578 obj = _device_get_object_with_handle(obj_handle);
579 if (NULL == obj || NULL == obj->obj_info)
580 return MTP_ERROR_GENERAL;
583 return MTP_ERROR_INVALID_PARAM;
586 return MTP_ERROR_NONE;
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)
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;
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;
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);
612 if ((src == NULL) || (dst == NULL) || (obj == NULL)) {
614 return MTP_ERROR_GENERAL;
617 /* LCOV_EXCL_START */
620 /* two sam handle can occurs in folder copy case
621 * (find last appended object in target storage)
623 par_obj = _entity_get_last_object_from_store(dst,
626 par_obj = _device_get_object_with_handle(h_parent);
631 _util_get_file_name(obj->file_path, utf8_temp);
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;
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;
648 if (!strcasecmp(fpath, obj->file_path)) {
649 ERR("Identical path of source and destination[%s]\n", fpath);
650 return MTP_ERROR_GENERAL;
653 new_obj = _entity_alloc_mtp_object();
654 if (new_obj == NULL) {
655 ERR("_entity_alloc_mtp_object Fail");
656 return MTP_ERROR_GENERAL;
659 memset(new_obj, 0, sizeof(mtp_obj_t));
660 new_obj->child_array.type = UINT32_TYPE;
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;
668 new_obj->obj_info->store_id = dst_store_id;
669 _entity_set_object_file_path(new_obj, fpath, CHAR_TYPE);
671 if (MTP_EXTERNAL_STORE_ID == new_obj->obj_info->store_id) {
672 new_obj->obj_info->protcn_status =
673 PTP_PROTECTIONSTATUS_NOPROTECTION;
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 :
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",
685 if (_util_file_copy(obj->file_path, new_obj->file_path,
687 memset(g_last_copied, 0, MTP_MAX_PATHNAME_SIZE + 1);
688 ERR("Copy file Fail");
689 _entity_dealloc_mtp_obj(new_obj);
691 return MTP_ERROR_ACCESS_DENIED;
692 else if (ENOSPC == error)
693 return MTP_ERROR_STORE_FULL;
694 return MTP_ERROR_GENERAL;
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;
706 #endif /* MTP_SUPPORT_SET_PROTECTION */
708 /* Update the storeinfo after successfully copy of the object */
709 dst->store_info.free_space -= obj->obj_info->file_size;
713 _entity_add_object_to_store(dst, new_obj);
715 _prop_copy_ptparray(&(new_obj->child_array),
716 &(obj->child_array));
718 _entity_add_object_to_store(dst, new_obj);
721 *new_hobj = new_obj->obj_handle;
722 return MTP_ERROR_NONE;
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;
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);
744 return MTP_ERROR_STORE_FULL;
745 return MTP_ERROR_GENERAL;
748 /* Add the new object to this store's object list */
749 _entity_add_object_to_store(dst, new_obj);
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);
755 ERR("But object is not registered!!");
756 return MTP_ERROR_GENERAL;
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);
768 return MTP_ERROR_STORE_FULL;
769 return MTP_ERROR_GENERAL;
772 /* Add the new object to this store's object list */
773 _entity_add_object_to_store(dst, new_obj);
776 /* Child addition to data structures is not required in Copy
777 * case as on demand enumeration is supported
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;
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);
803 *new_hobj = new_obj->obj_handle;
805 return MTP_ERROR_NONE;
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);
813 for (ii = 0; ii < child_arr.num_ele; ii++) {
814 mtp_uint32 *ptr32 = child_arr.array_entry;
816 child_obj = _entity_get_object_from_store(src, ptr32[ii]);
817 if (child_obj == NULL)
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);
830 /* Recursive copy is required when folder is not enumerated so it may
831 * return 0 child handles
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]",
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) ==
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);
851 return MTP_ERROR_STORE_FULL;
852 return MTP_ERROR_GENERAL;
855 _prop_deinit_ptparray(&child_arr);
856 *new_hobj = new_obj->obj_handle;
858 return MTP_ERROR_NONE;
862 mtp_err_t _hutil_move_object_entry(mtp_uint32 dst_store_id, mtp_uint32 h_parent,
863 mtp_uint32 obj_handle)
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;
873 mtp_err_t ret = MTP_ERROR_NONE;
875 obj = _device_get_object_with_handle(obj_handle);
877 ERR("object is [%p]\n", obj);
878 return MTP_ERROR_INVALID_OBJECTHANDLE;
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;
886 src = _device_get_store_containing_obj(obj_handle);
888 ERR("error retrieving source store");
889 return MTP_ERROR_STORE_NOT_AVAILABLE;
892 if (src->store_info.access == PTP_STORAGEACCESS_R) {
893 ERR("Store access is read only");
894 return MTP_ERROR_STORE_READ_ONLY;
897 dst = _device_get_store(dst_store_id);
899 ERR("error retrieving destination store");
900 return MTP_ERROR_STORE_NOT_AVAILABLE;
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;
908 /* Get the Parent Object Handle */
910 par_obj = _device_get_object_with_handle(h_parent);
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;
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;
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,
929 return MTP_ERROR_INVALID_PARAM;
932 par_obj = NULL; /* Parent is the root */
935 /* Check if the source store is the target store */
936 if (dst->store_id == src->store_id) {
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;
943 DBG("same storage , type[0x%x]\n",
944 obj->obj_info->association_type);
945 _util_get_file_name(obj->file_path, utf8_temp);
948 parent_path = dst->root_path;
950 parent_path = par_obj->file_path;
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;
958 /* Do a real "Move" for the object in the same store: no need to
959 * check space available
961 g_strlcpy(str_buf, obj->file_path, sizeof(str_buf));
963 if (obj->obj_info != NULL && obj->obj_info->obj_fmt ==
964 PTP_FMT_ASSOCIATION) {
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;
972 g_strlcpy(new_fpath, dst_fpath, sizeof(new_fpath));
975 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
977 if (rename(str_buf, new_fpath) < 0) {
978 /* Failed to move the object */
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);
985 return MTP_ERROR_ACCESS_DENIED;
986 else if (ENOSPC == error)
987 return MTP_ERROR_STORE_FULL;
988 return MTP_ERROR_GENERAL;
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);
996 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
998 if (FALSE == _util_file_move(str_buf, dst_fpath,
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;
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);
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);
1021 _entity_remove_reference_child_array(old_par,
1026 if (par_obj != NULL) {
1027 obj->obj_info->h_parent = par_obj->obj_handle;
1028 _entity_add_reference_child_array(par_obj,
1031 obj->obj_info->h_parent = PTP_OBJECTHANDLE_ROOT;
1034 return MTP_ERROR_NONE;
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);
1042 /* Simulate a Move operation: First copy the Object,
1043 * then remove the old object
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);
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;
1060 if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1061 _util_scan_folder_contents_in_db(new_obj->file_path);
1063 _util_add_file_to_db(new_obj->file_path);
1065 return MTP_ERROR_NONE;
1066 /* LCOV_EXCL_STOP */
1068 return MTP_ERROR_GENERAL;
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)
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;
1082 obj = _device_get_object_with_handle(obj_handle);
1084 ERR("Object not found");
1085 return MTP_ERROR_INVALID_OBJECTHANDLE;
1088 /* LCOV_EXCL_START */
1089 src = _device_get_store_containing_obj(obj_handle);
1091 ERR("Source store not found");
1092 return MTP_ERROR_STORE_NOT_AVAILABLE;
1095 dst = _device_get_store(dst_store_id);
1097 ERR("Destination store not found");
1098 return MTP_ERROR_STORE_NOT_AVAILABLE;
1101 if (dst->store_info.access != PTP_STORAGEACCESS_RWD) {
1102 ERR("Store is read only");
1103 return MTP_ERROR_STORE_READ_ONLY;
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;
1112 if (dst != _device_get_store_containing_obj(h_parent))
1113 return MTP_ERROR_INVALID_PARENT;
1115 if (dst->store_id == src->store_id) {
1116 if (_entity_check_if_B_parent_of_A(dst, h_parent,
1118 return MTP_ERROR_INVALID_PARENT;
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;
1129 if ((ret = _hutil_copy_object_entries(dst_store_id, src->store_id,
1130 h_parent, obj_handle, new_handle, FALSE)) != MTP_ERROR_NONE) {
1134 * After this command, Initiator will ask get object prop list (0x9805).
1135 * update the media DB.
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;
1143 if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1144 _util_scan_folder_contents_in_db(new_obj->file_path);
1146 _util_add_file_to_db(new_obj->file_path);
1148 return MTP_ERROR_NONE;
1150 /* LCOV_EXCL_STOP */
1152 mtp_err_t _hutil_read_file_data_from_offset(mtp_uint32 obj_handle, off_t offset,
1153 void *data, mtp_uint32 *data_sz)
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];
1160 mtp_uint32 num_bytes;
1162 obj = _device_get_object_with_handle(obj_handle);
1164 ERR("_device_get_object_with_handle returned NULL object");
1165 return MTP_ERROR_INVALID_OBJECTHANDLE;
1168 /* LCOV_EXCL_START */
1169 if (obj->obj_info->protcn_status ==
1170 MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA) {
1172 ERR("protection data, NONTRANSFERABLE_OBJECT");
1173 return MTP_ERROR_GENERAL;
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;
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;
1190 num_bytes = *data_sz;
1191 _util_file_read(h_file, data, *data_sz, data_sz);
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;
1200 _util_file_close(h_file);
1201 /* LCOV_EXCL_STOP */
1202 return MTP_ERROR_NONE;
1205 mtp_err_t _hutil_write_file_data(mtp_uint32 store_id, mtp_obj_t *obj,
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;
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;
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;
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)) {
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;
1244 #endif /*MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE*/
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);
1252 return MTP_ERROR_STORE_FULL;
1255 #ifdef MTP_SUPPORT_SET_PROTECTION
1256 if ((obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) ||
1257 (obj_info->ProtectionStatus ==
1258 MTP_PROTECTIONSTATUS_READONLY_DATA)) {
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;
1265 _util_set_file_attrs(fname, attrs.attribute |
1266 MTP_FILE_ATTR_MODE_READ_ONLY);
1268 #endif /* MTP_SUPPORT_SET_PROTECTION */
1270 _util_add_file_to_db(obj->file_path);
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;
1278 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1280 _entity_add_object_to_store(store, obj);
1281 /* LCOV_EXCL_STOP */
1282 return MTP_ERROR_NONE;
1285 mtp_err_t _hutil_get_object_entry_size(mtp_uint32 obj_handle,
1288 mtp_obj_t *obj = NULL;
1290 obj = _device_get_object_with_handle(obj_handle);
1292 ERR("_device_get_object_with_handle returned Null object");
1293 return MTP_ERROR_INVALID_OBJECTHANDLE;
1296 *obj_sz = obj->obj_info->file_size;
1297 return MTP_ERROR_NONE;
1300 #ifdef MTP_SUPPORT_SET_PROTECTION
1301 mtp_err_t _hutil_set_protection(mtp_uint32 obj_handle, mtp_uint16 prot_status)
1303 mtp_obj_t *obj = NULL;
1304 mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1305 file_attr_t attrs = { 0 };
1307 obj = _device_get_object_with_handle(obj_handle);
1309 return MTP_ERROR_INVALID_OBJECTHANDLE;
1311 if (MTP_EXTERNAL_STORE_ID == obj->obj_info->store_id) {
1312 ERR("Storage is external");
1313 return MTP_ERROR_OPERATION_NOT_SUPPORTED;
1316 g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1317 obj->obj_info->protcn_status = prot_status;
1319 if (FALSE == _util_get_file_attrs(fname, &attrs)) {
1320 ERR("Failed to get file[%s] attrs\n", fname);
1321 return MTP_ERROR_GENERAL;
1324 if (MTP_FILE_ATTR_MODE_NONE == attrs.attribute)
1325 return MTP_ERROR_GENERAL;
1327 if (prot_status == PTP_PROTECTIONSTATUS_READONLY)
1328 attrs.attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
1330 attrs.attribute &= ~MTP_FILE_ATTR_MODE_READ_ONLY;
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;
1337 return MTP_ERROR_NONE;
1339 #endif /* MTP_SUPPORT_SET_PROTECTION */
1341 mtp_err_t _hutil_get_num_objects(mtp_uint32 store_id, mtp_uint32 h_parent,
1342 mtp_uint32 format, mtp_uint32 *num_obj)
1344 mtp_store_t *store = NULL;
1345 mtp_obj_t *obj = NULL;
1347 mtp_uint32 numobj = 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;
1358 /* LCOV_EXCL_START */
1361 *num_obj = _device_get_num_objects(store_id);
1363 *num_obj = _device_get_num_objects_with_format(store_id,
1366 return MTP_ERROR_NONE;
1369 /* return the number of direct children for a particular association
1370 * (in a single store)
1372 if (h_parent == PTP_OBJECTHANDLE_ALL) {
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;
1382 numobj += _entity_get_num_children(store,
1387 return MTP_ERROR_NONE;
1390 /* Initiator wants number of children of a particular association */
1391 obj = _device_get_object_with_handle(h_parent);
1394 return MTP_ERROR_INVALID_OBJECTHANDLE;
1397 if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
1398 ERR("format is not association");
1399 return MTP_ERROR_INVALID_PARENT;
1402 store = _device_get_store_containing_obj(h_parent);
1405 if (store == NULL) {
1406 ERR("store is null");
1407 return MTP_ERROR_STORE_NOT_AVAILABLE;
1410 *num_obj = _entity_get_num_children(store, h_parent, format);
1411 return MTP_ERROR_NONE;
1413 /* LCOV_EXCL_STOP */
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)
1418 mtp_store_t *store = NULL;
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);
1427 g_is_full_enum = TRUE;
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
1435 return MTP_ERROR_NONE;
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
1443 return MTP_ERROR_NONE;
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;
1452 /* LCOV_EXCL_START */
1453 _entity_get_objects_from_store_by_format(store, format, handle_arr);
1454 return MTP_ERROR_NONE;
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;
1463 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1464 return MTP_ERROR_NONE;
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;
1473 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1474 return MTP_ERROR_NONE;
1475 /* LCOV_EXCL_STOP */
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,
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 };
1489 h_parent = _device_get_default_parent_handle();
1490 else if (h_parent == 0xFFFFFFFF)
1491 h_parent = PTP_OBJECTHANDLE_ROOT;
1493 store_id = _device_get_default_store_id();
1496 ERR("_device_get_default_store_id Fail");
1497 return MTP_ERROR_STORE_NOT_AVAILABLE;
1501 /* If the second parameter is used,
1502 * the first must also be used.
1504 return MTP_ERROR_INVALID_PARAM;
1506 h_parent = _device_get_default_parent_handle();
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));
1518 /* Delete and invalidate the old obj_info for send object */
1519 if (objdata->obj != NULL)
1520 _entity_dealloc_mtp_obj(objdata->obj);
1523 store = _device_get_store(store_id);
1524 if (store == NULL) {
1525 ERR("Store not found");
1526 return MTP_ERROR_INVALID_STORE;
1529 if (store->store_info.access == PTP_STORAGEACCESS_R) {
1530 ERR("Read only storage");
1531 return MTP_ERROR_STORE_READ_ONLY;
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;
1543 obj_info = _entity_alloc_object_info();
1544 if (obj_info == NULL) {
1545 ERR("_entity_alloc_object_info Fail");
1546 return MTP_ERROR_GENERAL;
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;
1556 obj_info->store_id = store_id;
1557 obj_info->h_parent = h_parent;
1559 switch (_hutil_add_object_entry(obj_info, file_name, &tobj)) {
1560 case MTP_ERROR_NONE:
1564 case MTP_ERROR_STORE_FULL:
1565 return MTP_ERROR_STORE_FULL;
1567 case MTP_ERROR_INVALID_OBJECTHANDLE:
1568 return MTP_ERROR_INVALID_OBJECTHANDLE;
1570 case MTP_ERROR_INVALID_PARENT:
1571 return MTP_ERROR_INVALID_PARENT;
1574 return MTP_ERROR_GENERAL;
1577 return MTP_ERROR_NONE;
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)
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;
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 };
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));
1618 _entity_dealloc_mtp_obj(obj_data->obj);
1619 /* LCOV_EXCL_STOP */
1622 store = _device_get_store(store_id);
1623 if (store == NULL) {
1624 ERR("Could not get the store");
1625 return MTP_ERROR_INVALID_STORE;
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;
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;
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;
1647 obj_info = _entity_alloc_object_info();
1648 if (obj_info == NULL) {
1649 ERR("_entity_alloc_object_info Fail");
1650 return MTP_ERROR_GENERAL;
1653 obj_info->obj_fmt = format;
1654 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1655 obj_info->association_type = PTP_ASSOCIATIONTYPE_FOLDER;
1657 obj_info->file_size = obj_sz;
1659 /* Prop value quadruple: Object Handle, PropertyCode, DataType
1660 * and DTS Prop Value (assume a byte value)
1662 temp = (mtp_uchar *) data;
1663 bytes_left = data_sz;
1664 quad_sz = sizeof(mtp_uint32) + sizeof(mtp_uint16) + sizeof(mtp_uint16) +
1666 memcpy(&num_elem, temp, sizeof(mtp_uint32));
1667 #ifdef __BIG_ENDIAN__
1668 _util_conv_byte_order(&num_elem, sizeof(mtp_uint32));
1670 temp += sizeof(mtp_uint32);
1671 bytes_left -= sizeof(mtp_uint32);
1673 /* frequent disconnect/connect make bluscreen since below process
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;
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;
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;
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;
1721 /* Verify that properties already present in parameters
1722 * don't get repeated in the list
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;
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;
1746 /* Acquire object information related data. */
1747 prop_val = _prop_alloc_obj_propval(prop_desc);
1748 if (prop_val == NULL)
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)
1756 case MTP_OBJ_PROPERTYCODE_TRACK:
1757 // TODO: find mechanism to save (integer)
1759 case MTP_OBJ_PROPERTYCODE_GENRE:
1760 // TODO: find mechanism to save (string)
1762 case MTP_OBJ_PROPERTYCODE_HEIGHT:
1763 // TODO: find mechanism to save (integer)
1765 case MTP_OBJ_PROPERTYCODE_ARTIST:
1766 // TODO: find mechanism to save (string)
1768 case MTP_OBJ_PROPERTYCODE_DURATION:
1769 // TODO: find mechanism to save (integer)
1771 case MTP_OBJ_PROPERTYCODE_COMPOSER:
1772 // TODO: find mechanism to save (string)
1774 case MTP_OBJ_PROPERTYCODE_ALBUMNAME:
1775 // TODO: find mechanism to save (string)
1777 case MTP_OBJ_PROPERTYCODE_SAMPLERATE:
1778 // TODO: find mechanism to save (integer)
1780 case MTP_OBJ_PROPERTYCODE_DATECREATED:
1781 // TODO: find mechanism to save (string)
1783 case MTP_OBJ_PROPERTYCODE_DATEMODIFIED:
1784 // TODO: find mechanism to save (string)
1786 case MTP_OBJ_PROPERTYCODE_AUDIOBITRATE:
1787 // TODO: find mechanism to save (integer)
1789 case MTP_OBJ_PROPERTYCODE_VIDEOBITRATE:
1790 // TODO: find mechanism to save (integer)
1792 case MTP_OBJ_PROPERTYCODE_OBJECTFILENAME:
1793 /* empty metadata folder problem
1796 if (prop_val->current_val.str->num_chars == 0) {
1797 g_strlcpy(file_name, MTP_UNKNOWN_METADATA, sizeof(file_name));
1799 _util_utf16_to_utf8(file_name, sizeof(file_name),
1800 prop_val->current_val.str->str);
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*/
1813 case MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE:
1814 memcpy(&obj_info->association_type, prop_val->current_val.integer,
1815 sizeof(mtp_uint16));
1818 case MTP_OBJ_PROPERTYCODE_NUMBEROFCHANNELS:
1819 // TODO: find mechanism to save (integer)
1821 case MTP_OBJ_PROPERTYCODE_FRAMESPER1KSECONDS:
1822 // TODO: find mechanism to save (integer)
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
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) {
1839 sizeof(mtp_uchar) * alb_sz + 1);
1842 (prop_val->current_val.array->array_entry),
1843 sizeof(mtp_uchar) * alb_sz);
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;
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
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");
1862 case PTP_FMT_IMG_GIF:
1863 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "gif");
1865 case PTP_FMT_IMG_PNG:
1866 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "png");
1869 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "wma");
1872 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "mpg");
1875 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "dat");
1879 ERR("sampleformatl![0x%x], extension[%s]\n", prop_code, alb_extn);
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);
1887 #endif /*MTP_SUPPORT_ALBUM_ART*/
1890 DBG("Unsupported Property [0x%x]\n", prop_code);
1894 temp += _prop_size_obj_propval(prop_val);
1895 bytes_left -= _prop_size_obj_propval(prop_val);
1896 _prop_destroy_obj_propval(prop_val);
1899 obj_info->store_id = store_id;
1900 obj_info->h_parent = h_parent;
1902 if ((resp = _hutil_add_object_entry(obj_info, file_name, &obj)) !=
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 };
1911 g_strlcpy(full_path, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
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)) {
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
1925 if (alb_buf != NULL) {
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);
1934 ERR("open album file Fail!!");
1937 ERR("no album art data");
1943 #endif /* MTP_SUPPORT_ALBUM_ART */
1946 return MTP_ERROR_NONE;
1949 #ifdef MTP_SUPPORT_ALBUM_ART
1951 #endif /* MTP_SUPPORT_ALBUM_ART */
1952 /* LCOV_EXCL_STOP */
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)
1959 obj_prop_val_t *tprop = NULL;
1960 mtp_obj_t *tobj = NULL;
1962 tobj = _device_get_object_with_handle(obj_handle);
1964 ERR("requested handle does not exist[0x%x]\n", obj_handle);
1965 return MTP_ERROR_INVALID_OBJECTHANDLE;
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));
1973 return MTP_ERROR_NONE;
1976 ERR("can not get the prop value for propcode [0x%x]\n", prop_code);
1977 return MTP_ERROR_GENERAL;
1978 /* LCOV_EXCL_STOP */
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)
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 };
1996 retv_if(NULL == buf, MTP_ERROR_INVALID_PARAM);
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;
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;
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;
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;
2023 #endif /* MTP_SUPPORT_SET_PROTECTION */
2025 if (prp_dev->propinfo.get_set == PTP_PROPGETSET_GETONLY) {
2026 ERR("property type is GETONLY");
2027 return MTP_ERROR_ACCESS_DENIED;
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;
2036 /* Set up needed object info fields */
2037 if (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFILENAME) {
2038 ptp_string_t fname = { 0 };
2040 _prop_init_ptpstring(&fname);
2041 _prop_parse_rawstring(&fname, buf, buf_sz);
2043 _util_utf16_to_utf8(temp_buf, sizeof(temp_buf),
2045 g_strlcpy(orig_fpath, obj->file_path,
2046 MTP_MAX_PATHNAME_SIZE + 1);
2047 _util_get_parent_path(orig_fpath, orig_pfpath);
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;
2054 _util_utf8_to_utf16(mov_fpath,
2055 sizeof(mov_fpath) / WCHAR_SIZ, dest_fpath);
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 };
2063 _util_get_file_extn(orig_fpath, orig_extn);
2064 _util_get_file_extn(dest_fpath, dest_extn);
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;
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;
2078 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
2080 if (FALSE == _util_file_move(orig_fpath, dest_fpath,
2082 if (EACCES == error)
2083 return MTP_ERROR_ACCESS_DENIED;
2084 return MTP_ERROR_GENERAL;
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);
2091 _util_delete_file_from_db(orig_fpath);
2092 _util_add_file_to_db(dest_fpath);
2096 /* Finally assign new handle and update full path */
2097 _entity_set_object_file_path(obj, dest_fpath,
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;
2107 DBG("File moved to [%s]\n", dest_fpath);
2109 ERR_SECURE("changed name is same with original one. [%s]\n",
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);
2117 ERR("Propert [0x%x] is GETONLY\n", prop_code);
2120 if (prop_sz != NULL)
2122 /* LCOV_EXCL_STOP */
2123 return MTP_ERROR_NONE;
2126 mtp_err_t _hutil_get_prop_desc(mtp_uint32 format, mtp_uint32 prop_code,
2129 obj_prop_desc_t *prop = NULL;
2131 prop = _prop_get_obj_prop_desc(format, prop_code);
2133 ERR("pProperty is NULL");
2134 return MTP_ERROR_GENERAL;
2137 memcpy(data, prop, sizeof(obj_prop_desc_t));
2138 return MTP_ERROR_NONE;
2141 mtp_err_t _hutil_get_object_prop_supported(mtp_uint32 format,
2142 ptp_array_t *prop_arr)
2144 _prop_get_supp_obj_props(format, prop_arr);
2145 return MTP_ERROR_NONE;
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 */
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;
2164 mtp_store_t *store = NULL;
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;
2175 /* LCOV_EXCL_STOP */
2178 if (prop_code == PTP_PROPERTY_UNDEFINED) {
2179 /* PropGroupCode should be used if Property code
2182 if (group_code == 0x0) {
2183 ERR("PropGroupCode is zero");
2184 return MTP_ERROR_INVALID_PARAM;
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;
2198 if (prop_list == NULL)
2199 return MTP_ERROR_INVALID_PARAM;
2201 _util_init_list(&(prop_list->prop_quad_list));
2202 _prop_init_ptparray(obj_arr, UINT32_TYPE);
2204 if (store != NULL) {
2205 _entity_get_objects_from_store_till_depth(store, obj_handle,
2206 format, depth, obj_arr);
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);
2215 if (obj_arr->num_ele != 0) {
2216 mtp_uint32 *obj_handles = obj_arr->array_entry;
2218 for (i = 0; i < obj_arr->num_ele; i++) {
2219 obj = _entity_get_object_from_store(store, obj_handles[i]);
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;
2232 /* LCOV_EXCL_STOP */
2235 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2236 prop_deinit_ptparray(&obj_arr);
2237 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2239 return MTP_ERROR_NONE;
2242 mtp_err_t _hutil_remove_object_reference(mtp_uint32 obj_handle,
2243 mtp_uint32 ref_handle)
2245 mtp_obj_t *obj = NULL;
2247 obj = _device_get_object_with_handle(obj_handle);
2249 ERR("No object for handle[%d]\n", obj_handle);
2250 return MTP_ERROR_NONE;
2253 if (_entity_remove_reference_child_array(obj, ref_handle) == FALSE)
2254 ERR("_entity_remove_reference_child_array Fail");
2256 return MTP_ERROR_NONE;
2259 mtp_err_t _hutil_add_object_references_enhanced(mtp_uint32 obj_handle,
2260 mtp_uchar *buffer, mtp_uint32 buf_sz)
2262 mtp_obj_t *obj = NULL;
2264 obj = _device_get_object_with_handle(obj_handle);
2266 DBG("No object for handle[0x%x]\n", obj_handle);
2267 return MTP_ERROR_NONE;
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;
2275 return MTP_ERROR_NONE;
2278 mtp_err_t _hutil_get_object_references(mtp_uint32 obj_handle,
2279 ptp_array_t *parray, mtp_uint32 *num_ele)
2281 mtp_obj_t *obj = NULL;
2282 mtp_obj_t *ref_obj = NULL;
2284 mtp_uint32 *ref_ptr = NULL;
2285 ptp_array_t ref_arr = { 0 };
2287 obj = _device_get_object_with_handle(obj_handle);
2288 if (NULL == obj || NULL == obj->obj_info) {
2290 return MTP_ERROR_INVALID_OBJECTHANDLE;
2293 /* LCOV_EXCL_START */
2294 if (parray == NULL) {
2296 return MTP_ERROR_GENERAL;
2299 if (obj->child_array.num_ele == 0) {
2301 return MTP_ERROR_NONE;
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);
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]);
2314 *num_ele = obj->child_array.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));
2321 _prop_deinit_ptparray(&ref_arr);
2322 /* LCOV_EXCL_STOP */
2323 return MTP_ERROR_NONE;
2326 mtp_err_t _hutil_get_number_of_objects(mtp_uint32 store_id, mtp_uint32 *num_obj)
2328 *num_obj = _device_get_num_objects(store_id);
2329 return MTP_ERROR_NONE;
2332 mtp_err_t _hutil_get_interdep_prop_config_list_size(mtp_uint32 *list_sz,
2335 *list_sz = _prop_get_size_interdep_proplist(&interdep_proplist,
2337 return MTP_ERROR_NONE;
2340 mtp_err_t _hutil_get_interdep_prop_config_list_data(void *data,
2341 mtp_uint32 list_sz, mtp_uint32 format)
2343 if (list_sz == _prop_pack_interdep_proplist(&interdep_proplist,
2344 format, data, list_sz)) {
2345 return MTP_ERROR_NONE;
2348 ERR("packet and requested size do not match");
2349 return MTP_ERROR_GENERAL;
2352 mtp_err_t _hutil_get_playback_skip(mtp_int32 skip_param)
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;
2364 retv_if(skip_param == 0, MTP_ERROR_INVALID_PARAM);
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;
2372 if (obj_handle == 0x0)
2373 return MTP_ERROR_NONE;
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;
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);
2389 ERR("parent not found in obj_list");
2390 return MTP_ERROR_GENERAL;
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)
2400 new_idx = idx + skip_param;
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;
2410 _prop_set_current_integer(dev_prop, 0xFFFFFFFF);
2411 _device_set_playback_obj(new_hobj);
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;
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)
2429 new_idx = idx + skip_param;
2431 _prop_set_current_integer(dev_prop, new_idx);
2432 return MTP_ERROR_NONE;
2435 return MTP_ERROR_GENERAL;
2437 /* LCOV_EXCL_STOP */
2439 mtp_err_t _hutil_format_storage(mtp_uint32 store_id, mtp_uint32 fs_format)
2441 mtp_err_t error = MTP_ERROR_GENERAL;
2442 mtp_store_t *store = NULL;
2444 store = _device_get_store(store_id);
2445 if (store == NULL) {
2446 ERR("Store is NULL");
2450 error = _entity_format_store(store, fs_format);
2451 if (error == PTP_RESPONSE_OK)
2452 return MTP_ERROR_NONE;
2454 ERR("Format store Fail");
2458 mtp_uint32 _hutil_get_storage_info_size(store_info_t *store_info)
2460 mtp_uint32 size = 0;
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));