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.
23 #include <sys/sendfile.h>
24 #include <sys/types.h>
28 #include <glib/gprintf.h>
32 #include "mtp_support.h"
33 #include "ptp_datacodes.h"
34 #include "mtp_device.h"
41 * mtp_uint32 _util_file_open(const mtp_char *filename,
42 * file_mode_t mode, mtp_int32 *error)
43 * This function opens the file in specific mode.
45 * @param[in] filename Specifies the name of file to open.
46 * @param[in] mode Specifies the mode of file to open.
47 * @param[out] error Specifies the type of error
48 * @return This function returns the file handle on success,
49 or INVALID_FILE on failure
51 FILE* _util_file_open(const mtp_char *filename, file_mode_t mode,
72 case MTP_FILE_READ | MTP_FILE_WRITE:
76 case MTP_FILE_READ | MTP_FILE_WRITE | MTP_FILE_APPEND:
81 ERR("Invalid mode : %d\n", mode);
87 fhandle = fopen(filename, fmode);
88 if (fhandle == NULL) {
89 ERR("File open Fail:mode[0x%x], errno [%d]\n", mode, errno);
90 ERR_SECURE("filename[%s]\n", filename);
96 fcntl(fileno(fhandle), F_SETFL, O_NOATIME);
100 #else /* __USE_STDIO__ */
102 mtp_int32 fhandle = 0;
112 flags = O_WRONLY | O_CREAT | O_TRUNC;
116 case MTP_FILE_APPEND:
117 flags = O_WRONLY | O_APPEND | O_CREAT;
121 case MTP_FILE_READ | MTP_FILE_WRITE:
125 case MTP_FILE_READ | MTP_FILE_WRITE | MTP_FILE_APPEND:
126 flags = O_RDWR | O_APPEND | O_CREAT;
131 ERR("Invalid mode : %d\n", mode);
137 fhandle = open(filename, flags, perm);
139 fhandle = open(filename, flags);
142 ERR("File open Fail:mode[0x%x], errno [%d]\n", mode, errno);
143 ERR_SECURE("filename[%s]\n", filename);
149 #endif /* __USE_STDIO__ */
153 * void _util_file_read(mtp_uint32 handle, void *bufptr, mtp_uint32 size,
154 * mtp_uint32 *preadcount)
156 * This function reads data from the file handle into the data buffer.
158 * @param[in] handle Specifies the handle of file to read.
159 * @param[out] bufptr Points to buff where data is to be read.
160 * @param[in] size Specifies the num bytes to be read.
161 * @param[out] preadcount Will store the actual num bytes read.
164 void _util_file_read(FILE* fhandle, void *bufptr, mtp_uint32 size,
165 mtp_uint32 *read_count)
167 mtp_uint32 bytes_read = 0;
170 bytes_read = fread_unlocked(bufptr, sizeof(mtp_char), size, fhandle);
171 #else /* __USE_STDIO__ */
172 bytes_read = read(fhandle, bufptr, size);
173 #endif /* __USE_STDIO__ */
175 *read_count = bytes_read;
178 * mtp_uint32 _util_file_write(mtp_uint32 fhandle, void *bufptr, mtp_uint32 size)
180 * This function writes data to the file using the data buffer passed.
182 * @param[in] handle Specifies the handle of file to write.
183 * @param[in] bufptr Points the buffer which holds the data.
184 * @param[in] size Specifies num bytes to be written.
185 * @return This function returns num bytes written.
188 mtp_uint32 _util_file_write(FILE* fhandle, void *bufptr, mtp_uint32 size)
190 mtp_uint32 bytes_written = 0;
193 bytes_written = fwrite_unlocked(bufptr, sizeof(mtp_char), size, fhandle);
194 #else /* __USE_STDIO__ */
197 ret = write(fhandle, bufptr, size);
202 #endif /* __USE_STDIO__ */
204 return bytes_written;
208 * mtp_int32 _util_file_close(mtp_uint32 fhandle)
209 * This function closes the file.
211 * @param[in] handle Specifies the handle of file to close.
212 * @return 0 in case of success or EOF on failure.
214 mtp_int32 _util_file_close(FILE* fhandle)
217 return fclose(fhandle);
218 #else /* __USE_STDIO__ */
219 return close(fhandle);
220 #endif /* __USE_STDIO__ */
224 * This function seeks to a particular location in a file.
226 * @param[in] handle Specifies the handle of file to seek.
227 * @param[in] offset Specifies the starting point.
228 * @param[in] whence Specifies the setting value
229 * @return Returns TRUE in case of success or FALSE on Failure.
231 mtp_bool _util_file_seek(FILE* handle, off_t offset, mtp_int32 whence)
233 mtp_int64 ret_val = 0;
236 ret_val = fseek(handle, offset, whence);
237 #else /* __USE_STDIO__ */
238 ret_val = lseek(handle, offset, whence);
241 #endif /* __USE_STDIO__ */
243 ERR(" _util_file_seek error errno [%d]\n", errno);
250 mtp_bool _util_file_copy(const mtp_char *origpath, const mtp_char *newpath,
258 mtp_char buf[BUFSIZ] = { 0 };
260 if ((fold = fopen(origpath, "rb")) == NULL) {
261 ERR("In-file open Fail errno [%d]\n", errno);
266 if ((fnew = fopen(newpath, "wb")) == NULL) {
267 ERR("Out-file open Fail errno [%d]\n", errno);
274 nmemb = fread(buf, sizeof(mtp_char), BUFSIZ, fold);
275 if (nmemb < BUFSIZ && ferror(fold)) {
276 ERR("fread Fail errno [%d] \n", errno);
280 if (remove(newpath) < 0)
285 ret = fwrite(buf, sizeof(mtp_char), nmemb, fnew);
286 if (ret < nmemb && ferror(fnew)) {
287 ERR("fwrite Fail errno [%d]\n", errno);
291 if (remove(newpath) < 0)
295 } while (!feof(fold));
299 #else /* __USE_STDIO__ */
301 mtp_int32 out_fd = 0;
305 if ((in_fd = open(origpath, O_RDONLY)) < 0) {
306 ERR("In-file open Fail, errno [%d]\n", errno);
311 if ((out_fd = open(newpath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
312 ERR("Out-file open Fail errno [%d] \n", errno);
319 ret = sendfile(out_fd, in_fd, &offset, BUFSIZ);
321 ERR("sendfile Fail errno [%d]\n", errno);
325 if (remove(newpath) < 0)
329 } while (ret == BUFSIZ);
333 #endif /* __USE_STDIO__ */
338 mtp_bool _util_copy_dir_children_recursive(const mtp_char *origpath,
339 const mtp_char *newpath, mtp_uint32 store_id, mtp_int32 *error)
342 struct dirent entry = { 0 };
343 struct dirent *entryptr = NULL;
344 mtp_int32 retval = 0;
345 mtp_char old_pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
346 mtp_char new_pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
347 struct stat entryinfo;
349 retv_if(origpath == NULL, FALSE);
350 retv_if(newpath == NULL, FALSE);
352 /* Open the given directory */
353 dir = opendir(origpath);
355 ERR("opendir(%s) Fail", origpath);
360 retval = readdir_r(dir, &entry, &entryptr);
362 while (retval == 0 && entryptr != NULL) {
363 /* Skip the names "." and ".." as we don't want to recurse on them. */
364 if (!g_strcmp0(entry.d_name, ".") ||
365 !g_strcmp0(entry.d_name, "..")) {
366 retval = readdir_r(dir, &entry, &entryptr);
369 g_snprintf(old_pathname, MTP_MAX_PATHNAME_SIZE + 1,
370 "%s/%s", origpath, entry.d_name);
371 g_snprintf(new_pathname, MTP_MAX_PATHNAME_SIZE + 1,
372 "%s/%s", newpath, entry.d_name);
374 if (stat(old_pathname, &entryinfo) != 0) {
375 ERR("Error statting [%s] errno [%d]\n", old_pathname, errno);
380 /* Create new mtp object */
381 mtp_store_t *store = _device_get_store(store_id);
383 ERR("store is NULL");
388 mtp_obj_t *orig_obj = _entity_get_object_from_store_by_path(store, old_pathname);
389 if (orig_obj == NULL) {
390 ERR("orig_obj is NULL");
395 mtp_obj_t *parent_obj = _entity_get_object_from_store_by_path(store, newpath);
396 if (parent_obj == NULL) {
397 ERR("orig_obj is NULL");
402 mtp_obj_t *new_obj = _entity_alloc_mtp_object();
403 if (new_obj == NULL) {
404 ERR("_entity_alloc_mtp_object Fail");
409 memset(new_obj, 0, sizeof(mtp_obj_t));
411 new_obj->child_array.type = UINT32_TYPE;
412 _entity_copy_mtp_object(new_obj, orig_obj);
413 if (new_obj->obj_info == NULL) {
414 _entity_dealloc_mtp_obj(new_obj);
419 _entity_set_object_file_path(new_obj, new_pathname, CHAR_TYPE);
420 new_obj->obj_handle = _entity_generate_next_obj_handle();
421 new_obj->obj_info->h_parent = parent_obj->obj_handle;
423 if (S_ISDIR(entryinfo.st_mode)) {
424 if (FALSE == _util_dir_create(new_pathname, error)) {
425 /* dir already exists
426 merge the contents */
427 if (EEXIST != *error) {
428 ERR("directory[%s] create Fail errno [%d]\n", new_pathname, errno);
429 _entity_dealloc_mtp_obj(new_obj);
435 /* The directory is created. Add object to mtp store */
436 _entity_add_object_to_store(store, new_obj);
438 if (FALSE == _util_copy_dir_children_recursive(old_pathname,
439 new_pathname, store_id, error)) {
440 ERR("Recursive Copy of Children Fail\
441 [%s]->[%s], errno [%d]\n", old_pathname, new_pathname, errno);
446 if (FALSE == _util_file_copy(old_pathname, new_pathname, error)) {
447 ERR("file copy fail [%s]->[%s]\n",
448 old_pathname, new_pathname);
449 /* Cannot overwrite a read-only file,
450 Skip copy and retain the read-only file
452 if (EACCES == *error)
454 _entity_dealloc_mtp_obj(new_obj);
458 #ifdef MTP_SUPPORT_SET_PROTECTION
459 mtp_bool ret = FALSE;
461 if (!((S_IWUSR & entryInfo.st_mode) ||
462 (S_IWGRP & entryInfo.st_mode) ||
463 (S_IWOTH & entryInfo.st_mode))) {
464 ret = _util_set_file_attrs(newPathName,
465 MTP_FILE_ATTR_MODE_REG |
466 MTP_FILE_ATTR_MODE_READ_ONLY);
468 ERR("Failed to set directory attributes errno [%d]\n", errno);
469 _entity_dealloc_mtp_obj(new_obj);
474 #endif /* MTP_SUPPORT_SET_PROTECTION */
475 /* The file is created. Add object to mtp store */
476 _entity_add_object_to_store(store, new_obj);
479 retval = readdir_r(dir, &entry, &entryptr);
483 return (retval == 0) ? TRUE : FALSE;
486 mtp_bool _util_file_move(const mtp_char *origpath, const mtp_char *newpath,
491 ret = rename(origpath, newpath);
493 if (errno == EXDEV) {
494 DBG("oldpath and newpath are not on the same\
495 mounted file system.");
496 if (_util_file_copy(origpath, newpath, error) == FALSE) {
497 ERR("_util_file_copy Fail errno [%d]\n", errno);
500 if (remove(origpath) < 0) {
501 ERR("remove Fail : %d\n", errno);
505 ERR("rename Fail : %d\n", errno);
514 mtp_bool _util_is_file_opened(const mtp_char *fullpath)
518 ret = rename(fullpath, fullpath);
522 mtp_bool _util_dir_create(const mtp_char *dirname, mtp_int32 *error)
525 if (mkdir(dirname, S_IRWXU | S_IRGRP |
526 S_IXGRP | S_IROTH | S_IXOTH) < 0) {
533 mtp_int32 _util_remove_dir_children_recursive(const mtp_char *dirname,
534 mtp_uint32 *num_of_deleted_file, mtp_uint32 *num_of_file, mtp_bool breadonly)
536 retv_if(dirname == NULL, FALSE);
539 struct dirent entry = { 0 };
540 struct dirent *entryptr = NULL;
541 mtp_int32 retval = 0;
542 mtp_char pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
543 struct stat entryinfo;
544 mtp_int32 ret = MTP_ERROR_NONE;
546 /* Open the given directory */
547 dir = opendir(dirname);
549 ERR("Open directory Fail[%s], errno [%d]", dirname, errno);
550 return MTP_ERROR_GENERAL;
553 retval = readdir_r(dir, &entry, &entryptr);
555 while (retval == 0 && entryptr != NULL) {
556 /* Skip the names "." and ".."
557 as we don't want to recurse on them. */
558 if (!g_strcmp0(entry.d_name, ".") ||
559 !g_strcmp0(entry.d_name, "..")) {
560 retval = readdir_r(dir, &entry, &entryptr);
563 g_snprintf(pathname, MTP_MAX_PATHNAME_SIZE + 1,
564 "%s/%s", dirname, entry.d_name);
565 if (stat(pathname, &entryinfo) != 0) {
566 ERR("Error statting %s errno [%d]\n", pathname, errno);
568 return MTP_ERROR_GENERAL;
571 if (S_ISDIR(entryinfo.st_mode)) {
572 ret = _util_remove_dir_children_recursive(pathname,
573 num_of_deleted_file, num_of_file, breadonly);
574 if (MTP_ERROR_GENERAL == ret || MTP_ERROR_ACCESS_DENIED == ret) {
575 ERR("deletion fail [%s]\n", pathname);
579 if (MTP_ERROR_OBJECT_WRITE_PROTECTED == ret) {
580 DBG("Folder[%s] contains read-only files,hence\
581 folder is not deleted\n", pathname);
582 /* Read the next entry */
585 if (rmdir(pathname) < 0) {
586 ERR("deletion fail [%s], errno [%d]\n", pathname, errno);
589 return MTP_ERROR_ACCESS_DENIED;
590 return MTP_ERROR_GENERAL;
592 *num_of_deleted_file += 1;
594 /* Only during Deleteobject, bReadOnly(TRUE)
595 do not delete read-only files */
596 #ifdef MTP_SUPPORT_SET_PROTECTION
598 /* check for file attributes */
599 if (!((S_IWUSR & entryinfo.st_mode) ||
600 (S_IWGRP & entryinfo.st_mode) ||
601 (S_IWOTH & entryinfo.st_mode))) {
602 ret = MTP_ERROR_OBJECT_WRITE_PROTECTED;
603 DBG("File [%s] is readOnly:Deletion Fail\n", pathname);
607 #endif /* MTP_SUPPORT_SET_PROTECTION */
608 if (unlink(pathname) < 0) {
609 ERR("deletion fail [%s], errno [%d]\n", pathname, errno);
612 return MTP_ERROR_ACCESS_DENIED;
613 return MTP_ERROR_GENERAL;
615 *num_of_deleted_file += 1;
618 retval = readdir_r(dir, &entry, &entryptr);
621 return MTP_ERROR_GENERAL;
631 * mtp_bool _util_get_file_attrs(const mtp_char *filename, file_attr_t *attrs)
632 * This function gets the file attributes.
634 * @param[in] filename Specifies the name of file to find.
635 * @param[out] attrs Points the file Attributes.
636 * @return This function returns TRUE if gets the attributes
637 * successfully, otherwise FALSE.
639 mtp_bool _util_get_file_attrs(const mtp_char *filename, file_attr_t *attrs)
641 struct stat fileinfo = { 0 };
643 if (stat(filename, &fileinfo) < 0) {
644 ERR_SECURE("%s : stat Fail errno [%d]\n", filename, errno);
648 memset(attrs, 0, sizeof(file_attr_t));
649 attrs->fsize = (mtp_uint64)fileinfo.st_size;
650 attrs->ctime = fileinfo.st_ctime;
651 attrs->mtime = fileinfo.st_mtime;
653 /*Reset attribute mode */
654 attrs->attribute = MTP_FILE_ATTR_MODE_NONE;
655 if (S_ISREG(fileinfo.st_mode)) {
656 /* LCOV_EXCL_START */
657 attrs->attribute |= MTP_FILE_ATTR_MODE_REG;
658 if (!((S_IWUSR & fileinfo.st_mode) ||
659 (S_IWGRP & fileinfo.st_mode) ||
660 (S_IWOTH & fileinfo.st_mode))) {
661 attrs->attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
663 } else if (S_ISDIR(fileinfo.st_mode)) {
664 attrs->attribute |= MTP_FILE_ATTR_MODE_DIR;
665 } else if (S_ISBLK(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) ||
666 S_ISLNK(fileinfo.st_mode) || S_ISSOCK(fileinfo.st_mode)) {
667 attrs->attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
672 mtp_bool _util_set_file_attrs(const mtp_char *filename, mtp_dword attrib)
676 if (MTP_FILE_ATTR_MODE_REG & attrib) {
678 if (MTP_FILE_ATTR_MODE_READ_ONLY & attrib)
679 attrs |= (S_IRUSR | S_IRGRP | S_IROTH);
681 attrs |= (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
683 /* do nothing for files other than File/Folder */
684 DBG("entered here nothing");
688 if (0 != chmod(filename, attrs)) {
691 ERR_SECURE("Change mode of [File : %s] Fail\n", filename);
700 * mtp_bool _util_ifind_first(mtp_char *dirname, DIR **dirp,
701 * dir_entry_t *dir_info)
702 * This function finds the first file in the directory stream.
704 * @param[in] dirname specifies the name of directory.
705 * @param[out] dirp pointer to the directory stream.
706 * @param[in] dir_info pointer to the file information.
707 * @return This function returns TRUE on success, otherwise FALSE.
709 mtp_bool _util_ifind_first(mtp_char *dirname, DIR **dirp, dir_entry_t *dir_info)
713 retv_if(dirp == NULL, FALSE);
714 retv_if(dirname == NULL, FALSE);
715 retv_if(dir_info == NULL, FALSE);
717 dir = opendir(dirname);
719 /* LCOV_EXCL_START */
720 ERR("opendir(%s) Fail", dirname);
726 if (_util_ifind_next(dirname, dir, dir_info) == FALSE) {
727 DBG("Stop enumeration");
740 * mtp_bool _util_ifind_next(mtp_char *dirname, DIR *dirp, dir_entry_t *dir_info)
741 * This function finds the next successive file in the directory stream.
743 * @param[in] dirname name of the directory.
744 * @param[in] dirp pointer to the directory stream.
745 * @param[out] dir_info Points the file information.
746 * @return This function returns TRUE on success, otherwise FALSE.
748 mtp_bool _util_ifind_next(mtp_char *dir_name, DIR *dirp, dir_entry_t *dir_info)
751 struct dirent entry = {0};
752 struct stat stat_buf = {0};
753 struct dirent *result = NULL;
754 mtp_char path_name[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
756 retv_if(dir_name == NULL, FALSE);
757 retv_if(dir_info == NULL, FALSE);
760 ret = readdir_r(dirp, &entry, &result);
762 ERR("readdir_r Fail : %d\n", ret);
764 } else if (result == NULL) {
765 DBG("There is no more entry");
769 if (_util_create_path(path_name, sizeof(path_name),
770 dir_name, entry.d_name) == FALSE) {
774 if (stat(path_name, &stat_buf) < 0) {
775 ERR_SECURE("stat Fail, skip [%s]\n", path_name);
781 g_strlcpy(dir_info->filename, path_name, sizeof(dir_info->filename));
782 dir_info->attrs.attribute = MTP_FILE_ATTR_MODE_NONE;
784 switch (stat_buf.st_mode & S_IFMT) {
786 dir_info->type = MTP_FILE_TYPE;
787 if (!(stat_buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
788 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
792 dir_info->type = MTP_DIR_TYPE;
793 dir_info->attrs.attribute = MTP_FILE_ATTR_MODE_DIR;
801 /* LCOV_EXCL_START */
802 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
806 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
807 ERR_SECURE("%s has unknown type. mode[0x%x]\n",
808 dir_info->filename, stat_buf.st_mode);
813 /* Directory Information */
814 dir_info->attrs.mtime = stat_buf.st_mtime;
815 dir_info->attrs.fsize = (mtp_uint64)stat_buf.st_size;
820 /* LCOV_EXCL_START */
821 mtp_bool _util_get_filesystem_info_ext(mtp_char *storepath,
824 struct statfs buf = { 0 };
825 mtp_uint64 avail_size = 0;
826 mtp_uint64 capacity = 0;
827 mtp_uint64 used_size = 0;
829 if (statfs(storepath, &buf) != 0) {
830 ERR("statfs is failed\n");
834 capacity = used_size = avail_size = (mtp_uint64)buf.f_bsize;
835 DBG("Block size : %lu\n", (unsigned long)buf.f_bsize);
836 capacity *= buf.f_blocks;
837 used_size *= (buf.f_blocks - buf.f_bavail);
838 avail_size *= buf.f_bavail;
840 fs_info->disk_size = capacity;
841 fs_info->reserved_size = used_size;
842 fs_info->avail_size = avail_size;
848 mtp_bool _util_get_filesystem_info_int(mtp_char *storepath, fs_info_t *fs_info)
853 mtp_uint64 avail_size = 0;
854 mtp_uint64 capacity = 0;
855 mtp_uint64 used_size = 0;
857 ret = storage_get_internal_memory_size(&s);
859 ERR("storage_get_internal_memory_size : ret = %d", ret);
863 capacity = (mtp_uint64)s.f_frsize*s.f_blocks;
864 avail_size = (mtp_uint64)s.f_bsize*s.f_bavail;
865 used_size = (capacity - avail_size);
867 DBG("total : %llu , avail %llu , used %llu", capacity, avail_size, used_size);
869 fs_info->disk_size = capacity;
870 fs_info->reserved_size = used_size;
871 fs_info->avail_size = avail_size;
876 mtp_bool _util_get_filesystem_info(mtp_char *storepath,
879 if (!g_strcmp0(storepath, MTP_EXTERNAL_PATH_CHAR))
880 return _util_get_filesystem_info_ext(storepath, fs_info);
882 return _util_get_filesystem_info_int(storepath, fs_info);
887 /* LCOV_EXCL_START */
888 void _util_count_num_lines(FILE* fhandle, mtp_uint32 *num_lines)
893 mtp_uint32 line_count = 0;
894 mtp_char *buffer = NULL;
895 mtp_int32 read_bytes;
896 mtp_uint32 line_max_length;
898 line_max_length = LINUX_MAX_PATHNAME_LENGTH + 2;
899 buffer = (mtp_char *)g_malloc(line_max_length);
900 if (buffer == NULL) {
906 while ((read_bytes = getline(&buffer,
907 (size_t *)&line_max_length, fhandle)) != -1) {
908 if (read_bytes > MTP_MAX_PATHNAME_SIZE + 1)
912 #else /* __USE_STDIO__ */
915 mtp_uint32 prev_pos = -1;
917 mtp_uint32 filename_len = 0;
918 while ((read_bytes = read(fhandle, buffer, LINUX_MAX_PATHNAME_LENGTH)) > 0) {
919 for (ii = 0; ii < read_bytes; ii++) {
920 if (buffer[ii] != '\n')
923 filename_len = new_pos - prev_pos -1;
925 if (filename_len > MTP_MAX_PATHNAME_SIZE)
929 if (buffer[read_bytes - 1] != '\n')
930 _util_file_seek(fhandle, prev_pos + 1 - read_bytes, SEEK_CUR);
934 #endif /* __USE_STDIO__ */
936 *num_lines = line_count;
941 void _util_fill_guid_array(void *guidarray, mtp_uint32 start_index,
942 FILE* fhandle, mtp_uint32 size)
944 ptp_array_t *pguidarray = NULL;
945 mtp_uint32 *guidptr = NULL;
946 mtp_uint32 num_lines = 0;
947 mtp_wchar objfullpath[MTP_MAX_PATHNAME_SIZE * 2 + 1] = { 0 };
948 mtp_char guid[16] = { 0 };
949 mtp_char *buffer = NULL;
950 mtp_uint32 line_max_length;
953 line_max_length = LINUX_MAX_PATHNAME_LENGTH + 2;
954 pguidarray = (ptp_array_t *)guidarray;
955 guidptr = (mtp_uint32 *)(pguidarray->array_entry);
957 buffer = (mtp_char *)g_malloc(line_max_length);
958 if (buffer == NULL) {
964 while ((len = getline(&buffer, (size_t *)&line_max_length, fhandle)) != -1 &&
965 (num_lines - start_index) <= size) {
966 if (len > MTP_MAX_PATHNAME_SIZE + 1)
969 if (num_lines < start_index)
971 buffer[len - 1] = '\0';
972 _util_utf8_to_utf16(objfullpath,
973 sizeof(objfullpath) / WCHAR_SIZ, buffer);
974 _util_conv_wstr_to_guid(objfullpath, (mtp_uint64 *)guid);
975 memcpy(&(guidptr[pguidarray->num_ele]),
977 pguidarray->num_ele += sizeof(mtp_uint32);
979 #else /* __USE_STDIO__ */
981 mtp_uint32 prev_pos = -1;
983 mtp_char file_name[MTP_MAX_PATHNAME_SIZE + 1];
984 mtp_int32 read_bytes;
986 while ((read_bytes = read(fhandle, buffer,
987 LINUX_MAX_PATHNAME_LENGTH)) > 0 &&
988 (num_lines - start_index) <= size) {
990 for (ii = 0; ii < read_bytes; ii++) {
991 if (buffer[ii] != '\n')
994 len = new_pos - prev_pos - 1;
996 if (len > MTP_MAX_PATHNAME_SIZE)
999 if (num_lines < start_index)
1001 strncpy(file_name, &buffer[new_pos - len], len);
1002 file_name[len] = '\0';
1003 _util_utf8_to_utf16(objfullpath,
1004 sizeof(objfullpath) / WCHAR_SIZ, file_name);
1005 _util_conv_wstr_to_guid(objfullpath, (mtp_uint64 *)guid);
1006 memcpy(&(guidptr[pguidarray->num_elements]),
1007 guid, sizeof(guid));
1008 pguidarray->num_elements += sizeof(mtp_uint32);
1011 if (buffer[read_bytes - 1] != '\n')
1012 _util_file_seek(fhandle, prev_pos + 1 - read_bytes, SEEK_CUR);
1016 #endif /* __USE_STDIO__ */
1024 * void FLOGD(const char *fmt, ...)
1025 * This function writes MTP debug message to MTP log file
1027 * @param[in] fmt Formatted debug message.
1031 void FLOGD(const char *fmt, ...)
1033 static mtp_int64 written_bytes = 0;
1037 if (written_bytes == 0 || written_bytes > MTP_LOG_MAX_SIZE) {
1038 fp = fopen(MTP_LOG_FILE, "w");
1041 fp = fopen(MTP_LOG_FILE, "a+");
1047 written_bytes += fprintf(fp, "%s ", __FILE__);
1049 written_bytes += vfprintf(fp, fmt, ap);
1055 /* LCOV_EXCL_STOP */