Revert manifest to default one
[profile/ivi/download-provider.git] / src / agent / download-agent-file.c
1 /*
2  * Download Agent
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * @file                download-agent-file.c
21  * @brief               functions for file operation
22  * @author              Keunsoon Lee(keunsoon.lee@samsung.com)
23  * @author              Jungki Kwak(jungki.kwak@samsung.com)
24  ***/
25
26 #include <dirent.h>
27 #include <unistd.h>
28 #include <math.h>
29
30 #include "download-agent-client-mgr.h"
31 #include "download-agent-debug.h"
32 #include "download-agent-utils.h"
33 #include "download-agent-dl-mgr.h"
34 #include "download-agent-file.h"
35 #include "download-agent-installation.h"
36 #include "download-agent-mime-util.h"
37 #include "download-agent-http-mgr.h"
38
39 #define NO_NAME_TEMP_STR "No name"
40
41 static da_result_t  __set_file_size(stage_info *stage);
42 static da_result_t  __tmp_file_open(stage_info *stage);
43
44 static char *__derive_extension(stage_info *stage);
45 static da_result_t __divide_file_name_into_pure_name_N_extesion(
46                 const char *in_file_name,
47                 char **out_pure_file_name,
48                 char **out_extension);
49 static da_result_t __get_candidate_file_name(stage_info *stage,
50                 char **out_pure_file_name, char **out_extension);
51
52 static da_result_t __file_write_buf_make_buf(file_info *file_storage);
53 static da_result_t __file_write_buf_destroy_buf(file_info *file_storage);
54 static da_result_t __file_write_buf_flush_buf(stage_info *stage,
55                 file_info *file_storage);
56 static da_result_t __file_write_buf_copy_to_buf(file_info *file_storage,
57                 char *body, int body_len);
58 static da_result_t __file_write_buf_directly_write(stage_info *stage,
59                 file_info *file_storage, char *body, int body_len);
60
61
62 da_result_t create_temp_saved_dir(void)
63 {
64         da_result_t ret = DA_RESULT_OK;
65         char *client_dir_path = DA_NULL;
66
67         DA_LOG_FUNC_START(FileManager);
68
69         ret = get_client_download_path(&client_dir_path);
70         if (DA_RESULT_OK != ret) {
71                 goto ERR;
72         } else {
73                 if (DA_NULL == client_dir_path) {
74                         DA_LOG_ERR(FileManager, "client_dir_path is DA_NULL");
75                         ret = DA_ERR_INVALID_ARGUMENT;
76                         goto ERR;
77                 }
78         }
79
80         if (DA_FALSE == is_dir_exist(client_dir_path)) {
81                 ret = create_dir(client_dir_path);
82         }
83
84 ERR:
85         if (client_dir_path) {
86                 free(client_dir_path);
87                 client_dir_path = DA_NULL;
88         }
89         return ret;
90 }
91
92 da_result_t clean_files_from_dir(char* dir_path)
93 {
94         da_result_t ret = DA_RESULT_OK;
95         struct dirent *d = DA_NULL;
96         DIR *dir;
97         char file_path[DA_MAX_FULL_PATH_LEN] = { 0, };
98
99         DA_LOG_FUNC_START(FileManager);
100
101         if (dir_path == DA_NULL) {
102                 ret = DA_ERR_INVALID_ARGUMENT;
103                 goto ERR;
104         }
105
106         if (is_dir_exist(dir_path)) {
107                 dir = opendir(dir_path);
108                 if (DA_NULL == dir) {
109                         DA_LOG_ERR(FileManager, "opendir() for DA_DEFAULT_TMP_FILE_DIR_PATH is failed.");
110                         ret = DA_ERR_FAIL_TO_ACCESS_FILE;
111                 } else {
112                         while (DA_NULL != (d = readdir(dir))) {
113                                 DA_LOG(FileManager, "%s",d->d_name);
114                                 if (0 == strncmp(d->d_name, ".", strlen("."))
115                                                 || 0 == strncmp(d->d_name,
116                                                                 "..",
117                                                                 strlen(".."))) {
118                                         continue;
119                                 }
120
121                                 memset(file_path, 0x00, DA_MAX_FULL_PATH_LEN);
122                                 snprintf(file_path, DA_MAX_FULL_PATH_LEN,
123                                                 "%s/%s", dir_path, d->d_name);
124                                 if (remove(file_path) < 0) {
125                                         DA_LOG_ERR(FileManager, "fail to remove file");
126                                 }
127                         }
128
129                         closedir(dir);
130                         if (remove(dir_path) < 0) {
131                                 DA_LOG_ERR(FileManager, "fail to remove dir");
132                         }
133                 }
134         }
135
136 ERR:
137         return ret;
138 }
139
140 /* Priority to obtain MIME Type
141  * 1. HTTP response header's <Content-Type> field
142  * 2. from OMA descriptor file's <content-type> attribute (mandatory field)
143  * 3. Otherwise, leave blank for MIME Type
144  */
145 da_result_t get_mime_type(stage_info *stage, char **out_mime_type)
146 {
147         char *mime_type = DA_NULL;
148
149         if (!GET_STAGE_SOURCE_INFO(stage))
150                 return DA_ERR_INVALID_ARGUMENT;
151
152         /* Priority 1 */
153         if (GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage))) {
154                 mime_type = GET_REQUEST_HTTP_HDR_CONT_TYPE(GET_STAGE_TRANSACTION_INFO(stage));
155                  DA_LOG(FileManager, "content type from HTTP response header [%s]", mime_type);
156         }
157
158         if (!mime_type) {
159                 DA_LOG(FileManager, "no content type derived");
160                 return DA_RESULT_OK;
161         }
162
163         /* FIXME really need memory allocation? */
164         *out_mime_type = (char *) calloc(1, strlen(mime_type) + 1);
165         if (*out_mime_type) {
166                 snprintf(*out_mime_type, strlen(mime_type) + 1, mime_type);
167                 DA_LOG_VERBOSE(FileManager, "out_mime_type str[%s] ptr[%p] len[%d]",
168                                 *out_mime_type,*out_mime_type,strlen(*out_mime_type));
169         } else {
170                 DA_LOG_ERR(FileManager, "fail to allocate memory");
171                 return DA_ERR_FAIL_TO_MEMALLOC;
172         }
173
174         DA_LOG(FileManager, "mime type = %s", *out_mime_type);
175         return DA_RESULT_OK;
176 }
177
178 da_bool_t is_file_exist(const char *file_path)
179 {
180         struct stat dir_state;
181         int stat_ret;
182
183         if (file_path == DA_NULL) {
184                 DA_LOG_ERR(FileManager, "file path is DA_NULL");
185                 return DA_FALSE;
186         }
187
188         stat_ret = stat(file_path, &dir_state);
189
190         if (stat_ret == 0) {
191                 if (dir_state.st_mode & S_IFREG) {
192                         DA_LOG(FileManager, "Exist! %s is a regular file & its size = %lu", file_path, dir_state.st_size);
193                         return DA_TRUE;
194                 }
195
196                 return DA_FALSE;
197         }
198         return DA_FALSE;
199
200 }
201
202 da_bool_t is_dir_exist(char *file_path)
203 {
204         struct stat dir_state;
205         int stat_ret;
206
207         if (file_path == DA_NULL) {
208                 DA_LOG_ERR(FileManager, "file path is DA_NULL");
209                 return DA_FALSE;
210         }
211
212         stat_ret = stat(file_path, &dir_state);
213
214         if (stat_ret == 0) {
215                 if (dir_state.st_mode & S_IFDIR) {
216                         DA_LOG(FileManager, "Exist! %s is a directory.", file_path);
217                         return DA_TRUE;
218                 }
219
220                 return DA_FALSE;
221         }
222         return DA_FALSE;
223 }
224
225 void get_file_size(char *file_path, int *out_file_size)
226 {
227         struct stat dir_state;
228         int stat_ret;
229
230         *out_file_size = -1;
231
232         if (file_path == DA_NULL) {
233                 DA_LOG_ERR(FileManager, "file path is DA_NULL");
234                 return;
235         }
236
237         /* Please do not use ftell() to obtain file size, use stat instead.
238          *  This is a guide from www.securecoding.cert.org
239          *    : FIO19-C. Do not use fseek() and ftell() to compute the size of a file
240          */
241         stat_ret = stat(file_path, &dir_state);
242         if (stat_ret == 0) {
243                 if (dir_state.st_mode & S_IFREG) {
244                         DA_LOG(FileManager, "size = %lu", dir_state.st_size);
245                         *out_file_size = dir_state.st_size;
246                 }
247         }
248         return;
249 }
250
251 da_result_t __tmp_file_open(stage_info *stage)
252 {
253         da_result_t ret = DA_RESULT_OK;
254
255         file_info *file_storage = DA_NULL;
256         char *actual_file_path = DA_NULL;
257         char *tmp_file_path = DA_NULL;
258         void *fd = DA_NULL;
259
260         DA_LOG_FUNC_START(FileManager);
261
262         file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
263         if (!file_storage)
264                 return DA_ERR_INVALID_ARGUMENT;
265
266         actual_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage);
267         DA_LOG(FileManager, "actual_file_path = %s", actual_file_path);
268         if (!actual_file_path)
269                 return DA_ERR_INVALID_ARGUMENT;
270
271         tmp_file_path = (char *) calloc(1, (strlen(actual_file_path) + 1));
272         if (!tmp_file_path) {
273                 ret = DA_ERR_FAIL_TO_MEMALLOC;
274                 goto ERR;
275         }
276         snprintf(tmp_file_path, strlen(actual_file_path) + 1, "%s", actual_file_path);
277
278         GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = tmp_file_path;
279         DA_LOG(FileManager, "GET_CONTENT_STORE_TMP_FILE_NAME = %s ",GET_CONTENT_STORE_TMP_FILE_NAME(file_storage));
280
281         fd = fopen(tmp_file_path, "a"); // for resume
282         if (fd == DA_NULL) {
283                 DA_LOG_ERR(FileManager, "File open failed");
284                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
285                 goto ERR;
286         }
287         GET_CONTENT_STORE_FILE_HANDLE(file_storage) = fd;
288
289         DA_LOG(FileManager, "file path for tmp saving = %s", GET_CONTENT_STORE_TMP_FILE_NAME(file_storage));
290
291 ERR:
292         if (DA_RESULT_OK != ret) {
293                 if (tmp_file_path) {
294                         free(tmp_file_path);
295                 }
296                 if (file_storage != DA_NULL) {
297                         GET_CONTENT_STORE_TMP_FILE_NAME(file_storage) = DA_NULL;
298                         GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL;
299                 }
300         }
301         return ret;
302 }
303
304 da_result_t __set_file_size(stage_info *stage)
305 {
306         da_result_t ret = DA_RESULT_OK;
307         req_dl_info *stage_req_info = DA_NULL;
308         file_info *file_storage = DA_NULL;
309
310         DA_LOG_FUNC_START(FileManager);
311
312         if (!stage) {
313                 ret = DA_ERR_INVALID_ARGUMENT;
314                 goto ERR;
315         }
316
317         stage_req_info = GET_STAGE_TRANSACTION_INFO(stage);
318
319         file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
320         if (!file_storage)
321                 goto ERR;
322
323         if (GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info) != DA_NULL) {
324                 GET_CONTENT_STORE_FILE_SIZE(file_storage)
325                                 = GET_REQUEST_HTTP_HDR_CONT_LEN(stage_req_info);
326         } else {
327                 GET_CONTENT_STORE_FILE_SIZE(file_storage) = 0;
328         }
329         DA_LOG(FileManager, "file size = %d", GET_CONTENT_STORE_FILE_SIZE(file_storage));
330 ERR:
331         return ret;
332
333 }
334
335 /* Priority to derive extension
336  * 1. according to MIME-Type
337  * 2. if MIME-Type is ambiguous or blank,
338  *    2-1. derived from <Content-Disposition> field's "filename" attribute
339  *    2-2. derived from url
340  * 3. if url does not have extension, leave blank for extension
341  */
342 char *__derive_extension(stage_info *stage)
343 {
344         if (!stage)
345                 return DA_NULL;
346
347         source_info_t *source_info = GET_STAGE_SOURCE_INFO(stage);
348         req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage);
349         file_info *file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
350         char *extension = DA_NULL;
351         char *url = DA_NULL;
352
353         /* Priority 1 */
354         char *mime_type = DA_NULL;
355         mime_type = GET_CONTENT_STORE_CONTENT_TYPE(file_info_data);
356         if (mime_type && !is_ambiguous_MIME_Type(mime_type)) {
357                 char *extension = DA_NULL;
358                 da_result_t ret = get_extension_from_mime_type(mime_type, &extension);
359                 if (ret == DA_RESULT_OK && extension)
360                         return extension;
361         }
362
363         /* Priority 2-1 */
364         http_msg_response_t *http_msg_response = DA_NULL;
365         http_msg_response = request_info->http_info.http_msg_response;
366         if (http_msg_response) {
367                 char *file_name = DA_NULL;
368                 da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response,
369                                 DA_NULL, &file_name);
370                 if (b_ret && file_name) {
371                         char *extension = DA_NULL;
372                         DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name);
373                         __divide_file_name_into_pure_name_N_extesion(file_name, DA_NULL, &extension);
374                                 if (file_name) {
375                                 free(file_name);
376                                 file_name = DA_NULL;
377                         }
378                         if (extension)
379                                 return extension;
380                 }
381         }
382         /* Priority 2-2 */
383         /* If there is location url from response header in case of redirection,
384          * it try to parse the extention name from the location url */
385         if (GET_REQUEST_HTTP_REQ_LOCATION(request_info))
386                 url = GET_REQUEST_HTTP_REQ_LOCATION(request_info);
387         else
388                 url = GET_SOURCE_BASIC_URL(source_info);
389         if (url) {
390                 DA_LOG(FileManager, "url:[%s]", url);
391                 da_bool_t b_ret = da_get_extension_name_from_url(url, &extension);
392                 if (b_ret && extension)
393                         return extension;
394         }
395
396         return DA_NULL;
397 }
398
399 /** Priority for deciding file name
400  * 1. what client wants, which is conveyed by DA_FEATURE_FILE_NAME
401  * 2. 'filename' option on HTTP response header's Content-Disposition field
402  * 3. requesting URL
403  * 4. Otherwise, define it as "No name"
404  */
405 da_result_t __get_candidate_file_name(stage_info *stage, char **out_pure_file_name, char **out_extension)
406 {
407         da_result_t ret = DA_RESULT_OK;
408         source_info_t *source_info = DA_NULL;
409         char *pure_file_name = DA_NULL;
410         char *extension = DA_NULL;
411
412         DA_LOG_FUNC_START(FileManager);
413
414         if (!stage || !out_pure_file_name)
415                 return DA_ERR_INVALID_ARGUMENT;
416
417         source_info = GET_STAGE_SOURCE_INFO(stage);
418         if (!source_info)
419                 return DA_ERR_INVALID_ARGUMENT;
420
421         /* Priority 1 */
422         if (!pure_file_name && GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage))) {
423                 __divide_file_name_into_pure_name_N_extesion(
424                         GET_DL_USER_FILE_NAME(GET_STAGE_DL_ID(stage)),
425                         &pure_file_name, &extension);
426         }
427
428         /* Priority 2 */
429         if (!pure_file_name) {
430                 req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage);
431                 http_msg_response_t *http_msg_response = DA_NULL;
432                 http_msg_response = request_info->http_info.http_msg_response;
433                 if (http_msg_response) {
434                         char *file_name = DA_NULL;
435                         da_bool_t b_ret = http_msg_response_get_content_disposition(http_msg_response,
436                                         DA_NULL, &file_name);
437                         if (b_ret && file_name) {
438                                 DA_LOG(FileManager, "Name from Content-Disposition :[%s]", file_name);
439                                 __divide_file_name_into_pure_name_N_extesion(file_name, &pure_file_name, DA_NULL);
440                                 if (file_name) {
441                                         free(file_name);
442                                         file_name = DA_NULL;
443                                 }
444                         }
445                 }
446         }
447
448         /* Priority 3 */
449         if (!pure_file_name) {
450                 char *url = DA_NULL;
451                 req_dl_info *request_info = GET_STAGE_TRANSACTION_INFO(stage);
452                 /* If there is location url from response header in case of redirection,
453                  * it try to parse the file name from the location url */
454                 if (GET_REQUEST_HTTP_REQ_LOCATION(request_info))
455                         url = GET_REQUEST_HTTP_REQ_LOCATION(request_info);
456                 else
457                         url = GET_SOURCE_BASIC_URL(source_info);
458                 if (url) {
459                         DA_LOG(FileManager, "url: [%s]", url);
460                         da_get_file_name_from_url(url, &pure_file_name);
461                 }
462         }
463
464         /* Priority 4 */
465         if (!pure_file_name) {
466                 pure_file_name = strdup(NO_NAME_TEMP_STR);
467                 if (!pure_file_name) {
468                         ret = DA_ERR_FAIL_TO_MEMALLOC;
469                         goto ERR;
470                 }
471         }
472
473         *out_pure_file_name = pure_file_name;
474         pure_file_name = DA_NULL;
475         DA_LOG(FileManager, "candidate file name [%s]", *out_pure_file_name);
476
477         if (out_extension) {
478                 if (extension) {
479                         *out_extension = extension;
480                         extension = DA_NULL;
481                 } else {
482                         *out_extension = __derive_extension(stage);
483                         DA_LOG(FileManager, "candidate extension [%s]", *out_extension);
484                 }
485         }
486
487         if (extension)
488                 free(extension);
489
490         return DA_RESULT_OK;
491
492 ERR:
493         if (extension)
494                 free(extension);
495
496         return ret;
497 }
498
499
500 da_result_t decide_final_file_path(stage_info *stage)
501 {
502         da_result_t ret = DA_RESULT_OK;
503         char *default_dir = DA_NULL;
504         char *extension = DA_NULL;
505         char *tmp_file_path = DA_NULL;
506         char *file_name_without_extension = DA_NULL;
507         file_info *file_info_data = DA_NULL;
508
509         DA_LOG_FUNC_START(FileManager);
510
511         file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
512         if (!file_info_data)
513                 return DA_ERR_INVALID_ARGUMENT;
514
515         ret = __get_candidate_file_name(stage, &file_name_without_extension, &extension);
516         if (ret != DA_RESULT_OK)
517                 goto ERR;
518
519         ret = get_client_download_path(&default_dir);
520         if (DA_RESULT_OK != ret || DA_NULL == default_dir) {
521                 goto ERR;
522         }
523
524         tmp_file_path = get_full_path_avoided_duplication(default_dir, file_name_without_extension, extension);
525         if (tmp_file_path) {
526                 GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage))
527                                 = tmp_file_path;
528                 tmp_file_path = DA_NULL;
529         } else {
530                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
531                 goto ERR;
532         }
533
534         if (file_name_without_extension && !GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data)) {
535                 GET_CONTENT_STORE_PURE_FILE_NAME(file_info_data) = file_name_without_extension;
536                 file_name_without_extension = DA_NULL;
537         }
538
539         if (extension && !GET_CONTENT_STORE_EXTENSION(file_info_data)) {
540                 GET_CONTENT_STORE_EXTENSION(file_info_data) = extension;
541                 extension = DA_NULL;
542         }
543
544 ERR:
545         DA_LOG(FileManager, "decided file path = %s", GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data));
546         if (default_dir) {
547                 free(default_dir);
548                 default_dir = DA_NULL;
549         }
550
551         if (file_name_without_extension) {
552                 free(file_name_without_extension);
553                 file_name_without_extension = DA_NULL;
554         }
555
556         if (extension) {
557                 free(extension);
558                 extension = DA_NULL;
559         }
560
561         return ret;
562 }
563
564 char *get_full_path_avoided_duplication(char *in_dir, char *in_candidate_file_name, char * in_extension)
565 {
566         char *dir = in_dir;
567         char *file_name = in_candidate_file_name;
568         char *extension = in_extension;
569         char *final_path = DA_NULL;
570
571         int final_path_len = 0;
572         int extension_len = 0;
573
574         int suffix_count = 0;   /* means suffix on file name. up to "_99" */
575         const int max_suffix_count = 99;
576         int suffix_len = (int)log10(max_suffix_count+1) + 1;    /* 1 means "_" */
577
578         if (!in_dir || !in_candidate_file_name)
579                 return DA_NULL;
580
581 //      DA_LOG_FUNC_START(FileManager);
582         DA_LOG(FileManager, "in_candidate_file_name=[%s], in_extension=[%s]", in_candidate_file_name, in_extension);
583
584         if (extension)
585                 extension_len = strlen(extension);
586
587         /* first 1 for "/", second 1 for ".", last 1 for DA_NULL */
588         final_path_len = strlen(dir) + 1 + strlen(file_name) + 1
589                         + suffix_len + extension_len + 1;
590
591         final_path = (char*)calloc(1, final_path_len);
592         if (!final_path) {
593                 DA_LOG_ERR(FileManager, "DA_ERR_FAIL_TO_MEMALLOC");
594                 return DA_NULL;
595         }
596
597         do {
598                 /* e.g) /tmp/abc.jpg
599                  * if there is no extension name, just make a file name without extension */
600                 if (0 == extension_len) {
601                         if (suffix_count == 0) {
602                                 snprintf(final_path, final_path_len,
603                                                 "%s/%s", dir, file_name);
604                         } else {
605                                 snprintf(final_path, final_path_len,
606                                                 "%s/%s_%d", dir, file_name, suffix_count);
607                         }
608                 } else {
609                         if (suffix_count == 0) {
610                                 snprintf(final_path, final_path_len,
611                                                 "%s/%s.%s", dir, file_name, extension);
612                         } else {
613                                 snprintf(final_path, final_path_len,
614                                                 "%s/%s_%d.%s",
615                                                 dir, file_name, suffix_count, extension);
616                         }
617                 }
618
619                 if (is_file_exist(final_path)) {
620                         suffix_count++;
621                         if (suffix_count > max_suffix_count) {
622                                 free(final_path);
623                                 final_path = DA_NULL;
624                                 break;
625                         } else {
626                                 memset(final_path, 0x00, final_path_len);
627                                 continue;
628                         }
629                 }
630
631                 break;
632         } while (1);
633
634         DA_LOG(FileManager, "decided path = [%s]", final_path);
635         return final_path;
636 }
637
638 da_result_t __divide_file_name_into_pure_name_N_extesion(const char *in_file_name, char **out_pure_file_name, char **out_extension)
639 {
640         char *file_name = DA_NULL;
641         char *tmp_ptr = DA_NULL;
642         char temp_file[DA_MAX_FILE_PATH_LEN] = {0,};
643         char tmp_ext[DA_MAX_STR_LEN] = {0,};
644         int len = 0;
645         da_result_t ret = DA_RESULT_OK;
646
647         DA_LOG_FUNC_START(FileManager);
648
649         if (!in_file_name)
650                 return DA_ERR_INVALID_ARGUMENT;
651
652         file_name = (char *)in_file_name;
653         tmp_ptr = strrchr(file_name, '.');
654         if (tmp_ptr)
655                 tmp_ptr++;
656         if (tmp_ptr && out_extension) {
657                 strncpy((char*) tmp_ext, tmp_ptr, sizeof(tmp_ext) - 1);
658                 *out_extension = strdup((const char*) tmp_ext);
659                 DA_LOG(FileManager, "extension [%s]", *out_extension);
660         }
661
662         if (!out_pure_file_name)
663                 return ret;
664
665         if (tmp_ptr)
666                 len = tmp_ptr - file_name - 1;
667         else
668                 len = strlen(file_name);
669
670         if (len >= DA_MAX_FILE_PATH_LEN) {
671                 strncpy((char*) temp_file, file_name,
672                                 DA_MAX_FILE_PATH_LEN - 1);
673         } else {
674                 strncpy((char*) temp_file, file_name, len);
675         }
676
677         delete_prohibited_char((char*) temp_file,
678                         strlen((char*) temp_file));
679         if (strlen(temp_file) < 1) {
680                 *out_pure_file_name = strdup(NO_NAME_TEMP_STR);
681         } else {
682                 *out_pure_file_name = strdup(
683                                 (const char*) temp_file);
684         }
685
686         DA_LOG(FileManager, "pure file name [%s]", *out_pure_file_name);
687         return ret;
688 }
689
690 da_result_t __file_write_buf_make_buf(file_info *file_storage)
691 {
692         da_result_t ret = DA_RESULT_OK;
693         char *buffer = DA_NULL;
694
695         DA_LOG_FUNC_START(FileManager);
696
697         buffer = (char*) calloc(DOWNLOAD_NOTIFY_LIMIT, 1);
698         if (DA_NULL == buffer) {
699                 DA_LOG_ERR(FileManager, "Calloc failure ");
700                 ret = DA_ERR_FAIL_TO_MEMALLOC;
701         } else {
702                 GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0;
703                 GET_CONTENT_STORE_FILE_BUFFER(file_storage) = buffer;
704         }
705
706         return ret;
707 }
708
709 da_result_t __file_write_buf_destroy_buf(file_info *file_storage)
710 {
711         da_result_t ret = DA_RESULT_OK;
712
713         DA_LOG_FUNC_START(FileManager);
714
715         if (GET_CONTENT_STORE_FILE_BUFFER(file_storage))
716                 free(GET_CONTENT_STORE_FILE_BUFFER(file_storage));
717
718         GET_CONTENT_STORE_FILE_BUFFER(file_storage) = DA_NULL;
719         GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0;
720
721         return ret;
722 }
723
724 da_result_t __file_write_buf_flush_buf(stage_info *stage, file_info *file_storage)
725 {
726         da_result_t ret = DA_RESULT_OK;
727         char *buffer = DA_NULL;
728         int buffer_size = 0;
729         int write_success_len = 0;
730         void *fd = DA_NULL;
731
732         //      DA_LOG_FUNC_START(FileManager);
733
734         buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage);
735         buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage);
736
737         if (buffer_size == 0) {
738                 DA_LOG_ERR(FileManager, "no data on buffer..");
739                 return ret;
740         }
741
742         fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage);
743         if (DA_NULL == fd) {
744                 DA_LOG_ERR(FileManager, "There is no file handle.");
745
746                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
747                 goto ERR;
748         }
749
750         write_success_len = fwrite(buffer, sizeof(char), buffer_size,
751                         (FILE *) fd);
752         fflush((FILE *) fd);
753         if (write_success_len != buffer_size) {
754                 DA_LOG_ERR(FileManager, "write  fails ");
755                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
756                 goto ERR;
757         }
758         GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
759                         += write_success_len;
760         DA_LOG(FileManager, "write %d bytes", write_success_len);
761
762         IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE;
763         GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0;
764
765 ERR:
766         return ret;
767 }
768
769 da_result_t __file_write_buf_copy_to_buf(file_info *file_storage, char *body,
770                 int body_len)
771 {
772         da_result_t ret = DA_RESULT_OK;
773         char *buffer = DA_NULL;
774         int buffer_size = 0;
775
776         //      DA_LOG_FUNC_START(FileManager);
777
778         buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage);
779         buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage);
780
781         memcpy(buffer + buffer_size, body, body_len);
782         GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) += body_len;
783
784         return ret;
785 }
786
787 da_result_t __file_write_buf_directly_write(stage_info *stage,
788                 file_info *file_storage, char *body, int body_len)
789 {
790         da_result_t ret = DA_RESULT_OK;
791         int write_success_len = 0;
792         void *fd = DA_NULL;
793
794         //      DA_LOG_FUNC_START(FileManager);
795
796         fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage);
797         if (DA_NULL == fd) {
798                 DA_LOG_ERR(FileManager, "There is no file handle.");
799
800                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
801                 goto ERR;
802         }
803
804         write_success_len = fwrite(body, sizeof(char), body_len,
805                         (FILE *) fd);
806         fflush((FILE *) fd);
807         if (write_success_len != body_len) {
808                 DA_LOG_ERR(FileManager, "write  fails ");
809                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
810                 goto ERR;
811         }
812         GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
813                         += write_success_len;
814         DA_LOG(FileManager, "write %d bytes", write_success_len);
815         IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_TRUE;
816
817 ERR:
818         return ret;
819 }
820
821 da_result_t file_write_ongoing(stage_info *stage, char *body, int body_len)
822 {
823         da_result_t ret = DA_RESULT_OK;
824         file_info *file_storage = DA_NULL;
825         int buffer_size = 0;
826         char *buffer = DA_NULL;
827
828         //      DA_LOG_FUNC_START(FileManager);
829
830         if (DA_TRUE == is_this_client_manual_download_type()) {
831                 return ret;
832         }
833         file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
834         if (!file_storage) {
835                 DA_LOG_ERR(FileManager, "file_info is empty.");
836                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
837                 goto ERR;
838         }
839
840         buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage);
841         buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage);
842         IS_CONTENT_STORE_FILE_BYTES_WRITTEN_TO_FILE(file_storage) = DA_FALSE;
843
844         if (DA_NULL == buffer) {
845                 if (body_len < DOWNLOAD_NOTIFY_LIMIT) {
846                         ret = __file_write_buf_make_buf(file_storage);
847                         if (ret != DA_RESULT_OK)
848                                 goto ERR;
849
850                         __file_write_buf_copy_to_buf(file_storage, body, body_len);
851                 } else {
852                         ret = __file_write_buf_directly_write(stage,
853                                         file_storage, body, body_len);
854                         if (ret != DA_RESULT_OK)
855                                 goto ERR;
856                 }
857         } else {
858                 if (DOWNLOAD_NOTIFY_LIMIT <= body_len) {
859                         ret = __file_write_buf_flush_buf(stage, file_storage);
860                         if (ret != DA_RESULT_OK)
861                                 goto ERR;
862
863                         ret = __file_write_buf_directly_write(stage,
864                                         file_storage, body, body_len);
865                         if (ret != DA_RESULT_OK)
866                                 goto ERR;
867
868                 } else if ((DOWNLOAD_NOTIFY_LIMIT - buffer_size) <= body_len) {
869                         ret = __file_write_buf_flush_buf(stage, file_storage);
870                         if (ret != DA_RESULT_OK)
871                                 goto ERR;
872
873                         __file_write_buf_copy_to_buf(file_storage, body, body_len);
874                 } else {
875                         __file_write_buf_copy_to_buf(file_storage, body, body_len);
876                 }
877         }
878
879 ERR:
880         if (ret != DA_RESULT_OK) {
881                 if (file_storage) {
882                         GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage) = 0;
883                         if (GET_CONTENT_STORE_FILE_BUFFER(file_storage)) {
884                                 free(
885                                                 GET_CONTENT_STORE_FILE_BUFFER(file_storage));
886                                 GET_CONTENT_STORE_FILE_BUFFER(file_storage)
887                                                 = DA_NULL;
888                         }
889                 }
890         }
891         return ret;
892 }
893
894 da_result_t file_write_complete(stage_info *stage)
895 {
896         da_result_t ret = DA_RESULT_OK;
897         file_info*file_storage = DA_NULL;
898         char *buffer = DA_NULL;
899         unsigned int buffer_size = 0;
900         void *fd = DA_NULL;
901
902         DA_LOG_FUNC_START(FileManager);
903
904         if (DA_TRUE == is_this_client_manual_download_type()) {
905                 return ret;
906         }
907         file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
908         if (!file_storage) {
909                 DA_LOG_ERR(FileManager, "file_info is DA_NULL.");
910                 ret = DA_ERR_FAIL_TO_ACCESS_FILE;
911                 goto ERR;
912         }
913
914         buffer = GET_CONTENT_STORE_FILE_BUFFER(file_storage);
915         buffer_size = GET_CONTENT_STORE_FILE_BUFF_LEN(file_storage);
916
917         if (DA_NULL == buffer) {
918                 DA_LOG_ERR(FileManager, "file buffer is DA_NULL");
919         } else {
920                 if (buffer_size != 0) {
921                         ret = __file_write_buf_flush_buf(stage, file_storage);
922                         if (ret != DA_RESULT_OK)
923                                 goto ERR;
924                 }
925                 __file_write_buf_destroy_buf(file_storage);
926         }
927         fd = GET_CONTENT_STORE_FILE_HANDLE(file_storage);
928
929         if (fd) {
930                 // call sync
931                 fsync(fileno(fd));
932                 fclose(fd);
933                 fd = DA_NULL;
934         }
935         GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL;
936 ERR:
937         return ret;
938 }
939
940 da_result_t start_file_writing(stage_info *stage)
941 {
942         da_result_t ret = DA_RESULT_OK;
943         file_info *file_info_data = DA_NULL;
944
945         DA_LOG_FUNC_START(FileManager);
946
947         if (DA_TRUE == is_this_client_manual_download_type()) {
948                 return ret;
949         }
950         file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
951         ret = get_mime_type(stage,
952                         &GET_CONTENT_STORE_CONTENT_TYPE(file_info_data));
953         if (ret != DA_RESULT_OK)
954                 goto ERR;
955
956         ret = decide_final_file_path(stage);
957         if (ret != DA_RESULT_OK)
958                 goto ERR;
959
960         ret = __set_file_size(stage);
961         if (DA_RESULT_OK != ret)
962                 goto ERR;
963
964         GET_CONTENT_STORE_CURRENT_FILE_SIZE(GET_STAGE_CONTENT_STORE_INFO(stage))
965                         = 0;
966
967         ret = __tmp_file_open(stage);
968
969 ERR:
970         return ret;
971 }
972
973 da_result_t start_file_writing_append(stage_info *stage)
974 {
975         da_result_t ret = DA_RESULT_OK;
976
977         DA_LOG_FUNC_START(FileManager);
978         if (DA_TRUE == is_this_client_manual_download_type()) {
979                 return ret;
980         }
981
982         ret = __tmp_file_open(stage);
983
984         return ret;
985 }
986
987 da_result_t discard_download(stage_info *stage)
988 {
989         da_result_t ret = DA_RESULT_OK;
990         file_info *file_storage = DA_NULL;
991         char *temp_file_path = DA_NULL;
992         FILE *f_handle = DA_NULL;
993
994         DA_LOG_FUNC_START(FileManager);
995
996         file_storage = GET_STAGE_CONTENT_STORE_INFO(stage);
997
998         f_handle = GET_CONTENT_STORE_FILE_HANDLE(file_storage);
999         if (f_handle) {
1000                 fclose(f_handle);
1001                 GET_CONTENT_STORE_FILE_HANDLE(file_storage) = DA_NULL;
1002         }
1003         temp_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage);
1004         if (temp_file_path) {
1005                 remove_file((const char*) temp_file_path);
1006                 free(temp_file_path);
1007                 GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_storage) = DA_NULL;
1008         }
1009
1010         return ret;
1011 }
1012
1013 void clean_paused_file(stage_info *stage)
1014 {
1015         file_info *file_info_data = DA_NULL;
1016         char *paused_file_path = DA_NULL;
1017         FILE *fd = DA_NULL;
1018
1019         DA_LOG_FUNC_START(FileManager);
1020
1021         file_info_data = GET_STAGE_CONTENT_STORE_INFO(stage);
1022
1023         fd = GET_CONTENT_STORE_FILE_HANDLE(file_info_data);
1024         if (fd) {
1025                 fclose(fd);
1026                 GET_CONTENT_STORE_FILE_HANDLE(file_info_data) = DA_NULL;
1027         }
1028
1029         paused_file_path = GET_CONTENT_STORE_ACTUAL_FILE_NAME(file_info_data);
1030         remove_file((const char*) paused_file_path);
1031
1032         return;
1033 }
1034
1035 da_result_t replace_content_file_in_stage(stage_info *stage,
1036                 const char *dest_dd_file_path)
1037 {
1038         da_result_t ret = DA_RESULT_OK;
1039         char *dd_file_path = DA_NULL;
1040         int len;
1041
1042         DA_LOG_FUNC_START(FileManager);
1043
1044         if (!dest_dd_file_path
1045                         && (DA_FALSE == is_file_exist(dest_dd_file_path))) {
1046                 ret = DA_ERR_INVALID_ARGUMENT;
1047                 goto ERR;
1048         }
1049
1050         dd_file_path
1051                         =GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage));
1052
1053         if (DA_NULL != dd_file_path) {
1054                 remove_file((const char*) dd_file_path);
1055                 free(dd_file_path);
1056         }
1057         len = strlen(dest_dd_file_path);
1058         dd_file_path = calloc(1, len + 1);
1059         if (!dd_file_path) {
1060                 ret = DA_ERR_FAIL_TO_MEMALLOC;
1061                 goto ERR;
1062         }
1063         strncpy(dd_file_path, dest_dd_file_path, len);
1064         GET_CONTENT_STORE_ACTUAL_FILE_NAME(GET_STAGE_CONTENT_STORE_INFO(stage))
1065                         = dd_file_path;
1066
1067 ERR:
1068         return ret;
1069
1070 }
1071
1072 da_result_t copy_file(const char *src, const char *dest)
1073 {
1074         FILE *fs = DA_NULL;
1075         FILE *fd = DA_NULL;
1076         int freadnum = 0;
1077         int fwritenum = 0;
1078         char buff[4096] = { 0, };
1079
1080         DA_LOG_FUNC_START(FileManager);
1081
1082         /* open files to copy */
1083         fs = fopen(src, "rb");
1084         if (!fs) {
1085                 DA_LOG_ERR(FileManager, "Fail to open src file");
1086                 return DA_ERR_FAIL_TO_ACCESS_FILE;
1087         }
1088
1089         fd = fopen(dest, "wb");
1090         if (!fd) {
1091                 DA_LOG_ERR(FileManager, "Fail to open dest file");
1092
1093                 fclose(fs);
1094                 return DA_ERR_FAIL_TO_ACCESS_FILE;
1095         }
1096
1097         /* actual copy */
1098         while (!feof(fs)) {
1099                 memset(buff, 0x00, 4096);
1100                 freadnum = fread(buff, sizeof(char), sizeof(buff), fs);
1101                 if (freadnum > 0) {
1102                         fwritenum = fwrite(buff, sizeof(char), freadnum, fd);
1103                         if (fwritenum <= 0) {
1104                                 DA_LOG(FileManager, "written = %d",fwritenum);
1105                                 break;
1106                         }
1107                 } else {
1108                         DA_LOG(FileManager, "read = %d",freadnum);
1109                         break;
1110                 }
1111         }
1112
1113         fflush(fd);
1114         fsync(fileno(fd));
1115         fclose(fd);
1116         fclose(fs);
1117
1118         return DA_RESULT_OK;
1119 }
1120
1121 da_result_t create_dir(const char *install_dir)
1122 {
1123         da_result_t ret = DA_RESULT_OK;
1124                 /* read/write/search permissions for owner and group,
1125                  * and with read/search permissions for others. */
1126         if (mkdir(install_dir, S_IRWXU | S_IRWXG | S_IRWXO)) {
1127                 DA_LOG_ERR(FileManager, "Fail to creaate directory [%s]", install_dir);
1128                 ret = DA_ERR_FAIL_TO_ACCESS_STORAGE;
1129         } else {
1130                 DA_LOG(FileManager, "[%s] is created!", install_dir);
1131         }
1132         return ret;
1133 }
1134