2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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.
26 #include "download-agent-debug.h"
27 #include "download-agent-file.h"
28 #include "download-agent-mime-util.h"
30 #include "download-agent-http-msg-handler.h"
31 #include "download-agent-plugin-drm.h"
32 #include "download-agent-plugin-conf.h"
33 #include "download-provider-client-manager.h"
37 #define NO_NAME_TEMP_STR "No name"
38 #define MAX_SUFFIX_COUNT 1000000000
46 da_ret_t __saved_file_open(file_info_t *file_info)
48 da_ret_t ret = DA_RESULT_OK;
49 char *actual_file_path = DA_NULL;
50 char *resolved_path = DA_NULL;
55 actual_file_path = file_info->file_path;
56 if (!actual_file_path)
57 return DA_ERR_INVALID_ARGUMENT;
59 resolved_path = realpath(actual_file_path, NULL);
61 /* Check if actual_file_path is symbolic file or not */
62 if (strcmp(resolved_path, actual_file_path) != 0) {
64 return DA_ERR_INVALID_ARGUMENT;
66 } else if (errno != ENOENT) {
67 return DA_ERR_INVALID_ARGUMENT;
70 fd = fopen(actual_file_path, "a+"); // for resume
72 DA_LOGE("File open failed");
74 ret = DA_ERR_DISK_FULL;
76 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
80 file_info->file_handle = fd;
82 if (DA_RESULT_OK != ret)
83 file_info->file_handle = DA_NULL;
88 da_ret_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char *url, char **out_pure_file_name, char **out_extension)
90 char *file_name = DA_NULL;
91 char *tmp_ptr = DA_NULL;
92 char temp_file[DA_MAX_FILE_NAME_LEN + 1] = {0,};
93 char tmp_ext[DA_MAX_STR_LEN] = {0,};
95 da_ret_t ret = DA_RESULT_OK;
100 return DA_ERR_INVALID_ARGUMENT;
102 file_name = (char *)in_file_name;
104 tmp_ptr = strrchr(file_name, '.');
106 if (tmp_ptr == file_name) {
107 // a leading dot means the file is hidden.
112 if (tmp_ptr && out_extension) {
113 strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1);
114 *out_extension = strdup((const char*) tmp_ext);
115 DA_SECURE_LOGD("extension [%s]", *out_extension);
116 } else if (!tmp_ptr && url) {
117 char *extension = DA_NULL;
118 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
119 if (b_ret && !extension)
120 *out_extension = NULL;
124 if (!out_pure_file_name)
128 len = tmp_ptr - file_name - 1;
130 len = strlen(file_name);
132 if (len >= DA_MAX_FILE_NAME_LEN) {
133 strncpy((char*) temp_file, file_name, DA_MAX_FILE_NAME_LEN);
134 temp_file[DA_MAX_FILE_NAME_LEN] = '\0';
136 strncpy((char*) temp_file, file_name, len);
137 temp_file[len] = '\0';
140 delete_prohibited_char((char*) temp_file,
141 strlen((char*) temp_file));
142 if (strlen(temp_file) < 1) {
143 *out_pure_file_name = strdup(NO_NAME_TEMP_STR);
145 *out_pure_file_name = strdup(
146 (const char*) temp_file);
149 DA_LOGD("pure file name [%s]", *out_pure_file_name);
153 da_ret_t __file_write_buf_make_buf(file_info_t *file_info)
155 da_ret_t ret = DA_RESULT_OK;
156 char *buffer = DA_NULL;
160 buffer = (char*) calloc(1, DA_FILE_BUF_SIZE);
161 if (DA_NULL == buffer) {
162 DA_LOGE("Calloc failure ");
163 ret = DA_ERR_FAIL_TO_MEMALLOC;
165 file_info->buffer_len = 0;
166 file_info->buffer = buffer;
172 da_ret_t __file_write_buf_destroy_buf(file_info_t *file_info)
174 da_ret_t ret = DA_RESULT_OK;
177 NULL_CHECK_RET(file_info);
179 free(file_info->buffer);
180 file_info->buffer = DA_NULL;
181 file_info->buffer_len = 0;
186 da_ret_t __file_write_buf_flush_buf(file_info_t *file_info)
188 da_ret_t ret = DA_RESULT_OK;
189 char *buffer = DA_NULL;
190 size_t buffer_size = 0;
191 size_t write_success_len = 0;
196 buffer = file_info->buffer;
197 buffer_size = file_info->buffer_len;
199 if (buffer_size == 0) {
200 DA_LOGE("no data on buffer..");
204 fd = file_info->file_handle;
206 DA_LOGE("There is no file handle.");
208 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
212 write_success_len = fwrite(buffer, sizeof(char), buffer_size,
214 /* FIXME : This can be necessary later due to progressive download.
215 * The solution for reducing fflush is needed */
216 //fflush((FILE *) fd);
217 if (write_success_len != buffer_size) {
218 DA_LOGE("write fails ");
220 ret = DA_ERR_DISK_FULL;
222 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
225 file_info->bytes_written_to_file += write_success_len;
226 file_info->is_updated = DA_TRUE;
227 file_info->buffer_len = 0;
232 da_ret_t __file_write_buf_copy_to_buf(file_info_t *file_info, char *body,
235 da_ret_t ret = DA_RESULT_OK;
236 char *buffer = DA_NULL;
237 size_t buffer_size = 0;
241 NULL_CHECK_RET(file_info->buffer);
242 buffer = file_info->buffer;
243 buffer_size = file_info->buffer_len;
245 memcpy(buffer + buffer_size, body, body_len);
246 file_info->buffer_len += body_len;
251 da_ret_t __file_write_buf_directly_write(file_info_t *file_info,
252 char *body, int body_len)
254 da_ret_t ret = DA_RESULT_OK;
255 size_t write_success_len = 0;
260 fd = file_info->file_handle;
262 DA_LOGE("There is no file handle.");
263 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
267 write_success_len = fwrite(body, sizeof(char), (size_t)body_len,
269 /* FIXME : This can be necessary later due to progressive download.
270 * The solution for reducing fflush is needed */
271 //fflush((FILE *) fd);
272 if (write_success_len != (size_t)body_len) {
273 DA_LOGE("write fails ");
275 ret = DA_ERR_DISK_FULL;
277 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
280 file_info->bytes_written_to_file += write_success_len;
281 DA_LOGV("write %llu bytes", write_success_len);
282 file_info->is_updated = DA_TRUE;
288 /* Priority to derive extension
289 * 1. extension name which client set
290 * 2. according to MIME-Type
291 * 3. if MIME-Type is ambiguous or blank,
292 * 3-1. derived from <Content-Disposition> field's "filename" attribute
293 * 3-2. derived from url
294 * 4. if url does not have extension, leave blank for extension
296 char *__get_extension_name(char *mime_type,
297 char *file_name_from_header, char *url)
299 char *extension = DA_NULL;
302 if (mime_type && !is_ambiguous_MIME_Type(mime_type)) {
304 DA_LOGV("If the file extension exists and mime type exists, choose the file extension over mime type");
305 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
306 if (b_ret && extension)
309 char *extension = DA_NULL;
310 da_ret_t ret = get_extension_from_mime_type(mime_type, &extension);
311 if (ret == DA_RESULT_OK && extension)
315 if (file_name_from_header) {
316 char *extension = DA_NULL;
317 DA_SECURE_LOGI("Content-Disposition :[%s]", file_name_from_header);
318 __divide_file_name_into_pure_name_N_extesion(file_name_from_header, DA_NULL,
319 DA_NULL, &extension);
325 DA_LOGV("Get extension from url");
326 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
327 if (b_ret && extension)
333 /** Priority for deciding file name
334 * 1. file name which client set
335 * 2. 'filename' option on HTTP response header's Content-Disposition field
337 * 4. Otherwise, define it as "No name"
339 da_ret_t __get_candidate_file_name(const char *user_file_name, char *url,
340 char *file_name_from_header,
341 char **out_pure_file_name, char **out_extension)
343 da_ret_t ret = DA_RESULT_OK;
348 if (user_file_name) {
349 __divide_file_name_into_pure_name_N_extesion(
350 user_file_name, url, out_pure_file_name, out_extension);
352 if (*out_pure_file_name)
355 if (file_name_from_header) {
356 DA_SECURE_LOGI("Content-Disposition:[%s]", file_name_from_header);
357 __divide_file_name_into_pure_name_N_extesion(file_name_from_header, DA_NULL,
358 out_pure_file_name, out_extension);
360 if (*out_pure_file_name)
364 DA_LOGD("Get file name from url");
365 da_get_file_name_from_url(url, out_pure_file_name, out_extension);
367 if (*out_pure_file_name)
370 *out_pure_file_name = strdup(NO_NAME_TEMP_STR);
371 if (*out_pure_file_name == DA_NULL)
372 ret = DA_ERR_FAIL_TO_MEMALLOC;
376 da_ret_t __decide_file_path(da_info_t *da_info)
378 da_ret_t ret = DA_RESULT_OK;
379 char *extension = DA_NULL;
380 char *file_name = DA_NULL;
381 char *tmp_file_path = DA_NULL;
382 char *file_name_from_header = DA_NULL;
384 const char *install_dir = DA_NULL;
385 const char *user_file_name = DA_NULL;
386 file_info_t *file_info = DA_NULL;
387 req_info_t *req_info = DA_NULL;
388 http_info_t *http_info = DA_NULL;
389 dp_client_slots_fmt *slot = DA_NULL;
393 NULL_CHECK_RET(da_info);
394 file_info = da_info->file_info;
395 NULL_CHECK_RET(file_info);
396 req_info = da_info->req_info;
397 NULL_CHECK_RET(req_info);
398 http_info = da_info->http_info;
399 NULL_CHECK_RET(http_info);
400 slot = req_info->user_client_data;
401 NULL_CHECK_RET(slot);
403 if (req_info->install_path)
404 install_dir = (const char *)req_info->install_path;
406 tzplatform_set_user(slot->credential.uid);
407 install_dir = DA_DEFAULT_INSTALL_PATH_FOR_PHONE;
408 tzplatform_reset_user();
410 user_file_name = (const char *)req_info->file_name;
411 /* If there is location url from response header in case of redirection,
412 * it try to parse the file name from the location url */
413 if (http_info->location_url) {
414 url = http_info->location_url;
415 DA_LOGI("[TEST] location_url[%s][%p]", http_info->location_url, http_info->location_url);
419 file_name_from_header = http_info->file_name_from_header;
421 /* extension is extracted only if User set specific name */
422 ret = __get_candidate_file_name(user_file_name, url, file_name_from_header,
423 &file_name, &extension);
424 if (ret != DA_RESULT_OK)
427 if (file_name && strpbrk(file_name, DA_INVALID_PATH_STRING) != NULL) {
428 DA_LOGI("Invalid string at file name");
430 file_name = strdup(NO_NAME_TEMP_STR);
432 ret = DA_ERR_FAIL_TO_MEMALLOC;
438 DA_SECURE_LOGI("candidate file name [%s]", file_name);
441 if (file_info->mime_type
442 && strncmp(file_info->mime_type, "application/x-xz", strlen("application/x-xz"))
443 && strncmp(file_info->mime_type, "application/rss+xml", strlen("application/rss+xml")))
444 extension = __get_extension_name(file_info->mime_type, file_name_from_header, url);
446 extension = __get_extension_name(NULL, file_name_from_header, url);
448 if (file_name && !file_info->pure_file_name) {
449 file_info->pure_file_name = file_name;
452 if (extension && !file_info->extension) {
453 DA_LOGV("candidate extension [%s]", extension);
454 file_info->extension = extension;
459 tmp_file_path = get_full_path_avoided_duplication(install_dir,
460 file_info->pure_file_name, file_info->extension);
462 file_info->file_path = tmp_file_path;
463 tmp_file_path = DA_NULL;
465 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
470 DA_SECURE_LOGI("decided file path [%s]", file_info->file_path);
478 // for resume with new download request
479 da_ret_t __decide_file_path_for_resume(file_info_t *file_info)
481 da_ret_t ret = DA_RESULT_OK;
482 char *extension = DA_NULL;
483 char *file_name = DA_NULL;
484 char *file_path = DA_NULL;
486 char *ptr2 = DA_NULL;
490 NULL_CHECK_RET(file_info);
492 file_path = file_info->file_path;
494 NULL_CHECK_RET(file_path);
496 ptr = strrchr(file_path, '/');
499 ptr2 = strrchr(ptr, '.');
504 extension = strdup(ptr2);
505 file_name = calloc(1, len + 1);
507 snprintf(file_name, len + 1, "%s", ptr);
509 file_name = strdup(ptr);
513 if (file_name && !file_info->pure_file_name) {
514 file_info->pure_file_name = file_name;
519 if (extension && !file_info->extension) {
520 DA_LOGV("candidate extension [%s]", extension);
521 file_info->extension = extension;
529 da_ret_t start_file_writing(da_info_t *da_info)
531 da_ret_t ret = DA_RESULT_OK;
532 file_info_t *file_info = DA_NULL;
533 req_info_t *req_info = DA_NULL;
537 NULL_CHECK_RET(da_info);
538 file_info = da_info->file_info;
539 NULL_CHECK_RET(file_info);
540 req_info = da_info->req_info;
541 NULL_CHECK_RET(req_info);
544 if (req_info->etag || req_info->temp_file_path) {
545 char *file_path = DA_NULL;
546 char *origin_path = DA_NULL;
547 file_path = req_info->temp_file_path;
549 return DA_ERR_INVALID_ARGUMENT;
550 origin_path = file_info->file_path;
551 file_info->file_path = strdup(file_path);
554 ret = __decide_file_path_for_resume(file_info);
556 ret = __decide_file_path(da_info);
559 if (ret != DA_RESULT_OK)
562 if (req_info->etag || req_info->temp_file_path) {
563 da_size_t file_size = 0;
564 get_file_size(req_info->temp_file_path, &file_size);
568 file_info->file_size_of_temp_file = file_size;
570 file_info->bytes_written_to_file = file_size;
572 file_info->bytes_written_to_file = 0;
574 ret = __saved_file_open(file_info);
579 da_ret_t start_file_append(file_info_t *file_info)
581 da_ret_t ret = DA_RESULT_OK;
585 NULL_CHECK_RET(file_info);
587 ret = __saved_file_open(file_info);
591 da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len)
593 da_ret_t ret = DA_RESULT_OK;
594 size_t buffer_size = 0;
595 char *buffer = DA_NULL;
599 buffer = file_info->buffer;
600 buffer_size = file_info->buffer_len;
602 if (DA_NULL == buffer) {
603 if (body_len < DA_FILE_BUF_SIZE) {
604 ret = __file_write_buf_make_buf(file_info);
605 if (ret != DA_RESULT_OK)
607 __file_write_buf_copy_to_buf(file_info, body, body_len);
609 ret = __file_write_buf_directly_write(file_info,
611 if (ret != DA_RESULT_OK)
615 if (DA_FILE_BUF_SIZE <= body_len) {
616 ret = __file_write_buf_flush_buf(file_info);
617 if (ret != DA_RESULT_OK)
619 ret = __file_write_buf_directly_write(file_info,
621 if (ret != DA_RESULT_OK)
623 } else if ((DA_FILE_BUF_SIZE - buffer_size) <= body_len) {
624 ret = __file_write_buf_flush_buf(file_info);
625 if (ret != DA_RESULT_OK)
627 __file_write_buf_copy_to_buf(file_info, body, body_len);
629 __file_write_buf_copy_to_buf(file_info, body, body_len);
633 if (ret != DA_RESULT_OK) {
634 file_info->buffer_len = 0;
635 free(file_info->buffer);
636 file_info->buffer = DA_NULL;
642 da_ret_t file_write_complete_for_raf(file_info_t *file_info)
644 da_ret_t ret = DA_RESULT_OK;
645 char *buffer = DA_NULL;
646 da_size_t wrriten_size = 0;
647 da_size_t file_size = 0;
651 fd = file_info->file_handle;
653 wrriten_size = file_info->bytes_written_to_file;
655 get_file_size(file_info->file_path, &file_size);
656 DA_LOGI("wrriten_size:%llu file_size:%llu file[%s]",
657 wrriten_size, file_size, file_info->file_path);
662 file_info->file_handle = DA_NULL;
663 if (wrriten_size < file_size) {
664 DA_LOGD("Try truncate");
665 if (truncate(file_info->file_path, wrriten_size) < 0)
666 DA_LOGE("Fail to ftruncate: errno[%d]", errno);
667 DA_LOGD("Try truncate done");
675 da_ret_t file_write_complete(file_info_t *file_info)
677 da_ret_t ret = DA_RESULT_OK;
678 char *buffer = DA_NULL;
679 unsigned int buffer_size = 0;
684 buffer = file_info->buffer;
685 buffer_size = file_info->buffer_len;
687 if (DA_NULL == buffer) {
688 DA_LOGE("file buffer is NULL");
690 if (buffer_size != 0) {
691 ret = __file_write_buf_flush_buf(file_info);
692 if (ret != DA_RESULT_OK)
695 __file_write_buf_destroy_buf(file_info);
697 fd = file_info->file_handle;
703 file_info->file_handle = DA_NULL;
708 da_ret_t discard_download(file_info_t *file_info)
710 da_ret_t ret = DA_RESULT_OK;
711 FILE *f_handle = DA_NULL;
715 f_handle = file_info->file_handle;
718 file_info->file_handle = DA_NULL;
723 void clean_paused_file(file_info_t *file_info)
725 char *paused_file_path = DA_NULL;
730 fd = file_info->file_handle;
733 file_info->file_handle = DA_NULL;
736 paused_file_path = file_info->file_path;
737 file_info->bytes_written_to_file = 0; // Ignore resume flow after failed or cancled.
738 remove_file((const char*) paused_file_path);
743 static file_state_e get_file_state(const char *file_path)
745 struct stat dir_state;
748 if (file_path == DA_NULL) {
749 DA_LOGE("file path is DA_NULL");
750 return NOT_EXIST_FILE;
752 stat_ret = stat(file_path, &dir_state);
754 if (dir_state.st_mode & S_IFREG) {
755 //DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size);
761 return NOT_EXIST_FILE;
764 void get_file_size(char *file_path, da_size_t *out_file_size)
766 struct stat dir_state;
771 if (file_path == DA_NULL) {
772 DA_LOGE("file path is DA_NULL");
775 /* Please do not use ftell() to obtain file size, use stat instead.
776 * This is a guide from www.securecoding.cert.org
777 * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file
779 stat_ret = stat(file_path, &dir_state);
781 if (dir_state.st_mode & S_IFREG) {
782 DA_LOGV("size = %lu", dir_state.st_size);
783 *out_file_size = dir_state.st_size;
789 char *get_full_path_avoided_duplication(const char *in_dir,
790 char *in_candidate_file_name, char *in_extension)
793 char *file_name = in_candidate_file_name;
794 char *extension = in_extension;
795 char *final_path = DA_NULL;
797 int dir_path_len = 0;
798 int final_path_len = 0;
799 int extension_len = 0;
801 int suffix_count = 0; /* means suffix on file name. up to "_99" */
802 int suffix_len = (int)log10(MAX_SUFFIX_COUNT + 1) + 1; /* 1 means "_" */
804 if (!in_dir || !in_candidate_file_name)
807 dir = strdup(in_dir);
811 //DA_SECURE_LOGI("in_candidate_file_name=[%s],in_extension=[%s]",
812 //in_candidate_file_name, in_extension);
815 extension_len = strlen(extension);
817 // to remove trailing slash from dir path
818 dir_path_len = strlen(dir);
819 if (dir[dir_path_len - 1] == '/') {
820 dir[dir_path_len - 1] = '\0';
824 /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */
825 final_path_len = dir_path_len + 1 + strlen(file_name) + 1
826 + suffix_len + extension_len + 1;
828 final_path = (char*)calloc(1, final_path_len);
830 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
837 * if there is no extension name, just make a file name without extension */
838 if (0 == extension_len) {
839 if (suffix_count == 0) {
840 snprintf(final_path, final_path_len,
841 "%s/%s", dir, file_name);
843 snprintf(final_path, final_path_len,
844 "%s/%s_%d", dir, file_name, suffix_count);
847 if (suffix_count == 0) {
848 snprintf(final_path, final_path_len,
849 "%s/%s.%s", dir, file_name, extension);
851 snprintf(final_path, final_path_len,
853 dir, file_name, suffix_count, extension);
856 if (get_file_state(final_path) != NOT_EXIST_FILE) {
858 if (suffix_count > MAX_SUFFIX_COUNT) {
860 final_path = DA_NULL;
863 memset(final_path, 0x00, final_path_len);
870 //DA_SECURE_LOGD("decided path = [%s]", final_path);
877 da_ret_t check_drm_convert(file_info_t *file_info)
879 da_ret_t ret = DA_RESULT_OK;
880 #ifdef _ENABLE_OMA_DRM
881 da_bool_t ret_b = DA_TRUE;
886 NULL_CHECK_RET(file_info);
888 #ifdef _ENABLE_OMA_DRM
890 /* In case of OMA DRM 1.0 SD, it is not necessary to call DRM convert API.
891 * Because it is already converted itself.
892 * And, the case will return fail because The SD is not supported now.
894 if (is_content_drm_dcf(file_info->mime_type)) {
895 DA_LOGI("DRM SD case");
896 unlink(file_info->file_path);
897 free(file_info->file_path);
898 file_info->file_path = DA_NULL;
899 return DA_ERR_DRM_FAIL;
901 if (is_content_drm_dm(file_info->mime_type)) {
902 char *actual_file_path = DA_NULL;
903 char *out_file_path = DA_NULL;
905 actual_file_path = file_info->file_path;
906 DA_SECURE_LOGD("actual_file_path = %s", actual_file_path);
907 if (!actual_file_path)
908 return DA_ERR_INVALID_ARGUMENT;
909 ret_b = EDRM_convert(actual_file_path, &out_file_path);
910 unlink(actual_file_path);
911 free(actual_file_path);
913 ret = DA_ERR_DRM_FAIL;
914 file_info->file_path = out_file_path;
923 void remove_file(const char *file_path)
927 if (file_path && get_file_state(file_path) == REGULAR_FILE) {
928 DA_SECURE_LOGD("remove file [%s]", file_path);
929 if (unlink(file_path) < 0)
930 DA_LOGE("file removing failed.");
934 da_ret_t get_available_memory(const char *dir_path, da_size_t len)
936 da_ret_t ret = DA_RESULT_OK;
938 struct statfs filesys_info = {0, };
939 //struct statvfs filesys_info;
944 return DA_ERR_INVALID_INSTALL_PATH;
945 DA_LOGD("Dir_path : %s", dir_path);
947 fs_ret = statfs(dir_path, &filesys_info);
948 // Using this as it considers FOTA memory while returning available memory
949 //fs_ret = storage_get_internal_memory_size(&filesys_info);
952 // DA_LOGE("statfs error[%s]", strerror(errno));
953 return DA_ERR_INVALID_ARGUMENT;
954 // return DA_ERR_INVALID_INSTALL_PATH;
957 double available_size = (double)filesys_info.f_frsize * filesys_info.f_bavail;
958 double total_size = (double)filesys_info.f_frsize * filesys_info.f_blocks;
959 DA_SECURE_LOGI(" total = %lf ", total_size);
960 DA_SECURE_LOGI(" available = %lf ", available_size);
962 DA_LOGV("Available Memory(f_bavail) : %lu", filesys_info.f_bavail);
963 DA_LOGV("Available Memory(f_bsize) : %d", filesys_info.f_bsize);
964 DA_LOGD("Available Memory(kbytes) : %lu", (filesys_info.f_bavail/1024)*filesys_info.f_bsize);
965 DA_LOGV("Content: %llu", len);
966 if (available_size < (len
967 + SAVE_FILE_BUFFERING_SIZE_50KB)) /* 50KB buffering */
968 ret = DA_ERR_DISK_FULL;