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