2 * Copyright (c) 2023 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.
19 #include "include/cache-agent-interface.h"
21 static pthread_mutex_t mutex_ca_info_list = PTHREAD_MUTEX_INITIALIZER;
22 static pthread_mutex_t mutex_ca_file_io = PTHREAD_MUTEX_INITIALIZER;
23 static ca_info_t *ca_info_list[CA_MAX_ID];
24 static ca_size_t cache_dir_size;
26 static char *__get_file_name(const char *file_path)
28 char *file_name = CA_NULL;
30 file_name = strrchr(file_path, '/');
34 return strdup(file_path);
36 return strdup(file_name);
39 static void __ca_progress_cb(int cache_id,
40 unsigned long long copied_size, void *user_req_data, void *user_client_data)
42 CA_LOGI("__ca_progress_cb id: %d, copied size: %llu", cache_id, copied_size);
45 static int __sum(const char *fpath, const struct stat *sb, int typeflag) {
46 cache_dir_size += sb->st_size;
50 static void __destroy_ca_req_info(ca_req_info_t *req_info)
53 if (req_info->install_path)
54 free(req_info->install_path);
55 if (req_info->file_name)
56 free(req_info->file_name);
57 if (req_info->pkg_name)
58 free(req_info->pkg_name);
60 req_info->user_req_data = CA_NULL;
61 req_info->user_client_data = CA_NULL;
65 static void __init_ca_info(int id)
67 ca_info_t *ca_info = CA_NULL;
68 ca_req_info_t *req_info = CA_NULL;
70 ca_info = (ca_info_t *)calloc(1, sizeof(ca_info_t));
72 CA_LOGE("Fail to calloc. id[%d]", id);
73 ca_info_list[id] = CA_NULL;
77 req_info = (ca_req_info_t *)calloc(1, sizeof(ca_req_info_t));
79 CA_LOGE("Fail to calloc. id[%d]", id);
84 CA_MUTEX_INIT(&(ca_info->mutex_state), CA_NULL);
85 CA_COND_INIT(&(ca_info->cond), CA_NULL);
87 ca_info->state = CA_STATE_NONE;
88 ca_info->ca_id = CA_INVALID_ID;
89 ca_info->req_info = req_info;
90 ca_info_list[id] = ca_info;
93 static int __remove_func(const char *filename,
94 const struct stat *statptr, int fileflags)
97 char *cache_path = ca_config_get_cache_path();
99 if (strlen(filename) == strlen(cache_path)) {
104 ret = unlink(filename);
106 char err_buf[CA_MAX_ERROR_STR_LEN] = { 0, };
108 strerror_r(errno, err_buf, CA_MAX_ERROR_STR_LEN);
109 CA_LOGE("Unable to remove the file: %s, error [%d/%s]", filename, errno, err_buf);
116 void ca_destroy_ca_info(int id)
118 ca_info_t *ca_info = CA_NULL;
120 CA_MUTEX_LOCK(&mutex_ca_info_list);
122 ca_info = ca_info_list[id];
125 fclose(ca_info->dst_fp);
127 if (ca_info->src_file)
128 free(ca_info->src_file);
130 if (ca_info->dst_file)
131 free(ca_info->dst_file);
133 if (ca_info->file_name)
134 free(ca_info->file_name);
136 if (ca_info->req_info) {
137 __destroy_ca_req_info(ca_info->req_info);
138 free(ca_info->req_info);
141 CA_MUTEX_DESTROY(&(ca_info->mutex_state));
142 CA_COND_DESTROY(&(ca_info->cond));
145 ca_info_list[id] = CA_NULL;
148 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
151 ca_info_t *ca_get_ca_info(int ca_id)
153 CA_MUTEX_LOCK(&mutex_ca_info_list);
154 ca_info_t *ca_info = ca_info_list[ca_id];
155 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
160 int ca_check_ca_id(ca_info_t *ca_info, int ca_id)
162 int ret = CA_ERR_INVALID_ARGUMENT;
164 CA_MUTEX_LOCK(&mutex_ca_info_list);
166 if (ca_info && ca_info->ca_id == ca_id)
169 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
174 int ca_get_info_with_ca_id(int id, ca_info_t **out_info)
176 int ret = CA_ERR_INVALID_ARGUMENT;
178 CA_MUTEX_LOCK(&mutex_ca_info_list);
180 for (int i = 0; i < CA_MAX_ID; i++) {
181 if (CA_NULL != ca_info_list[i] && ca_info_list[i]->ca_id == id) {
182 *out_info = ca_info_list[i];
188 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
193 void ca_cancel_all_cache_operations(void)
195 CA_MUTEX_LOCK(&mutex_ca_info_list);
197 for (int i = 0; i < CA_MAX_ID; i++) {
198 if (CA_NULL != ca_info_list[i])
199 ca_request_to_cancel_cache_download(ca_info_list[i]);
202 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
205 int ca_clear_all_cache_files(void)
207 int ret = CA_RESULT_OK;
208 char *cache_path = ca_config_get_cache_path();
210 if (ftw(cache_path, __remove_func, 1) == -1)
211 ret = CA_ERR_FAIL_TO_ACCESS_FILE;
217 int ca_request_to_cancel_cache_download(ca_info_t *ca_info)
219 int ret = CA_RESULT_OK;
221 CA_MUTEX_LOCK(&(ca_info->mutex_state));
222 CA_LOGD("state [%d]", ca_info->state);
224 switch (ca_info->state) {
225 case CA_STATE_PAUSED:
226 CA_COND_SIGNAL(&(ca_info->cond));
227 ca_info->state = CA_STATE_CANCELED;
229 case CA_STATE_COPYING:
230 ca_info->state = CA_STATE_CANCELED;
232 case CA_STATE_CANCELED:
233 ret = CA_ERR_ALREADY_CANCELED;
236 case CA_STATE_COMPLETED:
237 case CA_STATE_FAILED:
238 ret = CA_ERR_INVALID_STATE;
241 ret = CA_ERR_INVALID_STATE;
245 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
249 int ca_request_to_suspend_cache_download(ca_info_t *ca_info)
251 int ret = CA_RESULT_OK;
253 CA_MUTEX_LOCK(&(ca_info->mutex_state));
254 CA_LOGD("state [%d]", ca_info->state);
256 switch (ca_info->state) {
257 case CA_STATE_PAUSED:
258 ret = CA_ERR_ALREADY_SUSPENDED;
260 case CA_STATE_COPYING:
261 ca_info->state = CA_STATE_PAUSED;
264 case CA_STATE_COMPLETED:
265 case CA_STATE_CANCELED:
266 case CA_STATE_FAILED:
267 ret = CA_ERR_INVALID_STATE;
270 ret = CA_ERR_INVALID_STATE;
274 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
278 int ca_request_to_resume_cache_download(ca_info_t *ca_info)
280 int ret = CA_RESULT_OK;
282 CA_MUTEX_LOCK(&(ca_info->mutex_state));
283 CA_LOGD("state [%d]", ca_info->state);
285 switch (ca_info->state) {
286 case CA_STATE_PAUSED:
287 CA_COND_SIGNAL(&(ca_info->cond));
288 ca_info->state = CA_STATE_COPYING;
290 case CA_STATE_COPYING:
292 case CA_STATE_COMPLETED:
293 case CA_STATE_CANCELED:
294 case CA_STATE_FAILED:
295 ret = CA_ERR_INVALID_STATE;
298 ret = CA_ERR_INVALID_STATE;
302 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
306 int ca_get_available_ca_id(int *available_id)
308 int ret = CA_ERR_ALREADY_MAX_COPY;
311 CA_MUTEX_LOCK(&mutex_ca_info_list);
313 for (i = 0; i < CA_MAX_ID; i++) {
314 if (ca_info_list[i] == CA_NULL) {
316 CA_LOGV("available cache id[%d]", *available_id);
325 CA_MUTEX_UNLOCK(&mutex_ca_info_list);
330 void ca_storage_get_file_size(const char *file_path, ca_size_t *file_size)
332 struct stat dir_state;
338 CA_LOGE("NULL CHECK!: file path");
342 CA_MUTEX_LOCK(&mutex_ca_file_io);
343 stat_ret = stat(file_path, &dir_state);
344 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
349 if (dir_state.st_mode & S_IFREG) {
350 CA_LOGV("file size = %lu", dir_state.st_size);
351 *file_size = dir_state.st_size;
355 static ca_file_state_e __get_file_state(const char *file_path)
357 struct stat dir_state;
360 if (file_path == CA_NULL) {
361 CA_LOGE("file path is CA_NULL");
362 return CA_NOT_EXIST_FILE;
365 CA_MUTEX_LOCK(&mutex_ca_file_io);
366 stat_ret = stat(file_path, &dir_state);
367 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
370 if (dir_state.st_mode & S_IFREG)
371 return CA_REGULAR_FILE;
373 return CA_OTHER_FILE;
375 return CA_NOT_EXIST_FILE;
378 static int __extract_file_name_and_extension(const char *in_file_name, char **pure_file_name, char **extension)
380 char *file_name = CA_NULL;
381 char *tmp_ptr = CA_NULL;
382 char temp_file[CA_MAX_FILE_NAME_LEN + 1] = {0,};
383 char tmp_ext[CA_MAX_FILE_NAME_LEN] = {0,};
386 if (!in_file_name || !pure_file_name)
387 return CA_ERR_INVALID_ARGUMENT;
389 file_name = (char *)in_file_name;
390 tmp_ptr = strrchr(file_name, '.');
392 if (!tmp_ptr || tmp_ptr == file_name)
397 if (tmp_ptr && extension) {
398 strncpy((char*)tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1);
399 *extension = strdup((const char *)tmp_ext);
400 CA_LOGD("extension [%s]", *extension);
404 len = tmp_ptr - file_name - 1;
406 len = strlen(file_name);
408 if (len >= CA_MAX_FILE_NAME_LEN) {
409 strncpy((char*)temp_file, file_name, CA_MAX_FILE_NAME_LEN);
410 temp_file[CA_MAX_FILE_NAME_LEN] = '\0';
412 strncpy((char*) temp_file, file_name, len);
413 temp_file[len] = '\0';
416 if (strlen(temp_file) >= 1)
417 *pure_file_name = strdup((const char*)temp_file);
419 CA_LOGD("pure file name [%s]", *pure_file_name ? *pure_file_name : "NoName");
423 static char *__generate_cache_file_name(char *dst_path, char *file_name)
428 CA_MUTEX_LOCK(&mutex_ca_file_io);
430 cache_path = ca_config_get_cache_path();
432 for (i = 1; i <= CA_MAX_DUP_FILE_COUNT; i++) {
433 if (access(dst_path, F_OK) != 0)
436 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s.%d", cache_path, file_name, i);
439 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
443 if (i > CA_MAX_DUP_FILE_COUNT)
446 return __get_file_name(dst_path);
449 static char *__generate_dst_file_name(char *dst_path, const char *dir_path, const char *file_name)
452 char *pure_file_name = CA_NULL;
453 char *extension = CA_NULL;
455 __extract_file_name_and_extension(file_name, &pure_file_name, &extension);
459 CA_MUTEX_LOCK(&mutex_ca_file_io);
461 for (i = 1; i <= CA_MAX_DUP_FILE_COUNT; i++) {
462 if (access(dst_path, F_OK) != 0)
466 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s(%d).%s", dir_path, pure_file_name, i, extension);
468 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s(%d)", dir_path, pure_file_name, i);
471 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
473 free(pure_file_name);
476 if (i > CA_MAX_DUP_FILE_COUNT)
479 return __get_file_name(dst_path);
482 static int __is_realpath(const char *file_path)
484 char *resolved_path = CA_NULL;
487 return CA_ERR_INVALID_ARGUMENT;
489 CA_MUTEX_LOCK(&mutex_ca_file_io);
490 resolved_path = realpath(file_path, NULL);
491 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
494 /* Check if actual_file_path is symbolic file or not */
495 if (strcmp(resolved_path, file_path) != 0) {
497 return CA_ERR_INVALID_ARGUMENT;
499 } else if (errno != ENOENT) {
500 return CA_ERR_INVALID_ARGUMENT;
507 static void *__open_dst_file(const char *dst_file)
512 CA_LOGE("NULL CHECK!: dst_file");
516 CA_MUTEX_LOCK(&mutex_ca_file_io);
517 fp = fopen(dst_file, "wb");
518 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
521 char err_buf[CA_MAX_ERROR_STR_LEN] = { 0, };
523 strerror_r(errno, err_buf, CA_MAX_ERROR_STR_LEN);
524 CA_LOGE("File open failed [%d/%s]", errno, err_buf);
527 CA_LOGE("Disk full!");
529 CA_LOGE("Fail to access file!");
535 static void *__open_src_file(const char *src_file)
540 CA_LOGE("NULL CHECK!: src_file");
544 CA_MUTEX_LOCK(&mutex_ca_file_io);
545 fp = fopen(src_file, "rb");
546 CA_MUTEX_UNLOCK(&mutex_ca_file_io);
549 char err_buf[CA_MAX_ERROR_STR_LEN] = { 0, };
551 strerror_r(errno, err_buf, CA_MAX_ERROR_STR_LEN);
552 CA_LOGE("File open failed [%d/%s]", errno, err_buf);
558 static void __call_started_cb(int error, ca_info_t *ca_info, ca_size_t src_file_size)
560 cache_info_t cache_info = { 0, CA_RESULT_OK, 0, CA_NULL, CA_NULL };
565 cache_info.cache_id = ca_info->ca_id;
566 cache_info.error = error;
567 cache_info.file_size = src_file_size;
568 cache_info.content_name = ca_info->file_name;
569 cache_info.saved_path = ca_info->dst_file;
571 if (ca_info->cb_info.cache_info_cb)
572 ca_info->cb_info.cache_info_cb(&cache_info,
573 ca_info->req_info->user_req_data, ca_info->req_info->user_client_data);
577 static void __call_finidhed_cb(int error, int http_status, ca_info_t *ca_info, ca_size_t src_file_size)
579 ca_finished_info_t finished_info = { 0, CA_RESULT_OK, 0, CA_NULL, 0};
581 if (!ca_info || !ca_info->is_cb_update)
584 finished_info.cache_id = ca_info->ca_id;
585 finished_info.error = error;
586 finished_info.file_size = src_file_size;
588 if (error == CA_RESULT_OK)
589 finished_info.saved_path = ca_info->dst_file;
591 finished_info.http_status = http_status;
593 if (ca_info->cb_info.finished_cb)
594 ca_info->cb_info.finished_cb(&finished_info,
595 ca_info->req_info->user_req_data, ca_info->req_info->user_client_data);
598 static void __call_paused_cb(ca_info_t *ca_info)
600 if (!ca_info || !ca_info->is_cb_update)
603 if (ca_info->cb_info.paused_cb)
604 ca_info->cb_info.paused_cb(ca_info->ca_id,
605 ca_info->req_info->user_req_data, ca_info->req_info->user_client_data);
608 static void __set_cache_state(int state, ca_info_t *ca_info)
610 CA_MUTEX_LOCK(&(ca_info->mutex_state));
612 ca_info->state = state;
614 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
617 static ca_bool_t __check_cancel_state(ca_info_t *ca_info)
619 ca_bool_t ret = CA_TRUE;
621 CA_MUTEX_LOCK(&(ca_info->mutex_state));
622 if (ca_info->state != CA_STATE_CANCELED)
624 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
629 static void __handle_suspend_state(ca_info_t *ca_info)
631 CA_MUTEX_LOCK(&(ca_info->mutex_state));
632 if (ca_info->state != CA_STATE_PAUSED) {
633 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
636 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
638 __call_paused_cb(ca_info);
640 CA_MUTEX_LOCK(&(ca_info->mutex_state));
641 CA_COND_WAIT(&(ca_info->cond), &(ca_info->mutex_state));
642 CA_MUTEX_UNLOCK(&(ca_info->mutex_state));
645 static int __copy_content(ca_info_t *ca_info)
647 int ret = CA_RESULT_OK;
648 FILE *src_fp = CA_NULL;
649 FILE *dst_fp = CA_NULL;
650 void *file_buff = CA_NULL;
653 ca_size_t src_file_size = 0;
654 ca_size_t dst_file_size = 0;
655 struct timespec curr_time = {0};
656 __time_t prev_time = 0;
658 if (!ca_info || !ca_info->src_file || !ca_info->dst_file) {
659 CA_LOGE("NULL CHECK!: ca_info, src_file, dst_file");
660 ret = CA_ERR_INVALID_ARGUMENT;
664 CA_LOGI("=====START thread : ca_id[%d]=====", ca_info->ca_id);
666 file_buff = calloc(CA_MAX_FILE_BUFFER_SIZE, sizeof(char));
668 CA_LOGE("Out of memory");
669 ret = CA_ERR_FAIL_TO_MEMALLOC;
673 ca_storage_get_file_size(ca_info->src_file, &src_file_size);
674 if (src_file_size < 0) {
675 CA_LOGE("Unable to get dst file size!");
676 ret = CA_ERR_FAIL_TO_ACCESS_FILE;
680 if (ca_info->dst_fp) {
681 dst_fp = ca_info->dst_fp;
683 dst_fp = __open_dst_file(ca_info->dst_file);
685 CA_LOGE("Unable to open dst file!");
686 ret = CA_ERR_FAIL_TO_ACCESS_FILE;
689 ca_info->dst_fp = dst_fp;
692 src_fp = (FILE *)__open_src_file(ca_info->src_file);
694 CA_LOGE("Unable to open src file!");
695 ret = CA_ERR_FAIL_TO_ACCESS_FILE;
699 if (ca_info->is_cb_update)
700 __call_started_cb(CA_RESULT_OK, ca_info, src_file_size);
702 while (0 < (r_size = fread(file_buff, 1, CA_MAX_FILE_BUFFER_SIZE, src_fp)) ) {
703 w_size = fwrite(file_buff, 1, r_size, dst_fp);
704 if (w_size != r_size)
707 dst_file_size += w_size;
709 __handle_suspend_state(ca_info);
711 if (__check_cancel_state(ca_info)) {
712 dst_file_size = src_file_size;
713 ret = CA_RESULT_USER_CANCELED;
717 if (!ca_info->is_cb_update)
720 clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_time);
721 if (curr_time.tv_sec - prev_time >= 1) {
722 if (ca_info->cb_info.progress_cb)
723 ca_info->cb_info.progress_cb(ca_info->ca_id, dst_file_size,
724 ca_info->req_info->user_req_data, ca_info->req_info->user_client_data);
726 prev_time = curr_time.tv_sec;
730 if (dst_file_size != src_file_size) {
731 ret = CA_ERR_FAIL_TO_ACCESS_FILE;
732 CA_LOGE("The file sizes of the src and dst do not match!");
737 ca_info->dst_fp = CA_NULL;
743 if (ret == CA_RESULT_OK)
744 __call_finidhed_cb(CA_RESULT_OK, 200, ca_info, src_file_size);
746 __call_finidhed_cb(ret, 0, ca_info, src_file_size);
748 if (ca_info && ca_info->is_cache_adding && ret == CA_RESULT_OK) {
749 ca_size_t cache_size;
751 ca_config_get_cache_size(&cache_size);
752 cache_size += dst_file_size;
753 ca_config_set_cache_size(cache_size);
759 static void *__thread_start_copy(void *data)
761 ca_info_t *ca_info = CA_NULL;
762 int ca_id = CA_INVALID_ID;
763 int ret = CA_RESULT_OK;
765 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, CA_NULL);
767 ca_info = (ca_info_t *)data;
769 CA_LOGE("[NULL Check] ca_info");
773 __set_cache_state(CA_STATE_COPYING, ca_info);
775 ca_id = ca_info->ca_id;
777 ret = __copy_content(ca_info);
778 if (ret != CA_RESULT_OK) {
779 CA_LOGE("Failed to copy file");
781 if (ca_info->dst_file)
782 unlink(ca_info->dst_file);
785 ca_destroy_ca_info(ca_id);
787 CA_LOGI("=====EXIT thread : ca_id[%d]=====", ca_id);
788 pthread_exit((void *)CA_NULL);
793 static void __reduce_cache_size(ca_size_t total_file_size)
795 ca_size_t cache_size;
797 if (total_file_size <= 0)
800 ca_config_get_cache_size(&cache_size);
801 cache_size -= total_file_size;
802 ca_config_set_cache_size(cache_size);
805 int ca_storage_init()
810 if (CA_RESULT_OK != ca_storage_get_used_cache_size(&size))
811 return CA_ERR_FAIL_TO_ACCESS_FILE;
813 return ca_config_set_cache_size(size);
816 int ca_storage_deinit()
818 int ret = CA_RESULT_OK;
820 ca_cancel_all_cache_operations();
825 char *ca_storage_store_file(const char *file_path)
827 int ret = CA_RESULT_OK;
828 int ca_id = CA_INVALID_ID;
829 char dst_path[CA_MAX_FILE_PATH_LEN] = { 0, };
830 char *file_name = CA_NULL;
831 char *dst_file_name = CA_NULL;
832 ca_info_t *ca_info = CA_NULL;
833 void *dst_fp = CA_NULL;
834 char *cache_path = ca_config_get_cache_path();
836 if (__get_file_state(file_path) != CA_REGULAR_FILE) {
837 CA_LOGE("Not a regular file!");
842 if (__is_realpath(file_path) != CA_RESULT_OK) {
843 CA_LOGE("Not a real file!");
848 ret = ca_get_available_ca_id(&ca_id);
849 if (ret != CA_RESULT_OK) {
850 CA_LOGD("No available cache id");
862 ca_info = ca_info_list[ca_id];
863 ca_info->ca_id = ca_id;
865 file_name = __get_file_name(file_path);
866 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s", cache_path, file_name);
867 dst_file_name = __generate_cache_file_name(dst_path, file_name);
871 if (dst_file_name == CA_NULL) {
872 CA_LOGE("Fail to generate dst file name!");
873 ca_destroy_ca_info(ca_info->ca_id);
877 dst_fp = __open_dst_file(dst_path);
878 if (dst_fp == CA_NULL) {
879 CA_LOGE("Unable to open dst file!");
881 ca_destroy_ca_info(ca_info->ca_id);
885 ca_info->dst_fp = (FILE *)dst_fp;
886 ca_info->src_file = strdup(file_path);
887 ca_info->dst_file = strdup(dst_path);
888 ca_info->file_name = strdup(dst_file_name);
890 ca_info->is_cb_update = CA_TRUE;
891 ca_info->is_cache_adding = CA_TRUE;
892 memcpy(&(ca_info->cb_info), &ca_cb, sizeof(ca_cb_t));
894 ret = ca_storage_copy_file(ca_info);
896 if (ret != CA_RESULT_OK) {
898 dst_file_name = CA_NULL;
900 if (ca_info->dst_fp) {
901 fclose(ca_info->dst_fp);
902 ca_info->dst_fp = CA_NULL;
906 ca_destroy_ca_info(ca_info->ca_id);
909 CA_LOGI("file name: %s, id: %d, ret: %d", dst_file_name, ca_id, ret);
911 return dst_file_name;
914 int ca_storage_remove_files(int file_count, const char *cache_files[])
916 int ret = CA_RESULT_OK;
917 char dst_path[CA_MAX_FILE_PATH_LEN] = { 0, };
918 char *cache_path = ca_config_get_cache_path();
919 ca_size_t total_file_size = 0;
920 ca_size_t file_size = 0;
922 for (int i = 0; i < file_count; i++) {
923 if (!cache_files[i]) {
924 CA_LOGE("[NULL-CHECK] cache_files[%d]", i);
926 ret = CA_ERR_INVALID_ARGUMENT;
930 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s", cache_path, cache_files[i]);
931 ca_storage_get_file_size(dst_path, &file_size);
933 if (unlink(dst_path) < 0) {
934 char err_buf[CA_MAX_ERROR_STR_LEN] = { 0, };
936 strerror_r(errno, err_buf, CA_MAX_ERROR_STR_LEN);
937 CA_LOGE("Unable to remove the file: %s, error [%d/%s]", dst_path, errno, err_buf);
939 ret = CA_ERR_INVALID_PATH;
944 total_file_size += file_size;
948 __reduce_cache_size(total_file_size);
953 int ca_storage_is_file_available(const char *cache_file)
955 int ret = CA_RESULT_OK;
956 char dst_path[CA_MAX_FILE_PATH_LEN] = { 0, };
957 char *cache_path = ca_config_get_cache_path();
959 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s", cache_path, cache_file);
961 if (__get_file_state(dst_path) != CA_REGULAR_FILE) {
962 CA_LOGE("Not a regular file!");
963 ret = CA_ERR_INVALID_ARGUMENT;
967 if (__is_realpath(dst_path) != CA_RESULT_OK) {
968 CA_LOGE("Not a real file!");
969 ret = CA_ERR_INVALID_ARGUMENT;
977 int ca_storage_get_used_cache_size(ca_size_t *size)
980 char *cache_path = ca_config_get_cache_path();
982 if (ftw(cache_path, __sum, 1) != 0) {
983 CA_LOGE("Failed to get cache directory size!");
985 return CA_ERR_INVALID_ARGUMENT;
988 *size = cache_dir_size;
990 CA_LOGD("size(Bytes): %lld", *size);
996 int ca_storage_copy_file(ca_info_t *ca_info)
998 pthread_attr_t thread_attr;
1001 if (pthread_attr_init(&thread_attr) != 0)
1002 return CA_ERR_FAIL_TO_CREATE_THREAD;
1004 if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) != 0)
1005 return CA_ERR_FAIL_TO_CREATE_THREAD;
1007 if (pthread_create(&(tid), &thread_attr, __thread_start_copy, ca_info) != 0) {
1008 CA_LOGE("Fail to make thread:id[%d]", ca_info->ca_id);
1009 return CA_ERR_FAIL_TO_CREATE_THREAD;
1012 ca_info->thread_id = tid;
1013 CA_LOGI("Thread is created:thread id[%lu]", ca_info->thread_id);
1015 return CA_RESULT_OK;
1018 int ca_init_cache_download_data(ca_info_t *ca_info,
1019 const char *cache_file, ca_req_data_t *ext_data)
1021 char src_path[CA_MAX_FILE_PATH_LEN] = { 0, };
1022 char dst_path[CA_MAX_FILE_PATH_LEN] = { 0, };
1023 char *gen_dst_file_name = CA_NULL;
1024 void *dst_fp = CA_NULL;
1025 const char *dst_file_name = ext_data->file_name;
1026 const char *dst_file_path = ext_data->install_path;
1027 char *cache_path = ca_config_get_cache_path();
1029 if (!dst_file_name || !dst_file_path) {
1030 CA_LOGE("Invalid dst file path or dst file name!");
1032 return CA_ERR_INVALID_ARGUMENT;
1035 snprintf(src_path, CA_MAX_FILE_PATH_LEN, "%s/%s", cache_path, cache_file);
1036 snprintf(dst_path, CA_MAX_FILE_PATH_LEN, "%s/%s", dst_file_path, dst_file_name);
1040 if (__get_file_state(src_path) != CA_REGULAR_FILE) {
1041 CA_LOGE("No src file exist!");
1042 return CA_ERR_INVALID_PATH;
1045 gen_dst_file_name = __generate_dst_file_name(dst_path, dst_file_path, dst_file_name);
1047 if (gen_dst_file_name == CA_NULL) {
1048 CA_LOGE("Fail to generate dst file name!");
1049 return CA_ERR_INVALID_STATE;
1052 dst_fp = __open_dst_file(dst_path);
1053 if (dst_fp == CA_NULL) {
1054 CA_LOGE("Unable to open dst file!");
1055 free(gen_dst_file_name);
1056 return CA_ERR_FAIL_TO_ACCESS_FILE;
1059 ca_info->dst_fp = (FILE *)dst_fp;
1060 ca_info->src_file = strdup(src_path);
1061 ca_info->dst_file = strdup(dst_path);
1062 ca_info->file_name = gen_dst_file_name;
1064 ca_req_info_t *req_info = ca_info->req_info;
1066 if (ext_data->install_path)
1067 req_info->install_path = strdup(ext_data->install_path);
1068 if (ext_data->file_name)
1069 req_info->file_name = strdup(ext_data->file_name);
1070 if (ext_data->pkg_name)
1071 req_info->pkg_name = strdup(ext_data->pkg_name);
1072 if (ext_data->user_req_data)
1073 req_info->user_req_data = ext_data->user_req_data;
1074 if (ext_data->user_client_data)
1075 req_info->user_client_data = ext_data->user_client_data;
1077 return CA_RESULT_OK;