Merge "change uid/gid" into tizen
[platform/core/messaging/msg-service.git] / utils / MsgUtilFile.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15 */
16
17 #include <stdio.h>
18 #include <stddef.h>
19 #include <time.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <sys/stat.h>
23 #include <sys/smack.h>
24 #include <string.h>
25 #include <dirent.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <libgen.h>
29
30 #include <thumbnail_util.h>
31 #include <image_util.h>
32 #include <TCSImpl.h>
33 #include <TCSErrorCodes.h>
34
35 #include "MsgStorageTypes.h"
36 #include "MsgDebug.h"
37 #include "MsgException.h"
38 #include "MsgUtilFile.h"
39 #include "MsgMmsTypes.h"
40 #include "MsgInternalTypes.h"
41 #include "MsgDrmWrapper.h"
42 #include "MsgMutex.h"
43
44 extern "C" {
45         #include <aul.h>
46 }
47
48 MsgMutex g_mx;
49 MsgCndVar g_cv;
50
51 void thumbnail_completed_cb(thumbnail_util_error_e error, const char *request_id,
52                                                                         int thumb_width, int thumb_height,
53                                                                         unsigned char *thumb_data, int thumb_size, void *user_data)
54 {
55         MSG_BEGIN();
56
57         g_mx.lock();
58
59         if (!user_data) {
60                 MSG_WARN("dstPath is NULL");
61                 g_cv.signal();
62                 g_mx.unlock();
63                 return;
64         }
65
66         MSG_DEBUG("=================[RESULT]");
67         MSG_DEBUG("error_code [%d]", error);
68         MSG_DEBUG("request id [%s]", request_id);
69         MSG_DEBUG("width [%d], height [%d]", thumb_width, thumb_height);
70         MSG_DEBUG("raw_data [0x%x], size [%d]", *thumb_data, thumb_size);
71
72         int ret = 0;
73         ret = image_util_encode_jpeg(thumb_data, thumb_width, thumb_height, IMAGE_UTIL_COLORSPACE_BGRA8888, 100, (char *)user_data);
74         if (ret != IMAGE_UTIL_ERROR_NONE)
75                 MSG_WARN("image_util_encode_jpeg() is failed");
76
77         g_cv.signal();
78         g_mx.unlock();
79
80         MSG_END();
81 }
82
83 /*==================================================================================================
84                                      FUNCTION IMPLEMENTATION
85 ==================================================================================================*/
86 bool MakeThumbnail(char *srcPath, char *dstPath)
87 {
88         if (srcPath == NULL || dstPath == NULL) {
89                 MSG_SEC_DEBUG("Invalid Param src = %p, dst = %p", srcPath, dstPath);
90                 return false;
91         }
92
93         if (MsgAccessFile(srcPath, R_OK) == false) {
94                 MSG_SEC_DEBUG("not exist source file [%s]", srcPath);
95                 return false;
96         }
97
98         g_mx.lock();
99
100         int time_ret = 0;
101
102         int ret = THUMBNAIL_UTIL_ERROR_NONE;
103         char *req_id = NULL;
104         thumbnail_h thumb_h;
105         thumbnail_util_create(&thumb_h);
106         thumbnail_util_set_path(thumb_h, srcPath);
107
108         ret = thumbnail_util_extract(thumb_h, thumbnail_completed_cb, dstPath, &req_id);
109         thumbnail_util_destroy(thumb_h);
110         if (req_id) {
111                 g_free(req_id);
112                 req_id = NULL;
113         }
114
115         if (ret != THUMBNAIL_UTIL_ERROR_NONE) {
116                 MSG_ERR("thumbnail_util_extract is failed");
117                 g_mx.unlock();
118                 return false;
119         }
120
121         time_ret = g_cv.timedwait(g_mx.pMsgMutex(), 5);
122
123         g_mx.unlock();
124
125         if (time_ret == ETIMEDOUT) {
126                 MSG_ERR("@@ WAKE by timeout@@");
127                 return false;
128         }
129
130         if (MsgAccessFile(dstPath, F_OK) == false) {
131                 MSG_SEC_DEBUG("not exist result file [%s]", dstPath);
132                 return false;
133         }
134
135         MSG_SEC_DEBUG("Make thumbnail: success [%s]", dstPath);
136         return true;
137 }
138
139 /* File operation wrappers */
140 FILE *MsgOpenFile(const char *filepath, const char *opt)
141 {
142         if (!filepath || !opt) {
143                 MSG_FATAL("Null parameter");
144                 return NULL;
145         }
146
147         MSG_SEC_DEBUG("[FILE] filepath : [%s], opt [%s]", filepath, opt);
148
149         FILE *pFile = NULL;
150
151         try {
152                 pFile = fopen(filepath, opt);
153                 MSG_DEBUG("[FILE] pFile [%p]", pFile);
154         } catch (exception &e) {
155                 MSG_FATAL("%s", e.what());
156                 return NULL;
157         }
158
159         return pFile;
160 }
161
162 void MsgCloseFile(FILE *pFile)
163 {
164         if (!pFile) {
165                 MSG_FATAL("NULL parameter");
166                 return;
167         }
168
169         MSG_DEBUG("[FILE] pFile [%p]", pFile);
170
171         try {
172                 fclose(pFile);
173         } catch (exception &e) {
174                 MSG_FATAL("%s", e.what());
175         }
176 }
177
178 int MsgFseek(FILE *pFile, long int offset, int origin)
179 {
180         if (!pFile) {
181                 MSG_FATAL("pFile NULL");
182                 return -1;
183         }
184
185         int ret = -1;
186
187         MSG_DEBUG("[FILE] pFile [%p], offset [%d], origin [%d]", pFile, offset, origin);
188
189         try {
190                 ret = fseek(pFile, offset, origin); /* return 0, if success. */
191         } catch (exception &e) {
192                 MSG_FATAL("%s", e.what());
193                 return -1;
194         }
195
196         return ret;
197 }
198
199 size_t MsgWriteFile(const char *pData, size_t size, size_t count, FILE *pFile)
200 {
201         if (!pData || !pFile) {
202                 MSG_FATAL("pData or pFile NULL");
203                 return 0;
204         }
205
206         size_t nWrite = 0;
207
208         MSG_DEBUG("[FILE] pData [%p], size [%d], count [%d], pFile [%p]", pData, size, count, pFile);
209
210         try {
211                 nWrite = fwrite(pData, size, count, pFile);
212         } catch (exception &e) {
213                 MSG_FATAL("%s", e.what());
214         }
215
216         return nWrite;
217 }
218
219 size_t MsgReadFile(void *pData, size_t size, size_t count, FILE *pFile)
220 {
221         if (!pData || !pFile) {
222                 MSG_FATAL("pData or pFile NULL");
223                 return 0;
224         }
225
226         size_t nRead = 0;
227
228         try {
229                 nRead = fread(pData, size, count, pFile);
230         } catch (exception &e) {
231                 MSG_FATAL("%s", e.what());
232         }
233
234         return nRead;
235 }
236
237 long int MsgFtell(FILE *pFile)
238 {
239         if (!pFile) {
240                 MSG_FATAL("pFile NULL");
241                 return -1L;
242         }
243
244         long int ret = -1L; /* -1L return if error occured. */
245
246         try {
247                 ret = ftell(pFile);
248         } catch (exception &e) {
249                 MSG_FATAL("%s", e.what());
250         }
251
252         return ret;
253 }
254
255 int MsgFflush(FILE *pFile)
256 {
257         if(!pFile) {
258                 MSG_FATAL("pFile NULL");
259                 return -1;
260         }
261
262         int ret = -1;
263
264         try {
265                 ret = fflush(pFile); /* return 0 if success */
266         } catch (exception &e) {
267                 MSG_FATAL("%s", e.what());
268         }
269
270         return ret;
271 }
272
273 int MsgFsync(FILE *pFile)
274 {
275         if(!pFile) {
276                 MSG_FATAL("pFile NULL");
277                 return -1;
278         }
279
280         int ret = -1;
281
282         try {
283                 ret = fdatasync(pFile->_fileno); /* return 0 if success */
284         } catch (exception &e) {
285                 MSG_FATAL("%s", e.what());
286         }
287
288         return ret;
289 }
290
291 bool MsgCreateFileName(char *pFileName)
292 {
293         if (pFileName == NULL) {
294                 MSG_DEBUG("[ERROR] pFileName is NULL");
295                 return false;
296         }
297
298         struct timespec ts;
299
300         try {
301                 if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
302                         MSG_DEBUG("clock_gettime() error: %s", g_strerror(errno));
303                         return false;
304                 }
305
306                 /* Create Random Number */
307                 srandom((unsigned int)ts.tv_nsec);
308
309                 MSG_DEBUG("ts.tv_nsec : %d", ts.tv_nsec);
310
311                 /* between 1 - 1000000000 */
312                 snprintf(pFileName, MSG_FILENAME_LEN_MAX, "MSG_%lu.DATA", random()%1000000000+1);
313         } catch (exception& e) {
314                 MSG_FATAL("%s", e.what());
315                 return false;
316         }
317
318         return true;
319 }
320
321
322 bool MsgOpenAndReadFile(const char *pFileName, char **ppData, int *pDataSize)
323 {
324         if (!pFileName || !ppData || !pDataSize) {
325                 MSG_ERR("Invalid params!! pFileName=%x, ppData=%x, pDataSize=%x", pFileName, ppData, pDataSize);
326                 return false;
327         }
328
329         MSG_DEBUG("MsgOpenAndReadFile");
330
331         FILE *pFile = NULL;
332
333         char fullPath[MAX_FULL_PATH_SIZE] = {0};
334
335         snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s%s", MSG_IPC_DATA_PATH, pFileName);
336         MSG_SEC_DEBUG("open file name: %s", fullPath);
337
338         pFile = MsgOpenFile(fullPath, "rb");
339
340         if (pFile == NULL) {
341                 MSG_DEBUG("File Open Error: %s", g_strerror(errno));
342                 return false;
343         }
344
345         if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
346                 MsgCloseFile(pFile);
347                 MSG_DEBUG("File Read Error: %s", g_strerror(errno));
348                 return false;
349         }
350
351         int FileSize = MsgFtell(pFile);
352
353         if (FileSize <= 0) {
354                 MSG_DEBUG("Filesize is error : %d", FileSize);
355                 *pDataSize = 0;
356                 MsgCloseFile(pFile);
357                 return false;
358         }
359
360         *ppData = new char[FileSize+1];
361         memset(*ppData, 0x00, (FileSize+1));
362
363         if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
364                 MsgCloseFile(pFile);
365                 MSG_DEBUG("File seek Error: %s", g_strerror(errno));
366                 return false;
367         }
368
369         if (MsgReadFile(*ppData, sizeof(char), FileSize, pFile) != (size_t)FileSize) {
370                 MsgCloseFile(pFile);
371                 MSG_DEBUG("File Read Error: %s", g_strerror(errno));
372                 return false;
373         }
374
375         *pDataSize = FileSize;
376
377         MsgCloseFile(pFile);
378
379         return true;
380 }
381
382
383 bool MsgReadFileForDecode(FILE *pFile, char *pBuf, int length, int *nSize)
384 {
385         MSG_BEGIN();
386
387         if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
388                 MSG_DEBUG("File Seek Error: %s", g_strerror(errno));
389                 MsgCloseFile(pFile);
390                 return false;
391         }
392
393         *nSize = MsgReadFile(pBuf, sizeof(char), length, pFile);
394
395         MSG_END();
396         return true;
397 }
398
399
400 bool MsgWriteIpcFile(const char *pFileName, const char *pData, int DataSize)
401 {
402         if (!pFileName) {
403                 MSG_DEBUG("NULL parameter, pFileName [%p], pData [%p]", pFileName, pData);
404                 return false;
405         }
406
407         char fullPath[MAX_FULL_PATH_SIZE] = {0};
408
409         snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s%s", MSG_IPC_DATA_PATH, pFileName);
410
411         FILE *pFile = MsgOpenFile(fullPath, "wb+");
412
413         if (pFile == NULL) {
414                 MSG_DEBUG("File Open Error: %s", g_strerror(errno));
415                 return false;
416         }
417
418         if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
419                 MsgCloseFile(pFile);
420                 MSG_DEBUG("File Seek Error: %s", g_strerror(errno));
421                 return false;
422         }
423
424         if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
425                 MsgCloseFile(pFile);
426                 MSG_DEBUG("File Write Error: %s", g_strerror(errno));
427                 return false;
428         }
429
430         MsgFflush(pFile);
431         MsgCloseFile(pFile);
432
433         return true;
434 }
435
436 int MsgReadSmilFile(const char *pFileName, char **ppData)
437 {
438         if (!pFileName) {
439                 MSG_DEBUG("pFileName is NULL");
440                 return -1;
441         }
442
443         int     nSize = 0;
444         char fullPath[MAX_FULL_PATH_SIZE] = {0};
445
446         snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s%s", MSG_SMIL_FILE_PATH, pFileName);
447
448         MSG_SEC_DEBUG("open file name: %s", fullPath);
449
450         FILE *pFile = MsgOpenFile(fullPath, "rb");
451
452         if (pFile == NULL) {
453                 MSG_DEBUG("File Open Error: %s", g_strerror(errno));
454                 return -1;
455         }
456
457         if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
458                 MsgCloseFile(pFile);
459                 MSG_DEBUG("File Seek Error: %s", g_strerror(errno));
460                 return -1;
461         }
462
463         int FileSize = MsgFtell(pFile);
464
465         if (FileSize <= 0) {
466                 MSG_DEBUG("Filesize is error : %d", FileSize);
467                 MsgCloseFile(pFile);
468                 return FileSize;
469         }
470
471         *ppData = new char[FileSize + 1];
472         memset(*ppData, 0x00, (FileSize+1));
473
474         if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
475                 MsgCloseFile(pFile);
476                 MSG_DEBUG("File Sead Error: %s", g_strerror(errno));
477                 return -1;
478         }
479
480         if (MsgReadFile(*ppData, sizeof(char), FileSize, pFile) != (size_t)FileSize) {
481                 MsgCloseFile(pFile);
482                 MSG_DEBUG("File Read Error: %s", g_strerror(errno));
483                 return -1;
484         }
485
486         /* ppData[FileSize] = '\0'; */
487
488         nSize = FileSize;
489         MsgCloseFile(pFile);
490
491         return nSize;
492 }
493
494
495 bool MsgWriteSmilFile(const char *pFilePath, char *pData, int DataSize)
496 {
497         if(!pFilePath) {
498                 MSG_DEBUG("pFilePath is NULL");
499                 return false;
500         }
501
502 #if 0
503         if (mkdir(MSG_SMIL_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
504                 if (errno == EEXIST) {
505                         MSG_SEC_DEBUG("The %s already exists", MSG_SMIL_FILE_PATH);
506                 } else {
507                         MSG_SEC_DEBUG("Error while mkdir %s", MSG_SMIL_FILE_PATH);
508                 }
509         }
510 #endif
511
512         FILE *pFile = MsgOpenFile(pFilePath, "wb+");
513
514         if (pFile == NULL) {
515                 MSG_DEBUG("File Open Error: %s", g_strerror(errno));
516                 return false;
517         }
518
519         if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
520                 MsgCloseFile(pFile);
521                 MSG_DEBUG("File Seek Error: %s", g_strerror(errno));
522                 return false;
523         }
524
525         if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
526                 MsgCloseFile(pFile);
527                 MSG_DEBUG("File Write Error: %s", g_strerror(errno));
528                 return false;
529         }
530
531         MsgFflush(pFile);
532         MsgCloseFile(pFile);
533
534         return true;
535 }
536
537
538 void MsgDeleteFile(const char *pFileName)
539 {
540         if (!pFileName) {
541                 MSG_FATAL("pFileName is NULL");
542                 return;
543         }
544
545         if (strlen(pFileName) == 0) {
546                 MSG_FATAL("pFileName has zero length");
547                 return;
548         }
549
550         char fullPath[MAX_FULL_PATH_SIZE] = {0};
551
552         try {
553                 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s%s", MSG_IPC_DATA_PATH, pFileName);
554
555                 MSG_SEC_DEBUG("%s", fullPath);
556
557                 if (remove(fullPath) != 0)
558                         MSG_SEC_ERR("File Delete Error [%s]: %s", fullPath, g_strerror(errno));
559         } catch (exception &e) {
560                 MSG_FATAL("%s", e.what());
561         }
562 }
563
564
565 void MsgDeleteSmilFile(const char *pFileName)
566 {
567         if (!pFileName) {
568                 MSG_FATAL("pFileName NULL");
569                 return;
570         }
571
572         try {
573                 char fullPath[MAX_FULL_PATH_SIZE] = {0};
574
575                 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s%s", MSG_SMIL_FILE_PATH, pFileName);
576
577                 if (remove(fullPath) != 0)
578                         MSG_SEC_ERR("File Delete Error [%s]: %s", fullPath, g_strerror(errno));
579         } catch (exception &e) {
580                 MSG_FATAL("%s", e.what());
581         }
582 }
583
584
585 bool MsgGetFileSize(const char *pFilePath, int *nSize)
586 {
587         if (!pFilePath) {
588                 MSG_FATAL("pFileName NULL");
589                 return false;
590         }
591
592         FILE *pFile = NULL;
593
594         pFile = MsgOpenFile(pFilePath, "rb");
595
596         if (!pFile) {
597                 MSG_DEBUG("File Open error: %s", g_strerror(errno));
598                 return false;
599         }
600
601         if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
602                 MsgCloseFile(pFile);
603                 MSG_FATAL("File Read Error: %s", g_strerror(errno));
604                 return false;
605         }
606
607         *nSize = MsgFtell(pFile);
608
609         MsgCloseFile(pFile);
610
611         return true;
612 }
613
614
615 FILE *MsgOpenMMSFile(char *pFileName)
616 {
617         int len;
618
619         if (!pFileName) {
620                 MSG_DEBUG("pFileName NULL: %s", g_strerror(errno));
621                 return NULL;
622         }
623
624         len = strlen(pFileName);
625
626         for (int i = 0; i < len; i++) {
627                 switch (pFileName[i]) {
628                 case '*':
629                         pFileName[i] = '-';
630                         break;
631                 }
632         }
633
634         MSG_SEC_DEBUG("pFileName = %s", pFileName);
635
636         char fullPath[MAX_FULL_PATH_SIZE+1] = {0};
637
638         snprintf(fullPath, MAX_FULL_PATH_SIZE+1, "%s.mms", pFileName);
639
640         FILE *pFile = MsgOpenFile(fullPath, "wb+");
641
642         if (pFile == NULL) {
643                 MSG_ERR("File Open Error: %s", g_strerror(errno));
644                 return NULL;
645         }
646
647         if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
648                 MsgCloseFile(pFile);
649                 MSG_ERR("File Read Error: %s", g_strerror(errno));
650                 return NULL;
651         }
652
653         return pFile;
654 }
655
656
657 bool MsgWriteDataFromEncodeBuffer(FILE *pFile, char *pInBuffer, int *pPtr, int maxLen, int *pOffset )
658 {
659         if (!pFile || !pPtr || !pInBuffer || !pOffset) {
660                 MSG_FATAL(" NULL parameter passed");
661                 return false;
662         }
663
664         MSG_DEBUG("MsgWriteDataFromEncodeBuffer:");
665         MSG_DEBUG("pInBuffer %x", pInBuffer);
666         MSG_DEBUG("pPtr %d",  (*pPtr));
667         MSG_DEBUG("before to fwite %x", pFile);
668
669         if (MsgWriteFile(pInBuffer, sizeof(char), (*pPtr), pFile) != (size_t)(*pPtr)) {
670                 MSG_FATAL("MsgWriteFile failed");
671                 return false;
672         }
673
674         MSG_DEBUG("after to fwite \n");
675
676         MsgFflush(pFile);
677
678         memset(pInBuffer, 0, maxLen);
679
680         *pPtr = 0;
681
682         if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
683                 MSG_FATAL("MsgFseek failed");
684                 return false;
685         }
686
687         *pOffset = MsgFtell(pFile);
688
689         if (*pOffset == -1L) {
690                 MSG_FATAL("MsgFtell failed");
691                 return false;
692         }
693
694         return true;
695 }
696
697
698 bool MsgOpenCreateAndOverwriteFile(char *pFullPath, char *pBuff, int TotalLength)
699 {
700         FILE *pFile = NULL ;
701
702         if ((pFile = MsgOpenFile(pFullPath, "wb+")) == NULL) {
703                 MSG_FATAL("MsgOpenFile errer");
704                 return false;
705         }
706
707         if (MsgWriteFile(pBuff, sizeof(char), TotalLength, pFile) != (size_t)TotalLength) {
708                 MsgCloseFile(pFile);
709                 return false;
710         }
711
712         MsgFsync(pFile);        /* file is written to device immediately, it prevents missing file data from unexpected power off */
713         MsgFflush(pFile);
714         MsgCloseFile(pFile);
715
716         return true;
717 }
718
719
720 char *MsgOpenAndReadMmsFile(const char *szFilePath, int offset, int size, int *npSize)
721 {
722         FILE *pFile = NULL;
723         char *pData = NULL;
724         int     readSize = 0;
725
726         if (szFilePath == NULL) {
727                 MSG_ERR("szFilePath id NULL");
728                 goto __CATCH;
729         }
730
731         *npSize = 0;
732
733         pFile = MsgOpenFile(szFilePath, "rb");
734
735         if (pFile == NULL) {
736                 MSG_ERR("Can't open file: %s", g_strerror(errno));
737                 goto __CATCH;
738         }
739
740         if (size == -1) {
741                 if (MsgGetFileSize(szFilePath, & readSize) == false) {
742                         MSG_DEBUG("MsgGetFileSize: failed");
743                         goto __CATCH;
744                 }
745         } else {
746                 readSize = size;
747         }
748 /* restore Kies backup data size greater than FM_READ_WRITE_BUFFER_MAX */
749 #if 0
750         if (readSize > FM_READ_WRITE_BUFFER_MAX) {
751                 MSG_DEBUG("MsgOpenAndReadMmsFile: File size tried to read too big");
752                 goto __CATCH;
753         }
754 #endif
755
756         pData = (char *)calloc(1, readSize + 1);
757         if ( NULL == pData ) {
758                 MSG_ERR("pData MemAlloc Fail : %s", g_strerror(errno) );
759                 goto __CATCH;
760         }
761
762         if (MsgFseek(pFile, offset, SEEK_SET) < 0) {
763                 MSG_ERR("FmSeekFile failed : %s", g_strerror(errno) );
764                 goto __CATCH;
765         }
766
767         *npSize = MsgReadFile(pData, sizeof(char), readSize, pFile);
768
769         MsgCloseFile(pFile);
770
771         pFile = NULL;
772
773         *(pData + (*npSize)) = '\0';
774
775         return pData;
776
777 __CATCH:
778
779         if (pData) {
780                 free(pData);
781                 pData = NULL;
782         }
783
784         *npSize = 0;
785
786         if (pFile != NULL) {
787                 MsgCloseFile(pFile);
788                 pFile = NULL;
789         }
790
791         return NULL;
792 }
793
794 /* it is equivalent to "rm -rf pDirPath" */
795 int MsgRmRf(char *pDirPath)
796 {
797         struct dirent *d = NULL;
798         struct dirent entry;
799         DIR *dir;
800
801         dir = opendir(pDirPath);
802
803         if (dir == NULL) {
804                 MSG_FATAL("error opendir: %s", g_strerror(errno));
805                 return -1;
806         }
807
808         int size = strlen(pDirPath) + 256;
809
810         char *path = (char*)malloc(size);
811
812         if (path == NULL) {
813                 MSG_DEBUG("path is NULL");
814                 closedir(dir);
815                 return -1;
816         }
817
818         bzero(path, size);
819
820         for (readdir_r(dir, &entry, &d); d != NULL; readdir_r(dir, &entry, &d)) {
821                 if (d->d_type == DT_DIR) {
822                         snprintf(path, size, "%s/%s", pDirPath, d->d_name);
823
824                         if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
825                                 continue;
826
827                         MsgRmRf(path);
828
829                         if (rmdir(path) != 0) {
830                                 if (path != NULL)
831                                         free(path);
832
833                                 closedir(dir);
834
835                                 MSG_FATAL("error rmdir: %s", g_strerror(errno));
836
837                                 return -1;
838                         }
839                 } else {
840                         snprintf(path, size, "%s/%s", pDirPath, d->d_name);
841
842                         if (MsgDrmIsDrmFile(path))
843                                 MsgDrmUnregisterFile(path);
844
845                         if (remove(path) != 0) {
846                                 if (path != NULL)
847                                         free(path);
848
849                                 closedir(dir);
850
851                                 MSG_FATAL("error remove: %s", g_strerror(errno));
852
853                                 return -1;
854                         }
855                 }
856                 d = NULL;
857         }
858
859         closedir(dir);
860
861         if (path != NULL)
862                 free(path);
863
864         return 0;
865 }
866
867
868 int MsgGetFileSize(const char *pFileName)
869 {
870         struct stat file_stat;
871
872         if (lstat(pFileName, &file_stat)) {
873                 MSG_FATAL("error lstat: %s", g_strerror(errno));
874                 return -1;
875         }
876
877         return file_stat.st_size;
878 }
879
880
881 /* it is equivalent to "du dir_path" */
882 unsigned int MsgDu(const char *pDirPath)
883 {
884         struct dirent *d = NULL;
885         struct dirent entry;
886         DIR *dir;
887
888         dir = opendir(pDirPath);
889
890         if (dir == NULL) {
891                 MSG_FATAL("error opendir: %s", g_strerror(errno));
892                 return -1;
893         }
894
895         int size = strlen(pDirPath) + 256;
896         char *path = (char*)malloc(size);
897         if (path == NULL) {
898                 closedir(dir);
899                 return -1;
900         }
901
902         bzero(path, size);
903
904         unsigned int totalFileSize = 0;
905
906         for (readdir_r(dir, &entry, &d); d != NULL; readdir_r(dir, &entry, &d)) {
907                 if(d->d_type == DT_DIR) {
908                         snprintf(path, size, "%s/%s", pDirPath, d->d_name);
909
910                         if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
911                                 continue;
912
913                         unsigned int dirSize = MsgDu(path);
914
915                         if (dirSize == 0) {
916                                 MSG_FATAL("error MsgDu");
917                                 closedir(dir);
918                                 free(path);
919                                 return dirSize;
920                         }
921
922                         totalFileSize += dirSize;
923                 } else {
924                         snprintf(path, size, "%s/%s", pDirPath, d->d_name);
925                         int fileSize = MsgGetFileSize(path);
926
927                         if (fileSize < 0) {
928                                 MSG_FATAL("error MsgGetFileSize");
929                                 closedir(dir);
930                                 free(path);
931                                 return fileSize;
932                         }
933
934                         totalFileSize += fileSize;
935                 }
936                 d = NULL;
937         }
938
939         closedir(dir);
940
941         free(path);
942
943         return totalFileSize;
944 }
945
946
947 bool MsgAppendFile(const char *pFilePath, const char *pData, int DataSize)
948 {
949         if (!pFilePath) {
950                 MSG_FATAL("NULL check error, pFileName %p, pData %p", pFilePath, pData);
951                 return false;
952         }
953
954         char fullPath[MAX_FULL_PATH_SIZE] = {0};
955
956         snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s", pFilePath);
957
958         FILE *pFile = MsgOpenFile(fullPath, "a+");
959
960         if (pFile == NULL) {
961                 MSG_FATAL("File Open Error: %s", g_strerror(errno));
962                 return false;
963         }
964
965         if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
966                 MsgCloseFile(pFile);
967                 MSG_FATAL("File Sead Error: %s", g_strerror(errno));
968                 return false;
969         }
970
971         if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
972                 MsgCloseFile(pFile);
973                 MSG_FATAL("File Write Error: %s", g_strerror(errno));
974                 return false;
975         }
976
977         MsgFsync(pFile);        /*file is written to device immediately, it prevents missing file data from unexpected power off */
978         MsgFflush(pFile);
979         MsgCloseFile(pFile);
980         return true;
981 }
982
983 void MsgMmsInitDir()
984 {
985         struct dirent *d = NULL;
986         struct dirent entry;
987         DIR* dir = NULL;
988
989         dir = opendir(MSG_DATA_PATH);
990
991         if (dir == NULL) {
992                 MSG_FATAL("error opendir: %s", g_strerror(errno));
993                 return;
994         }
995
996         /* Remove temporal Mms folder */
997         for (readdir_r(dir, &entry, &d); d != NULL; readdir_r(dir, &entry, &d)) {
998                 if (d->d_type == DT_DIR) {
999                         if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
1000                                 continue;
1001
1002                         if(strstr(d->d_name, ".dir") != NULL) {
1003                                 char filePath[MSG_FILEPATH_LEN_MAX] = {0, };
1004                                 snprintf(filePath, MSG_FILEPATH_LEN_MAX, "%s%s", MSG_DATA_PATH, d->d_name);
1005
1006                                 MsgRmRf(filePath);
1007                                 rmdir(filePath);
1008                         }
1009                 }
1010                 d = NULL;
1011         }
1012
1013         closedir(dir);
1014 }
1015
1016 /* mode : R_OK, W_OK, X_OK, or the existence test F_OK. */
1017 bool MsgAccessFile(const char *filepath, int mode)
1018 {
1019         int ret;
1020         if (filepath == NULL) {
1021                 MSG_DEBUG("filepath is NULL");
1022                 return false;
1023         }
1024
1025         MSG_SEC_DEBUG("request access path = %s, mode = %d", filepath, mode);
1026
1027         ret = access(filepath, mode);
1028
1029
1030         if (ret) {
1031                 MSG_DEBUG("Fail to access file, ret = %d", ret);
1032                 return false;
1033         }
1034
1035         return true;
1036 }
1037
1038
1039 bool MsgChmod(const char *filepath, int mode)
1040 {
1041 #if 0
1042         struct stat lstat_info;
1043         struct stat fstat_info;
1044         int fd;
1045
1046         if (lstat(filepath, &lstat_info) == -1) {
1047                 MSG_SEC_DEBUG("No such file as [%s].", filepath);
1048                 return false;
1049         }
1050
1051         fd = open(filepath, O_RDONLY);
1052
1053         if (fd == -1) {
1054                 MSG_SEC_DEBUG("Fail to open [%s].", filepath);
1055                 return false;
1056         }
1057
1058         if (fstat(fd, &fstat_info) == -1) {
1059                 MSG_SEC_DEBUG("Fail to fstat [%s].", filepath);
1060                 close(fd);
1061                 return false;
1062         }
1063
1064         if (lstat_info.st_mode == fstat_info.st_mode &&
1065                         lstat_info.st_ino == fstat_info.st_ino  &&
1066                         lstat_info.st_dev == fstat_info.st_dev) {
1067                 if (fchmod(fd, mode) < 0) {
1068                         MSG_SEC_DEBUG("Fail to fchmod [%s].", filepath);
1069                         close(fd);
1070                         return false;
1071                 }
1072         }
1073
1074         close(fd);
1075 #endif
1076         return true;
1077 }
1078
1079
1080 bool MsgChown(const char *filepath, int uid, int gid)
1081 {
1082         struct stat lstat_info;
1083         struct stat fstat_info;
1084         int fd;
1085
1086         if (lstat(filepath, &lstat_info) == -1) {
1087                 MSG_SEC_INFO("No such file as [%s].", filepath);
1088                 return false;
1089         }
1090
1091         fd = open(filepath, O_RDONLY);
1092
1093         if (fd == -1) {
1094                 MSG_SEC_INFO("Fail to open [%s].", filepath);
1095                 return false;
1096         }
1097
1098         if (fstat(fd, &fstat_info) == -1) {
1099                 MSG_SEC_INFO("Fail to fstat [%s].", filepath);
1100                 close(fd);
1101                 return false;
1102         }
1103
1104         if (lstat_info.st_mode == fstat_info.st_mode &&
1105                         lstat_info.st_ino == fstat_info.st_ino  &&
1106                         lstat_info.st_dev == fstat_info.st_dev) {
1107                 if (fchown(fd, uid, gid) < 0) {
1108                         MSG_SEC_INFO("Fail to fchown [%s].", filepath);
1109                         close(fd);
1110                         return false;
1111                 }
1112         }
1113
1114         close(fd);
1115         return true;
1116 }
1117
1118 bool MsgCreateFile(const char *pFilePath, char *pData, int DataSize)
1119 {
1120         if(!pFilePath) {
1121                 MSG_DEBUG("pFilePath is NULL");
1122                 return false;
1123         }
1124
1125         FILE *pFile = MsgOpenFile(pFilePath, "wb+");
1126
1127         if (pFile == NULL) {
1128                 MSG_ERR("File Open Error: %s", g_strerror(errno));
1129                 return false;
1130         }
1131
1132         if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
1133                 MsgCloseFile(pFile);
1134                 MSG_ERR("File Seek Error: %s", g_strerror(errno));
1135                 return false;
1136         }
1137
1138         if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
1139                 MsgCloseFile(pFile);
1140                 MSG_ERR("File Write Error: %s", g_strerror(errno));
1141                 return false;
1142         }
1143
1144         MsgFflush(pFile);
1145         MsgFsync(pFile);
1146         MsgCloseFile(pFile);
1147
1148         return true;
1149 }
1150
1151 char *MsgGetDirName(char *file_path)
1152 {
1153         return g_path_get_dirname(file_path);
1154 }
1155
1156
1157 char *MsgGetFileName(char *file_path)
1158 {
1159         return g_path_get_basename(file_path);
1160 }
1161
1162
1163 int MsgCheckFilepathSmack(const char *app_smack_label, char *file_path)
1164 {
1165         int err = MSG_SUCCESS;
1166
1167         char *path_smack_label = NULL;
1168         char *dir_smack_label = NULL;
1169         char *dir_name = NULL;
1170
1171         if (!file_path || file_path[0] == '\0') {
1172                 return MSG_SUCCESS;
1173         }
1174
1175         struct stat st;
1176         if (stat(file_path, &st) != 0) {
1177                 MSG_SEC_ERR("stat(%s, &st) != 0", file_path);
1178                 return MSG_ERR_PERMISSION_DENIED;
1179         }
1180         if (S_ISDIR(st.st_mode)) {
1181                 MSG_ERR("S_ISDIR(st.st_mode)");
1182                 return MSG_ERR_INVALID_PARAMETER;
1183         }
1184
1185         dir_name = MsgGetDirName(file_path);
1186         if (!dir_name || !g_strcmp0(dir_name, file_path)) {
1187                 MSG_SEC_ERR("!dir_name || !g_strcmp0(dir_name, %s)", file_path);
1188                 err = MSG_ERR_INVALID_PARAMETER;
1189                 goto __RETURN;
1190         }
1191
1192         smack_getlabel(dir_name, &dir_smack_label, SMACK_LABEL_ACCESS);
1193         if (dir_smack_label == NULL) {
1194                 MSG_ERR("smack_getlabel failed (dir_smack_label)");
1195                 err = MSG_ERR_PERMISSION_DENIED;
1196                 goto __RETURN;
1197         }
1198
1199         if (smack_have_access(app_smack_label, dir_smack_label, "RX") < 1) {
1200                 MSG_ERR("smack_have_access failed (dir_smack_label)");
1201                 err = MSG_ERR_PERMISSION_DENIED;
1202                 goto __RETURN;
1203         }
1204
1205         smack_getlabel(file_path, &path_smack_label, SMACK_LABEL_ACCESS);
1206         if (path_smack_label == NULL) {
1207                 MSG_ERR("smack_getlabel failed (path_smack_label)");
1208                 err = MSG_ERR_PERMISSION_DENIED;
1209                 goto __RETURN;
1210         }
1211
1212         if (smack_have_access(app_smack_label, path_smack_label, "R") < 1) {
1213                 MSG_ERR("smack_have_access failed (path_smack_label)");
1214                 err = MSG_ERR_PERMISSION_DENIED;
1215                 goto __RETURN;
1216         }
1217
1218         MSG_DEBUG("smack_have_access pass successfully");
1219
1220 __RETURN:
1221         MSG_FREE(path_smack_label);
1222         MSG_FREE(dir_smack_label);
1223         MSG_FREE(dir_name);
1224         return err;
1225 }
1226
1227
1228 void MsgGetMimeType(char *filePath, char *mimeType, int size)
1229 {
1230         aul_get_mime_from_file(filePath, mimeType, size);
1231 }
1232
1233
1234 int MsgTcsScanFile(const char *filepath, int *bLevel)
1235 {
1236         MSG_BEGIN();
1237         TCSLIB_HANDLE hLib;
1238         TCSScanResult result;
1239         TCSDetected* pDetected;
1240         int rtn, i;
1241         int ret_b_level = -1;
1242
1243         if (MsgAccessFile(filepath, R_OK) == false) {
1244                 MSG_SEC_DEBUG("not exist source file [%s]", filepath);
1245                 return -1;
1246         }
1247
1248         MSG_SEC_DEBUG("Scanning file name : %s\n", filepath);
1249
1250         hLib = TCSLibraryOpen();
1251         if(hLib == INVALID_TCSLIB_HANDLE) {
1252                 MSG_DEBUG("TCSLibraryOpen error\n");
1253                 return -1;
1254         }
1255
1256         rtn = TCSScanFile(hLib, filepath, TCS_DTYPE_UNKNOWN, TCS_SA_SCANONLY, 1, &result);
1257         if(rtn == 0)
1258         {
1259                 MSG_DEBUG("Detected malware number: %d\n", result.iNumDetected);
1260                 i = result.iNumDetected;
1261                 pDetected = result.pDList;
1262                 while(i && pDetected)
1263                 {
1264                         int temp_b_level;
1265                         int temp_s_class;
1266                         MSG_SEC_DEBUG(" +-- Malware [%d] Name: %s\n", i, pDetected->pszName);
1267                         MSG_DEBUG(" +-- Malware [%d] uAction: %u : 0x%04x\n", i, pDetected->uAction, pDetected->uAction);
1268
1269                         temp_b_level  = (pDetected->uAction & 0xFF00) >> 8;
1270                         MSG_DEBUG(" +-- Malware [%d] Behavior level: %u\n", i, temp_b_level);
1271
1272                         if (ret_b_level == -1 || ret_b_level < temp_b_level) {
1273                                 ret_b_level = temp_b_level;
1274                         }
1275
1276                         temp_s_class  = (pDetected->uAction & 0x00FF);
1277                         MSG_DEBUG(" +-- Malware [%d] Severity class: %u\n", i, temp_s_class);
1278
1279                         pDetected = pDetected->pNext;
1280                         i --;
1281                 }
1282
1283                 result.pfFreeResult(&result);
1284         } else {
1285                 MSG_DEBUG("TCSScanFile fail: err = %d\n", rtn);
1286         }
1287
1288         TCSLibraryClose(hLib);
1289
1290         if (bLevel)
1291                 *bLevel = ret_b_level;
1292
1293         MSG_END();
1294
1295         return 0;
1296 }