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;
62 _entity_update_store_info_run_time(&(store->store_info),
65 _prop_copy_ptpstring(&(info->store_desc), &(store->store_info.store_desc));
66 _prop_copy_ptpstring(&(info->vol_label), &(store->store_info.vol_label));
67 info->access = store->store_info.access;
68 info->fs_type = store->store_info.fs_type;
69 info->free_space = store->store_info.free_space;
70 info->capacity = store->store_info.capacity;
71 info->store_type = store->store_info.store_type;
72 info->free_space_in_objs = store->store_info.free_space_in_objs;
73 return MTP_ERROR_NONE;
76 mtp_err_t _hutil_get_storage_ids(ptp_array_t *store_ids)
78 mtp_uint32 num_elem = 0;
79 mtp_uint32 num_stores = 0;
81 num_elem = _device_get_store_ids(store_ids);
82 num_stores = _device_get_num_stores();
83 if (num_elem == num_stores)
84 return MTP_ERROR_NONE;
86 ERR("get storage id Fail. num_elem[%d], num_stores[%d]\n",
87 num_elem, num_stores);
88 return MTP_ERROR_GENERAL;
92 * This function gets the device property.
93 * @param[in] prop_id Specifies the property id to retrieve
94 * @param[in] dev_prop Points the device prop structure
95 * @return This function returns MTP_ERROR_NONE on success,
96 * or ERROR_NO on failure.
98 mtp_err_t _hutil_get_device_property(mtp_uint32 prop_id,
99 device_prop_desc_t* dev_prop)
101 device_prop_desc_t *prop = NULL;
103 prop = _device_get_device_property(prop_id);
105 return MTP_ERROR_GENERAL;
107 memcpy(dev_prop, prop, sizeof(device_prop_desc_t));
108 return MTP_ERROR_NONE;
112 * This function sets the device property.
113 * @param[in] prop_id Specifies the property id to retrieve.
114 * @param[in] data Points the associated data buffer.
115 * @param[in] data_sz Specifies the data size of property.
116 * @return This function returns MTP_ERROR_NONE on success or
117 * appropriate error on failure.
119 mtp_err_t _hutil_set_device_property(mtp_uint32 prop_id, void *data,
122 device_prop_desc_t *prop = NULL;
124 prop = _device_get_device_property(prop_id);
126 return MTP_ERROR_GENERAL;
128 if (prop->propinfo.get_set == PTP_PROPGETSET_GETONLY)
129 return MTP_ERROR_ACCESS_DENIED;
131 if (FALSE == _prop_set_current_device_prop(prop, data, data_sz))
132 return MTP_ERROR_INVALID_OBJ_PROP_VALUE;
134 return MTP_ERROR_NONE;
138 * This function resets the device property.
139 * @param[in] prop_id Specifies the property id to retrieve.
140 * @return This function returns MTP_ERROR_NONE on success,
141 * appropriate error on failure.
143 mtp_err_t _hutil_reset_device_entry(mtp_uint32 prop_id)
145 device_prop_desc_t *prop = NULL;
148 if (prop_id == 0xFFFFFFFF) {
150 prop = _device_get_ref_prop_list();
152 ERR("property reference is NULL");
153 return MTP_ERROR_GENERAL;
155 for (ii = 0; ii < NUM_DEVICE_PROPERTIES; ii++)
156 _prop_reset_device_prop_desc(&prop[ii]);
158 prop = _device_get_device_property(prop_id);
160 return MTP_ERROR_GENERAL;
162 _prop_reset_device_prop_desc(prop);
165 return MTP_ERROR_NONE;
169 * This function adds the object entry.
170 * @param[in] obj_info Points the objectinfo.
171 * @param[in] file_name Points the file name of the object.
172 * @param[out] new_obj Points to the new object added.
173 * @return This function returns MTP_ERROR_NONE on success or
174 * appropriate error on failure.
176 mtp_err_t _hutil_add_object_entry(obj_info_t *obj_info, mtp_char *file_name,
179 mtp_obj_t *obj = NULL;
180 mtp_obj_t *par_obj = NULL;
181 mtp_store_t *store = NULL;
182 mtp_wchar temp_wfname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
183 mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
184 mtp_char new_f_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
187 mtp_bool is_made_by_mtp = FALSE;
188 mtp_wchar w_file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
190 if (obj_info->h_parent != PTP_OBJECTHANDLE_ROOT) {
191 par_obj = _device_get_object_with_handle(obj_info->h_parent);
192 if (par_obj == NULL) {
193 ERR("parent is not existed.");
194 _entity_dealloc_obj_info(obj_info);
195 return MTP_ERROR_INVALID_OBJECTHANDLE;
198 if (par_obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
199 ERR("parent handle is not association format[0x%x]\
200 handle[%d]\n", par_obj->obj_info->obj_fmt,
201 par_obj->obj_info->h_parent);
202 _entity_dealloc_obj_info(obj_info);
203 return MTP_ERROR_INVALID_PARENT;
207 store = _device_get_store(obj_info->store_id);
209 ERR("store is null");
210 _entity_dealloc_obj_info(obj_info);
211 return MTP_ERROR_GENERAL;
214 if (store->store_info.free_space < obj_info->file_size) {
215 ERR("free space is not enough [%ld] bytes, object size[%ld]\n",
216 store->store_info.free_space, obj_info->file_size);
217 _entity_dealloc_obj_info(obj_info);
218 return MTP_ERROR_STORE_FULL;
221 obj = _entity_alloc_mtp_object();
223 ERR("allocation memory Fail");
224 _entity_dealloc_obj_info(obj_info);
225 return MTP_ERROR_GENERAL;
228 memset(obj, 0, sizeof(mtp_obj_t));
229 obj->child_array.type = UINT32_TYPE;
230 obj->obj_handle = _entity_generate_next_obj_handle();
231 obj->obj_info = obj_info;
233 /* For PC->MMC read-only file/folder transfer
234 * and for PC->Phone read-only folder transfer
235 * store PTP_PROTECTIONSTATUS_NOPROTECTION in
236 * the field obj_info->ProtectionStatus
238 if (MTP_EXTERNAL_STORE_ID == obj_info->store_id ||
239 obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
240 obj_info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
243 if (strlen(file_name) == 0) {
244 /* Generate a filename in 8.3 format for this object */
245 g_snprintf(utf8_temp, MTP_MAX_PATHNAME_SIZE + 1,
246 "Tmp_%04u.dat", obj->obj_handle);
247 _util_utf8_to_utf16(temp_wfname,
248 sizeof(temp_wfname) / WCHAR_SIZ, utf8_temp);
250 _util_utf8_to_utf16(temp_wfname,
251 sizeof(temp_wfname) / WCHAR_SIZ, file_name);
254 /* Does this path/filename already exist ? */
256 mtp_bool file_exist = FALSE;
257 mtp_uint32 path_len = 0;
259 /* Get/Generate the Full Path for the new Object; */
260 if (obj_info->h_parent == PTP_OBJECTHANDLE_ROOT) {
261 _util_utf16_to_utf8(utf8_temp, sizeof(utf8_temp),
264 if (_util_create_path(new_f_path, sizeof(new_f_path),
265 store->root_path, utf8_temp) == FALSE) {
266 _entity_dealloc_mtp_obj(obj);
267 return MTP_ERROR_GENERAL;
269 #ifdef MTP_SUPPORT_HIDE_WMPINFO_XML
270 /* WMPInfo.xml and DevLogo.fil.*/
271 /* find WMPInfo.xml and add file mtp store */
273 mtp_char wmp_info_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
274 mtp_char wmp_hidden_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
276 if (obj_info->store_id == MTP_INTERNAL_STORE_ID) {
277 char inter_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
278 _util_get_internal_path(inter_path);
280 g_snprintf(wmp_hidden_path,
281 MTP_MAX_PATHNAME_SIZE + 1,
282 "%s/%s/%s", MTP_USER_DIRECTORY,
284 MTP_FILE_NAME_WMPINFO_XML);
285 g_snprintf(wmp_info_path,
286 MTP_MAX_PATHNAME_SIZE + 1,
288 MTP_FILE_NAME_WMPINFO_XML);
290 char ext_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
291 _util_get_external_path(ext_path);
293 g_snprintf(wmp_hidden_path,
294 MTP_MAX_PATHNAME_SIZE + 1,
295 "%s/%s/%s", MTP_USER_DIRECTORY,
297 MTP_FILE_NAME_WMPINFO_XML);
298 g_snprintf(wmp_info_path,
299 MTP_MAX_PATHNAME_SIZE + 1,
301 MTP_FILE_NAME_WMPINFO_XML);
304 if (!strcasecmp(wmp_info_path, new_f_path)) {
305 DBG("substitute file[%s]-->[%s]\n",
306 wmp_info_path, wmp_hidden_path);
308 g_strlcpy(new_f_path, wmp_hidden_path,
311 if (obj_info->store_id ==
312 MTP_INTERNAL_STORE_ID) {
314 MTP_MAX_INT_OBJECT_NUM -
315 MTPSTORE_WMPINFO_PHONE;
318 MTP_MAX_INT_OBJECT_NUM -
319 MTPSTORE_WMPINFO_CARD;
323 #endif /*MTP_SUPPORT_HIDE_WMPINFO_XML*/
325 _util_utf16_to_utf8(utf8_temp, sizeof(utf8_temp),
327 if (_util_create_path(new_f_path, sizeof(new_f_path),
328 par_obj->file_path, utf8_temp) == FALSE) {
329 _entity_dealloc_mtp_obj(obj);
330 return MTP_ERROR_GENERAL;
335 * g_mgr->ftemp_st.filepath was allocated g_strdup("/tmp/.mtptemp.tmp");
336 * So if we need to change the path we need to allocate sufficient memory
337 * otherwise memory corruption may happen
340 path_len = strlen(store->root_path) + strlen(MTP_TEMP_FILE) + 2;
341 g_mgr->ftemp_st.filepath = g_realloc(g_mgr->ftemp_st.filepath, path_len);
342 if (g_mgr->ftemp_st.filepath == NULL) {
343 ERR("g_realloc Fail");
344 _entity_dealloc_mtp_obj(obj);
345 return MTP_ERROR_GENERAL;
348 if (_util_create_path(g_mgr->ftemp_st.filepath, path_len,
349 store->root_path, MTP_TEMP_FILE) == FALSE) {
350 ERR("Tempfile fullPath is too long");
351 _entity_dealloc_mtp_obj(obj);
352 return MTP_ERROR_GENERAL;
355 DBG_SECURE("Temp file path [%s]\n", g_mgr->ftemp_st.filepath);
358 #ifdef MTP_SUPPORT_ALBUM_ART
359 if (access(new_f_path, F_OK) == 0) {
361 /* if file is album, overwrite it. */
362 mtp_char alb_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
363 mtp_char alb_ext[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
365 /* find extension, if album or pla, overwrite that. */
366 _util_utf16_to_utf8(alb_buf, sizeof(alb_buf), temp_wfname);
368 if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
369 (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
370 obj_info->association_type !=
371 PTP_ASSOCIATIONTYPE_UNDEFINED &&
372 obj_info->association_type !=
373 PTP_ASSOCIATIONTYPE_FOLDER)) {
375 _util_get_file_extn(alb_buf, alb_ext);
376 if (!strcasecmp(alb_ext, "alb")) {
377 if (remove(new_f_path) == 0) {
379 DBG("[%s] file is found. Delete\
380 old and make new one\n",
383 ERR("[%s] file is found. but \
389 #endif /*MTP_SUPPORT_ALBUM_ART*/
391 if (file_exist == FALSE) {
392 DBG_SECURE("Found a unique file name for the incoming object\
393 [%s]\n", temp_wfname);
397 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
398 is_made_by_mtp = obj_info->file_size == 0 &&
399 obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
400 obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC;
401 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
402 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION ||
404 *new_obj = _device_get_object_with_path(new_f_path);
406 _entity_dealloc_mtp_obj(obj);
407 return MTP_ERROR_NONE;
409 DBG("+ not found object. [%s]\n", new_f_path);
414 /* Rename the Filename for this object */
415 memset(temp_wfname, 0, (MTP_MAX_PATHNAME_SIZE + 1) * 2);
416 _util_utf8_to_utf16(w_file_name, sizeof(w_file_name) / WCHAR_SIZ,
418 _util_wchar_swprintf(temp_wfname,
419 MTP_MAX_PATHNAME_SIZE + 1, "COPY%d_%s", i, w_file_name);
422 /* Save the full path to this object */
423 _entity_set_object_file_path(obj, new_f_path, CHAR_TYPE);
426 * Is this an association (or folder)?
427 * Associations are fully qualified by the ObjectInfo Dataset.
429 #ifdef MTP_USE_SELFMAKE_ABSTRACTION
430 is_made_by_mtp = (obj_info->file_size == 0 &&
431 obj_info->obj_fmt > MTP_FMT_UNDEFINED_COLLECTION &&
432 obj_info->obj_fmt < MTP_FMT_UNDEFINED_DOC);
433 #endif /*MTP_USE_SELFMAKE_ABSTRACTION*/
435 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION || is_made_by_mtp) {
436 /* Create the new object */
437 DBG("[normal] create association file/folder[%s][0x%x]\n",
438 new_f_path, obj_info->association_type);
440 if ((obj_info->association_type !=
441 PTP_ASSOCIATIONTYPE_UNDEFINED &&
442 obj_info->association_type !=
443 PTP_ASSOCIATIONTYPE_FOLDER) ||
445 FILE* h_abs_file = NULL;
446 h_abs_file = _util_file_open(new_f_path,
447 MTP_FILE_WRITE, &error);
448 if (h_abs_file == NULL) {
449 ERR("create file fail!!");
450 _entity_dealloc_mtp_obj(obj);
451 return MTP_ERROR_GENERAL;
453 _util_file_close(h_abs_file);
455 g_snprintf(g_last_created_dir,
456 MTP_MAX_PATHNAME_SIZE + 1, "%s", new_f_path);
457 if (_util_dir_create(new_f_path, &error) == FALSE) {
458 /* We failed to create the folder */
459 ERR("create directory Fail");
460 memset(g_last_created_dir, 0,
461 sizeof(g_last_created_dir));
462 _entity_dealloc_mtp_obj(obj);
463 return MTP_ERROR_GENERAL;
467 _entity_set_object_file_path(obj, new_f_path, CHAR_TYPE);
468 if (_entity_add_object_to_store(store, obj) == FALSE) {
469 ERR("_entity_add_object_to_store Fail");
470 _entity_dealloc_mtp_obj(obj);
471 return MTP_ERROR_STORE_FULL;
474 /* Reserve space for the object: Object itself, and probably
475 * some Filesystem-specific overhead
477 store->store_info.free_space -= obj_info->file_size;
482 return MTP_ERROR_NONE;
486 * This function removes the object entry.
487 * @param[in] obj_handle Specifies the object to remove.
488 * @param[in] format Specifies the format code.
489 * @return This function returns MTP_ERROR_NONE on success or
490 * appropriate error on failure.
492 mtp_err_t _hutil_remove_object_entry(mtp_uint32 obj_handle, mtp_uint32 format)
494 mtp_err_t resp = MTP_ERROR_GENERAL;
497 #ifdef MTP_SUPPORT_SET_PROTECTION
498 /* this will check to see if the protection is set */
499 mtp_obj_t *obj = NULL;
500 if (obj_handle != 0xFFFFFFFF) {
501 obj = _device_get_object_with_handle(obj_handle);
503 if ((obj->obj_info->protcn_status ==
504 MTP_PROTECTIONSTATUS_READONLY_DATA) ||
505 (obj->obj_info->protcn_status ==
506 PTP_PROTECTIONSTATUS_READONLY)) {
507 ERR("Protection status is [0x%x]\n",
508 obj->obj_info->protcn_status);
509 return MTP_ERROR_OBJECT_WRITE_PROTECTED;
513 #endif /*MTP_SUPPORT_SET_PROTECTION*/
515 ret = _device_delete_object(obj_handle, format);
517 case PTP_RESPONSE_OK:
518 resp = MTP_ERROR_NONE;
520 case PTP_RESPONSE_STORE_READONLY:
521 resp = MTP_ERROR_STORE_READ_ONLY;
523 case PTP_RESPONSE_PARTIAL_DELETION:
524 resp = MTP_ERROR_PARTIAL_DELETION;
526 case PTP_RESPONSE_OBJ_WRITEPROTECTED:
527 resp = MTP_ERROR_OBJECT_WRITE_PROTECTED;
529 case PTP_RESPONSE_ACCESSDENIED:
530 resp = MTP_ERROR_ACCESS_DENIED;
532 case PTP_RESPONSE_INVALID_OBJ_HANDLE:
533 resp = MTP_ERROR_INVALID_OBJECTHANDLE;
543 * This function gets the object entry.
544 * @param[in] obj_handle Specifies the object to get.
545 * @param[out] obj_ptr Points to object found.
546 * @return This function returns MTP_ERROR_NONE on success
547 * or appropriate error on failure.
549 mtp_err_t _hutil_get_object_entry(mtp_uint32 obj_handle, mtp_obj_t **obj_ptr)
551 mtp_obj_t *obj = NULL;
553 obj = _device_get_object_with_handle(obj_handle);
554 if (NULL == obj || NULL == obj->obj_info)
555 return MTP_ERROR_GENERAL;
558 return MTP_ERROR_NONE;
561 mtp_err_t _hutil_copy_object_entries(mtp_uint32 dst_store_id,
562 mtp_uint32 src_store_id, mtp_uint32 h_parent, mtp_uint32 obj_handle,
563 mtp_uint32 *new_hobj, mtp_bool keep_handle)
565 mtp_store_t *dst = NULL;
566 mtp_store_t *src = NULL;
567 mtp_obj_t *obj = NULL;
568 mtp_obj_t *par_obj = NULL;
569 mtp_obj_t *new_obj = NULL;
571 mtp_char fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
572 mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
573 mtp_err_t ret = MTP_ERROR_NONE;
574 mtp_uint32 num_of_deleted_file = 0;
575 mtp_uint32 num_of_file = 0;
576 ptp_array_t child_arr = { 0 };
577 mtp_obj_t *child_obj = NULL;
580 src = _device_get_store(src_store_id);
581 dst = _device_get_store(dst_store_id);
582 obj = _device_get_object_with_handle(obj_handle);
584 if ((src == NULL) || (dst == NULL) || (obj == NULL)) {
586 return MTP_ERROR_GENERAL;
591 /* two sam handle can occurs in folder copy case
592 * (find last appended object in target storage)
594 par_obj = _entity_get_last_object_from_store(dst,
597 par_obj = _device_get_object_with_handle(h_parent);
602 _util_get_file_name(obj->file_path, utf8_temp);
604 if (par_obj == NULL) {
605 /* Parent is the root of this store */
606 if (_util_create_path(fpath, sizeof(fpath), dst->root_path,
607 utf8_temp) == FALSE) {
608 ERR("new path is too LONG");
609 return MTP_ERROR_GENERAL;
612 if (_util_create_path(fpath, sizeof(fpath), par_obj->file_path,
613 utf8_temp) == FALSE) {
614 ERR("New path is too LONG!!");
615 return MTP_ERROR_GENERAL;
619 if (!strcasecmp(fpath, obj->file_path)) {
620 ERR("Identical path of source and destination[%s]\n", fpath);
621 return MTP_ERROR_GENERAL;
624 new_obj = _entity_alloc_mtp_object();
625 if (new_obj == NULL) {
626 ERR("_entity_alloc_mtp_object Fail");
627 return MTP_ERROR_GENERAL;
630 memset(new_obj, 0, sizeof(mtp_obj_t));
631 new_obj->child_array.type = UINT32_TYPE;
633 _entity_copy_mtp_object(new_obj, obj);
634 if (new_obj->obj_info == NULL) {
635 _entity_dealloc_mtp_obj(new_obj);
636 return MTP_ERROR_GENERAL;
639 new_obj->obj_info->store_id = dst_store_id;
640 _entity_set_object_file_path(new_obj, fpath, CHAR_TYPE);
642 if (MTP_EXTERNAL_STORE_ID == new_obj->obj_info->store_id) {
643 new_obj->obj_info->protcn_status =
644 PTP_PROTECTIONSTATUS_NOPROTECTION;
647 new_obj->obj_handle = (keep_handle) ? obj->obj_handle :
648 _entity_generate_next_obj_handle();
649 new_obj->obj_info->h_parent = (par_obj == NULL) ? PTP_OBJECTHANDLE_ROOT :
652 if (new_obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
653 DBG("Non-association type!!");
654 g_snprintf(g_last_copied, MTP_MAX_PATHNAME_SIZE + 1, "%s",
656 if (_util_file_copy(obj->file_path, new_obj->file_path,
658 memset(g_last_copied, 0, MTP_MAX_PATHNAME_SIZE + 1);
659 ERR("Copy file Fail");
660 _entity_dealloc_mtp_obj(new_obj);
662 return MTP_ERROR_ACCESS_DENIED;
663 else if (ENOSPC == error)
664 return MTP_ERROR_STORE_FULL;
665 return MTP_ERROR_GENERAL;
668 #ifdef MTP_SUPPORT_SET_PROTECTION
669 file_attr_t attr = { 0 };
670 attr.attribute = MTP_FILE_ATTR_MODE_REG;
671 if (PTP_PROTECTIONSTATUS_READONLY ==
672 new_obj->obj_info->protcn_status) {
673 if (FALSE == _util_set_file_attrs(new_obj->file_path,
674 attr.attribute | MTP_FILE_ATTR_MODE_READ_ONLY))
675 return MTP_ERROR_GENERAL;
677 #endif /* MTP_SUPPORT_SET_PROTECTION */
679 /* Update the storeinfo after successfully copy of the object */
680 dst->store_info.free_space -= obj->obj_info->file_size;
684 _entity_add_object_to_store(dst, new_obj);
686 _prop_copy_ptparray(&(new_obj->child_array),
687 &(obj->child_array));
689 _entity_add_object_to_store(dst, new_obj);
692 *new_hobj = new_obj->obj_handle;
693 return MTP_ERROR_NONE;
696 DBG("Association type!!");
697 if (access(new_obj->file_path, F_OK) == 0) {
698 if (TRUE == keep_handle) {
699 /*generate unique_path*/
700 mtp_char unique_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
701 if (FALSE == _util_get_unique_dir_path(new_obj->file_path,
702 unique_fpath, sizeof(unique_fpath))) {
703 _entity_dealloc_mtp_obj(new_obj);
704 return MTP_ERROR_GENERAL;
706 _entity_set_object_file_path(new_obj, unique_fpath, CHAR_TYPE);
707 g_snprintf(g_last_created_dir, MTP_MAX_PATHNAME_SIZE + 1,
708 "%s", new_obj->file_path);
709 if (_util_dir_create(new_obj->file_path, &error) == FALSE) {
710 memset(g_last_created_dir, 0,
711 MTP_MAX_PATHNAME_SIZE + 1);
712 ERR("Creating folder Fail!!");
713 _entity_dealloc_mtp_obj(new_obj);
715 return MTP_ERROR_STORE_FULL;
716 return MTP_ERROR_GENERAL;
719 /* Add the new object to this store's object list */
720 _entity_add_object_to_store(dst, new_obj);
722 DBG("Already existed association type!!");
723 _entity_dealloc_mtp_obj(new_obj);
724 new_obj = _entity_get_object_from_store_by_path(dst, fpath);
726 ERR("But object is not registered!!");
727 return MTP_ERROR_GENERAL;
731 g_snprintf(g_last_created_dir, MTP_MAX_PATHNAME_SIZE + 1,
732 "%s", new_obj->file_path);
733 if (_util_dir_create(new_obj->file_path, &error) == FALSE) {
734 memset(g_last_created_dir, 0,
735 MTP_MAX_PATHNAME_SIZE + 1);
736 ERR("Creating folder Fail!!");
737 _entity_dealloc_mtp_obj(new_obj);
739 return MTP_ERROR_STORE_FULL;
740 return MTP_ERROR_GENERAL;
743 /* Add the new object to this store's object list */
744 _entity_add_object_to_store(dst, new_obj);
747 /* Child addition to data structures is not required in Copy
748 * case as on demand enumeration is supported
750 if (FALSE == keep_handle) {
751 if (FALSE == _util_copy_dir_children_recursive(obj->file_path,
752 new_obj->file_path, &error)) {
753 ERR_SECURE("Recursive copy Fail [%s]->[%s]",
754 obj->file_path, new_obj->file_path);
755 ret = MTP_ERROR_GENERAL;
757 ret = MTP_ERROR_ACCESS_DENIED;
758 else if (ENOSPC == error)
759 ret = MTP_ERROR_STORE_FULL;
760 if (_util_remove_dir_children_recursive(new_obj->file_path,
761 &num_of_deleted_file, &num_of_file,
762 FALSE) == MTP_ERROR_NONE) {
763 g_snprintf(g_last_deleted,
764 MTP_MAX_PATHNAME_SIZE + 1,
765 "%s", new_obj->file_path);
766 if (rmdir(new_obj->file_path) < 0) {
767 memset(g_last_deleted, 0,
768 MTP_MAX_PATHNAME_SIZE + 1);
774 *new_hobj = new_obj->obj_handle;
776 return MTP_ERROR_NONE;
780 /* Since this is an association, copy its children as well*/
781 _prop_init_ptparray(&child_arr, UINT32_TYPE);
782 _entity_get_child_handles(src, obj->obj_handle, &child_arr);
784 for (ii = 0; ii < child_arr.num_ele; ii++) {
785 mtp_uint32 *ptr32 = child_arr.array_entry;
787 child_obj = _entity_get_object_from_store(src, ptr32[ii]);
788 if (child_obj == NULL)
791 ret = _hutil_copy_object_entries(dst_store_id, src_store_id,
792 new_obj->obj_handle, child_obj->obj_handle,
793 new_hobj, keep_handle);
794 if (ret != MTP_ERROR_NONE) {
795 ERR("Copy file Fail");
796 _prop_deinit_ptparray(&child_arr);
801 /* Recursive copy is required when folder is not enumerated so it may
802 * return 0 child handles
804 if (!((child_arr.num_ele > 0) ||
805 _util_copy_dir_children_recursive(obj->file_path,
806 new_obj->file_path, &error))) {
807 ERR_SECURE("Recursive copy Fail [%d], [%s]->[%s]",
809 obj->file_path, new_obj->file_path);
810 _prop_deinit_ptparray(&child_arr);
811 if (_util_remove_dir_children_recursive(new_obj->file_path,
812 &num_of_deleted_file, &num_of_file, FALSE) ==
814 g_snprintf(g_last_deleted, MTP_MAX_PATHNAME_SIZE + 1,
815 "%s", new_obj->file_path);
816 if (rmdir(new_obj->file_path) < 0) {
817 memset(g_last_deleted, 0,
818 MTP_MAX_PATHNAME_SIZE + 1);
822 return MTP_ERROR_STORE_FULL;
823 return MTP_ERROR_GENERAL;
826 _prop_deinit_ptparray(&child_arr);
827 *new_hobj = new_obj->obj_handle;
829 return MTP_ERROR_NONE;
832 mtp_err_t _hutil_move_object_entry(mtp_uint32 dst_store_id, mtp_uint32 h_parent,
833 mtp_uint32 obj_handle)
835 mtp_store_t *src = NULL;
836 mtp_store_t *dst = NULL;
837 mtp_obj_t *obj = NULL;
838 mtp_obj_t *par_obj = NULL;
839 mtp_char str_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
840 mtp_char utf8_temp[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
841 mtp_uint32 new_handle = 0;
843 mtp_err_t ret = MTP_ERROR_NONE;
845 obj = _device_get_object_with_handle(obj_handle);
847 ERR("object is [%p]\n", obj);
848 return MTP_ERROR_INVALID_OBJECTHANDLE;
850 if (NULL == obj->obj_info) {
851 ERR("obj_info is [%p]\n", obj->obj_info);
852 return MTP_ERROR_GENERAL;
855 src = _device_get_store_containing_obj(obj_handle);
857 ERR("error retrieving source store");
858 return MTP_ERROR_STORE_NOT_AVAILABLE;
861 if (src->store_info.access == PTP_STORAGEACCESS_R) {
862 ERR("Store access is read only");
863 return MTP_ERROR_STORE_READ_ONLY;
866 dst = _device_get_store(dst_store_id);
868 ERR("error retrieving destination store");
869 return MTP_ERROR_STORE_NOT_AVAILABLE;
872 if (dst->store_info.access != PTP_STORAGEACCESS_RWD) {
873 ERR("Write permission not there on target store");
874 return MTP_ERROR_STORE_READ_ONLY;
877 /* Get the Parent Object Handle */
879 par_obj = _device_get_object_with_handle(h_parent);
881 if (par_obj == NULL || par_obj->obj_info == NULL) {
882 ERR("par_obj[%p] or par_obj->obj_info is NULL\n", par_obj);
883 return MTP_ERROR_INVALID_PARENT;
884 } else if (PTP_FMT_ASSOCIATION != par_obj->obj_info->obj_fmt) {
885 ERR("par obj fmt = [0x%x]\n", par_obj->obj_info->obj_fmt);
886 return MTP_ERROR_INVALID_PARENT;
889 if (dst != _device_get_store_containing_obj(h_parent)) {
890 ERR("parent is not on the destination store");
891 return MTP_ERROR_INVALID_PARENT;
894 /* Parent must not be a descendant of the object to be moved */
895 if (dst->store_id == src->store_id) {
896 if (_entity_check_if_B_parent_of_A(dst, h_parent,
898 return MTP_ERROR_INVALID_PARAM;
901 par_obj = NULL; /* Parent is the root */
904 /* Check if the source store is the target store */
905 if (dst->store_id == src->store_id) {
907 mtp_obj_t *old_par = NULL;
908 mtp_char new_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
909 mtp_char dst_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
910 mtp_char *parent_path = NULL;
912 DBG("same storage , type[0x%x]\n",
913 obj->obj_info->association_type);
914 _util_get_file_name(obj->file_path, utf8_temp);
917 parent_path = dst->root_path;
919 parent_path = par_obj->file_path;
921 if (_util_create_path(dst_fpath, sizeof(dst_fpath), parent_path,
922 utf8_temp) == FALSE) {
923 ERR("dst path is too LONG!!");
924 return MTP_ERROR_GENERAL;
927 /* Do a real "Move" for the object in the same store: no need to
928 * check space available
930 g_strlcpy(str_buf, obj->file_path, sizeof(str_buf));
932 if (obj->obj_info != NULL && obj->obj_info->obj_fmt ==
933 PTP_FMT_ASSOCIATION) {
935 if (access(dst_fpath, F_OK) == 0) {
936 if (FALSE == _util_get_unique_dir_path(dst_fpath,
937 new_fpath, sizeof(new_fpath))) {
938 return MTP_ERROR_GENERAL;
941 g_strlcpy(new_fpath, dst_fpath, sizeof(new_fpath));
944 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
946 if (rename(str_buf, new_fpath) < 0) {
947 /* Failed to move the object */
949 memset(g_last_moved, 0,
950 MTP_MAX_PATHNAME_SIZE + 1);
951 ERR_SECURE("Directory rename fail in same storage\
952 [%s]->[%s]\n", str_buf, new_fpath);
954 return MTP_ERROR_ACCESS_DENIED;
955 else if (ENOSPC == error)
956 return MTP_ERROR_STORE_FULL;
957 return MTP_ERROR_GENERAL;
960 _util_scan_folder_contents_in_db(str_buf);
961 _entity_set_object_file_path(obj, new_fpath, CHAR_TYPE);
962 _entity_set_child_object_path(obj, str_buf, new_fpath);
963 _util_scan_folder_contents_in_db(new_fpath);
965 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
967 if (FALSE == _util_file_move(str_buf, dst_fpath,
969 /* Failed to move the object */
970 memset(g_last_moved, 0,
971 MTP_MAX_PATHNAME_SIZE + 1);
972 ERR("move file Fail in same storage\
973 [%s]->[%s]\n", str_buf, dst_fpath);
975 return MTP_ERROR_ACCESS_DENIED;
976 else if (ENOSPC == error)
977 return MTP_ERROR_STORE_FULL;
978 return MTP_ERROR_GENERAL;
981 _util_delete_file_from_db(obj->file_path);
982 _entity_set_object_file_path(obj, dst_fpath, CHAR_TYPE);
983 _util_add_file_to_db(obj->file_path);
986 if (obj->obj_info->h_parent != PTP_OBJECTHANDLE_ROOT) {
987 old_par = _entity_get_object_from_store(src,
988 obj->obj_info->h_parent);
990 _entity_remove_reference_child_array(old_par,
995 if (par_obj != NULL) {
996 obj->obj_info->h_parent = par_obj->obj_handle;
997 _entity_add_reference_child_array(par_obj,
1000 obj->obj_info->h_parent = PTP_OBJECTHANDLE_ROOT;
1003 return MTP_ERROR_NONE;
1005 /* Move is called between two stores */
1006 /* Calculate the space required for the new object(s) */
1007 mtp_obj_t *new_obj = NULL;
1008 DBG("Different storage or a folder, type[0x%x]\n",
1009 obj->obj_info->association_type);
1011 /* Simulate a Move operation: First copy the Object,
1012 * then remove the old object
1014 ret = _hutil_copy_object_entries(dst->store_id, src->store_id,
1015 (par_obj == NULL) ? 0 : (par_obj->obj_handle),
1016 obj->obj_handle, &new_handle, TRUE);
1017 if (ret != MTP_ERROR_NONE) {
1018 _entity_delete_obj_mtp_store(dst, obj->obj_handle,
1019 PTP_FORMATCODE_NOTUSED, FALSE);
1023 _entity_delete_obj_mtp_store(src, obj->obj_handle,
1024 PTP_FORMATCODE_NOTUSED, FALSE);
1025 new_obj = _device_get_object_with_handle(new_handle);
1026 if (NULL == new_obj || NULL == new_obj->obj_info)
1027 return MTP_ERROR_GENERAL;
1029 if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1030 _util_scan_folder_contents_in_db(new_obj->file_path);
1032 _util_add_file_to_db(new_obj->file_path);
1034 return MTP_ERROR_NONE;
1036 return MTP_ERROR_GENERAL;
1039 mtp_err_t _hutil_duplicate_object_entry(mtp_uint32 dst_store_id,
1040 mtp_uint32 h_parent, mtp_uint32 obj_handle, mtp_uint32 *new_handle)
1042 mtp_store_t *src = NULL;
1043 mtp_store_t *dst = NULL;
1044 mtp_obj_t *obj = NULL;
1045 mtp_obj_t *par_obj = NULL;
1046 mtp_obj_t *new_obj = NULL;
1047 mtp_uint32 space_req = 0;
1048 mtp_err_t ret = MTP_ERROR_NONE;
1050 obj = _device_get_object_with_handle(obj_handle);
1052 ERR("Object not found");
1053 return MTP_ERROR_INVALID_OBJECTHANDLE;
1056 src = _device_get_store_containing_obj(obj_handle);
1058 ERR("Source store not found");
1059 return MTP_ERROR_STORE_NOT_AVAILABLE;
1062 dst = _device_get_store(dst_store_id);
1064 ERR("Destination store not found");
1065 return MTP_ERROR_STORE_NOT_AVAILABLE;
1068 if (dst->store_info.access != PTP_STORAGEACCESS_RWD) {
1069 ERR("Store is read only");
1070 return MTP_ERROR_STORE_READ_ONLY;
1074 par_obj = _device_get_object_with_handle(h_parent);
1075 if ((par_obj == NULL) || (par_obj->obj_info->obj_fmt !=
1076 PTP_FMT_ASSOCIATION))
1077 return MTP_ERROR_INVALID_PARENT;
1079 if (dst != _device_get_store_containing_obj(h_parent))
1080 return MTP_ERROR_INVALID_PARENT;
1082 if (dst->store_id == src->store_id) {
1083 if (_entity_check_if_B_parent_of_A(dst, h_parent,
1085 return MTP_ERROR_INVALID_PARENT;
1090 space_req = _entity_get_object_tree_size(src, obj);
1091 if (dst->store_info.free_space < space_req) {
1092 ERR("Insufficient free space");
1093 return MTP_ERROR_STORE_FULL;
1096 if ((ret = _hutil_copy_object_entries(dst_store_id, src->store_id,
1097 h_parent, obj_handle, new_handle, FALSE)) != MTP_ERROR_NONE) {
1101 * After this command, Initiator will ask get object prop list (0x9805).
1102 * update the media DB.
1104 new_obj = _device_get_object_with_handle(*new_handle);
1105 if (NULL == new_obj || NULL == new_obj->obj_info) {
1106 ERR("new obj or info is NULL");
1107 return MTP_ERROR_GENERAL;
1110 if (new_obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1111 _util_scan_folder_contents_in_db(new_obj->file_path);
1113 _util_add_file_to_db(new_obj->file_path);
1115 return MTP_ERROR_NONE;
1118 mtp_err_t _hutil_read_file_data_from_offset(mtp_uint32 obj_handle, off_t offset,
1119 void *data, mtp_uint32 *data_sz)
1121 mtp_obj_t *obj = NULL;
1122 FILE* h_file = NULL;
1123 mtp_int32 error = 0;
1124 mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1];
1126 mtp_uint32 num_bytes;
1128 obj = _device_get_object_with_handle(obj_handle);
1130 ERR("_device_get_object_with_handle returned NULL object");
1131 return MTP_ERROR_INVALID_OBJECTHANDLE;
1134 if (obj->obj_info->protcn_status ==
1135 MTP_PROTECTIONSTATUS_NONTRANSFERABLE_DATA) {
1137 ERR("protection data, NONTRANSFERABLE_OBJECT");
1138 return MTP_ERROR_GENERAL;
1141 g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1142 h_file = _util_file_open(fname, MTP_FILE_READ, &error);
1143 if (h_file == NULL) {
1144 ERR("file open Fail[%s]\n", fname);
1145 return MTP_ERROR_GENERAL;
1148 result = _util_file_seek(h_file, offset, SEEK_SET);
1149 if (result == FALSE) {
1150 ERR("file seek Fail [%d]\n", errno);
1151 _util_file_close(h_file);
1152 return MTP_ERROR_GENERAL;
1155 num_bytes = *data_sz;
1156 _util_file_read(h_file, data, *data_sz, data_sz);
1158 if (num_bytes != *data_sz) {
1159 ERR("requested[%d] and read[%d] number of bytes do not match\n",
1160 *data_sz, num_bytes);
1161 _util_file_close(h_file);
1162 return MTP_ERROR_GENERAL;
1165 _util_file_close(h_file);
1166 return MTP_ERROR_NONE;
1169 mtp_err_t _hutil_write_file_data(mtp_uint32 store_id, mtp_obj_t *obj,
1173 mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1174 #ifdef MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE
1175 mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1176 #endif /*MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE*/
1177 mtp_int32 error = 0;
1179 retv_if(obj == NULL, MTP_ERROR_INVALID_PARAM);
1180 retv_if(obj->obj_info == NULL, MTP_ERROR_INVALID_PARAM);
1182 store = _device_get_store(store_id);
1183 if (store == NULL) {
1184 ERR("destination store is not valid");
1185 return MTP_ERROR_INVALID_OBJECT_INFO;
1188 g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1189 if (access(fpath, F_OK) < 0) {
1190 ERR("temp file does not exist");
1191 return MTP_ERROR_GENERAL;
1194 #ifdef MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE
1195 /* in case of alb extension, does not make real file just skip below */
1196 if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
1197 (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
1198 obj_info->association_type != PTP_ASSOCIATIONTYPE_UNDEFINED &&
1199 obj_info->association_type != PTP_ASSOCIATIONTYPE_FOLDER)) {
1201 _util_get_file_extn(fname, extn);
1202 if (strlen(extn) && !strcasecmp(extn, "alb")) {
1203 DBG("No need to create album file");
1204 remove(fpath, &error);
1205 return MTP_ERROR_NONE;
1208 #endif /*MTP_SUPPORT_DELETE_MEDIA_ALBUM_FILE*/
1210 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1, "%s", fpath);
1211 if (FALSE == _util_file_move(fpath, fname, &error)) {
1212 memset(g_last_moved, 0, MTP_MAX_PATHNAME_SIZE + 1);
1213 ERR("move to real file fail [%s]->[%s] \n", fpath, fname);
1214 _entity_dealloc_mtp_obj(obj);
1216 return MTP_ERROR_STORE_FULL;
1219 #ifdef MTP_SUPPORT_SET_PROTECTION
1220 if ((obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) ||
1221 (obj_info->ProtectionStatus ==
1222 MTP_PROTECTIONSTATUS_READONLY_DATA)) {
1224 if (_util_get_file_attrs(fname, &attrs) == FALSE) {
1225 ERR("real file get attributes Fail");
1226 _entity_dealloc_mtp_obj(obj);
1227 return MTP_ERROR_GENERAL;
1229 _util_set_file_attrs(fname, attrs.attribute |
1230 MTP_FILE_ATTR_MODE_READ_ONLY);
1232 #endif /* MTP_SUPPORT_SET_PROTECTION */
1234 _util_add_file_to_db(obj->file_path);
1236 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
1237 if (updatePropertyValuesMtpObject(obj) == FALSE) {
1238 ERR("update property values mtp obj Fail");
1239 _entity_dealloc_mtp_obj(obj);
1240 return MTP_ERROR_GENERAL;
1242 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
1244 _entity_add_object_to_store(store, obj);
1246 return MTP_ERROR_NONE;
1249 mtp_err_t _hutil_get_object_entry_size(mtp_uint32 obj_handle,
1252 mtp_obj_t *obj = NULL;
1254 obj = _device_get_object_with_handle(obj_handle);
1256 ERR("_device_get_object_with_handle returned Null object");
1257 return MTP_ERROR_INVALID_OBJECTHANDLE;
1260 *obj_sz = obj->obj_info->file_size;
1261 return MTP_ERROR_NONE;
1264 #ifdef MTP_SUPPORT_SET_PROTECTION
1265 mtp_err_t _hutil_set_protection(mtp_uint32 obj_handle, mtp_uint16 prot_status)
1267 mtp_obj_t *obj = NULL;
1268 mtp_char fname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1269 file_attr_t attrs = { 0 };
1271 obj = _device_get_object_with_handle(obj_handle);
1273 return MTP_ERROR_INVALID_OBJECTHANDLE;
1275 if (MTP_EXTERNAL_STORE_ID == obj->obj_info->store_id) {
1276 ERR("Storage is external");
1277 return MTP_ERROR_OPERATION_NOT_SUPPORTED;
1280 g_strlcpy(fname, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1281 obj->obj_info->protcn_status = prot_status;
1283 if (FALSE == _util_get_file_attrs(fname, &attrs)) {
1284 ERR("Failed to get file[%s] attrs\n", fname);
1285 return MTP_ERROR_GENERAL;
1288 if (MTP_FILE_ATTR_MODE_NONE == attrs.attribute)
1289 return MTP_ERROR_GENERAL;
1291 if (prot_status == PTP_PROTECTIONSTATUS_READONLY)
1292 attrs.attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
1294 attrs.attribute &= ~MTP_FILE_ATTR_MODE_READ_ONLY;
1296 if (FALSE == _util_set_file_attrs(fname, attrs.attribute)) {
1297 ERR("Failed to set file[%s] attrs\n", fname);
1298 return MTP_ERROR_GENERAL;
1301 return MTP_ERROR_NONE;
1303 #endif /* MTP_SUPPORT_SET_PROTECTION */
1305 mtp_err_t _hutil_get_num_objects(mtp_uint32 store_id, mtp_uint32 h_parent,
1306 mtp_uint32 format, mtp_uint32 *num_obj)
1308 mtp_store_t *store = NULL;
1309 mtp_obj_t *obj = NULL;
1311 mtp_uint32 numobj = 0;
1314 if (store_id != PTP_STORAGEID_ALL) {
1315 store = _device_get_store(store_id);
1316 if (store == NULL) {
1317 ERR("specific store is null");
1318 return MTP_ERROR_INVALID_STORE;
1324 *num_obj = _device_get_num_objects(store_id);
1326 *num_obj = _device_get_num_objects_with_format(store_id,
1329 return MTP_ERROR_NONE;
1332 /* return the number of direct children for a particular association
1333 * (in a single store)
1335 if (h_parent == PTP_OBJECTHANDLE_ALL) {
1337 h_parent = PTP_OBJECTHANDLE_ROOT;
1338 if (store_id == PTP_STORAGEID_ALL) {
1339 for (i = (_device_get_num_stores() - 1); i >= 0; i--) {
1340 store = _device_get_store_at_index(i);
1341 if (store == NULL) {
1342 ERR("Store is null");
1343 return MTP_ERROR_STORE_NOT_AVAILABLE;
1345 numobj += _entity_get_num_children(store,
1350 return MTP_ERROR_NONE;
1353 /* Initiator wants number of children of a particular association */
1354 obj = _device_get_object_with_handle(h_parent);
1357 return MTP_ERROR_INVALID_OBJECTHANDLE;
1360 if (obj->obj_info->obj_fmt != PTP_FMT_ASSOCIATION) {
1361 ERR("format is not association");
1362 return MTP_ERROR_INVALID_PARENT;
1365 store = _device_get_store_containing_obj(h_parent);
1368 if (store == NULL) {
1369 ERR("store is null");
1370 return MTP_ERROR_STORE_NOT_AVAILABLE;
1373 *num_obj = _entity_get_num_children(store, h_parent, format);
1374 return MTP_ERROR_NONE;
1377 mtp_err_t _hutil_get_object_handles(mtp_uint32 store_id, mtp_uint32 format,
1378 mtp_uint32 h_parent, ptp_array_t *handle_arr)
1380 mtp_store_t *store = NULL;
1383 if (h_parent == PTP_OBJECTHANDLE_ALL || h_parent == PTP_OBJECTHANDLE_ROOT) {
1384 for (i = 0; i < _device_get_num_stores(); i++) {
1385 store = _device_get_store_at_index(i);
1386 if (store && store->obj_list.nnodes == 0)
1387 _entity_store_recursive_enum_folder_objects(store, NULL);
1389 g_is_full_enum = TRUE;
1392 if (store_id == PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ROOT) {
1393 for (i = 0; i < _device_get_num_stores(); i++) {
1394 store = _device_get_store_at_index(i);
1395 _entity_get_objects_from_store_by_format(store, format, handle_arr);
1397 return MTP_ERROR_NONE;
1399 } else if (store_id == PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ALL) {
1400 h_parent = PTP_OBJECTHANDLE_ROOT;
1401 for (i = 0; i < _device_get_num_stores(); i++) {
1402 store = _device_get_store_at_index(i);
1403 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1405 return MTP_ERROR_NONE;
1407 } else if (store_id != PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ROOT) {
1408 store = _device_get_store(store_id);
1409 if (store == NULL) {
1410 ERR("invalid store id [%d]\n", store_id);
1411 return MTP_ERROR_INVALID_STORE;
1414 _entity_get_objects_from_store_by_format(store, format, handle_arr);
1415 return MTP_ERROR_NONE;
1417 } else if (store_id != PTP_STORAGEID_ALL && h_parent == PTP_OBJECTHANDLE_ALL) {
1418 h_parent = PTP_OBJECTHANDLE_ROOT;
1419 store = _device_get_store(store_id);
1420 if (store == NULL) {
1421 ERR("invalid store id [%d]\n", store_id);
1422 return MTP_ERROR_INVALID_STORE;
1424 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1425 return MTP_ERROR_NONE;
1428 store = _device_get_store(store_id);
1429 if (store == NULL) {
1430 ERR("invalid store id [%d]\n", store_id);
1431 return MTP_ERROR_INVALID_STORE;
1434 _entity_get_child_handles_with_same_format(store, h_parent, format, handle_arr);
1435 return MTP_ERROR_NONE;
1438 mtp_err_t _hutil_construct_object_entry(mtp_uint32 store_id,
1439 mtp_uint32 h_parent, obj_data_t *objdata, mtp_obj_t **obj, void *data,
1442 mtp_store_t *store = NULL;
1443 mtp_obj_t *tobj = NULL;
1444 obj_info_t *obj_info = NULL;
1445 mtp_char file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
1449 h_parent = _device_get_default_parent_handle();
1450 else if (h_parent == 0xFFFFFFFF)
1451 h_parent = PTP_OBJECTHANDLE_ROOT;
1453 store_id = _device_get_default_store_id();
1456 ERR("_device_get_default_store_id Fail");
1457 return MTP_ERROR_STORE_NOT_AVAILABLE;
1461 /* If the second parameter is used,
1462 * the first must also be used.
1464 return MTP_ERROR_INVALID_PARAM;
1466 h_parent = _device_get_default_parent_handle();
1470 if (objdata != NULL) {
1471 store = _device_get_store(objdata->store_id);
1472 if (store != NULL) {
1473 DBG("check free size instead of re-calculation");
1474 _entity_update_store_info_run_time(&(store->store_info),
1475 (store->root_path));
1478 /* Delete and invalidate the old obj_info for send object */
1479 if (objdata->obj != NULL)
1480 _entity_dealloc_mtp_obj(objdata->obj);
1483 store = _device_get_store(store_id);
1484 if (store == NULL) {
1485 ERR("Store not found");
1486 return MTP_ERROR_INVALID_STORE;
1489 if (store->store_info.access == PTP_STORAGEACCESS_R) {
1490 ERR("Read only storage");
1491 return MTP_ERROR_STORE_READ_ONLY;
1494 if ((store->store_info.free_space) == 0 ||
1495 (store->store_info.free_space >
1496 store->store_info.capacity)) {
1497 ERR("free space is not enough [%ld:%ld]\n",
1498 store->store_info.free_space,
1499 store->store_info.capacity);
1500 return MTP_ERROR_STORE_FULL;
1503 obj_info = _entity_alloc_object_info();
1504 if (obj_info == NULL) {
1505 ERR("_entity_alloc_object_info Fail");
1506 return MTP_ERROR_GENERAL;
1509 if (_entity_parse_raw_obj_info(data, data_sz, obj_info, file_name,
1510 sizeof(file_name)) != data_sz) {
1511 /* wrong object info sent from Host.*/
1512 ERR("Invalid objet info");
1513 _entity_dealloc_obj_info(obj_info);
1514 return MTP_ERROR_INVALID_OBJECT_INFO;
1516 obj_info->store_id = store_id;
1517 obj_info->h_parent = h_parent;
1519 switch (_hutil_add_object_entry(obj_info, file_name, &tobj)) {
1520 case MTP_ERROR_NONE:
1524 case MTP_ERROR_STORE_FULL:
1525 return MTP_ERROR_STORE_FULL;
1527 case MTP_ERROR_INVALID_OBJECTHANDLE:
1528 return MTP_ERROR_INVALID_OBJECTHANDLE;
1530 case MTP_ERROR_INVALID_PARENT:
1531 return MTP_ERROR_INVALID_PARENT;
1534 return MTP_ERROR_GENERAL;
1537 return MTP_ERROR_NONE;
1540 mtp_err_t _hutil_construct_object_entry_prop_list(mtp_uint32 store_id,
1541 mtp_uint32 h_parent, mtp_uint16 format, mtp_uint64 obj_sz,
1542 obj_data_t *obj_data, mtp_obj_t **obj_ptr, void *data,
1543 mtp_int32 data_sz, mtp_uint32 *err_idx)
1545 mtp_uint32 index = 0;
1546 mtp_store_t *store = NULL;
1547 mtp_obj_t *obj = NULL;
1548 obj_prop_desc_t *prop_desc = NULL;
1549 obj_prop_val_t *prop_val = NULL;
1550 mtp_uint32 num_elem = 0;
1551 mtp_int32 quad_sz = 0;
1552 mtp_uint32 obj_handle = 0;
1553 mtp_uint16 prop_code = 0;
1554 mtp_uint16 data_type = 0;
1555 obj_info_t *obj_info = NULL;
1556 mtp_uchar *temp = NULL;
1557 mtp_int32 bytes_left = data_sz;
1560 #ifdef MTP_SUPPORT_ALBUM_ART
1561 mtp_uint16 albumFormat = 0;
1562 mtp_char alb_extn[MTP_MAX_EXTENSION_LENGTH + 1] = { 0 };
1563 mtp_char *alb_buf = NULL;
1564 mtp_uint32 alb_sz = 0;
1565 FILE* h_temp = NULL;
1566 mtp_int32 error = 0;
1567 #endif /*MTP_SUPPORT_ALBUM_ART*/
1568 mtp_char file_name[MTP_MAX_FILENAME_SIZE + 1] = { 0 };
1570 if (obj_data != NULL && obj_data->obj != NULL) {
1571 store = _device_get_store(obj_data->store_id);
1572 if (store != NULL) {
1573 DBG("check free size instead of re-calculation");
1574 _entity_update_store_info_run_time(&(store->store_info),
1575 (store->root_path));
1577 _entity_dealloc_mtp_obj(obj_data->obj);
1580 store = _device_get_store(store_id);
1581 if (store == NULL) {
1582 ERR("Could not get the store");
1583 return MTP_ERROR_INVALID_STORE;
1586 if (store->store_info.access == PTP_STORAGEACCESS_R) {
1587 ERR("Only read access allowed on store");
1588 return MTP_ERROR_STORE_READ_ONLY;
1591 if ((store->store_info.free_space) == 0 ||
1592 (store->store_info.free_space > store->store_info.capacity)) {
1593 ERR("free space is not enough [%ld bytes]\n",
1594 store->store_info.free_space);
1595 return MTP_ERROR_STORE_FULL;
1598 obj_info = _entity_alloc_object_info();
1599 if (obj_info == NULL) {
1600 ERR("_entity_alloc_object_info Fail");
1601 return MTP_ERROR_GENERAL;
1604 obj_info->obj_fmt = format;
1605 if (obj_info->obj_fmt == PTP_FMT_ASSOCIATION)
1606 obj_info->association_type = PTP_ASSOCIATIONTYPE_FOLDER;
1608 obj_info->file_size = obj_sz;
1610 /* Prop value quadruple: Object Handle, PropertyCode, DataType
1611 * and DTS Prop Value (assume a byte value)
1613 temp = (mtp_uchar *) data;
1614 bytes_left = data_sz;
1615 quad_sz = sizeof(mtp_uint32) + sizeof(mtp_uint16) + sizeof(mtp_uint16) +
1617 memcpy(&num_elem, temp, sizeof(mtp_uint32));
1618 #ifdef __BIG_ENDIAN__
1619 _util_conv_byte_order(&num_elem, sizeof(mtp_uint32));
1621 temp += sizeof(mtp_uint32);
1622 bytes_left -= sizeof(mtp_uint32);
1624 /* frequent disconnect/connect make bluscreen since below process
1627 for (index = 0; index < num_elem; index++) {
1628 if (MTP_PHONE_USB_DISCONNECTED == _util_get_local_usb_status() ||
1629 TRUE == _transport_get_usb_discon_state()) {
1630 /* seems usb is disconnected, stop */
1631 _entity_dealloc_obj_info(obj_info);
1632 resp = MTP_ERROR_GENERAL;
1637 if (bytes_left < quad_sz) {
1638 /* seems invalid dataset received: Stops parsing */
1639 _entity_dealloc_obj_info(obj_info);
1640 resp = MTP_ERROR_INVALID_DATASET;
1644 /* Get ObjectHandle & validate */
1645 memcpy(&obj_handle, temp, sizeof(mtp_uint32));
1646 #ifdef __BIG_ENDIAN__
1647 _util_conv_byte_order(&obj_handle, sizeof(mtp_uint32));
1648 #endif /* __BIG_ENDIAN__ */
1649 temp += sizeof(mtp_uint32);
1650 bytes_left -= sizeof(mtp_uint32);
1651 if (obj_handle != 0x00000000) {
1652 _entity_dealloc_obj_info(obj_info);
1653 resp = MTP_ERROR_INVALID_OBJECTHANDLE;
1657 /* Get PropCode & Validate */
1658 memcpy(&prop_code, temp, sizeof(mtp_uint16));
1659 #ifdef __BIG_ENDIAN__
1660 _util_conv_byte_order(&prop_code, sizeof(mtp_uint16));
1661 #endif /* __BIG_ENDIAN__ */
1662 temp += sizeof(mtp_uint16);
1663 bytes_left -= sizeof(mtp_uint16);
1664 prop_desc = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1665 if (prop_desc == NULL) {
1666 _entity_dealloc_obj_info(obj_info);
1667 ERR("property may be unsupported!!");
1668 resp = MTP_ERROR_INVALID_OBJ_PROP_CODE;
1672 /* Verify that properties already present in parameters
1673 * don't get repeated in the list
1675 if ((prop_code == MTP_OBJ_PROPERTYCODE_STORAGEID) ||
1676 (prop_code == MTP_OBJ_PROPERTYCODE_PARENT) ||
1677 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFORMAT) ||
1678 (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTSIZE)) {
1679 _entity_dealloc_obj_info(obj_info);
1680 resp = MTP_ERROR_INVALID_DATASET;
1685 memcpy(&data_type, temp, sizeof(mtp_uint16));
1686 #ifdef __BIG_ENDIAN__
1687 _util_conv_byte_order(&data_type, sizeof(mtp_uint16));
1688 #endif /* __BIG_ENDIAN__ */
1689 temp += sizeof(mtp_uint16);
1690 bytes_left -= sizeof(mtp_uint16);
1691 if (data_type != prop_desc->propinfo.data_type) {
1692 _entity_dealloc_obj_info(obj_info);
1693 resp = MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1697 /* Acquire object information related data. */
1698 prop_val = _prop_alloc_obj_propval(prop_desc);
1699 if (prop_val == NULL)
1702 _prop_set_current_array_val(prop_val, temp, bytes_left);
1703 switch (prop_code) {
1704 case MTP_OBJ_PROPERTYCODE_WIDTH:
1705 // TODO: find mechanism to save (integer)
1707 case MTP_OBJ_PROPERTYCODE_TRACK:
1708 // TODO: find mechanism to save (integer)
1710 case MTP_OBJ_PROPERTYCODE_GENRE:
1711 // TODO: find mechanism to save (string)
1713 case MTP_OBJ_PROPERTYCODE_HEIGHT:
1714 // TODO: find mechanism to save (integer)
1716 case MTP_OBJ_PROPERTYCODE_ARTIST:
1717 // TODO: find mechanism to save (string)
1719 case MTP_OBJ_PROPERTYCODE_DURATION:
1720 // TODO: find mechanism to save (integer)
1722 case MTP_OBJ_PROPERTYCODE_COMPOSER:
1723 // TODO: find mechanism to save (string)
1725 case MTP_OBJ_PROPERTYCODE_ALBUMNAME:
1726 // TODO: find mechanism to save (string)
1728 case MTP_OBJ_PROPERTYCODE_SAMPLERATE:
1729 // TODO: find mechanism to save (integer)
1731 case MTP_OBJ_PROPERTYCODE_DATECREATED:
1732 // TODO: find mechanism to save (string)
1734 case MTP_OBJ_PROPERTYCODE_DATEMODIFIED:
1735 // TODO: find mechanism to save (string)
1737 case MTP_OBJ_PROPERTYCODE_AUDIOBITRATE:
1738 // TODO: find mechanism to save (integer)
1740 case MTP_OBJ_PROPERTYCODE_VIDEOBITRATE:
1741 // TODO: find mechanism to save (integer)
1743 case MTP_OBJ_PROPERTYCODE_OBJECTFILENAME:
1744 /* empty metadata folder problem
1747 if (prop_val->current_val.str->num_chars == 0) {
1748 g_strlcpy(file_name, MTP_UNKNOWN_METADATA, sizeof(file_name));
1750 _util_utf16_to_utf8(file_name, sizeof(file_name),
1751 prop_val->current_val.str->str);
1755 case MTP_OBJ_PROPERTYCODE_PROTECTIONSTATUS:
1756 #ifdef MTP_SUPPORT_SET_PROTECTION
1757 memcpy(&obj_info->protcn_status, prop_val->current_val.integer,
1758 sizeof(mtp_uint16));
1759 #else /* MTP_SUPPORT_SET_PROTECTION */
1760 obj_info->protcn_status = PTP_PROTECTIONSTATUS_NOPROTECTION;
1761 #endif /*MTP_SUPPORT_SET_PROTECTION*/
1764 case MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE:
1765 memcpy(&obj_info->association_type, prop_val->current_val.integer,
1766 sizeof(mtp_uint16));
1769 case MTP_OBJ_PROPERTYCODE_NUMBEROFCHANNELS:
1770 // TODO: find mechanism to save (integer)
1772 case MTP_OBJ_PROPERTYCODE_FRAMESPER1KSECONDS:
1773 // TODO: find mechanism to save (integer)
1775 #ifdef MTP_SUPPORT_ALBUM_ART
1776 case MTP_OBJ_PROPERTYCODE_SAMPLEDATA:
1777 /* save sample data(album cover data) with
1778 * sample format, otherwise no extension
1779 * update db with sample data path
1780 * there is no case that this position is called
1781 * again but prevent detect this
1785 alb_buf = g_malloc(sizeof(mtp_uchar) *
1786 (prop_val->current_val.array->num_ele) + 1);
1787 alb_sz = prop_val->current_val.array->num_ele;
1788 if (alb_buf != NULL) {
1790 sizeof(mtp_uchar) * alb_sz + 1);
1793 (prop_val->current_val.array->array_entry),
1794 sizeof(mtp_uchar) * alb_sz);
1796 ERR("album art test mem allocation Fail");
1797 _prop_destroy_obj_propval(prop_val);
1798 _entity_dealloc_obj_info(obj_info);
1799 return MTP_ERROR_GENERAL;
1803 case MTP_OBJ_PROPERTYCODE_SAMPLEFORMAT:
1804 /* if is_albumart is turned on, Move file with
1805 * new extension. And update db with data path
1807 memcpy(&albumFormat, prop_val->current_val.integer,
1808 sizeof(mtp_uint16));
1809 switch (albumFormat) {
1810 case PTP_FMT_IMG_EXIF:
1811 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "jpg");
1813 case PTP_FMT_IMG_GIF:
1814 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "gif");
1816 case PTP_FMT_IMG_PNG:
1817 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "png");
1820 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "wma");
1823 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "mpg");
1826 g_snprintf(alb_extn, sizeof(alb_extn), "%s", "dat");
1830 ERR("sampleformatl![0x%x], extension[%s]\n", prop_code, alb_extn);
1832 case MTP_OBJ_PROPERTYCODE_SAMPLESIZE:
1833 case MTP_OBJ_PROPERTYCODE_SAMPLEHEIGHT:
1834 case MTP_OBJ_PROPERTYCODE_SAMPLEWIDTH:
1835 case MTP_OBJ_PROPERTYCODE_SAMPLEDURATION:
1836 DBG("Sample data is not supported [0x%x]\n", prop_code);
1838 #endif /*MTP_SUPPORT_ALBUM_ART*/
1841 DBG("Unsupported Property [0x%x]\n", prop_code);
1845 temp += _prop_size_obj_propval(prop_val);
1846 bytes_left -= _prop_size_obj_propval(prop_val);
1847 _prop_destroy_obj_propval(prop_val);
1850 obj_info->store_id = store_id;
1851 obj_info->h_parent = h_parent;
1853 if ((resp = _hutil_add_object_entry(obj_info, file_name, &obj)) !=
1858 #ifdef MTP_SUPPORT_ALBUM_ART
1859 mtp_char full_path[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1860 mtp_char extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1862 g_strlcpy(full_path, obj->file_path, MTP_MAX_PATHNAME_SIZE + 1);
1864 /* in case of album, if there is album data, fill it in this file */
1865 if (obj_info->obj_fmt != PTP_FMT_ASSOCIATION ||
1866 (obj_info->obj_fmt == PTP_FMT_ASSOCIATION &&
1867 obj_info->association_type != PTP_ASSOCIATIONTYPE_UNDEFINED &&
1868 obj_info->association_type != PTP_ASSOCIATIONTYPE_FOLDER)) {
1870 _util_get_file_extn(full_path, extn);
1871 if (!strcasecmp(extn, "alb")) {
1872 /* check db whether it contains sample form
1873 * save sample data(album cover data) with
1874 * sample format, otherwise no extension
1876 if (alb_buf != NULL) {
1878 h_temp = _util_file_open(full_path,
1879 MTP_FILE_WRITE, &error);
1880 if (h_temp != NULL) {
1881 _util_file_write(h_temp, alb_buf,
1882 sizeof(mtp_uchar) *alb_sz);
1883 _util_file_close(h_temp);
1885 ERR("open album file Fail!!");
1888 ERR("no album art data");
1894 #endif /* MTP_SUPPORT_ALBUM_ART */
1896 return MTP_ERROR_NONE;
1899 #ifdef MTP_SUPPORT_ALBUM_ART
1901 #endif /* MTP_SUPPORT_ALBUM_ART */
1905 mtp_err_t _hutil_get_object_prop_value(mtp_uint32 obj_handle,
1906 mtp_uint32 prop_code, obj_prop_val_t *prop_val, mtp_obj_t **obj)
1908 obj_prop_val_t *tprop = NULL;
1909 mtp_obj_t *tobj = NULL;
1911 tobj = _device_get_object_with_handle(obj_handle);
1913 ERR("requested handle does not exist[0x%x]\n", obj_handle);
1914 return MTP_ERROR_INVALID_OBJECTHANDLE;
1917 tprop = _prop_get_prop_val(tobj, prop_code);
1918 if (tprop != NULL) {
1919 memcpy(prop_val, tprop, sizeof(obj_prop_val_t));
1921 return MTP_ERROR_NONE;
1924 ERR("can not get the prop value for propcode [0x%x]\n", prop_code);
1925 return MTP_ERROR_GENERAL;
1928 mtp_err_t _hutil_update_object_property(mtp_uint32 obj_handle,
1929 mtp_uint32 prop_code, mtp_uint16 *data_type, void *buf,
1930 mtp_uint32 buf_sz, mtp_uint32 *prop_sz)
1932 mtp_int32 error = 0;
1933 mtp_uint32 p_size = 0;
1934 mtp_obj_t *obj = NULL;
1935 obj_info_t *obj_info = NULL;
1936 obj_prop_desc_t *prp_dev = NULL;
1937 mtp_char temp_buf[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1938 mtp_char orig_pfpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1939 mtp_wchar mov_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1940 mtp_char orig_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1941 mtp_char dest_fpath[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
1943 retv_if(NULL == buf, MTP_ERROR_INVALID_PARAM);
1945 obj = _device_get_object_with_handle(obj_handle);
1946 if ((NULL == obj) || (NULL == obj->obj_info)) {
1947 ERR("Object not found");
1948 return MTP_ERROR_INVALID_OBJECTHANDLE;
1951 obj_info = obj->obj_info;
1952 /* Avoid to rename file/folder during file operating by phone side. */
1953 if (_util_is_file_opened(obj->file_path) == TRUE) {
1954 ERR_SECURE("Object [%s] is already opened\n", obj->file_path);
1955 return MTP_ERROR_GENERAL;
1958 prp_dev = _prop_get_obj_prop_desc(obj_info->obj_fmt, prop_code);
1959 if (prp_dev == NULL) {
1960 ERR("_prop_get_obj_prop_desc Fail");
1961 return MTP_ERROR_INVALID_OBJ_PROP_CODE;
1964 #ifdef MTP_SUPPORT_SET_PROTECTION
1965 if (obj_info->protcn_status == PTP_PROTECTIONSTATUS_READONLY) {
1966 ERR("protection is PTP_PROTECTIONSTATUS_READONLY");
1967 return MTP_ERROR_ACCESS_DENIED;
1969 #endif /* MTP_SUPPORT_SET_PROTECTION */
1971 if (prp_dev->propinfo.get_set == PTP_PROPGETSET_GETONLY) {
1972 ERR("property type is GETONLY");
1973 return MTP_ERROR_ACCESS_DENIED;
1976 if (data_type != NULL && *data_type != prp_dev->propinfo.data_type) {
1977 ERR("Not matched data type [%d][%d]\n",
1978 *data_type, prp_dev->propinfo.data_type);
1979 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
1982 /* Set up needed object info fields */
1983 if (prop_code == MTP_OBJ_PROPERTYCODE_OBJECTFILENAME) {
1984 ptp_string_t fname = { 0 };
1986 _prop_init_ptpstring(&fname);
1987 _prop_parse_rawstring(&fname, buf, buf_sz);
1989 _util_utf16_to_utf8(temp_buf, sizeof(temp_buf),
1991 g_strlcpy(orig_fpath, obj->file_path,
1992 MTP_MAX_PATHNAME_SIZE + 1);
1993 _util_get_parent_path(orig_fpath, orig_pfpath);
1995 if (_util_create_path(dest_fpath, sizeof(dest_fpath),
1996 orig_pfpath, temp_buf) == FALSE) {
1997 ERR("Path is too long");
1998 return MTP_ERROR_ACCESS_DENIED;
2000 _util_utf8_to_utf16(mov_fpath,
2001 sizeof(mov_fpath) / WCHAR_SIZ, dest_fpath);
2003 /* when changed name is different */
2004 if (strcasecmp(orig_fpath, dest_fpath)) {
2005 /* Extension change is not permitted */
2006 mtp_char orig_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2007 mtp_char dest_extn[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
2009 _util_get_file_extn(orig_fpath, orig_extn);
2010 _util_get_file_extn(dest_fpath, dest_extn);
2012 if (strcasecmp(orig_extn, dest_extn)) {
2013 ERR("file extension is different with original\
2014 one [%s]:[%s]\n", orig_extn, dest_extn);
2015 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2019 if (_entity_check_child_obj_path(obj, orig_fpath,
2020 dest_fpath) == FALSE) {
2021 ERR("_entity_check_child_obj_path FALSE. ");
2022 return MTP_ERROR_GENERAL;
2024 g_snprintf(g_last_moved, MTP_MAX_PATHNAME_SIZE + 1,
2026 if (FALSE == _util_file_move(orig_fpath, dest_fpath,
2028 if (EACCES == error)
2029 return MTP_ERROR_ACCESS_DENIED;
2030 return MTP_ERROR_GENERAL;
2033 if (obj->obj_info->obj_fmt == PTP_FMT_ASSOCIATION) {
2034 _util_scan_folder_contents_in_db(orig_fpath);
2035 _util_scan_folder_contents_in_db(dest_fpath);
2037 _util_delete_file_from_db(orig_fpath);
2038 _util_add_file_to_db(dest_fpath);
2042 /* Finally assign new handle and update full path */
2043 _entity_set_object_file_path(obj, dest_fpath,
2047 if (_entity_set_child_object_path(obj, orig_fpath,
2048 dest_fpath) == FALSE) {
2049 ERR("failed to set the full path!!");
2050 return MTP_ERROR_INVALID_OBJECT_PROP_FORMAT;
2053 DBG("File moved to [%s]\n", dest_fpath);
2055 ERR_SECURE("changed name is same with original one. [%s]\n",
2058 p_size = _prop_size_ptpstring(&fname);
2059 } else if (prop_code == MTP_OBJ_PROPERTYCODE_ASSOCIATIONTYPE) {
2060 memcpy(&obj_info->association_type, buf, sizeof(mtp_uint16));
2061 p_size = sizeof(mtp_uint16);
2063 ERR("Propert [0x%x] is GETONLY\n", prop_code);
2066 if (prop_sz != NULL)
2069 return MTP_ERROR_NONE;
2072 mtp_err_t _hutil_get_prop_desc(mtp_uint32 format, mtp_uint32 prop_code,
2075 obj_prop_desc_t *prop = NULL;
2077 prop = _prop_get_obj_prop_desc(format, prop_code);
2079 ERR("pProperty is NULL");
2080 return MTP_ERROR_GENERAL;
2083 memcpy(data, prop, sizeof(obj_prop_desc_t));
2084 return MTP_ERROR_NONE;
2087 mtp_err_t _hutil_get_object_prop_supported(mtp_uint32 format,
2088 ptp_array_t *prop_arr)
2090 _prop_get_supp_obj_props(format, prop_arr);
2091 return MTP_ERROR_NONE;
2094 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2095 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2096 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2097 obj_proplist_t *prop_list)
2098 #else /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2099 mtp_err_t _hutil_get_object_prop_list(mtp_uint32 obj_handle, mtp_uint32 format,
2100 mtp_uint32 prop_code, mtp_uint32 group_code, mtp_uint32 depth,
2101 obj_proplist_t *prop_list, ptp_array_t *obj_arr)
2102 #endif /* MTP_USE_RUNTIME_GETOBJECTPROPVALUE */
2104 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2105 ptp_array_t obj_arr = { 0 };
2106 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2107 mtp_obj_t *obj = NULL;
2110 mtp_store_t *store = NULL;
2112 if ((obj_handle != PTP_OBJECTHANDLE_UNDEFINED) &&
2113 (obj_handle != PTP_OBJECTHANDLE_ALL)) {
2114 /* Is this object handle valid? */
2115 store = _device_get_store_containing_obj(obj_handle);
2116 if (store == NULL) {
2117 ERR("invalid object handle");
2118 return MTP_ERROR_INVALID_OBJECTHANDLE;
2122 if (prop_code == PTP_PROPERTY_UNDEFINED) {
2123 /* PropGroupCode should be used if Property code
2126 if (group_code == 0x0) {
2127 ERR("PropGroupCode is zero");
2128 return MTP_ERROR_INVALID_PARAM;
2132 if (!(obj_handle == PTP_OBJECTHANDLE_ALL ||
2133 obj_handle == PTP_OBJECTHANDLE_UNDEFINED) &&
2134 !(format == PTP_FORMATCODE_NOTUSED ||
2135 format == PTP_FORMATCODE_ALL)) {
2136 ERR("both object handle and format code is specified!\
2137 return nospecification by format");
2138 return MTP_ERROR_NO_SPEC_BY_FORMAT;
2141 _util_init_list(&(prop_list->prop_quad_list));
2142 _prop_init_ptparray(obj_arr, UINT32_TYPE);
2144 if (store != NULL) {
2145 _entity_get_objects_from_store_till_depth(store, obj_handle,
2146 format, depth, obj_arr);
2148 for (ii = 0; ii < _device_get_num_stores(); ii++) {
2149 store = _device_get_store_at_index(ii);
2150 _entity_get_objects_from_store_till_depth(store,
2151 obj_handle, format, depth, obj_arr);
2155 if (obj_arr->num_ele != 0) {
2156 mtp_uint32 *obj_handles = obj_arr->array_entry;
2158 for (i = 0; i < obj_arr->num_ele; i++) {
2159 obj = _entity_get_object_from_store(store, obj_handles[i]);
2163 if (_prop_get_obj_proplist(obj, prop_code, group_code,
2164 prop_list) == FALSE) {
2165 ERR("Fail to create Proplist");
2166 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2167 _prop_deinit_ptparray(&obj_arr);
2168 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2169 return MTP_ERROR_GENERAL;
2174 #ifndef MTP_USE_RUNTIME_GETOBJECTPROPVALUE
2175 prop_deinit_ptparray(&obj_arr);
2176 #endif /*MTP_USE_RUNTIME_GETOBJECTPROPVALUE*/
2178 return MTP_ERROR_NONE;
2181 mtp_err_t _hutil_remove_object_reference(mtp_uint32 obj_handle,
2182 mtp_uint32 ref_handle)
2184 mtp_obj_t *obj = NULL;
2186 obj = _device_get_object_with_handle(obj_handle);
2188 ERR("No object for handle[%d]\n", obj_handle);
2189 return MTP_ERROR_NONE;
2192 if (_entity_remove_reference_child_array(obj, ref_handle) == FALSE)
2193 ERR("_entity_remove_reference_child_array Fail");
2195 return MTP_ERROR_NONE;
2198 mtp_err_t _hutil_add_object_references_enhanced(mtp_uint32 obj_handle,
2199 mtp_uchar *buffer, mtp_uint32 buf_sz)
2201 mtp_obj_t *obj = NULL;
2203 obj = _device_get_object_with_handle(obj_handle);
2205 DBG("No object for handle[0x%x]\n", obj_handle);
2206 return MTP_ERROR_NONE;
2209 if (_entity_set_reference_child_array(obj, buffer, buf_sz) == FALSE) {
2210 ERR("_entity_set_reference_child_array Fail");
2211 return MTP_ERROR_GENERAL;
2214 return MTP_ERROR_NONE;
2217 mtp_err_t _hutil_get_object_references(mtp_uint32 obj_handle,
2218 ptp_array_t *parray, mtp_uint32 *num_ele)
2220 mtp_obj_t *obj = NULL;
2221 mtp_obj_t *ref_obj = NULL;
2223 mtp_uint32 *ref_ptr = NULL;
2224 ptp_array_t ref_arr = { 0 };
2226 obj = _device_get_object_with_handle(obj_handle);
2227 if (NULL == obj || NULL == obj->obj_info) {
2229 return MTP_ERROR_INVALID_OBJECTHANDLE;
2232 if (parray == NULL) {
2234 return MTP_ERROR_GENERAL;
2237 if (obj->child_array.num_ele == 0) {
2239 return MTP_ERROR_NONE;
2242 _prop_init_ptparray(&ref_arr, obj->child_array.type);
2243 _prop_copy_ptparray(&ref_arr, &(obj->child_array));
2244 ref_ptr = (mtp_uint32 *)(ref_arr.array_entry);
2246 for (idx = 0; idx < ref_arr.num_ele; idx++) {
2247 ref_obj = _device_get_object_with_handle(ref_ptr[idx]);
2248 if (ref_obj == NULL)
2249 _entity_remove_reference_child_array(obj, ref_ptr[idx]);
2252 *num_ele = obj->child_array.num_ele;
2254 _prop_init_ptparray(parray, obj->child_array.type);
2255 _prop_grow_ptparray(parray, *num_ele);
2256 _prop_copy_ptparray(parray, &(obj->child_array));
2259 _prop_deinit_ptparray(&ref_arr);
2260 return MTP_ERROR_NONE;
2263 mtp_err_t _hutil_get_number_of_objects(mtp_uint32 store_id, mtp_uint32 *num_obj)
2265 *num_obj = _device_get_num_objects(store_id);
2266 return MTP_ERROR_NONE;
2269 mtp_err_t _hutil_get_interdep_prop_config_list_size(mtp_uint32 *list_sz,
2272 *list_sz = _prop_get_size_interdep_proplist(&interdep_proplist,
2274 return MTP_ERROR_NONE;
2277 mtp_err_t _hutil_get_interdep_prop_config_list_data(void *data,
2278 mtp_uint32 list_sz, mtp_uint32 format)
2280 if (list_sz == _prop_pack_interdep_proplist(&interdep_proplist,
2281 format, data, list_sz)) {
2282 return MTP_ERROR_NONE;
2285 ERR("packet and requested size do not match");
2286 return MTP_ERROR_GENERAL;
2289 mtp_err_t _hutil_get_playback_skip(mtp_int32 skip_param)
2292 mtp_obj_t *obj = NULL;
2293 mtp_uint32 new_idx = 0;
2294 mtp_uint32 new_hobj = 0;
2295 mtp_uint32 obj_handle = 0;
2296 mtp_obj_t *par_obj = NULL;
2297 obj_info_t *obj_info = NULL;
2298 ptp_array_t *ref_arr = NULL;
2299 device_prop_desc_t *dev_prop = NULL;
2301 retv_if(skip_param == 0, MTP_ERROR_INVALID_PARAM);
2303 if (_device_get_playback_obj(&obj_handle) == FALSE) {
2304 ERR("_device_get_playback_obj Fail");
2305 return MTP_ERROR_GENERAL;
2308 if (obj_handle == 0x0)
2309 return MTP_ERROR_NONE;
2311 obj = _device_get_object_with_handle(obj_handle);
2312 if (obj == NULL || obj->obj_info == NULL) {
2313 ERR("obj or obj_info is NULL");
2314 return MTP_ERROR_GENERAL;
2317 obj_info = obj->obj_info;
2318 if ((obj_info->obj_fmt == PTP_FMT_WAVE) ||
2319 (obj_info->obj_fmt == PTP_FMT_MP3) ||
2320 (obj_info->obj_fmt == MTP_FMT_WMA) ||
2321 (obj_info->obj_fmt == MTP_FMT_WMV) ||
2322 (obj_info->obj_fmt == MTP_FMT_UNDEFINED_AUDIO)) {
2323 par_obj = _device_get_object_with_handle(obj_info->h_parent);
2325 ERR("parent not found in obj_list");
2326 return MTP_ERROR_GENERAL;
2328 ref_arr = _entity_get_reference_child_array(par_obj);
2329 idx = _prop_find_ele_ptparray(ref_arr, obj_handle);
2330 if (idx != ELEMENT_NOT_FOUND) {
2331 if (((long long)idx + (long long)skip_param) > UINT_MAX)
2332 new_idx = ref_arr->num_ele - 1;
2333 else if ((idx + skip_param) >= ref_arr->num_ele)
2336 new_idx = idx + skip_param;
2338 if (_prop_get_ele_ptparray(ref_arr, new_idx,
2339 (void *)(&new_hobj)) == TRUE) {
2340 dev_prop = _device_get_device_property(
2341 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2342 if (dev_prop == NULL) {
2343 ERR("dev_prop is null");
2344 return MTP_ERROR_GENERAL;
2346 _prop_set_current_integer(dev_prop, 0xFFFFFFFF);
2347 _device_set_playback_obj(new_hobj);
2350 } else if ((obj_info->obj_fmt == MTP_FMT_ABSTRACT_AUDIO_ALBUM) ||
2351 (obj_info->obj_fmt == MTP_FMT_ABSTRACT_VIDEO_ALBUM)) {
2352 dev_prop = _device_get_device_property(
2353 MTP_PROPERTYCODE_PLAYBACK_CONT_INDEX);
2354 if (dev_prop == NULL) {
2355 ERR("dev_prop is null");
2356 return MTP_ERROR_GENERAL;
2358 memcpy(&idx, dev_prop->current_val.integer, sizeof(mtp_uint32));
2359 ref_arr = _entity_get_reference_child_array(obj);
2360 if (((long long)idx + (long long)skip_param) > UINT_MAX)
2361 new_idx = ref_arr->num_ele - 1;
2362 else if ((idx + skip_param) >= ref_arr->num_ele)
2365 new_idx = idx + skip_param;
2367 _prop_set_current_integer(dev_prop, new_idx);
2368 return MTP_ERROR_NONE;
2371 return MTP_ERROR_GENERAL;
2374 mtp_err_t _hutil_format_storage(mtp_uint32 store_id, mtp_uint32 fs_format)
2376 mtp_err_t error = MTP_ERROR_GENERAL;
2377 mtp_store_t *store = NULL;
2379 store = _device_get_store(store_id);
2380 if (store == NULL) {
2381 ERR("Store is NULL");
2385 error = _entity_format_store(store, fs_format);
2386 if (error == PTP_RESPONSE_OK)
2387 return MTP_ERROR_NONE;
2389 ERR("Format store Fail");
2393 mtp_uint32 _hutil_get_storage_info_size(store_info_t *store_info)
2395 mtp_uint32 size = 0;
2397 size += sizeof(store_info->access);
2398 size += sizeof(store_info->fs_type);
2399 size += sizeof(store_info->free_space);
2400 size += sizeof(store_info->free_space_in_objs);
2401 size += sizeof(store_info->capacity);
2402 size += sizeof(store_info->store_type);
2403 size += _prop_size_ptpstring(&(store_info->store_desc));
2404 size += _prop_size_ptpstring(&(store_info->vol_label));