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