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
40 da_ret_t __saved_file_open(file_info_t *file_info)
42 da_ret_t ret = DA_RESULT_OK;
43 char *actual_file_path = DA_NULL;
48 actual_file_path = file_info->file_path;
49 if (!actual_file_path)
50 return DA_ERR_INVALID_ARGUMENT;
52 fd = fopen(actual_file_path, "a+"); // for resume
54 DA_LOGE("File open failed");
56 ret = DA_ERR_DISK_FULL;
58 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
62 file_info->file_handle = fd;
63 //DA_SECURE_LOGD("file path for saving[%s]", file_info->file_path);
66 if (DA_RESULT_OK != ret) {
67 file_info->file_handle = DA_NULL;
72 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)
74 char *file_name = DA_NULL;
75 char *tmp_ptr = DA_NULL;
76 char temp_file[DA_MAX_FILE_NAME_LEN + 1] = {0,};
77 char tmp_ext[DA_MAX_STR_LEN] = {0,};
79 da_ret_t ret = DA_RESULT_OK;
84 return DA_ERR_INVALID_ARGUMENT;
86 file_name = (char *)in_file_name;
88 tmp_ptr = strrchr(file_name, '.');
91 if (tmp_ptr && out_extension) {
92 strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1);
93 *out_extension = strdup((const char*) tmp_ext);
94 DA_SECURE_LOGD("extension [%s]", *out_extension);
95 } else if (!tmp_ptr && url) {
96 char *extension = DA_NULL;
97 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
98 if (b_ret && !extension) {
100 tmp_ptr = strrchr(file_name, '.');
103 if (tmp_ptr && out_extension) {
104 strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1);
105 *out_extension = strdup((const char*) tmp_ext);
106 DA_SECURE_LOGD("extension [%s]", *out_extension);
109 *out_extension = NULL;
113 if (!out_pure_file_name)
117 len = tmp_ptr - file_name - 1;
119 len = strlen(file_name);
121 if (len >= DA_MAX_FILE_NAME_LEN) {
122 strncpy((char*) temp_file, file_name, DA_MAX_FILE_NAME_LEN);
123 temp_file[DA_MAX_FILE_NAME_LEN] = '\0';
125 strncpy((char*) temp_file, file_name, len);
126 temp_file[len] = '\0';
129 delete_prohibited_char((char*) temp_file,
130 strlen((char*) temp_file));
131 if (strlen(temp_file) < 1) {
132 *out_pure_file_name = strdup(NO_NAME_TEMP_STR);
134 *out_pure_file_name = strdup(
135 (const char*) temp_file);
138 DA_LOGD( "pure file name [%s]", *out_pure_file_name);
142 da_ret_t __file_write_buf_make_buf(file_info_t *file_info)
144 da_ret_t ret = DA_RESULT_OK;
145 char *buffer = DA_NULL;
149 buffer = (char*) calloc(1, DA_FILE_BUF_SIZE);
150 if (DA_NULL == buffer) {
151 DA_LOGE("Calloc failure ");
152 ret = DA_ERR_FAIL_TO_MEMALLOC;
154 file_info->buffer_len = 0;
155 file_info->buffer = buffer;
161 da_ret_t __file_write_buf_destroy_buf(file_info_t *file_info)
163 da_ret_t ret = DA_RESULT_OK;
166 NULL_CHECK_RET(file_info);
168 free(file_info->buffer);
169 file_info->buffer = DA_NULL;
170 file_info->buffer_len = 0;
175 da_ret_t __file_write_buf_flush_buf(file_info_t *file_info)
177 da_ret_t ret = DA_RESULT_OK;
178 char *buffer = DA_NULL;
179 size_t buffer_size = 0;
180 size_t write_success_len = 0;
185 buffer = file_info->buffer;
186 buffer_size = file_info->buffer_len;
188 if (buffer_size == 0) {
189 DA_LOGE("no data on buffer..");
193 fd = file_info->file_handle;
195 DA_LOGE("There is no file handle.");
197 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
201 write_success_len = fwrite(buffer, sizeof(char), buffer_size,
203 /* FIXME : This can be necessary later due to progressive download.
204 * The solution for reducing fflush is needed */
205 //fflush((FILE *) fd);
206 if (write_success_len != buffer_size) {
207 DA_LOGE("write fails ");
209 ret = DA_ERR_DISK_FULL;
211 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
214 file_info->bytes_written_to_file += write_success_len;
215 file_info->is_updated = DA_TRUE;
216 file_info->buffer_len = 0;
221 da_ret_t __file_write_buf_copy_to_buf(file_info_t *file_info, char *body,
224 da_ret_t ret = DA_RESULT_OK;
225 char *buffer = DA_NULL;
226 size_t buffer_size = 0;
230 NULL_CHECK_RET(file_info->buffer);
231 buffer = file_info->buffer;
232 buffer_size = file_info->buffer_len;
234 memcpy(buffer + buffer_size, body, body_len);
235 file_info->buffer_len += body_len;
240 da_ret_t __file_write_buf_directly_write(file_info_t *file_info,
241 char *body, int body_len)
243 da_ret_t ret = DA_RESULT_OK;
244 size_t write_success_len = 0;
249 fd = file_info->file_handle;
251 DA_LOGE("There is no file handle.");
252 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
256 write_success_len = fwrite(body, sizeof(char), (size_t)body_len,
258 /* FIXME : This can be necessary later due to progressive download.
259 * The solution for reducing fflush is needed */
260 //fflush((FILE *) fd);
261 if (write_success_len != (size_t)body_len) {
262 DA_LOGE("write fails ");
264 ret = DA_ERR_DISK_FULL;
266 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
269 file_info->bytes_written_to_file += write_success_len;
270 DA_LOGV( "write %llu bytes", write_success_len);
271 file_info->is_updated = DA_TRUE;
277 /* Priority to derive extension
278 * 1. extension name which client set
279 * 2. according to MIME-Type
280 * 3. if MIME-Type is ambiguous or blank,
281 * 3-1. derived from <Content-Disposition> field's "filename" attribute
282 * 3-2. derived from url
283 * 4. if url does not have extension, leave blank for extension
285 char *__get_extension_name(char *mime_type,
286 char *file_name_from_header, char *url)
288 char *extension = DA_NULL;
291 if (mime_type && !is_ambiguous_MIME_Type(mime_type)) {
293 DA_LOGV("If the file extension exists and mime type exists, choose the file extension over mime type");
294 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
295 if (b_ret && extension)
298 char *extension = DA_NULL;
299 da_ret_t ret = get_extension_from_mime_type(mime_type, &extension);
300 if (ret == DA_RESULT_OK && extension)
304 if (file_name_from_header) {
305 char *extension = DA_NULL;
306 DA_SECURE_LOGI("Content-Disposition :[%s]", file_name_from_header);
307 __divide_file_name_into_pure_name_N_extesion(file_name_from_header, DA_NULL,
308 DA_NULL, &extension);
314 DA_LOGV("Get extension from url");
315 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
316 if (b_ret && extension)
322 /** Priority for deciding file name
323 * 1. file name which client set
324 * 2. 'filename' option on HTTP response header's Content-Disposition field
326 * 4. Otherwise, define it as "No name"
328 da_ret_t __get_candidate_file_name(const char *user_file_name, char *url,
329 char *file_name_from_header,
330 char **out_pure_file_name, char **out_extension)
332 da_ret_t ret = DA_RESULT_OK;
337 if (user_file_name) {
338 __divide_file_name_into_pure_name_N_extesion(
339 user_file_name, url, out_pure_file_name, out_extension);
341 if (*out_pure_file_name)
344 if (file_name_from_header) {
345 DA_SECURE_LOGI("Content-Disposition:[%s]", file_name_from_header);
346 __divide_file_name_into_pure_name_N_extesion(file_name_from_header, DA_NULL,
347 out_pure_file_name, DA_NULL);
349 if (*out_pure_file_name)
353 DA_LOGD("Get file name from url");
354 da_get_file_name_from_url(url, out_pure_file_name);
356 if (*out_pure_file_name)
359 *out_pure_file_name = strdup(NO_NAME_TEMP_STR);
360 if (*out_pure_file_name == DA_NULL)
361 ret = DA_ERR_FAIL_TO_MEMALLOC;
365 da_ret_t __decide_file_path(da_info_t *da_info)
367 da_ret_t ret = DA_RESULT_OK;
368 char *extension = DA_NULL;
369 char *file_name = DA_NULL;
370 char *tmp_file_path = DA_NULL;
371 char *file_name_from_header = DA_NULL;
373 const char *install_dir = DA_NULL;
374 const char *user_file_name = DA_NULL;
375 file_info_t *file_info = DA_NULL;
376 req_info_t *req_info = DA_NULL;
377 http_info_t *http_info = DA_NULL;
378 dp_client_slots_fmt *slot = DA_NULL;
382 NULL_CHECK_RET(da_info);
383 file_info = da_info->file_info;
384 NULL_CHECK_RET(file_info);
385 req_info = da_info->req_info;
386 NULL_CHECK_RET(req_info);
387 http_info = da_info->http_info;
388 NULL_CHECK_RET(http_info);
389 slot = req_info->user_client_data;
390 NULL_CHECK_RET(slot);
392 if (req_info->install_path)
393 install_dir = (const char *)req_info->install_path;
395 tzplatform_set_user(slot->credential.uid);
396 install_dir = DA_DEFAULT_INSTALL_PATH_FOR_PHONE;
397 tzplatform_reset_user();
399 user_file_name = (const char *)req_info->file_name;
400 /* If there is location url from response header in case of redirection,
401 * it try to parse the file name from the location url */
402 if (http_info->location_url) {
403 url = http_info->location_url;
404 DA_LOGI("[TEST] location_url[%s][%p]",http_info->location_url, http_info->location_url);
408 file_name_from_header = http_info->file_name_from_header;
410 /* extension is extracted only if User set specific name */
411 ret = __get_candidate_file_name(user_file_name, url, file_name_from_header,
412 &file_name, &extension);
413 if (ret != DA_RESULT_OK)
416 if (file_name && strpbrk(file_name, DA_INVALID_PATH_STRING) != NULL) {
417 DA_LOGI("Invalid string at file name");
419 file_name = strdup(NO_NAME_TEMP_STR);
421 ret = DA_ERR_FAIL_TO_MEMALLOC;
427 DA_SECURE_LOGI("candidate file name [%s]", file_name);
430 && file_info->mime_type
431 && strncmp(file_info->mime_type, "application/json", strlen("application/json"))
432 && strncmp(file_info->mime_type, "application/x-xz", strlen("application/x-xz"))
433 && strncmp(file_info->mime_type, "application/rss+xml", strlen("application/rss+xml"))) {
434 extension = __get_extension_name(file_info->mime_type,
435 file_name_from_header, url);
437 if (file_name && !file_info->pure_file_name) {
438 file_info->pure_file_name = file_name;
441 if (extension && !file_info->extension) {
442 DA_LOGV("candidate extension [%s]", extension);
443 file_info->extension = extension;
448 tmp_file_path = get_full_path_avoided_duplication(install_dir,
449 file_info->pure_file_name, file_info->extension);
451 file_info->file_path = tmp_file_path;
452 tmp_file_path = DA_NULL;
454 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
459 DA_SECURE_LOGI("decided file path [%s]", file_info->file_path);
467 // for resume with new download request
468 da_ret_t __decide_file_path_for_resume(file_info_t *file_info)
470 da_ret_t ret = DA_RESULT_OK;
471 char *extension = DA_NULL;
472 char *file_name = DA_NULL;
473 char *file_path = DA_NULL;
475 char *ptr2 = DA_NULL;
479 NULL_CHECK_RET(file_info);
481 file_path = file_info->file_path;
483 NULL_CHECK_RET(file_path);
485 ptr = strrchr(file_path, '/');
488 ptr2 = strrchr(ptr, '.');
493 extension = strdup(ptr2);
494 file_name = calloc(1, len + 1);
496 snprintf(file_name, len + 1, "%s", ptr);
498 file_name = strdup(ptr);
502 if (file_name && !file_info->pure_file_name) {
503 file_info->pure_file_name = file_name;
508 if (extension && !file_info->extension) {
509 DA_LOGV( "candidate extension [%s]", extension);
510 file_info->extension = extension;
518 da_ret_t start_file_writing(da_info_t *da_info)
520 da_ret_t ret = DA_RESULT_OK;
521 file_info_t *file_info = DA_NULL;
522 req_info_t *req_info = DA_NULL;
526 NULL_CHECK_RET(da_info);
527 file_info = da_info->file_info;
528 NULL_CHECK_RET(file_info);
529 req_info = da_info->req_info;
530 NULL_CHECK_RET(req_info);
533 if (req_info->etag || req_info->temp_file_path) {
534 char *file_path = DA_NULL;
535 char *origin_path = DA_NULL;
536 file_path = req_info->temp_file_path;
538 return DA_ERR_INVALID_ARGUMENT;
539 origin_path = file_info->file_path;
540 file_info->file_path = strdup(file_path);
543 ret = __decide_file_path_for_resume(file_info);
546 ret = __decide_file_path(da_info);
549 if (ret != DA_RESULT_OK)
552 if (req_info->etag || req_info->temp_file_path) {
553 da_size_t file_size = 0;
554 get_file_size(req_info->temp_file_path, &file_size);
558 file_info->file_size_of_temp_file = file_size;
560 file_info->bytes_written_to_file = file_size;
562 file_info->bytes_written_to_file = 0;
564 ret = __saved_file_open(file_info);
569 da_ret_t start_file_append(file_info_t *file_info)
571 da_ret_t ret = DA_RESULT_OK;
575 NULL_CHECK_RET(file_info);
577 ret = __saved_file_open(file_info);
581 da_ret_t file_write_ongoing(file_info_t *file_info, char *body, int body_len)
583 da_ret_t ret = DA_RESULT_OK;
584 size_t buffer_size = 0;
585 char *buffer = DA_NULL;
589 buffer = file_info->buffer;
590 buffer_size = file_info->buffer_len;
592 if (DA_NULL == buffer) {
593 if (body_len < DA_FILE_BUF_SIZE) {
594 ret = __file_write_buf_make_buf(file_info);
595 if (ret != DA_RESULT_OK)
597 __file_write_buf_copy_to_buf(file_info, body, body_len);
599 ret = __file_write_buf_directly_write(file_info,
601 if (ret != DA_RESULT_OK)
605 if (DA_FILE_BUF_SIZE <= body_len) {
606 ret = __file_write_buf_flush_buf(file_info);
607 if (ret != DA_RESULT_OK)
609 ret = __file_write_buf_directly_write(file_info,
611 if (ret != DA_RESULT_OK)
613 } else if ((DA_FILE_BUF_SIZE - buffer_size) <= body_len) {
614 ret = __file_write_buf_flush_buf(file_info);
615 if (ret != DA_RESULT_OK)
617 __file_write_buf_copy_to_buf(file_info, body, body_len);
619 __file_write_buf_copy_to_buf(file_info, body, body_len);
623 if (ret != DA_RESULT_OK) {
624 file_info->buffer_len = 0;
625 free(file_info->buffer);
626 file_info->buffer = DA_NULL;
632 da_ret_t file_write_complete_for_raf(file_info_t *file_info) {
633 da_ret_t ret = DA_RESULT_OK;
634 char *buffer = DA_NULL;
635 da_size_t wrriten_size = 0;
636 da_size_t file_size = 0;
640 fd = file_info->file_handle;
642 wrriten_size = file_info->bytes_written_to_file;
644 get_file_size(file_info->file_path, &file_size);
645 DA_LOGI("wrriten_size:%llu file_size:%llu file[%s]",
646 wrriten_size, file_size, file_info->file_path);
651 file_info->file_handle = DA_NULL;
652 if (wrriten_size < file_size) {
653 DA_LOGD("Try truncate");
654 if (truncate(file_info->file_path, wrriten_size) < 0) {
655 DA_LOGE("Fail to ftruncate: errno[%d]", errno);
657 DA_LOGD("Try truncate done");
665 da_ret_t file_write_complete(file_info_t *file_info)
667 da_ret_t ret = DA_RESULT_OK;
668 char *buffer = DA_NULL;
669 unsigned int buffer_size = 0;
674 buffer = file_info->buffer;
675 buffer_size = file_info->buffer_len;
677 if (DA_NULL == buffer) {
678 DA_LOGE("file buffer is NULL");
680 if (buffer_size != 0) {
681 ret = __file_write_buf_flush_buf(file_info);
682 if (ret != DA_RESULT_OK)
685 __file_write_buf_destroy_buf(file_info);
687 fd = file_info->file_handle;
693 file_info->file_handle = DA_NULL;
698 da_ret_t discard_download(file_info_t *file_info)
700 da_ret_t ret = DA_RESULT_OK;
701 FILE *f_handle = DA_NULL;
705 f_handle = file_info->file_handle;
708 file_info->file_handle = DA_NULL;
713 void clean_paused_file(file_info_t *file_info)
715 char *paused_file_path = DA_NULL;
720 fd = file_info->file_handle;
723 file_info->file_handle = DA_NULL;
726 paused_file_path = file_info->file_path;
727 file_info->bytes_written_to_file = 0; // Ignore resume flow after failed or cancled.
728 remove_file((const char*) paused_file_path);
733 da_bool_t is_file_exist(const char *file_path)
735 struct stat dir_state;
738 if (file_path == DA_NULL) {
739 DA_LOGE("file path is DA_NULL");
742 stat_ret = stat(file_path, &dir_state);
744 if (dir_state.st_mode & S_IFREG) {
745 //DA_SECURE_LOGD("Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size);
755 void get_file_size(char *file_path, da_size_t *out_file_size)
757 struct stat dir_state;
762 if (file_path == DA_NULL) {
763 DA_LOGE("file path is DA_NULL");
766 /* Please do not use ftell() to obtain file size, use stat instead.
767 * This is a guide from www.securecoding.cert.org
768 * : FIO19-C. Do not use fseek() and ftell() to compute the size of a file
770 stat_ret = stat(file_path, &dir_state);
772 if (dir_state.st_mode & S_IFREG) {
773 DA_LOGV( "size = %lu", dir_state.st_size);
774 *out_file_size = dir_state.st_size;
780 char *get_full_path_avoided_duplication(const char *in_dir,
781 char *in_candidate_file_name, char *in_extension)
784 char *file_name = in_candidate_file_name;
785 char *extension = in_extension;
786 char *final_path = DA_NULL;
788 int dir_path_len = 0;
789 int final_path_len = 0;
790 int extension_len = 0;
792 int suffix_count = 0; /* means suffix on file name. up to "_99" */
793 int suffix_len = (int)log10(MAX_SUFFIX_COUNT + 1) + 1; /* 1 means "_" */
795 if (!in_dir || !in_candidate_file_name)
798 dir = strdup(in_dir);
802 //DA_SECURE_LOGI("in_candidate_file_name=[%s],in_extension=[%s]",
803 //in_candidate_file_name, in_extension);
806 extension_len = strlen(extension);
808 // to remove trailing slash from dir path
809 dir_path_len = strlen(dir);
810 if (dir[dir_path_len - 1] == '/') {
811 dir[dir_path_len - 1] = '\0';
815 /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */
816 final_path_len = dir_path_len + 1 + strlen(file_name) + 1
817 + suffix_len + extension_len + 1;
819 final_path = (char*)calloc(1, final_path_len);
821 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
828 * if there is no extension name, just make a file name without extension */
829 if (0 == extension_len) {
830 if (suffix_count == 0) {
831 snprintf(final_path, final_path_len,
832 "%s/%s", dir, file_name);
834 snprintf(final_path, final_path_len,
835 "%s/%s_%d", dir, file_name, suffix_count);
838 if (suffix_count == 0) {
839 snprintf(final_path, final_path_len,
840 "%s/%s.%s", dir, file_name, extension);
842 snprintf(final_path, final_path_len,
844 dir, file_name, suffix_count, extension);
847 if (is_file_exist(final_path)) {
849 if (suffix_count > MAX_SUFFIX_COUNT) {
851 final_path = DA_NULL;
854 memset(final_path, 0x00, final_path_len);
861 //DA_SECURE_LOGD("decided path = [%s]", final_path);
868 da_ret_t check_drm_convert(file_info_t *file_info)
870 da_ret_t ret = DA_RESULT_OK;
871 #ifdef _ENABLE_OMA_DRM
872 da_bool_t ret_b = DA_TRUE;
877 NULL_CHECK_RET(file_info);
879 #ifdef _ENABLE_OMA_DRM
881 /* In case of OMA DRM 1.0 SD, it is not necessary to call DRM convert API.
882 * Because it is already converted itself.
883 * And, the case will return fail because The SD is not supported now.
885 if (is_content_drm_dcf(file_info->mime_type)) {
886 DA_LOGI("DRM SD case");
887 unlink(file_info->file_path);
888 free(file_info->file_path);
889 file_info->file_path = DA_NULL;
890 return DA_ERR_DRM_FAIL;
892 if (is_content_drm_dm(file_info->mime_type)) {
893 char *actual_file_path = DA_NULL;
894 char *out_file_path = DA_NULL;
896 actual_file_path = file_info->file_path;
897 DA_SECURE_LOGD("actual_file_path = %s", actual_file_path);
898 if (!actual_file_path)
899 return DA_ERR_INVALID_ARGUMENT;
900 ret_b = EDRM_convert(actual_file_path, &out_file_path);
901 unlink(actual_file_path);
902 free(actual_file_path);
904 ret = DA_ERR_DRM_FAIL;
905 file_info->file_path = out_file_path;
914 void remove_file(const char *file_path)
918 if (file_path && is_file_exist(file_path)) {
919 DA_SECURE_LOGD("remove file [%s]", file_path);
920 if (unlink(file_path) < 0) {
921 DA_LOGE("file removing failed.");
926 da_ret_t get_available_memory(const char *dir_path, da_size_t len)
928 da_ret_t ret = DA_RESULT_OK;
930 struct statfs filesys_info = {0, };
931 //struct statvfs filesys_info;
936 return DA_ERR_INVALID_INSTALL_PATH;
937 DA_LOGD("Dir_path : %s", dir_path);
939 fs_ret = statfs(dir_path, &filesys_info);
940 // Using this as it considers FOTA memory while returning available memory
941 //fs_ret = storage_get_internal_memory_size(&filesys_info);
944 // DA_LOGE("statfs error[%s]", strerror(errno));
945 return DA_ERR_INVALID_ARGUMENT;
946 // return DA_ERR_INVALID_INSTALL_PATH;
949 double available_size = (double)filesys_info.f_frsize * filesys_info.f_bavail;
950 double total_size = (double)filesys_info.f_frsize * filesys_info.f_blocks;
951 DA_SECURE_LOGI(" total = %lf ", total_size);
952 DA_SECURE_LOGI(" available = %lf ",available_size);
954 DA_LOGV("Available Memory(f_bavail) : %lu", filesys_info.f_bavail);
955 DA_LOGV("Available Memory(f_bsize) : %d", filesys_info.f_bsize);
956 DA_LOGD("Available Memory(kbytes) : %lu", (filesys_info.f_bavail/1024)*filesys_info.f_bsize);
957 DA_LOGV("Content: %llu", len);
958 if (available_size < (len
959 + SAVE_FILE_BUFFERING_SIZE_50KB)) /* 50KB buffering */
960 ret = DA_ERR_DISK_FULL;