Remove hardcoded path for multiuser support
[platform/core/system/sync-agent.git] / src / framework / fsapi / operation.c
1 /*
2  * sync-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <time.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <sys/vfs.h>            /* for statfs */
26 #include "fsapi/operation.h"
27 #include "fsapi/operation_internal.h"
28 #include "fsapi/util.h"
29 #include "security-assistant/md5.h"
30
31 #include "utility/sync_util.h"
32
33 #include <tzplatform_config.h>
34
35 #ifndef EXPORT_API
36 #define EXPORT_API __attribute__ ((visibility("default")))
37 #endif
38
39 #ifndef SYNC_AGENT_LOG
40 #undef LOG_TAG
41 #define LOG_TAG "AF_FS"
42 #endif
43
44 #define FS_BUFFER_SIZE 2048
45
46 static bool file_append_started = FALSE;
47 static bool file_read_started = FALSE;
48 static char *temp_filename_kept = NULL;
49 static char *requested_filename_kept = NULL;
50 static FILE *fd_source_kept = NULL;
51
52 static unsigned char _sync_str_to_hex_char(unsigned char hex);
53
54 EXPORT_API sync_agent_fsapi_return_e sync_agent_is_existing_fs(const char *file_name)
55 {
56         _EXTERN_FUNC_ENTER;
57
58         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
59
60         _EXTERN_FUNC_EXIT;
61
62         return fs_is_existing(file_name);
63 }
64
65 EXPORT_API sync_agent_fsapi_return_e sync_agent_get_fs_info(char **result)
66 {
67         _EXTERN_FUNC_ENTER;
68
69         retvm_if(result == NULL, 0, "result paramter is NULL !!!");
70
71         int ret = 0;
72
73         long double free_size = 0;
74         long double total_size = 0;
75
76         int file_name_len_max = 256;
77         int folder_name_len_max = 256;
78
79         char *file_name_prevenet_char = ":;*?/<>\"";
80         char *folder_name_prevent_char = ":;*?/<>\"";
81
82         int file_name_code_schema = 2;
83         int allow_dup_name = 0;
84         int folder_depth_max = 15;
85
86         ret = sync_agent_get_fs_mem_size(tzplatform_getenv(TZ_USER_CONTENT), &free_size, &total_size);
87         if (!ret) {
88                 _DEBUG_ERROR("[sync_agent_get_fs_info] getting mem size fail");
89                 return SYNC_AGENT_FSAPI_FALSE;
90         }
91
92         *result = g_strdup_printf("%.0Lf,%d,%s,%d,%d,%d,%d,%s", total_size, file_name_len_max, file_name_prevenet_char, file_name_code_schema, allow_dup_name, folder_depth_max, folder_name_len_max, folder_name_prevent_char);
93
94         _EXTERN_FUNC_EXIT;
95
96         return SYNC_AGENT_FSAPI_TRUE;
97 }
98
99 EXPORT_API sync_agent_fsapi_return_e sync_agent_free_fs_info(char *result)
100 {
101         _EXTERN_FUNC_ENTER;
102
103         retvm_if(result == NULL, 0, "result paramter is NULL !!!");
104
105         if (result != NULL)
106                 g_free(result);
107
108         _EXTERN_FUNC_EXIT;
109
110         return SYNC_AGENT_FSAPI_TRUE;
111 }
112
113 EXPORT_API sync_agent_fsapi_return_e sync_agent_get_fs_mem_size(const char *root, long double *size_free, long double *size_total)
114 {
115         _EXTERN_FUNC_ENTER;
116
117         retvm_if(root == NULL, 0, "root paramter is NULL !!!");
118
119         if (!fs_is_existing(root)) {
120                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist.\n", __func__, root);
121                 return SYNC_AGENT_FSAPI_FALSE;
122         }
123
124         struct statfs fs_info;
125
126         if (statfs(root, &fs_info) != 0) {
127                 _DEBUG_ERROR("[sync_agent_get_fs_mem_size] statfs error.");
128                 return SYNC_AGENT_FSAPI_FALSE;
129         }
130
131         *size_free = ((long double)fs_info.f_bavail * (long double)fs_info.f_bsize);    /* / 1024; */
132         *size_total = ((long double)fs_info.f_blocks * (long double)fs_info.f_bsize);   /* / 1024; */
133
134         _DEBUG_INFO("[sync_agent_get_fs_mem_size] FS info root : %s.", root);
135         _DEBUG_INFO("[sync_agent_get_fs_mem_size] FS info free size : %.0f", *size_free);
136         _DEBUG_INFO("[sync_agent_get_fs_mem_size] FS info total size : %.0f", *size_total);
137
138         _EXTERN_FUNC_EXIT;
139
140         return SYNC_AGENT_FSAPI_TRUE;
141 }
142
143 /*
144  * File operation
145  */
146
147 EXPORT_API sync_agent_fsapi_return_e sync_agent_get_file_size(const char *file_name, unsigned long *size)
148 {
149         _EXTERN_FUNC_ENTER;
150
151         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
152
153         if (!fs_is_existing(file_name) || fs_is_directory(file_name)) {
154                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
155                 return SYNC_AGENT_FSAPI_FALSE;
156         }
157
158         struct stat buf;
159
160         int ret = stat(file_name, &buf);
161         if (ret == -1) {
162                 _DEBUG_ERROR("[%s] stat error : %s", __func__, strerror(errno));
163                 return SYNC_AGENT_FSAPI_FALSE;
164         }
165
166         *size = (unsigned long)buf.st_size;
167
168         _EXTERN_FUNC_EXIT;
169
170         return SYNC_AGENT_FSAPI_TRUE;
171 }
172
173 int fs_get_file_date(const char *file_name, char **time_string)
174 {
175         _EXTERN_FUNC_ENTER;
176
177         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
178
179         if (!fs_is_existing(file_name) || fs_is_directory(file_name)) {
180                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
181                 return SYNC_AGENT_FSAPI_FALSE;
182         }
183
184         struct stat buf;
185         char time[FS_MAX_TIME_STRING_BUF] = { 0 };
186
187         int ret = stat(file_name, &buf);
188         if (ret == -1) {
189                 _DEBUG_ERROR("[%s] stat error : %s", __func__, strerror(errno));
190                 return SYNC_AGENT_FSAPI_FALSE;
191         }
192
193         fs_get_time_string(&buf.st_mtime, time);
194         *time_string = g_strdup(time);
195
196         _EXTERN_FUNC_EXIT;
197
198         return SYNC_AGENT_FSAPI_TRUE;
199 }
200
201 EXPORT_API sync_agent_fsapi_return_e sync_agent_copy_file(const char *source, const char *dest)
202 {
203         _EXTERN_FUNC_ENTER;
204
205         retvm_if(source == NULL, 0, "source paramter is NULL !!!");
206         retvm_if(dest == NULL, 0, "dest paramter is NULL !!!");
207
208         if (!fs_is_existing(source) || fs_is_directory(source) || fs_is_existing(dest)) {
209                 _DEBUG_ERROR("[%s] Requested source instance '%s' not exist or not a file, or\n", __func__, source);
210                 _DEBUG_ERROR("[%s] requested dest instance '%s' already exist.\n", __func__, dest);
211                 return SYNC_AGENT_FSAPI_FALSE;
212         }
213
214         FILE *f1 = NULL, *f2 = NULL;
215         int ret = 1;
216         char buf[1024 * 100] = { 0 };
217         unsigned long bytes_read = 0;
218         unsigned long bytes_written = 0;
219
220         f1 = (FILE *) g_fopen(source, "rb");
221         if (f1 == NULL) {
222                 _DEBUG_ERROR("[sync_agent_copy_file] file f1 open error.");
223                 ret = 0;
224                 goto return_part;
225         }
226
227         f2 = (FILE *) g_fopen(dest, "wb");
228         if (f2 == NULL) {
229                 _DEBUG_ERROR("[sync_agent_copy_file] file f2 open error.");
230                 ret = 0;
231                 goto return_part;
232         }
233
234         while ((bytes_read = fread(buf, 1, sizeof(buf), f1)) > 0) {
235                 if (bytes_read > sizeof(buf)) {
236                         _DEBUG_ERROR("[sync_agent_copy_file] read error.");
237                         ret = 0;
238                         goto return_part;
239                 }
240
241                 bytes_written = fwrite(buf, 1, bytes_read, f2);
242                 if (!feof(f1) && bytes_written != bytes_read) {
243                         _DEBUG_ERROR("[sync_agent_copy_file] write error.");
244                         ret = 0;
245                         goto return_part;
246                 }
247         }
248
249         _EXTERN_FUNC_EXIT;
250
251  return_part:
252         if (f1 != NULL)
253                 fclose(f1);
254         if (f2 != NULL)
255                 fclose(f2);
256         return ret;
257
258 /*
259         char *body = NULL;
260         unsigned long size;
261
262         if( !File_Read(source, &body, &size) ) {
263                 fprintf(stderr, "[%s] File_Read() returned error.\n", __func__);
264                 return SYNC_AGENT_FSAPI_FALSE;
265         }
266
267         if( !File_Write(dest, body, size) ) {
268                 fprintf(stderr, "[%s] File_Read() returned error.\n", __func__);
269                 return SYNC_AGENT_FSAPI_FALSE;
270         }
271
272         free(body);
273
274         return SYNC_AGENT_FSAPI_TRUE;
275 */
276 }
277
278 EXPORT_API sync_agent_fsapi_return_e sync_agent_delete_file(const char *file_name)
279 {
280         _EXTERN_FUNC_ENTER;
281
282         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
283
284         if (!fs_is_existing(file_name) || fs_is_directory(file_name)) {
285                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
286                 return SYNC_AGENT_FSAPI_FALSE;
287         }
288
289         int ret = g_unlink(file_name);
290         if (ret == -1) {
291                 _DEBUG_ERROR("[%s] g_unlink error : %s\n", __func__, strerror(errno));
292                 return SYNC_AGENT_FSAPI_FALSE;
293         }
294
295         _EXTERN_FUNC_EXIT;
296
297         return SYNC_AGENT_FSAPI_TRUE;
298 }
299
300 EXPORT_API sync_agent_fsapi_return_e sync_agent_move_file(const char *source, const char *dest)
301 {
302         _EXTERN_FUNC_ENTER;
303
304         retvm_if(source == NULL, 0, "source paramter is NULL !!!");
305         retvm_if(dest == NULL, 0, "dest paramter is NULL !!!");
306
307         if (!fs_is_existing(source) || fs_is_directory(source) || fs_is_existing(dest)) {
308                 _DEBUG_ERROR("[%s] Requested source instance '%s' not exist or not a file, or\n", __func__, source);
309                 _DEBUG_ERROR("[%s] requested dest instance '%s' already exist.\n", __func__, dest);
310                 return SYNC_AGENT_FSAPI_FALSE;
311         }
312
313         int ret = g_rename(source, dest);
314         if (ret == -1) {
315                 _DEBUG_ERROR("[sync_agent_move_file] g_rename error : %s", strerror(errno));
316                 _DEBUG_ERROR("[sync_agent_move_file] source : %s target : %s", source, dest);
317                 return SYNC_AGENT_FSAPI_FALSE;
318         }
319
320         _EXTERN_FUNC_EXIT;
321
322         return SYNC_AGENT_FSAPI_TRUE;
323 }
324
325 EXPORT_API sync_agent_fsapi_return_e sync_agent_rename_file(const char *source, const char *dest)
326 {
327         _EXTERN_FUNC_ENTER;
328
329         retvm_if(source == NULL, 0, "source paramter is NULL !!!");
330         retvm_if(dest == NULL, 0, "dest paramter is NULL !!!");
331
332         _EXTERN_FUNC_EXIT;
333
334         return sync_agent_move_file(source, dest);
335 }
336
337 EXPORT_API sync_agent_fsapi_return_e sync_agent_get_file_list(const char *folder_name, GSList ** list)
338 {
339         _EXTERN_FUNC_ENTER;
340
341         retvm_if(folder_name == NULL, 0, "folder_name paramter is NULL !!!");
342
343         if (!fs_is_existing(folder_name) || !fs_is_directory(folder_name)) {
344                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a directory.\n", __func__, folder_name);
345                 return SYNC_AGENT_FSAPI_FALSE;
346         }
347
348         struct stat buf;
349         char *path = NULL;
350         char time[FS_MAX_TIME_STRING_BUF] = { 0 };
351         char *list_item = NULL;
352
353         GError *gerror = NULL;
354         GDir *dir = g_dir_open(folder_name, 0, &gerror);
355         if (dir == NULL) {
356                 _DEBUG_ERROR("[%s] g_dir_open error : %s\n", __func__, gerror->message);
357                 g_error_free(gerror);
358                 return SYNC_AGENT_FSAPI_FALSE;
359         }
360
361         const char *file_name = g_dir_read_name(dir);
362
363         for (; file_name; file_name = g_dir_read_name(dir)) {
364
365                 path = g_strdup_printf("%s/%s", folder_name, file_name);
366
367                 if (!fs_is_directory(path)) {
368                         int ret = stat(path, &buf);
369                         if (ret == -1) {
370                                 _DEBUG_ERROR("[%s] g_stat error : %s\n", __func__, strerror(errno));
371                                 return SYNC_AGENT_FSAPI_FALSE;
372                         }
373
374                         fs_get_time_string(&buf.st_mtime, time);
375                         list_item = g_strdup_printf("%s,%ld,%s", file_name, (long)buf.st_size, time);
376
377                         *list = g_slist_append(*list, list_item);
378                 }
379         }
380
381         free(path);
382         g_dir_close(dir);
383         dir = NULL;
384
385         _EXTERN_FUNC_EXIT;
386
387         return SYNC_AGENT_FSAPI_TRUE;
388 }
389
390 EXPORT_API sync_agent_fsapi_return_e sync_agent_read_file(const char *file_name, char **required_contents, unsigned long required_length, unsigned long *size_return, bool * is_final)
391 {
392         _EXTERN_FUNC_ENTER;
393
394         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
395
396         if (!fs_is_existing(file_name) || fs_is_directory(file_name)) {
397                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
398                 return SYNC_AGENT_FSAPI_FALSE;
399         }
400
401         int ret = 1;
402
403         if ((fd_source_kept == NULL) && !file_read_started) {
404                 fd_source_kept = (FILE *) g_fopen(file_name, "rb");
405                 if (fd_source_kept == NULL) {
406                         _DEBUG_ERROR("[sync_agent_read_file] temp_filename_kept open error.");
407                         ret = 0;
408                         goto return_part;
409                 }
410                 file_read_started = TRUE;
411         } else if ((fd_source_kept != NULL) && file_read_started) {
412         } else {
413                 _DEBUG_ERROR("[%s] internal condition not matching.\n", __func__);
414                 ret = 0;
415                 goto return_part;
416         }
417
418         *required_contents = (char *)calloc(required_length, sizeof(char));
419         if (*required_contents == NULL) {
420                 _DEBUG_ERROR("[sync_agent_read_file] calloc error. [*required_contents]");
421                 ret = 0;
422                 goto return_part;
423         }
424
425         int bytes_read = 0;
426         bytes_read = fread(*required_contents, 1, required_length, fd_source_kept);
427
428         if ((bytes_read > required_length) || ((!feof(fd_source_kept)) && (bytes_read < required_length))) {
429                 _DEBUG_ERROR("[sync_agent_read_file] read error.");
430                 ret = 0;
431                 goto return_part;
432         }
433
434         *size_return = bytes_read;
435
436         if (feof(fd_source_kept)) {
437                 *is_final = TRUE;
438                 goto return_part;
439         }
440
441         _EXTERN_FUNC_EXIT;
442
443         return ret;
444
445  return_part:
446
447         if (fd_source_kept != NULL) {
448                 fclose(fd_source_kept);
449                 fd_source_kept = NULL;
450         }
451         file_read_started = FALSE;
452
453         return ret;
454
455 /*
456         if( !fs_is_existing(file_name) || fs_is_directory(file_name) ) {
457                 fprintf(stderr, "[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
458                 return SYNC_AGENT_FSAPI_FALSE;
459         }
460
461         GError *gerror = NULL;
462
463         if( !g_file_get_contents(file_name, contents, (gsize*)length, &gerror) ) {
464                 fprintf(stderr, "[%s] g_file_get_contents error : %s\n", __func__, gerror->message);
465
466                 g_error_free(gerror);
467                 return SYNC_AGENT_FSAPI_FALSE;
468         }
469
470         return SYNC_AGENT_FSAPI_TRUE;
471 */
472 }
473
474 EXPORT_API sync_agent_fsapi_return_e sync_agent_read_whole_file(const char *file_name, char **required_contents, unsigned long *size_return)
475 {
476         _EXTERN_FUNC_ENTER;
477
478         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
479
480         if (!fs_is_existing(file_name) || fs_is_directory(file_name)) {
481                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a file.\n", __func__, file_name);
482                 return SYNC_AGENT_FSAPI_FALSE;
483         }
484
485         GError *gerror = NULL;
486
487         if (!g_file_get_contents(file_name, required_contents, (gsize *) size_return, &gerror)) {
488                 _DEBUG_ERROR("[%s] g_file_get_contents error : %s\n", __func__, gerror->message);
489
490                 g_error_free(gerror);
491                 return SYNC_AGENT_FSAPI_FALSE;
492         }
493
494         _EXTERN_FUNC_EXIT;
495
496         return SYNC_AGENT_FSAPI_TRUE;
497 }
498
499 EXPORT_API sync_agent_fsapi_return_e sync_agent_free_file(char **requested_contents)
500 {
501         _EXTERN_FUNC_ENTER;
502
503         retvm_if(requested_contents == NULL, 0, "requested_contents paramter is NULL !!!");
504
505         if (*requested_contents != NULL)
506                 free(*requested_contents);
507
508         _EXTERN_FUNC_EXIT;
509
510         return SYNC_AGENT_FSAPI_TRUE;
511 }
512
513 EXPORT_API sync_agent_fsapi_return_e sync_agent_write_file(const char *file_name, const char *contents, unsigned long length, bool is_final, bool overwrite)
514 {
515         _EXTERN_FUNC_ENTER;
516
517         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
518         retvm_if(contents == NULL, 0, "contents is NULL !!");
519
520         if (!overwrite) {
521                 if (fs_is_existing(file_name)) {
522                         _DEBUG_ERROR("[%s] Requested instance '%s' already exist.\n", __func__, file_name);
523                         return SYNC_AGENT_FSAPI_FALSE;
524                 }
525         }
526
527         FILE *fd_temp = NULL;
528         GError *gerror = NULL;
529         int ret = 1;
530         unsigned long temp_size = 0;
531
532         if ((temp_filename_kept == NULL) && !file_append_started) {
533                 if (!g_file_open_tmp(NULL, &temp_filename_kept, &gerror)) {
534                         _DEBUG_ERROR("[%s] g_file_open_tmp error : %s\n", __func__, gerror->message);
535
536                         g_error_free(gerror);
537                         ret = 0;
538                         goto return_part;
539                 }
540                 _DEBUG_INFO("[sync_agent_write_file] Temp file name kept new : %s", temp_filename_kept);
541
542                 file_append_started = TRUE;
543                 requested_filename_kept = g_strdup(file_name);
544
545         } else if ((temp_filename_kept != NULL) && file_append_started) {
546                 if (!fs_is_existing(temp_filename_kept)) {
547                         _DEBUG_ERROR("[%s] Temp file '%s' not existing.\n", __func__, temp_filename_kept);
548                         ret = 0;
549                         goto return_part;
550                 }
551                 _DEBUG_INFO("[sync_agent_write_file] Temp file %s kept previously, existing", temp_filename_kept);
552
553         } else {
554                 _DEBUG_ERROR("[%s] internal condition not matching.\n", __func__);
555                 ret = 0;
556                 goto return_part;
557         }
558
559         if (temp_filename_kept != NULL) {
560                 fd_temp = (FILE *) g_fopen(temp_filename_kept, "ab");
561         } else {
562                 goto return_part;
563         }
564
565         if (fd_temp == NULL) {
566                 _DEBUG_ERROR("[sync_agent_write_file] temp file open error.");
567                 ret = 0;
568                 goto return_part;
569         }
570
571         if (fwrite(contents, 1, length, fd_temp) != length) {
572                 _DEBUG_ERROR("[sync_agent_write_file] fwrite error.");
573                 ret = 0;
574                 goto return_part;
575         }
576
577         if (fd_temp != NULL) {
578                 fclose(fd_temp);
579                 fd_temp = NULL;
580         }
581
582         sync_agent_get_file_size(temp_filename_kept, &temp_size);
583         _DEBUG_INFO("[sync_agent_write_file] temp file size %ld", temp_size);
584
585         if (is_final) {
586                 if (overwrite) {
587                         if (fs_is_existing(file_name)) {
588                                 if (!sync_agent_delete_file(file_name)) {
589                                         _DEBUG_ERROR("[sync_agent_write_file] deleting destination file for overwriting fail.");
590                                         ret = 0;
591                                 } else {
592                                         if (!sync_agent_copy_file(temp_filename_kept, file_name)) {
593                                                 _DEBUG_ERROR("[sync_agent_write_file] copying temp file to destination fail.");
594                                                 ret = 0;
595                                         } else {
596                                                 if (!sync_agent_delete_file(temp_filename_kept)) {
597                                                         _DEBUG_ERROR("[sync_agent_write_file] deleting temp file fail.");
598                                                         ret = 0;
599                                                 }
600                                         }
601                                 }
602                         } else {
603                                 if (!sync_agent_copy_file(temp_filename_kept, file_name)) {
604                                         _DEBUG_ERROR("[sync_agent_write_file] copying temp file to destination fail.");
605                                         ret = 0;
606                                 } else {
607                                         if (!sync_agent_delete_file(temp_filename_kept)) {
608                                                 _DEBUG_ERROR("[sync_agent_write_file] deleting temp file fail.");
609                                                 ret = 0;
610                                         }
611                                 }
612                         }
613                 } else {
614                         if (!sync_agent_copy_file(temp_filename_kept, file_name)) {
615                                 _DEBUG_ERROR("[sync_agent_write_file] copying temp file to destination fail.");
616                                 ret = 0;
617                         } else {
618                                 if (!sync_agent_delete_file(temp_filename_kept)) {
619                                         _DEBUG_ERROR("[sync_agent_write_file] deleting temp file fail.");
620                                         ret = 0;
621                                 }
622                         }
623                 }
624                 goto return_part;
625         }
626
627         _EXTERN_FUNC_EXIT;
628
629         return ret;
630
631  return_part:
632
633         if (fd_temp != NULL)
634                 fclose(fd_temp);
635         g_free(temp_filename_kept);
636         g_free(requested_filename_kept);
637         temp_filename_kept = NULL;
638         requested_filename_kept = NULL;
639         file_append_started = FALSE;
640
641         return ret;
642
643 /*
644         if( fs_is_existing(file_name) ) {
645                 fprintf(stderr, "[%s] Requested instance '%s' already exist.", __func__, file_name);
646                 return SYNC_AGENT_FSAPI_FALSE;
647         }
648
649         GError *gerror = NULL;
650
651         if( !g_file_set_contents(file_name, contents, length, &gerror) ) {
652                 fprintf(stderr, "[%s] g_file_set_contents error : %s\n", __func__, gerror->message);
653
654                 g_error_free(gerror);
655                 return SYNC_AGENT_FSAPI_FALSE;
656         }
657
658         return SYNC_AGENT_FSAPI_TRUE;
659 */
660 }
661
662 EXPORT_API sync_agent_fsapi_return_e sync_agent_write_whole_file(const char *file_name, const char *contents, unsigned long length, bool overwrite)
663 {
664         _EXTERN_FUNC_ENTER;
665
666         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
667         retvm_if(contents == NULL, 0, "contents is NULL !!");
668
669         if (fs_is_existing(file_name)) {
670                 if (overwrite && !fs_is_directory(file_name)) {
671                         int result = sync_agent_delete_file(file_name);
672                         if (result == 0) {
673                                 _DEBUG_ERROR("[%s] sync_agent_delete_file() FAIL !!!.", __func__, file_name);
674                                 return SYNC_AGENT_FSAPI_FALSE;
675                         }
676                 } else {
677                         _DEBUG_ERROR("[%s] Requested instance '%s' already exist.", __func__, file_name);
678                         return SYNC_AGENT_FSAPI_FALSE;
679                 }
680         }
681
682         GError *gerror = NULL;
683
684         if (!g_file_set_contents(file_name, contents, length, &gerror)) {
685                 _DEBUG_ERROR("[%s] g_file_set_contents error : %s\n", __func__, gerror->message);
686
687                 g_error_free(gerror);
688                 return SYNC_AGENT_FSAPI_FALSE;
689         }
690
691         _EXTERN_FUNC_EXIT;
692
693         return SYNC_AGENT_FSAPI_TRUE;
694 }
695
696 EXPORT_API sync_agent_fsapi_return_e sync_agent_append_file(const char *file_name, const char *contents, unsigned long length, bool overwrite)
697 {
698         _EXTERN_FUNC_ENTER;
699
700         retvm_if(file_name == NULL, 0, "file_name paramter is NULL !!!");
701         retvm_if(contents == NULL, 0, "contents is NULL !!");
702
703         if (overwrite) {
704                 if (!sync_agent_delete_file(file_name)) {
705                         if (!fs_is_existing(file_name)) {
706                                 _DEBUG_ERROR("[%s] The file %s requested to delete for overwriting is not existing, so just continue.", __func__, file_name);
707                         } else {
708                                 if (fs_is_directory(file_name)) {
709                                         _DEBUG_ERROR("[%s] Can't overwrite because requested instance '%s' not a file.", __func__, file_name);
710                                         return SYNC_AGENT_FSAPI_FALSE;
711                                 } else {
712                                         _DEBUG_ERROR("[%s] FAILED to delete requested file '%s'.", __func__, file_name);
713                                         return SYNC_AGENT_FSAPI_FALSE;
714                                 }
715                         }
716                 }
717         }
718
719         FILE *fd = NULL;
720         int ret = 1;
721
722         fd = (FILE *) g_fopen(file_name, "ab");
723         if (fd == NULL) {
724                 _DEBUG_ERROR("[sync_agent_append_file] file open error.");
725                 ret = 0;
726                 goto return_part;
727         }
728
729         if (fwrite(contents, 1, length, fd) != length) {
730                 _DEBUG_ERROR("[%s] fwrite error '%s'.", __func__, file_name);
731                 ret = 0;
732                 goto return_part;
733         }
734
735         if (fsync(fileno(fd)) != 0)
736                 ret = 0;
737
738         _EXTERN_FUNC_EXIT;
739
740  return_part:
741
742         if (fd != NULL)
743                 fclose(fd);
744
745         _DEBUG_INFO("[%s] Returning..", __func__);
746         return ret;
747 }
748
749 /*
750  * Folder operation
751  */
752
753 EXPORT_API sync_agent_fsapi_return_e sync_agent_create_directory(const char *folder_name)
754 {
755         _EXTERN_FUNC_ENTER;
756
757         retvm_if(folder_name == NULL, 0, "folder_name paramter is NULL !!!");
758
759         if (fs_is_existing(folder_name)) {
760                 _DEBUG_ERROR("[%s] Requested instance '%s' already exist.\n", __func__, folder_name);
761                 return SYNC_AGENT_FSAPI_FALSE;
762         }
763
764         int ret = g_mkdir_with_parents(folder_name, 0755);
765         if (ret == -1) {
766                 _DEBUG_ERROR("[%s] g_mkdir error : %s\n", __func__, strerror(errno));
767                 return SYNC_AGENT_FSAPI_FALSE;
768         }
769
770         _EXTERN_FUNC_EXIT;
771
772         return SYNC_AGENT_FSAPI_TRUE;
773 }
774
775 EXPORT_API sync_agent_fsapi_return_e sync_agent_delete_directory(const char *folder_name, bool recursive)
776 {
777         _EXTERN_FUNC_ENTER;
778
779         retvm_if(folder_name == NULL, 0, "folder_name paramter is NULL !!!");
780
781         if (!fs_is_existing(folder_name) || !fs_is_directory(folder_name)) {
782                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a directory.\n", __func__, folder_name);
783                 return SYNC_AGENT_FSAPI_FALSE;
784         }
785
786         GError *gerror = NULL;
787         GDir *dir = NULL;
788         int ret = 0;
789         char *path = NULL;
790         char *name = NULL;
791
792         if (recursive) {
793                 dir = g_dir_open(folder_name, 0, &gerror);
794                 if (dir == NULL) {
795                         _DEBUG_ERROR("[%s] g_dir_open error : %s\n", __func__, gerror->message);
796                         g_error_free(gerror);
797                         return SYNC_AGENT_FSAPI_FALSE;
798                 }
799
800                 name = (char *)g_dir_read_name(dir);
801
802                 for (; name; name = (char *)g_dir_read_name(dir)) {
803
804                         path = g_strdup_printf("%s/%s", folder_name, name);
805
806                         if (fs_is_directory(path)) {
807                                 if (!sync_agent_delete_directory(path, true))
808                                         return SYNC_AGENT_FSAPI_FALSE;
809                         } else {
810                                 if (!sync_agent_delete_file(path))
811                                         return SYNC_AGENT_FSAPI_FALSE;
812                         }
813                 }
814
815                 if (path != NULL)
816                         free(path);
817                 g_dir_close(dir);
818                 dir = NULL;
819         }
820
821         ret = g_rmdir(folder_name);
822         if (ret == -1) {
823                 _DEBUG_ERROR("[%s] g_rmdir error : %s\n", __func__, strerror(errno));
824                 return SYNC_AGENT_FSAPI_FALSE;
825         }
826
827         _EXTERN_FUNC_EXIT;
828
829         return SYNC_AGENT_FSAPI_TRUE;
830 }
831
832 EXPORT_API sync_agent_fsapi_return_e sync_agent_empty_directory_contents(const char *folder_name)
833 {
834         _EXTERN_FUNC_ENTER;
835
836         retvm_if(folder_name == NULL, 0, "folder_name paramter is NULL !!!");
837
838         if (!fs_is_existing(folder_name) || !fs_is_directory(folder_name)) {
839                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a directory.\n", __func__, folder_name);
840                 return SYNC_AGENT_FSAPI_FALSE;
841         }
842
843         GError *gerror = NULL;
844         GDir *dir = NULL;
845         char *path = NULL;
846         char *name = NULL;
847
848         dir = g_dir_open(folder_name, 0, &gerror);
849         if (dir == NULL) {
850                 _DEBUG_ERROR("[%s] g_dir_open error : %s\n", __func__, gerror->message);
851                 g_error_free(gerror);
852                 return SYNC_AGENT_FSAPI_FALSE;
853         }
854
855         name = (char *)g_dir_read_name(dir);
856
857         for (; name; name = (char *)g_dir_read_name(dir)) {
858
859                 path = g_strdup_printf("%s/%s", folder_name, name);
860
861                 if (fs_is_directory(path)) {
862                         if (!sync_agent_delete_directory(path, true)) {
863                                 _DEBUG_ERROR("[%s] sync_agent_delete_directory error : %s\n", __func__, strerror(errno));
864                                 return SYNC_AGENT_FSAPI_FALSE;
865                         }
866                 } else {
867                         if (!sync_agent_delete_file(path)) {
868                                 _DEBUG_ERROR("[%s] sync_agent_delete_file error : %s\n", __func__, strerror(errno));
869                                 return SYNC_AGENT_FSAPI_FALSE;
870                         }
871                 }
872         }
873
874         if (path != NULL)
875                 free(path);
876         g_dir_close(dir);
877         dir = NULL;
878
879         _EXTERN_FUNC_EXIT;
880
881         return SYNC_AGENT_FSAPI_TRUE;
882 }
883
884 EXPORT_API sync_agent_fsapi_return_e sync_agent_rename_directory(const char *source, const char *dest)
885 {
886         _EXTERN_FUNC_ENTER;
887
888         retvm_if(source == NULL, 0, "source paramter is NULL !!!");
889         retvm_if(dest == NULL, 0, "dest paramter is NULL !!!");
890
891         if (!fs_is_existing(source) || !fs_is_directory(source) || fs_is_existing(dest)) {
892                 _DEBUG_ERROR("[%s] Requested source instance '%s' not exist or not a directory, or\n", __func__, source);
893                 _DEBUG_ERROR("[%s] requested dest instance '%s' already exist.\n", __func__, dest);
894                 return SYNC_AGENT_FSAPI_FALSE;
895         }
896
897         int ret = g_rename(source, dest);
898         if (ret == -1) {
899                 _DEBUG_ERROR("[%s] g_rename error : %s\n", __func__, strerror(errno));
900                 return SYNC_AGENT_FSAPI_FALSE;
901         }
902
903         _EXTERN_FUNC_EXIT;
904
905         return SYNC_AGENT_FSAPI_TRUE;
906 }
907
908 EXPORT_API sync_agent_fsapi_return_e sync_agent_get_directory_list(const char *folder_name, GSList ** list)
909 {
910         _EXTERN_FUNC_ENTER;
911
912         retvm_if(folder_name == NULL, 0, "folder_name paramter is NULL !!!");
913
914         if (!fs_is_existing(folder_name) || !fs_is_directory(folder_name)) {
915                 _DEBUG_ERROR("[%s] Requested instance '%s' not exist, or not a directory.\n", __func__, folder_name);
916                 return SYNC_AGENT_FSAPI_FALSE;
917         }
918
919         struct stat buf;
920         char *path = NULL;
921         char time[FS_MAX_TIME_STRING_BUF] = { 0 };
922         char *list_item = NULL;
923
924         GError *gerror = NULL;
925         GDir *dir = g_dir_open(folder_name, 0, &gerror);
926         if (dir == NULL) {
927                 _DEBUG_ERROR("[%s] g_dir_open error : %s\n", __func__, gerror->message);
928                 g_error_free(gerror);
929                 return SYNC_AGENT_FSAPI_FALSE;
930         }
931
932         const char *file_name = g_dir_read_name(dir);
933
934         for (; file_name; file_name = g_dir_read_name(dir)) {
935
936                 path = g_strdup_printf("%s/%s", folder_name, file_name);
937
938                 if (fs_is_directory(path)) {
939                         int ret = stat(path, &buf);
940                         if (ret == -1) {
941                                 _DEBUG_ERROR("[%s] g_stat error : %s\n", __func__, strerror(errno));
942                                 return SYNC_AGENT_FSAPI_FALSE;
943                         }
944
945                         fs_get_time_string(&buf.st_mtime, time);
946                         list_item = g_strdup_printf("%s,%ld,%s", file_name, (long)buf.st_nlink - 2, time);
947
948                         *list = g_slist_append(*list, list_item);
949                 }
950         }
951
952         free(path);
953         g_dir_close(dir);
954         dir = NULL;
955
956         _EXTERN_FUNC_EXIT;
957
958         return SYNC_AGENT_FSAPI_TRUE;
959
960 }
961
962 EXPORT_API void sync_agent_free_fs_list(GSList * list)
963 {
964         _EXTERN_FUNC_ENTER;
965
966         retm_if(list == NULL, "folder_name paramter is NULL !!!");
967
968         GSList *iter = NULL;
969
970         for (iter = list; iter != NULL; iter = g_slist_next(iter)) {
971                 g_free(iter->data);
972         }
973
974         g_slist_free(list);
975
976         _EXTERN_FUNC_EXIT;
977 }
978
979 EXPORT_API sync_agent_fsapi_return_e sync_agent_file_md5_validation(const char *file_path, const char *find_md5_word, bool * is_same)
980 {
981         _EXTERN_FUNC_ENTER;
982
983         retvm_if(file_path == NULL, 0, "file_path paramter is NULL !!!");
984         retvm_if(find_md5_word == NULL, 0, "find_md5_word paramter is NULL !!!");
985
986         int ret = 1;
987         unsigned char *real_md5_word = NULL;
988
989         _DEBUG_INFO("File_Path = %s\n", file_path);
990
991         /* get file hash key */
992         ret = fs_file_md5_hashkey(file_path, &real_md5_word);
993         if (ret != 1) {
994                 _DEBUG_ERROR("fs_file_md5_hashkey() Fail!!\n");
995                 goto return_part;
996         }
997
998         /* convert hex char to string (=> hash key) */
999         char szTmp_digest[256] = { 0, };
1000         int k;
1001         for (k = 0; k < 16; k++) {
1002                 szTmp_digest[k * 2] = _sync_str_to_hex_char((unsigned char)((real_md5_word[k] >> 4) & 0x0f));
1003                 szTmp_digest[k * 2 + 1] = _sync_str_to_hex_char((unsigned char)(real_md5_word[k] & 0x0f));
1004         }
1005
1006         _DEBUG_INFO("find_md5_word = %s\n", find_md5_word);
1007         _DEBUG_INFO("real_md5_word = %s\n", szTmp_digest);
1008
1009         /* compare read md5 checksum to file_md5_checksum */
1010         if (memcmp(find_md5_word, szTmp_digest, strlen(szTmp_digest))) {
1011                 _DEBUG_ERROR("MD5 Hash Keys are not equal.\n");
1012                 *is_same = false;
1013                 ret = 0;
1014                 goto return_part;
1015         }
1016
1017         _DEBUG_INFO("MD5 Hash Keys are equal.\n");
1018         *is_same = true;
1019
1020         _EXTERN_FUNC_EXIT;
1021
1022  return_part:
1023
1024         if (real_md5_word != NULL)
1025                 free(real_md5_word);
1026
1027         return ret;
1028 }
1029
1030 int fs_file_md5_hashkey(const char *file_path, unsigned char **hash_key)
1031 {
1032         _EXTERN_FUNC_ENTER;
1033
1034         retvm_if(file_path == NULL, 0, "file_path paramter is NULL !!!");
1035
1036         int ret = 1;
1037         *hash_key = NULL;
1038
1039         unsigned long full_file_size = 0;
1040         ret = sync_agent_get_file_size(file_path, &full_file_size);
1041         _DEBUG_INFO("full_file_size = %d\n", full_file_size);
1042
1043         /* get MD5 encryption Hash Key */
1044         char *required_contents = NULL;
1045         unsigned char *real_md5_word = (unsigned char *)calloc(16, sizeof(char));
1046         if (real_md5_word == NULL) {
1047                 _DEBUG_ERROR("CALLOC failed !!!");
1048                 ret = 0;
1049                 goto return_part;
1050         }
1051         bool isFinal = false;
1052         unsigned long read_file_size = 0;
1053
1054         sa_md5_context_s context;
1055
1056         sa_md5_init(&context);
1057
1058         while (isFinal == false) {
1059
1060                 ret = sync_agent_read_file(file_path, &required_contents, FS_BUFFER_SIZE, &read_file_size, &isFinal);
1061                 if (ret != 1) {
1062                         _DEBUG_ERROR("sync_agent_read_file() Fail\n");
1063                         ret = 0;
1064                         goto return_part;
1065                 }
1066
1067                 _DEBUG_INFO("read_file_size = %d\n", read_file_size);
1068                 _DEBUG_INFO("isFinal = %d\n", isFinal);
1069                 sa_md5_update(&context, required_contents, read_file_size);
1070         }
1071         sa_md5_final(&context, real_md5_word);
1072
1073         /* print Hex char MD5 */
1074         int real_md5_length = strlen((const char *)real_md5_word);
1075         _DEBUG_INFO("real_md5_length = %d\n", real_md5_length);
1076         _DEBUG_INFO(" real md5 : ");
1077         int i = 0;
1078         for (; i < real_md5_length; ++i) {
1079                 _DEBUG_INFO("%02x", real_md5_word[i]);
1080         }
1081         _DEBUG_INFO("\n");
1082
1083         *hash_key = real_md5_word;
1084
1085         _DEBUG_INFO("Free Part");
1086         sync_agent_free_file(&required_contents);
1087
1088         _EXTERN_FUNC_EXIT;
1089         return ret;
1090
1091  return_part:
1092         if (real_md5_word != NULL) {
1093                 free(real_md5_word);
1094                 real_md5_word = NULL;
1095         }
1096         _DEBUG_INFO("Free Part");
1097         sync_agent_free_file(&required_contents);
1098
1099         _EXTERN_FUNC_EXIT;
1100         return ret;
1101 }
1102
1103 static unsigned char _sync_str_to_hex_char(unsigned char hex)
1104 {
1105         _INNER_FUNC_ENTER;
1106
1107         if (0 <= (char)hex && (char)hex <= 9) {
1108                 _EXTERN_FUNC_EXIT;
1109                 return '0' + hex;
1110         } else {
1111                 if (10 <= (char)hex && (char)hex <= 15) {
1112                         _INNER_FUNC_EXIT;
1113                         return 'A' + hex - 10;
1114                 }
1115         }
1116
1117         _INNER_FUNC_EXIT;
1118
1119         return '?';
1120 }