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