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>
31 #include "mtp_support.h"
32 #include "ptp_datacodes.h"
39 * mtp_uint32 _util_file_open(const mtp_char *filename,
40 * file_mode_t mode, mtp_int32 *error)
41 * This function opens the file in specific mode.
43 * @param[in] filename Specifies the name of file to open.
44 * @param[in] mode Specifies the mode of file to open.
45 * @param[out] error Specifies the type of error
46 * @return This function returns the file handle on success,
47 or INVALID_FILE on failure
49 FILE* _util_file_open(const mtp_char *filename, file_mode_t mode,
69 case MTP_FILE_READ | MTP_FILE_WRITE:
73 case MTP_FILE_READ | MTP_FILE_WRITE | MTP_FILE_APPEND:
78 ERR("Invalid mode : %d\n", mode);
83 fhandle = fopen(filename, fmode);
84 if (fhandle == NULL) {
85 ERR("File open Fail:mode[0x%x], errno [%d]\n", mode, errno);
86 ERR_SECURE("filename[%s]\n", filename);
91 fcntl(fileno(fhandle), F_SETFL, O_NOATIME);
95 #else /* __USE_STDIO__ */
97 mtp_int32 fhandle = 0;
107 flags = O_WRONLY | O_CREAT | O_TRUNC;
111 case MTP_FILE_APPEND:
112 flags = O_WRONLY | O_APPEND | O_CREAT;
116 case MTP_FILE_READ | MTP_FILE_WRITE:
120 case MTP_FILE_READ | MTP_FILE_WRITE | MTP_FILE_APPEND:
121 flags = O_RDWR | O_APPEND | O_CREAT;
126 ERR("Invalid mode : %d\n", mode);
132 fhandle = open(filename, flags, perm);
134 fhandle = open(filename, flags);
137 ERR("File open Fail:mode[0x%x], errno [%d]\n", mode, errno);
138 ERR_SECURE("filename[%s]\n", filename);
144 #endif /* __USE_STDIO__ */
148 * void _util_file_read(mtp_uint32 handle, void *bufptr, mtp_uint32 size,
149 * mtp_uint32 *preadcount)
151 * This function reads data from the file handle into the data buffer.
153 * @param[in] handle Specifies the handle of file to read.
154 * @param[out] bufptr Points to buff where data is to be read.
155 * @param[in] size Specifies the num bytes to be read.
156 * @param[out] preadcount Will store the actual num bytes read.
159 void _util_file_read(FILE* fhandle, void *bufptr, mtp_uint32 size,
160 mtp_uint32 *read_count)
162 mtp_uint32 bytes_read = 0;
165 bytes_read = fread_unlocked(bufptr, sizeof(mtp_char), size, fhandle);
166 #else /* __USE_STDIO__ */
167 bytes_read = read(fhandle, bufptr, size);
168 #endif /* __USE_STDIO__ */
170 *read_count = bytes_read;
173 * mtp_uint32 _util_file_write(mtp_uint32 fhandle, void *bufptr, mtp_uint32 size)
175 * This function writes data to the file using the data buffer passed.
177 * @param[in] handle Specifies the handle of file to write.
178 * @param[in] bufptr Points the buffer which holds the data.
179 * @param[in] size Specifies num bytes to be written.
180 * @return This function returns num bytes written.
183 mtp_uint32 _util_file_write(FILE* fhandle, void *bufptr, mtp_uint32 size)
185 mtp_uint32 bytes_written = 0;
188 bytes_written = fwrite_unlocked(bufptr, sizeof(mtp_char), size, fhandle);
189 #else /* __USE_STDIO__ */
192 ret = write(fhandle, bufptr, size);
197 #endif /* __USE_STDIO__ */
199 return bytes_written;
203 * mtp_int32 _util_file_close(mtp_uint32 fhandle)
204 * This function closes the file.
206 * @param[in] handle Specifies the handle of file to close.
207 * @return 0 in case of success or EOF on failure.
209 mtp_int32 _util_file_close(FILE* fhandle)
212 return fclose(fhandle);
213 #else /* __USE_STDIO__ */
214 return close(fhandle);
215 #endif /* __USE_STDIO__ */
219 * This function seeks to a particular location in a file.
221 * @param[in] handle Specifies the handle of file to seek.
222 * @param[in] offset Specifies the starting point.
223 * @param[in] whence Specifies the setting value
224 * @return Returns TRUE in case of success or FALSE on Failure.
226 mtp_bool _util_file_seek(FILE* handle, off_t offset, mtp_int32 whence)
228 mtp_int64 ret_val = 0;
231 ret_val = fseek(handle, offset, whence);
232 #else /* __USE_STDIO__ */
233 ret_val = lseek(handle, offset, whence);
236 #endif /* __USE_STDIO__ */
238 ERR(" _util_file_seek error errno [%d]\n", errno);
245 mtp_bool _util_file_copy(const mtp_char *origpath, const mtp_char *newpath,
253 mtp_char buf[BUFSIZ] = { 0 };
255 if ((fold = fopen(origpath, "rb")) == NULL) {
256 ERR("In-file open Fail errno [%d]\n", errno);
261 if ((fnew = fopen(newpath, "wb")) == NULL) {
262 ERR("Out-file open Fail errno [%d]\n", errno);
269 nmemb = fread(buf, sizeof(mtp_char), BUFSIZ, fold);
270 if (nmemb < BUFSIZ && ferror(fold)) {
271 ERR("fread Fail errno [%d] \n", errno);
275 if (remove(newpath) < 0)
280 ret = fwrite(buf, sizeof(mtp_char), nmemb, fnew);
281 if (ret < nmemb && ferror(fnew)) {
282 ERR("fwrite Fail errno [%d]\n", errno);
286 if (remove(newpath) < 0)
290 } while (!feof(fold));
294 #else /* __USE_STDIO__ */
296 mtp_int32 out_fd = 0;
300 if ((in_fd = open(origpath, O_RDONLY)) < 0) {
301 ERR("In-file open Fail, errno [%d]\n", errno);
306 if ((out_fd = open(newpath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) {
307 ERR("Out-file open Fail errno [%d] \n", errno);
314 ret = sendfile(out_fd, in_fd, &offset, BUFSIZ);
316 ERR("sendfile Fail errno [%d]\n", errno);
320 if (remove(newpath) < 0)
324 } while (ret == BUFSIZ);
328 #endif /* __USE_STDIO__ */
333 mtp_bool _util_copy_dir_children_recursive(const mtp_char *origpath,
334 const mtp_char *newpath, mtp_int32 *error)
337 struct dirent entry = { 0 };
338 struct dirent *entryptr = NULL;
339 mtp_int32 retval = 0;
340 mtp_char old_pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
341 mtp_char new_pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
342 struct stat entryinfo;
344 retv_if(origpath == NULL, FALSE);
345 retv_if(newpath == NULL, FALSE);
347 /* Open the given directory */
348 dir = opendir(origpath);
350 ERR("opendir(%s) Fail", origpath);
355 retval = readdir_r(dir, &entry, &entryptr);
357 while (retval == 0 && entryptr != NULL) {
358 /* Skip the names "." and ".." as we don't want to recurse on them. */
359 if (!g_strcmp0(entry.d_name, ".") ||
360 !g_strcmp0(entry.d_name, "..")) {
361 retval = readdir_r(dir, &entry, &entryptr);
364 g_snprintf(old_pathname, MTP_MAX_PATHNAME_SIZE + 1,
365 "%s/%s", origpath, entry.d_name);
366 g_snprintf(new_pathname, MTP_MAX_PATHNAME_SIZE + 1,
367 "%s/%s", newpath, entry.d_name);
369 if (stat(old_pathname, &entryinfo) != 0) {
370 ERR("Error statting [%s] errno [%d]\n", old_pathname, errno);
375 if (S_ISDIR(entryinfo.st_mode)) {
376 if (FALSE == _util_dir_create(new_pathname, error)) {
377 /* dir already exists
378 merge the contents */
379 if (EEXIST != *error) {
380 ERR("directory[%s] create Fail errno [%d]\n", new_pathname, errno);
385 if (FALSE == _util_copy_dir_children_recursive(old_pathname,
386 new_pathname, error)) {
387 ERR("Recursive Copy of Children Fail\
388 [%s]->[%s], errno [%d]\n", old_pathname, new_pathname, errno);
393 if (FALSE == _util_file_copy(old_pathname, new_pathname, error)) {
394 ERR("file copy fail [%s]->[%s]\n",
395 old_pathname, new_pathname);
396 /* Cannot overwrite a read-only file,
397 Skip copy and retain the read-only file
399 if (EACCES == *error)
404 #ifdef MTP_SUPPORT_SET_PROTECTION
405 mtp_bool ret = FALSE;
407 if (!((S_IWUSR & entryInfo.st_mode) ||
408 (S_IWGRP & entryInfo.st_mode) ||
409 (S_IWOTH & entryInfo.st_mode))) {
410 ret = _util_set_file_attrs(newPathName,
411 MTP_FILE_ATTR_MODE_REG |
412 MTP_FILE_ATTR_MODE_READ_ONLY);
414 ERR("Failed to set directory attributes errno [%d]\n", errno);
419 #endif /* MTP_SUPPORT_SET_PROTECTION */
422 retval = readdir_r(dir, &entry, &entryptr);
426 return (retval == 0) ? TRUE : FALSE;
429 mtp_bool _util_file_move(const mtp_char *origpath, const mtp_char *newpath,
434 ret = rename(origpath, newpath);
436 if (errno == EXDEV) {
437 DBG("oldpath and newpath are not on the same\
438 mounted file system.");
439 if (_util_file_copy(origpath, newpath, error) == FALSE) {
440 ERR("_util_file_copy Fail errno [%d]\n", errno);
443 if (remove(origpath) < 0) {
444 ERR("remove Fail : %d\n", errno);
448 ERR("rename Fail : %d\n", errno);
457 mtp_bool _util_is_file_opened(const mtp_char *fullpath)
461 ret = rename(fullpath, fullpath);
465 mtp_bool _util_dir_create(const mtp_char *dirname, mtp_int32 *error)
468 if (mkdir(dirname, S_IRWXU | S_IRGRP |
469 S_IXGRP | S_IROTH | S_IXOTH) < 0) {
476 mtp_int32 _util_remove_dir_children_recursive(const mtp_char *dirname,
477 mtp_uint32 *num_of_deleted_file, mtp_uint32 *num_of_file, mtp_bool breadonly)
479 retv_if(dirname == NULL, FALSE);
482 struct dirent entry = { 0 };
483 struct dirent *entryptr = NULL;
484 mtp_int32 retval = 0;
485 mtp_char pathname[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
486 struct stat entryinfo;
487 mtp_int32 ret = MTP_ERROR_NONE;
489 /* Open the given directory */
490 dir = opendir(dirname);
492 ERR("Open directory Fail[%s], errno [%d]", dirname, errno);
493 return MTP_ERROR_GENERAL;
496 retval = readdir_r(dir, &entry, &entryptr);
498 while (retval == 0 && entryptr != NULL) {
499 /* Skip the names "." and ".."
500 as we don't want to recurse on them. */
501 if (!g_strcmp0(entry.d_name, ".") ||
502 !g_strcmp0(entry.d_name, "..")) {
503 retval = readdir_r(dir, &entry, &entryptr);
506 g_snprintf(pathname, MTP_MAX_PATHNAME_SIZE + 1,
507 "%s/%s", dirname, entry.d_name);
508 if (stat(pathname, &entryinfo) != 0) {
509 ERR("Error statting %s errno [%d]\n", pathname, errno);
511 return MTP_ERROR_GENERAL;
514 if (S_ISDIR(entryinfo.st_mode)) {
515 ret = _util_remove_dir_children_recursive(pathname,
516 num_of_deleted_file, num_of_file, breadonly);
517 if (MTP_ERROR_GENERAL == ret || MTP_ERROR_ACCESS_DENIED == ret) {
518 ERR("deletion fail [%s]\n", pathname);
522 if (MTP_ERROR_OBJECT_WRITE_PROTECTED == ret) {
523 DBG("Folder[%s] contains read-only files,hence\
524 folder is not deleted\n", pathname);
525 /* Read the next entry */
528 if (rmdir(pathname) < 0) {
529 ERR("deletion fail [%s], errno [%d]\n", pathname, errno);
532 return MTP_ERROR_ACCESS_DENIED;
533 return MTP_ERROR_GENERAL;
535 *num_of_deleted_file += 1;
537 /* Only during Deleteobject, bReadOnly(TRUE)
538 do not delete read-only files */
539 #ifdef MTP_SUPPORT_SET_PROTECTION
541 /* check for file attributes */
542 if (!((S_IWUSR & entryinfo.st_mode) ||
543 (S_IWGRP & entryinfo.st_mode) ||
544 (S_IWOTH & entryinfo.st_mode))) {
545 ret = MTP_ERROR_OBJECT_WRITE_PROTECTED;
546 DBG("File [%s] is readOnly:Deletion Fail\n", pathname);
550 #endif /* MTP_SUPPORT_SET_PROTECTION */
551 if (unlink(pathname) < 0) {
552 ERR("deletion fail [%s], errno [%d]\n", pathname, errno);
555 return MTP_ERROR_ACCESS_DENIED;
556 return MTP_ERROR_GENERAL;
558 *num_of_deleted_file += 1;
561 retval = readdir_r(dir, &entry, &entryptr);
564 return MTP_ERROR_GENERAL;
573 * mtp_bool _util_get_file_attrs(const mtp_char *filename, file_attr_t *attrs)
574 * This function gets the file attributes.
576 * @param[in] filename Specifies the name of file to find.
577 * @param[out] attrs Points the file Attributes.
578 * @return This function returns TRUE if gets the attributes
579 * successfully, otherwise FALSE.
581 mtp_bool _util_get_file_attrs(const mtp_char *filename, file_attr_t *attrs)
583 struct stat fileinfo = { 0 };
585 if (stat(filename, &fileinfo) < 0) {
586 ERR_SECURE("%s : stat Fail errno [%d]\n", filename, errno);
590 memset(attrs, 0, sizeof(file_attr_t));
591 attrs->fsize = (mtp_uint64)fileinfo.st_size;
592 attrs->ctime = fileinfo.st_ctime;
593 attrs->mtime = fileinfo.st_mtime;
595 /*Reset attribute mode */
596 attrs->attribute = MTP_FILE_ATTR_MODE_NONE;
597 if (S_ISREG(fileinfo.st_mode)) {
598 attrs->attribute |= MTP_FILE_ATTR_MODE_REG;
599 if (!((S_IWUSR & fileinfo.st_mode) ||
600 (S_IWGRP & fileinfo.st_mode) ||
601 (S_IWOTH & fileinfo.st_mode))) {
602 attrs->attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
604 } else if (S_ISDIR(fileinfo.st_mode)) {
605 attrs->attribute |= MTP_FILE_ATTR_MODE_DIR;
606 } else if (S_ISBLK(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) ||
607 S_ISLNK(fileinfo.st_mode) || S_ISSOCK(fileinfo.st_mode)) {
608 attrs->attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
613 mtp_bool _util_set_file_attrs(const mtp_char *filename, mtp_dword attrib)
617 if (MTP_FILE_ATTR_MODE_REG & attrib) {
619 if (MTP_FILE_ATTR_MODE_READ_ONLY & attrib)
620 attrs |= (S_IRUSR | S_IRGRP | S_IROTH);
622 attrs |= (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
624 /* do nothing for files other than File/Folder */
625 DBG("entered here nothing");
629 if (0 != chmod(filename, attrs)) {
632 ERR_SECURE("Change mode of [File : %s] Fail\n", filename);
640 * mtp_bool _util_ifind_first(mtp_char *dirname, DIR **dirp,
641 * dir_entry_t *dir_info)
642 * This function finds the first file in the directory stream.
644 * @param[in] dirname specifies the name of directory.
645 * @param[out] dirp pointer to the directory stream.
646 * @param[in] dir_info pointer to the file information.
647 * @return This function returns TRUE on success, otherwise FALSE.
649 mtp_bool _util_ifind_first(mtp_char *dirname, DIR **dirp, dir_entry_t *dir_info)
653 retv_if(dirp == NULL, FALSE);
654 retv_if(dirname == NULL, FALSE);
655 retv_if(dir_info == NULL, FALSE);
657 dir = opendir(dirname);
659 ERR("opendir(%s) Fail", dirname);
665 if (_util_ifind_next(dirname, dir, dir_info) == FALSE) {
666 DBG("Stop enumeration");
678 * mtp_bool _util_ifind_next(mtp_char *dirname, DIR *dirp, dir_entry_t *dir_info)
679 * This function finds the next successive file in the directory stream.
681 * @param[in] dirname name of the directory.
682 * @param[in] dirp pointer to the directory stream.
683 * @param[out] dir_info Points the file information.
684 * @return This function returns TRUE on success, otherwise FALSE.
686 mtp_bool _util_ifind_next(mtp_char *dir_name, DIR *dirp, dir_entry_t *dir_info)
689 struct dirent entry = {0};
690 struct stat stat_buf = {0};
691 struct dirent *result = NULL;
692 mtp_char path_name[MTP_MAX_PATHNAME_SIZE + 1] = { 0 };
694 retv_if(dir_name == NULL, FALSE);
695 retv_if(dir_info == NULL, FALSE);
698 ret = readdir_r(dirp, &entry, &result);
700 ERR("readdir_r Fail : %d\n", ret);
702 } else if (result == NULL) {
703 DBG("There is no more entry");
707 if (_util_create_path(path_name, sizeof(path_name),
708 dir_name, entry.d_name) == FALSE) {
712 if (stat(path_name, &stat_buf) < 0) {
713 ERR_SECURE("stat Fail, skip [%s]\n", path_name);
719 g_strlcpy(dir_info->filename, path_name, sizeof(dir_info->filename));
720 dir_info->attrs.attribute = MTP_FILE_ATTR_MODE_NONE;
722 switch (stat_buf.st_mode & S_IFMT) {
724 dir_info->type = MTP_FILE_TYPE;
725 if (!(stat_buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
726 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_READ_ONLY;
730 dir_info->type = MTP_DIR_TYPE;
731 dir_info->attrs.attribute = MTP_FILE_ATTR_MODE_DIR;
739 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
743 dir_info->attrs.attribute |= MTP_FILE_ATTR_MODE_SYSTEM;
744 ERR_SECURE("%s has unknown type. mode[0x%x]\n",
745 dir_info->filename, stat_buf.st_mode);
749 /* Directory Information */
750 dir_info->attrs.mtime = stat_buf.st_mtime;
751 dir_info->attrs.fsize = (mtp_uint64)stat_buf.st_size;
756 mtp_bool _util_get_filesystem_info(mtp_char *storepath, fs_info_t *fs_info)
758 struct statfs buf = { 0 };
759 mtp_uint64 avail_size = 0;
760 mtp_uint64 capacity = 0;
761 mtp_uint64 used_size = 0;
763 if (statfs(storepath, &buf) != 0) {
768 capacity = used_size = avail_size = (mtp_uint64)buf.f_bsize;
769 DBG("Block size : %d\n", buf.f_bsize);
770 capacity *= buf.f_blocks;
771 used_size *= (buf.f_blocks - buf.f_bavail);
772 avail_size *= buf.f_bavail;
774 fs_info->disk_size = capacity;
775 fs_info->reserved_size = used_size;
776 fs_info->avail_size = avail_size;
781 void _util_count_num_lines(FILE* fhandle, mtp_uint32 *num_lines)
786 mtp_uint32 line_count = 0;
787 mtp_char *buffer = NULL;
788 mtp_int32 read_bytes;
789 mtp_uint32 line_max_length;
791 line_max_length = LINUX_MAX_PATHNAME_LENGTH + 2;
792 buffer = (mtp_char *)g_malloc(line_max_length);
793 if (buffer == NULL) {
799 while ((read_bytes = getline(&buffer,
800 (size_t *)&line_max_length, fhandle)) != -1) {
801 if (read_bytes > MTP_MAX_PATHNAME_SIZE + 1)
805 #else /* __USE_STDIO__ */
808 mtp_uint32 prev_pos = -1;
810 mtp_uint32 filename_len = 0;
811 while ((read_bytes = read(fhandle, buffer, LINUX_MAX_PATHNAME_LENGTH)) > 0) {
812 for (ii = 0; ii < read_bytes; ii++) {
813 if (buffer[ii] != '\n')
816 filename_len = new_pos - prev_pos -1;
818 if (filename_len > MTP_MAX_PATHNAME_SIZE)
822 if (buffer[read_bytes - 1] != '\n')
823 _util_file_seek(fhandle, prev_pos + 1 - read_bytes, SEEK_CUR);
827 #endif /* __USE_STDIO__ */
829 *num_lines = line_count;
834 void _util_fill_guid_array(void *guidarray, mtp_uint32 start_index,
835 FILE* fhandle, mtp_uint32 size)
837 ptp_array_t *pguidarray = NULL;
838 mtp_uint32 *guidptr = NULL;
839 mtp_uint32 num_lines = 0;
840 mtp_wchar objfullpath[MTP_MAX_PATHNAME_SIZE * 2 + 1] = { 0 };
841 mtp_char guid[16] = { 0 };
842 mtp_char *buffer = NULL;
843 mtp_uint32 line_max_length;
846 line_max_length = LINUX_MAX_PATHNAME_LENGTH + 2;
847 pguidarray = (ptp_array_t *)guidarray;
848 guidptr = (mtp_uint32 *)(pguidarray->array_entry);
850 buffer = (mtp_char *)g_malloc(line_max_length);
851 if (buffer == NULL) {
857 while ((len = getline(&buffer, (size_t *)&line_max_length, fhandle)) != -1 &&
858 (num_lines - start_index) <= size) {
859 if (len > MTP_MAX_PATHNAME_SIZE + 1)
862 if (num_lines < start_index)
864 buffer[len - 1] = '\0';
865 _util_utf8_to_utf16(objfullpath,
866 sizeof(objfullpath) / WCHAR_SIZ, buffer);
867 _util_conv_wstr_to_guid(objfullpath, (mtp_uint64 *)guid);
868 memcpy(&(guidptr[pguidarray->num_ele]),
870 pguidarray->num_ele += sizeof(mtp_uint32);
872 #else /* __USE_STDIO__ */
874 mtp_uint32 prev_pos = -1;
876 mtp_char file_name[MTP_MAX_PATHNAME_SIZE + 1];
877 mtp_int32 read_bytes;
879 while ((read_bytes = read(fhandle, buffer,
880 LINUX_MAX_PATHNAME_LENGTH)) > 0 &&
881 (num_lines - start_index) <= size) {
883 for (ii = 0; ii < read_bytes; ii++) {
884 if (buffer[ii] != '\n')
887 len = new_pos - prev_pos - 1;
889 if (len > MTP_MAX_PATHNAME_SIZE)
892 if (num_lines < start_index)
894 strncpy(file_name, &buffer[new_pos - len], len);
895 file_name[len] = '\0';
896 _util_utf8_to_utf16(objfullpath,
897 sizeof(objfullpath) / WCHAR_SIZ, file_name);
898 _util_conv_wstr_to_guid(objfullpath, (mtp_uint64 *)guid);
899 memcpy(&(guidptr[pguidarray->num_elements]),
901 pguidarray->num_elements += sizeof(mtp_uint32);
904 if (buffer[read_bytes - 1] != '\n')
905 _util_file_seek(fhandle, prev_pos + 1 - read_bytes, SEEK_CUR);
909 #endif /* __USE_STDIO__ */
917 * void FLOGD(const char *fmt, ...)
918 * This function writes MTP debug message to MTP log file
920 * @param[in] fmt Formatted debug message.
924 void FLOGD(const char *fmt, ...)
926 static int written_bytes = 0;
930 if (written_bytes == 0 || written_bytes > MTP_LOG_MAX_SIZE) {
931 fp = fopen(MTP_LOG_FILE, "w");
934 fp = fopen(MTP_LOG_FILE, "a+");
940 written_bytes += fprintf(fp, "%s ", __FILE__);
942 written_bytes += vfprintf(fp, fmt, ap);