2 * Copyright 2012-2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (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
8 * http://floralicense.org/license/
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.
25 #include <unistd.h> //sync()
27 #include "MsgStorageTypes.h"
29 #include "MsgException.h"
30 #include "MsgUtilFile.h"
31 #include "MsgMmsTypes.h"
32 #include "MsgInternalTypes.h"
33 #include "MsgDrmWrapper.h"
36 /*==================================================================================================
37 FUNCTION IMPLEMENTATION
38 ==================================================================================================*/
39 // File operation wrappers
40 FILE *MsgOpenFile(const char *filepath, const char *opt)
42 if (!filepath || !opt) {
43 MSG_FATAL("Null parameter");
47 MSG_DEBUG("[FILE] filepath : [%s], opt [%s]", filepath, opt);
52 pFile = fopen(filepath, opt);
53 MSG_DEBUG("[FILE] pFile [%p]", pFile);
54 } catch (exception &e) {
55 MSG_FATAL("%s", e.what());
62 void MsgCloseFile(FILE *pFile)
65 MSG_FATAL("NULL parameter");
69 MSG_DEBUG("[FILE] pFile [%p]", pFile);
73 } catch (exception &e) {
74 MSG_FATAL("%s", e.what());
78 int MsgFseek(FILE *pFile, long int offset, int origin)
81 MSG_FATAL("pFile NULL");
87 MSG_DEBUG("[FILE] pFile [%p], offset [%d], origin [%d]", pFile, offset, origin);
90 ret = fseek(pFile, offset, origin); // return 0, if success.
91 } catch (exception &e) {
92 MSG_FATAL("%s", e.what());
99 size_t MsgWriteFile(const char *pData, size_t size, size_t count, FILE *pFile)
101 if (!pData || !pFile) {
102 MSG_FATAL("pData or pFile NULL");
108 MSG_DEBUG("[FILE] pData [%p], size [%d], count [%d], pFile [%p]", pData, size, count, pFile);
111 nWrite = fwrite(pData, size, count, pFile);
112 } catch (exception &e) {
113 MSG_FATAL("%s", e.what());
119 size_t MsgReadFile(void *pData, size_t size, size_t count, FILE *pFile)
121 if (!pData || !pFile) {
122 MSG_FATAL("pData or pFile NULL");
129 nRead = fread(pData, size, count, pFile);
130 } catch (exception &e) {
131 MSG_FATAL("%s", e.what());
137 long int MsgFtell(FILE *pFile)
140 MSG_FATAL("pFile NULL");
144 long int ret = -1L; // -1L return if error occured.
148 } catch (exception &e) {
149 MSG_FATAL("%s", e.what());
155 int MsgFflush(FILE *pFile)
158 MSG_FATAL("pFile NULL");
165 ret = fflush(pFile); // return 0 if success
166 } catch (exception &e) {
167 MSG_FATAL("%s", e.what());
173 int MsgFsync(FILE *pFile)
176 MSG_FATAL("pFile NULL");
183 ret = fdatasync(pFile->_fileno); // return 0 if success
184 } catch (exception &e) {
185 MSG_FATAL("%s", e.what());
191 bool MsgCreateFileName(char *pFileName)
193 if (pFileName == NULL) {
194 MSG_DEBUG("[ERROR] pFileName is NULL");
201 if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
202 MSG_DEBUG("clock_gettime() error: %s", strerror(errno));
206 // Create Random Number
207 srandom((unsigned int)ts.tv_nsec);
209 MSG_DEBUG("ts.tv_nsec : %d", ts.tv_nsec);
211 // between 1 - 1000000000
212 snprintf(pFileName, MSG_FILENAME_LEN_MAX, "MSG_%lu.DATA", random()%1000000000+1);
213 } catch (exception& e) {
214 MSG_FATAL("%s", e.what());
222 bool MsgOpenAndReadFile(const char *pFileName, char **ppData, int *pDataSize)
224 MSG_DEBUG("MsgOpenAndReadFile");
228 char fullPath[MAX_FULL_PATH_SIZE] = {0};
230 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s/%s", MSG_IPC_DATA_PATH, pFileName);
231 MSG_DEBUG("open file name: %s", fullPath);
234 pFile = MsgOpenFile(fullPath, "rb");
237 MSG_DEBUG("File Open Error: %s", strerror(errno));
241 if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
243 MSG_DEBUG("File Read Error: %s", strerror(errno));
247 int FileSize = MsgFtell(pFile);
250 MSG_DEBUG("Filesize is error : %d", FileSize);
256 *ppData = new char[FileSize+1];
257 memset(*ppData, 0x00, (FileSize+1));
259 if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
261 MSG_DEBUG("File seek Error: %s", strerror(errno));
265 if (MsgReadFile(*ppData, sizeof(char), FileSize, pFile) != (size_t)FileSize) {
267 MSG_DEBUG("File Read Error: %s", strerror(errno));
271 *pDataSize = FileSize;
279 bool MsgReadFileForDecode(FILE *pFile, char *pBuf, int length, int *nSize)
283 if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
284 MSG_DEBUG("File Seek Error: %s", strerror(errno));
289 *nSize = MsgReadFile(pBuf, sizeof(char), length, pFile);
296 bool MsgWriteIpcFile(const char *pFileName, const char *pData, int DataSize)
299 MSG_DEBUG("NULL parameter, pFileName [%p], pData [%p]", pFileName, pData);
303 char fullPath[MAX_FULL_PATH_SIZE] = {0};
305 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s/%s", MSG_IPC_DATA_PATH, pFileName);
307 FILE *pFile = MsgOpenFile(fullPath, "wb+");
310 MSG_DEBUG("File Open Error: %s", strerror(errno));
314 if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
316 MSG_DEBUG("File Seek Error: %s", strerror(errno));
320 if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
322 MSG_DEBUG("File Write Error: %s", strerror(errno));
329 if (chmod(fullPath, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ) != 0) {
330 MSG_DEBUG("File chmod Error: %s", strerror(errno));
333 if (chown(fullPath, 0, 6502 ) != 0) {
334 MSG_DEBUG("File chown Error: %s", strerror(errno));
340 int MsgReadSmilFile(const char *pFileName, char **ppData)
343 MSG_DEBUG("pFileName is NULL");
348 char fullPath[MAX_FULL_PATH_SIZE] = {0};
350 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s/%s", MSG_SMIL_FILE_PATH, pFileName);
352 MSG_DEBUG("open file name: %s", fullPath);
354 FILE *pFile = MsgOpenFile(fullPath, "rb");
357 MSG_DEBUG("File Open Error: %s", strerror(errno));
361 if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
363 MSG_DEBUG("File Seek Error: %s", strerror(errno));
367 int FileSize = MsgFtell(pFile);
370 MSG_DEBUG("Filesize is error : %d", FileSize);
375 *ppData = new char[FileSize + 1];
377 if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
379 MSG_DEBUG("File Sead Error: %s", strerror(errno));
383 if (MsgReadFile(*ppData, sizeof(char), FileSize, pFile) != (size_t)FileSize) {
385 MSG_DEBUG("File Read Error: %s", strerror(errno));
389 ppData[FileSize] = '\0';
399 bool MsgWriteSmilFile(const char *pFilePath,char *pData, int DataSize)
402 MSG_DEBUG("pFilePath is NULL");
406 if (mkdir(MSG_SMIL_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
407 if (errno == EEXIST) {
408 MSG_DEBUG("The %s already exists", MSG_SMIL_FILE_PATH);
410 MSG_DEBUG("Error while mkdir %s", MSG_SMIL_FILE_PATH);
414 FILE *pFile = MsgOpenFile(pFilePath, "wb+");
417 MSG_DEBUG("File Open Error: %s", strerror(errno));
421 if (MsgFseek(pFile, 0L, SEEK_SET) < 0) {
423 MSG_DEBUG("File Seek Error: %s", strerror(errno));
427 if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
429 MSG_DEBUG("File Write Error: %s", strerror(errno));
440 void MsgDeleteFile(const char *pFileName)
443 MSG_FATAL("pFileName is NULL");
447 if (strlen(pFileName) == 0) {
448 MSG_FATAL("pFileName has zero length");
452 char fullPath[MAX_FULL_PATH_SIZE] = {0};
455 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s/%s", MSG_IPC_DATA_PATH, pFileName);
457 MSG_DEBUG("%s", fullPath);
459 if (remove(fullPath) != 0)
460 MSG_FATAL("File Delete Error [%s]: %s", fullPath, strerror(errno));
461 } catch (exception &e) {
462 MSG_FATAL ("%s", e.what());
468 void MsgDeleteSmilFile(const char *pFileName)
471 MSG_FATAL("pFileName NULL");
476 char fullPath[MAX_FULL_PATH_SIZE] = {0};
478 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s/%s", MSG_SMIL_FILE_PATH, pFileName);
480 if (remove(fullPath) != 0)
481 MSG_FATAL("File Delete Error [%s]: %s", fullPath, strerror(errno));
482 } catch (exception &e) {
483 MSG_FATAL("%s", e.what());
488 bool MsgGetFileSize(const char *pFilePath, int *nSize)
491 MSG_FATAL("pFileName NULL");
497 pFile = MsgOpenFile(pFilePath, "rb");
500 MSG_DEBUG("File Open error: %s", strerror(errno));
504 if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
506 MSG_FATAL("File Read Error: %s", strerror(errno));
510 *nSize = MsgFtell(pFile);
518 FILE *MsgOpenMMSFile(char *pFileName)
523 MSG_DEBUG("pFileName NULL: %s", strerror(errno));
527 len = strlen(pFileName);
529 for (int i = 0; i < len; i++) {
530 switch (pFileName[i]) {
537 MSG_DEBUG("pFileName = %s", pFileName);
539 char fullPath[MAX_FULL_PATH_SIZE+1] = {0};
541 snprintf(fullPath, MAX_FULL_PATH_SIZE+1, "%s.mms", pFileName);
543 FILE *pFile = MsgOpenFile(fullPath, "wb+");
546 MSG_FATAL("File Open Error: %s", strerror(errno));
550 if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
552 MSG_DEBUG("File Read Error: %s", strerror(errno));
560 bool MsgWriteDataFromEncodeBuffer(FILE *pFile, char *pInBuffer, int *pPtr, int maxLen, int *pOffset )
562 if (!pFile || !pPtr || !pInBuffer || !pOffset) {
563 MSG_FATAL(" NULL parameter passed");
567 MSG_DEBUG("MsgWriteDataFromEncodeBuffer:");
568 MSG_DEBUG("pInBuffer %x", pInBuffer);
569 MSG_DEBUG("pPtr %d", (*pPtr));
570 MSG_DEBUG("before to fwite %x", pFile);
572 if (MsgWriteFile(pInBuffer, sizeof(char), (*pPtr), pFile) != (size_t)(*pPtr)) {
573 MSG_FATAL("MsgWriteFile failed");
577 MSG_DEBUG("after to fwite \n");
581 memset( pInBuffer, 0, maxLen );
585 if (MsgFseek(pFile, 0L, SEEK_END) < 0) {
586 MSG_FATAL("MsgFseek failed");
590 *pOffset = MsgFtell(pFile);
592 if (*pOffset == -1L) {
593 MSG_FATAL("MsgFtell failed");
601 bool MsgOpenCreateAndOverwriteFile(char *pFullPath, char *pBuff, int TotalLength)
606 file_mode = (S_IRUSR | S_IWUSR);
608 if ((pFile = MsgOpenFile(pFullPath, "wb+")) == NULL) {
609 MSG_FATAL("MsgOpenFile errer");
613 if (MsgWriteFile(pBuff, sizeof(char), TotalLength, pFile) != (size_t)TotalLength) {
614 MsgCloseFile( pFile );
618 MsgFsync(pFile); //file is written to device immediately, it prevents missing file data from unexpected power off
622 if (chmod(pFullPath, file_mode) < 0)
623 MSG_FATAL("File chmod Error: %s", strerror(errno));
629 char *MsgOpenAndReadMmsFile( const char *szFilePath, int offset, int size, int *npSize )
635 if (szFilePath == NULL) {
636 MSG_DEBUG("MsgOpenAndReadMmsFile: [ERROR] szFilePath id NULL");
642 pFile = MsgOpenFile( szFilePath, "rb" );
645 MSG_DEBUG("MsgOpenAndReadMmsFile: [ERROR] Can't open filepath", strerror(errno));
650 if (MsgGetFileSize(szFilePath, & readSize) == false) {
651 MSG_DEBUG("MsgGetFileSize: failed");
658 if (readSize > FM_READ_WRITE_BUFFER_MAX) {
659 MSG_DEBUG("MsgOpenAndReadMmsFile: File size tried to read too big");
663 pData = (char *)malloc(readSize + 1);
664 if ( NULL == pData ) {
665 MSG_DEBUG( "MsgOpenAndReadMmsFile: [ERROR] pData MemAlloc Fail", strerror(errno) );
668 memset( pData, 0, readSize + 1 );
670 if (MsgFseek( pFile, offset, SEEK_SET) < 0) {
671 MSG_DEBUG( "MsgOpenAndReadMmsFile: [ERROR] FmSeekFile failed", strerror(errno) );
675 *npSize = MsgReadFile(pData, sizeof(char), readSize, pFile);
681 *(pData + (*npSize)) = '\0';
695 MsgCloseFile( pFile );
702 // it is equivalent to "rm -rf pDirPath"
703 int MsgRmRf(char *pDirPath)
708 dir = opendir(pDirPath);
711 MSG_FATAL("error opendir: %s", strerror(errno));
715 int size = strlen(pDirPath) + 256;
717 char *path = (char*)malloc(size);
720 MSG_DEBUG("path is NULL");
727 while ((d = readdir(dir)) != NULL) {
728 if (d->d_type == DT_DIR) {
729 snprintf(path, size, "%s/%s", pDirPath, d->d_name);
731 if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
736 if (rmdir(path) != 0) {
743 MSG_FATAL("error rmdir: %s", strerror(errno));
748 snprintf(path, size, "%s/%s", pDirPath, d->d_name);
750 if (MsgDrmIsDrmFile(path))
751 MsgDrmUnregisterFile(path);
753 if (remove(path) != 0) {
760 MSG_FATAL("error remove: %s", strerror(errno));
776 int MsgGetFileSize(const char *pFileName)
778 struct stat file_stat;
780 if (lstat(pFileName, &file_stat)) {
781 MSG_FATAL("error lstat: %s", strerror(errno));
785 return file_stat.st_size;
789 // it is equivalent to "du dir_path"
790 unsigned int MsgDu(const char *pDirPath)
795 dir = opendir(pDirPath);
798 MSG_FATAL("error opendir: %s", strerror(errno));
802 int size = strlen(pDirPath) + 256;
803 char *path = (char*)malloc(size);
806 unsigned int totalFileSize = 0;
808 while ((d = readdir(dir)) != NULL) {
809 if( d->d_type == DT_DIR) {
810 snprintf(path, size, "%s/%s", pDirPath, d->d_name);
812 if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
815 unsigned int dirSize = MsgDu(path);
818 MSG_FATAL("error MsgDu");
824 totalFileSize += dirSize;
826 snprintf(path, size, "%s/%s", pDirPath, d->d_name);
827 int fileSize = MsgGetFileSize(path);
830 MSG_FATAL("error MsgGetFileSize");
836 totalFileSize += fileSize;
844 return totalFileSize;
848 bool MsgAppendFile(const char *pFilePath, const char *pData, int DataSize)
851 MSG_FATAL("NULL check error, pFileName %p, pData %p", pFilePath, pData);
855 char fullPath[MAX_FULL_PATH_SIZE] = {0};
857 snprintf(fullPath, MAX_FULL_PATH_SIZE, "%s", pFilePath);
859 FILE *pFile = MsgOpenFile(fullPath, "a+");
862 MSG_FATAL("File Open Error: %s", strerror(errno));
866 if (MsgFseek(pFile, 0L, SEEK_CUR) < 0) {
868 MSG_FATAL("File Sead Error: %s", strerror(errno));
872 if (MsgWriteFile(pData, sizeof(char), DataSize, pFile) != (size_t)DataSize) {
874 MSG_FATAL("File Write Error: %s", strerror(errno));
878 MsgFsync(pFile); //file is written to device immediately, it prevents missing file data from unexpected power off
886 struct dirent *d = NULL;
889 dir = opendir(MSG_DATA_PATH);
892 MSG_FATAL("error opendir: %s", strerror(errno));
896 // Remove temporal Mms folder (/opt/usr/data/msg-service/msgdata/*.dir)
897 while ((d = readdir(dir)) != NULL) {
898 if (d->d_type == DT_DIR) {
899 if ((strcmp(".", d->d_name) == 0) || (strcmp("..", d->d_name) == 0))
902 if(strstr(d->d_name, ".dir") != NULL) {
903 char filePath[MSG_FILEPATH_LEN_MAX] = {0,};
904 snprintf(filePath, MSG_FILEPATH_LEN_MAX, "%s/%s", MSG_DATA_PATH, d->d_name);
915 //mode : R_OK, W_OK, X_OK, or the existence test F_OK.
916 bool MsgAccessFile(const char *filepath, int mode)
919 if (filepath == NULL) {
920 MSG_DEBUG("filepath is NULL");
924 MSG_DEBUG("request access path = %s, mode = %d", filepath, mode);
926 ret = access(filepath, mode);
930 MSG_DEBUG("Fail to access file, ret = %d", ret);