4 * Copyright (c) 2017 - 2022 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #define _XOPEN_SOURCE 600
20 #define _POSIX_C_SOURCE 200809L
27 #include <sys/types.h>
35 #include <sys/xattr.h>
36 #include "SS_Common.h"
38 #include "fota_common.h"
41 static int feature_support_capability;
43 enum smack_label_type {
47 SMACK_LABEL_TRANSMUTE,
52 #define SMACK_LABEL_LEN 255
54 /************************************************************
56 ************************************************************/
57 void SS_create_dir(char *pathname, int mode)
62 /* Strip trailing '/' */
63 if (pathname[strlen(pathname) - 1] == '/')
64 pathname[strlen(pathname) - 1] = '\0';
66 /* Try creating the directory. */
67 r = mkdir(pathname, mode);
70 /* On failure, try creating parent directory. */
71 p = strrchr(pathname, '/');
74 SS_create_dir(pathname, 0755);
76 r = mkdir(pathname, mode);
80 if (r != EEXIST && r != -1)
81 LOG("Could not create directory [%s] Error[%d]\n", pathname, r);
86 void SS_unicode_to_char(const char *src, char *dest, int size)
91 strncpy(dest, src, size);
94 void SS_char_to_unicode(const char *src, char *dest, int size)
99 strncpy(dest, src, size);
102 long SS_recursive_folder_creater(const char *path, const mode_t mode) {
105 LOGL(LOG_SSENGINE, "Bad path param value \n");
106 return -E_SS_BAD_PARAMS;
109 if (path[0] == '\0') {
110 LOGL(LOG_SSENGINE, "Path empty \n");
111 return -E_SS_FILENAMELENERROR;
114 char input_path[MAX_PATH] = {'\0'};
115 char temppath[MAX_PATH] = {'\0'};
117 strncpy(input_path, path, MAX_PATH - 1);
119 if (input_path[0] == '/') {
124 char *path_pos = input_path;
126 int temppath_current_len = (temppath[0] == '/');
128 while((path_token = strtok_r(path_pos, "/", &path_pos))) {
130 int path_token_len = strnlen(path_token, MAX_PATH-temppath_current_len);
131 strncat(temppath, path_token, path_token_len);
132 temppath_current_len += path_token_len;
134 int mkd_res = mkdir(temppath, mode);
136 if(mkd_res != 0 && errno != EEXIST) {
137 LOGL(LOG_SSENGINE,"cannot create dir %s\n system error: %d error: %m\n", temppath, errno);
138 return -E_SS_CANNOT_CREATE_DIRECTORY;
141 if(temppath_current_len < (MAX_PATH - 1)) {
142 strncat(temppath, "/", 1);
149 SS_CopyFile(const char *strFromPath, const char *strToPath)
152 int readCount = 0, writeCount = 0;
153 char buf[1 << 15]; // copy 32KB wise
156 char path1[MAX_PATH] = { '\0' };
157 char path2[MAX_PATH] = { '\0' };
159 if (!strFromPath || !strToPath) {
160 LOGE("NULL file name find. Abort.\n");
164 SS_unicode_to_char((const char *)strFromPath, (char *)path1, MAX_PATH - 1);
165 SS_unicode_to_char((const char *)strToPath, (char *)path2, MAX_PATH - 1);
167 //LOGL(LOG_SSENGINE, "%s -> %s \n", path1, path2);
169 fd1 = open(path1, O_RDONLY);
171 return E_SS_OPENFILE_ONLYR;
172 ret = SS_OpenFile(strToPath, ONLY_W, (long *)&fd2);
173 if (ret != S_SS_SUCCESS || fd2 < 0) {
175 LOGE(" SS_OpenFile fail leaved path1:%s | path2:%s\n", path1, path1);
176 return E_SS_WRITE_ERROR;
179 while ((readCount = read(fd1, buf, sizeof(buf))) > 0) {
180 writeCount = write(fd2, buf, readCount);
181 if (writeCount != readCount) {
182 LOGE(" read %d, but write %d, abort.\n", readCount,
184 ret = E_SS_WRITE_ERROR;
192 //LOGL(LOG_INFO, " leaved path1:%s | path2:%s\n", path1, path2);
197 long SS_DeleteFile(const char *strPath)
199 char path[MAX_PATH] = { '\0' };
202 SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
203 //LOGL(LOG_SSENGINE, "%s\n", path);
208 LOGE("failed to delete path [%s] unlink value: %d, errno: %d\n", path, ret, errno);
209 if (ret < 0 && errno == ENOENT)
211 return E_SS_DELETEFILE;
214 int SS_unlink_cbf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
216 int rv = remove(fpath);//returns zero on success and -1 on failure
220 LOGE("path : %s, remove value: %d, errno: %d\n", fpath, rv, errno);
224 long SS_DeleteFolder(const char *strPath)
226 //runs till either tree is exhausted or when unlink_cbf returns non zero value.
227 return ((long)nftw(strPath, SS_unlink_cbf, 64, FTW_DEPTH | FTW_PHYS) == 0) ? S_SS_SUCCESS : E_SS_FAILURE;
230 long SS_CreateFolder(const char *strPath)
234 char path[MAX_PATH] = { '\0' };
236 SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
237 mode = S_IRUSR /*Read by owner */ |
238 S_IWUSR /*Write by owner */ |
239 S_IXUSR /*Execute by owner */ |
240 S_IRGRP /*Read by group */ |
241 S_IWGRP /*Write by group */ |
242 S_IXGRP /*Execute by group */ |
243 S_IROTH /*Read by others */ |
244 S_IWOTH /*Write by others */ |
245 S_IXOTH /*Execute by others */ ;
247 LOGL(LOG_SSENGINE, "%s, mode:0x%x\n", path, mode);
249 ret = mkdir(path, mode);
251 if (ret == 0 || ((ret == -1) && (errno == EEXIST))) {
253 } else if ((ret == -1) && (errno == ENOENT)) { //maybe multi directory problem
254 //do//Recursive Function
256 ret = SS_recursive_folder_creater(path, mode);
257 if (ret == S_SS_SUCCESS) {
258 ret = mkdir(path, mode); //After creating all the depth Directories we try to create the Original one again.
274 mode_t SS_get_mode(E_RW_TYPE wFlag)
278 //LOGL(LOG_SSENGINE, " RDONLY \n");
281 //LOGL(LOG_SSENGINE, " WRONLY \n");
282 return O_WRONLY | O_CREAT;
284 //LOGL(LOG_SSENGINE, " RDWR \n");
285 return O_RDWR | O_CREAT;
287 //LOGL(LOG_SSENGINE, " Unknown \n");
293 SS_OpenFile(const char *strPath, E_RW_TYPE wFlag, long *pwHandle)
296 char path[MAX_PATH] = { '\0' };
298 SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
300 mode = SS_get_mode(wFlag);
301 //LOGL(LOG_SSENGINE, "Path:%s wFlag:%d Mode:%d\n", path, wFlag, mode);
303 if (mode & O_CREAT) {
304 //LOGL(LOG_SSENGINE, " open() S_IRWXU\n");
305 *pwHandle = open(path, mode, S_IRWXU);
307 //LOGL(LOG_SSENGINE, " open() %d\n", mode);
308 *pwHandle = open(path, mode);
310 if (*pwHandle == -1) {
312 LOGE(" First open() with error %d\n", errno);
313 if (wFlag == ONLY_R) {
314 LOGE(" error in ONLY_R return E_SS_OPENFILE_ONLYR\n");
315 return E_SS_OPENFILE_ONLYR;
318 //if we need to open the file for write or read/write then we need to create the folder (in case it does not exist)
319 if ((wFlag != ONLY_R) && (errno == ENOENT)) {
320 char dir[MAX_PATH] = { '\0' };
321 char dirShort[MAX_PATH] = { '\0' };
323 //copy the full file path to directory path variable
324 while (path[i] != '\0') {
328 LOGL(LOG_SSENGINE, " copy dir[]=%s\n", dir);
329 //search for the last '/' char
330 while (dir[i--] != '/') ;
333 SS_char_to_unicode((const char *)dir,
334 (char *)dirShort, MAX_PATH - 1);
336 if (SS_CreateFolder(dirShort)) {
337 LOGE(" Fail create folder, Leave SS_OpenFile\n");
338 return E_SS_OPENFILE_WRITE;
341 *pwHandle = open(path, mode);
342 if (*pwHandle == -1) {
344 LOGE(" After successful creating folder, fail open() with error %d\n", errno);
345 return E_SS_OPENFILE_WRITE;
348 LOG(" fail open() *pwHandle:%ld\n", *pwHandle);
349 return E_SS_OPENFILE_WRITE;
353 //LOGL(LOG_SSENGINE, " Successful open() *pwHandle:%ld\n", *pwHandle);
358 long SS_CloseFile(long wHandle)
361 LOGL(LOG_SSENGINE, "wHandle = %ld\n", wHandle);
364 ret = fsync(wHandle);
366 LOG(" fsync Failed with return value: %d\n", ret);
367 return E_SS_WRITE_ERROR;
369 LOG(" fsync after write: %d\n", ret);
370 ret = close(wHandle);
376 return E_SS_CLOSEFILE_ERROR;
380 SS_WriteFile(long wHandle,
381 SS_UINT32 dwPosition,
382 unsigned char *pbBuffer, SS_UINT32 dwSize)
386 LOGL(LOG_SSENGINE, "Handle:%ld , Pos:%u , Size: %u\n", wHandle,
389 ret = lseek(wHandle, dwPosition, SEEK_SET);
391 LOGE(" lseek failed with return value: %d\n", ret);
392 LOGL(LOG_SSENGINE, "lseek errno=%d\n", errno);
393 return E_SS_WRITE_ERROR;
396 ret = write(wHandle, pbBuffer, dwSize);
397 if (ret < 0 || ret != dwSize) {
398 LOGE(" Failed with return value: %d\n", ret);
399 LOGL(LOG_SSENGINE, "ret=%d, dwSize=%u write errno=%d\n",
400 ret, (unsigned int)dwSize, errno);
401 return E_SS_WRITE_ERROR;
403 LOGL(LOG_SSENGINE, "leave Bytes Write: %d\n", ret);
408 long SS_MoveFile(const char *strFromPath, const char *strToPath)
412 char path1[MAX_PATH] = { '\0' };
413 char path2[MAX_PATH] = { '\0' };
415 if (!strFromPath || !strToPath)
416 return -1; //should never happen
418 SS_unicode_to_char(strFromPath, (char *)path1, MAX_PATH - 1);
419 SS_unicode_to_char(strToPath, (char *)path2, MAX_PATH - 1);
421 LOGL(LOG_INFO, "entered path1:%s | path2:%s\n", path1, path2);
422 ret = stat(path1, &sbuf);
424 LOGE("stat failed with return value: %d errno: %d\n", ret, errno);
427 ret = rename(path1, path2);
429 LOGL(LOG_INFO, "rename fail with code [%d], try to create dir if errno is 2\n", errno);
431 char * file_name = strrchr(path2, '/');
433 SS_create_dir(path2, 0755);
435 ret = rename(path1, path2);
437 LOGE("Move failed, error code [%d]\n", errno);
438 return E_SS_WRITE_ERROR;
440 } else if (errno == 18) { //EXDEV 18 /* Cross-device link */
441 //Moving file across partitions if mount point is different (Extremely rare)
442 ret = (int)SS_CopyFile(path1, path2);
443 if (ret != S_SS_SUCCESS) {
444 LOGE("failed to copy file [%s] result [%d]\n", path1, ret);
445 return E_SS_WRITE_ERROR;
449 LOGE("failed to unlink [%s] code [%d]\n", path1, errno);
450 return E_SS_WRITE_ERROR;
453 LOGE("Move failed, error code [%d]\n", errno);
454 return E_SS_WRITE_ERROR;
457 LOGL(LOG_INFO, "leaved path1:%s | path2:%s\n", path1, path2);
462 SS_ReadFile(long wHandle,
463 SS_UINT32 dwPosition,
464 unsigned char *pbBuffer, SS_UINT32 dwSize)
469 LOG(" %s: Handle:%ld , Pos:%u , Size: %u", __func__, wHandle,
472 ret = lseek(wHandle, dwPosition, SEEK_SET);
474 LOGE("Handle:%ld , Pos:%u , Size: %u\n", wHandle, dwPosition,
476 LOGE("lseek failed with return value: %d\n", ret);
477 return E_SS_READ_ERROR;
479 ret = read(wHandle, pbBuffer, dwSize);
481 LOGE("Handle:%ld , Pos:%u , Size: %u\n", wHandle, dwPosition,
483 LOGE("read failed with return value: %d\n", ret);
484 return E_SS_READ_ERROR;
487 if (ret != dwSize && ((ret + dwPosition) != (unsigned long)SS_GetFileSize(wHandle)))
488 return E_SS_READ_ERROR;
490 pbBuffer[ret] = '\0';
492 LOGL(LOG_DEBUG, "Bytes Read: %d\n", ret);
497 long SS_GetFileSize(long wHandle)
502 ret = lseek(wHandle, 0, SEEK_END);
505 LOGE(" lseek errno: %d\n", errno);
506 return E_SS_READFILE_SIZE;
508 LOGL(LOG_SSENGINE, "handle=%d Returning Size = %ld(0x%x)\n",
509 (int)wHandle, (long int)ret, ret);
514 long SS_Unlink(char *pLinkName)
517 char path[MAX_PATH] = { '\0' };
518 //enumFileType fileType = FT_REGULAR_FILE;
521 SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
524 if (ret < 0 && errno != ENOENT) {
525 LOGE("unlink failed with return value: %d\n", ret);
528 LOGL(LOG_SSENGINE, "unlink with return value: %d\n", ret);
534 SS_VerifyLinkReference(char *pLinkName, char *pReferenceFileName)
537 char path[MAX_PATH] = { '\0' };
538 char linkedpath[MAX_PATH] = { '\0' };
539 char refpath[MAX_PATH] = { '\0' };
542 SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
543 SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath, MAX_PATH - 1);
545 ret = readlink(path, linkedpath, MAX_PATH);
547 LOGE("readlink failed with return value: %d\n", ret);
551 if ((memcmp(&linkedpath, &refpath, ret)) != 0) {
552 LOGE("not same linked path\n");
555 LOGL(LOG_SSENGINE, "same linked path\n");
561 SS_Link(void *pbUserData, char *pLinkName, char *pReferenceFileName)
564 char sympath[MAX_PATH] = { '\0' };
565 char refpath[MAX_PATH] = { '\0' };
566 //enumFileType fileType = FT_SYMBOLIC_LINK;
569 SS_unicode_to_char((const char *)pLinkName, (char *)sympath, MAX_PATH - 1);
570 SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath, MAX_PATH - 1);
572 ret = symlink(refpath, sympath);
574 LOGE(" symlink failed with return value: %d, errno: %d\n", ret, errno);
576 if (errno == EEXIST) {
577 ret = lstat(sympath, &sbuf);
578 LOGL(LOG_SSENGINE, "symlink LSTAT with return value: %d\n", ret);
580 if (S_ISREG(sbuf.st_mode)) {
581 LOGL(LOG_SSENGINE, " stat->st_mode = regular file, To be deleted and create a LINK \n");
582 SS_DeleteFile(sympath);
583 SS_Link(pbUserData, pLinkName, pReferenceFileName);
586 if (SS_VerifyLinkReference(pLinkName
587 , pReferenceFileName) == S_SS_SUCCESS) {
592 } else if (errno == ENOENT) {//to handle cases where new symlink points to a new symlink yet to be created
598 //LOGL(LOG_SSENGINE, "symlink with return value: %d\n", ret);
604 SS_HardLink(char *hardLinkName, char *referenceName)
607 char hardpath[MAX_PATH] = { '\0' };
608 char refpath[MAX_PATH] = { '\0' };
610 SS_unicode_to_char((const char *)hardLinkName, (char *)hardpath, MAX_PATH - 1);
611 SS_unicode_to_char((const char *)referenceName, (char *)refpath, MAX_PATH - 1);
613 ret = link(refpath, hardpath);
615 LOGE("Linking failed for hardlink %s with errno: %d\n", hardpath, errno);
621 long SS_GetFileType(char *pLinkName, enumFileType * fileType)
624 char path[MAX_PATH] = { '\0' };
627 //LOGL(LOG_SSENGINE, "\n");
628 SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
630 ret = lstat(path, &sbuf);
632 ret = stat(path, &sbuf);
634 LOGE("stat failed with return value: %d errno: %d\n",
636 *fileType = FT_MISSING;
640 //LOGL(LOG_SSENGINE, " sbuf.st_mode: %d\n", sbuf.st_mode);
641 //LOGL(LOG_SSENGINE, " S_ISREG(sbuf.st_mode): %d\n", S_ISREG(sbuf.st_mode));
642 //LOGL(LOG_SSENGINE, " S_ISLNK(sbuf.st_mode): %d\n", S_ISLNK(sbuf.st_mode));
644 if (S_ISLNK(sbuf.st_mode)) {
645 //LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
646 *fileType = FT_SYMBOLIC_LINK;
650 if (S_ISREG(sbuf.st_mode)) {
651 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
652 *fileType = FT_REGULAR_FILE;
656 if (S_ISDIR(sbuf.st_mode)) {
657 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
658 *fileType = FT_FOLDER;
661 LOGE("failed to lstat, err : %d\n", ret);
665 static inline char *SS_get_xattr_name(enum smack_label_type type)
668 case SMACK_LABEL_ACCESS:
669 return "security.SMACK64";
670 case SMACK_LABEL_EXEC:
671 return "security.SMACK64EXEC";
672 case SMACK_LABEL_MMAP:
673 return "security.SMACK64MMAP";
674 case SMACK_LABEL_TRANSMUTE:
675 return "security.SMACK64TRANSMUTE";
676 case SMACK_LABEL_IPIN:
677 return "security.SMACK64IPIN";
678 case SMACK_LABEL_IPOUT:
679 return "security.SMACK64IPOUT";
681 /* Should not reach this point */
686 int SS_smack_lsetlabel(const char *path, const char *label, enum smack_label_type type)
689 LOGE("Path is NULL\n");
693 char *xattr_name = SS_get_xattr_name(type);
694 if (xattr_name == NULL) {
695 LOGE("Failed get xattr name\n");
699 /* Check validity of labels for LABEL_TRANSMUTE */
700 if (type == SMACK_LABEL_TRANSMUTE && label != NULL) {
701 if (!strncmp(label, "0", strlen("0"))) {
703 } else if (!strncmp(label, "1", strlen("0"))) {
710 if (label == NULL || label[0] == '\0') {
711 return lremovexattr(path, xattr_name);
713 int len = strnlen(label, SMACK_LABEL_LEN + 1);
714 if (len > SMACK_LABEL_LEN) {
717 return lsetxattr(path, xattr_name, label, len, 0);
722 *******************************************************************************
723 * Set file attributes.<p>
725 * The file attributes token (\a ui8pAttribs) is defined at generation time.
726 * If attributes are not defined explicitly, they are given the following,
727 * OS-dependent values:
728 * \li Windows: _foo_ro_ for R/O files, _foo_rw_ for R/W files
729 * \li Linux: _foo_oooooo:xxxx:yyyy indicating the file mode, uid, and gid
730 * (uid and gid use capitalized hex digits as required)
732 * \param pbUserData Optional opaque data-structure to pass to IPL
734 * \param ui16pFilePath File path
735 * \param ui32AttribSize Size of \a ui8pAttribs
736 * \param ui8pAttribs Attributes to set
738 * \return S_SS_SUCCESS on success or < 0 on error
739 *******************************************************************************
742 long SS_SetFileAttributes(const char *ui16pFilePath,
743 const SS_UINT32 ui32AttribSize,
744 const unsigned char *ui8pAttribs)
746 static char tmpAttribs[512];
747 static char tmpSmackAttribs[512];
751 char *smack_value, *psmack;
753 gid_t setGroupID = 0;
754 mode_t setFileMode = 0;
755 const char attrDelim[2] = ":";
757 char setFilePath[MAX_PATH] = { '\0' };
760 char *smack_attr_pos = NULL;
769 if (NULL == ui16pFilePath) {
770 LOGL(LOG_SSENGINE, "ui16pFilePath NULL [error]\n");
771 return E_SS_BAD_PARAMS;
772 } else if (NULL == ui8pAttribs) {
773 LOGL(LOG_SSENGINE, "ui8pAttribs NULL [error]\n");
774 return E_SS_BAD_PARAMS;
775 } else if (0 == ui32AttribSize) {
776 LOGL(LOG_SSENGINE, "ui32AttribSize 0\n");
780 SS_unicode_to_char((const char *)ui16pFilePath, (char *)setFilePath, MAX_PATH - 1);
782 ret = lstat(setFilePath, &sbuf);
784 ret = stat(setFilePath, &sbuf);
786 LOGL(LOG_SSENGINE, " stat failed with return value: %d\n", ret);
789 if (S_ISLNK(sbuf.st_mode)) {
790 LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
791 // return S_RB_SUCCESS; // sybolic link should be set mode.
793 if (S_ISREG(sbuf.st_mode))
794 LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
795 if (S_ISDIR(sbuf.st_mode))
796 LOGL(LOG_SSENGINE, " stat->st_mode = directory\n");
799 LOGL(LOG_SSENGINE, "ui16pFilePath = %s\n", setFilePath);
800 LOGL(LOG_SSENGINE, "ui32AttribSize = %u\n", ui32AttribSize);
801 LOGL(LOG_SSENGINE, "ui8pAttribs = %s\n", ui8pAttribs);
804 memset(tmpAttribs, 0x0, sizeof(tmpAttribs));
805 memcpy(tmpAttribs, ui8pAttribs, (size_t) ui32AttribSize-1);
806 smack_attr_pos = tmpAttribs;
807 tp = strtok_r(tmpAttribs, attrDelim, &saveptr);
811 smack_attr_pos += strlen(tp);
813 setFileMode = strtol(tp, &endstr, 8);
814 tp = strtok_r(NULL, attrDelim, &saveptr);
818 smack_attr_pos += strlen(tp);
820 setUserID = (uid_t) strtol(tp, &endstr, 10);
821 tp = strtok_r(NULL, attrDelim, &saveptr);
825 smack_attr_pos += strlen(tp);
827 setGroupID = (gid_t) strtol(tp, &endstr, 10);
830 if (feature_support_capability) {
833 if (*smack_attr_pos != '\0') {
834 char *cap_mark = "capability=0x";
835 int cap_mark_len = strlen(cap_mark);
836 psmack = strstr(smack_attr_pos, cap_mark);
843 tp = strstr(psmack, ":");
844 smack_attr_pos = tp + 1;
845 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
846 memcpy(tmpSmackAttribs, psmack+cap_mark_len,
847 (int)tp - (int)psmack - cap_mark_len);
849 // convert hexadecimal into raw data
850 cap_hex_len = strlen(tmpSmackAttribs);
851 cap_len = cap_hex_len/2;
852 memset(cap_raw, 0x00, sizeof(cap_raw));
853 for (i = 0; i < cap_len; i++) {
854 ch1 = tmpSmackAttribs[i*2];
855 ch2 = tmpSmackAttribs[i*2+1];
856 if ((ch1 >= '0') && (ch1 <= '9')) raw1 = ch1 - '0';
857 else if ((ch1 >= 'a') && (ch1 <= 'f')) raw1 = ch1 - 'a' + 10;
858 else if ((ch1 >= 'A') && (ch1 <= 'F')) raw1 = ch1 - 'A' + 10;
860 if ((ch2 >= '0') && (ch2 <= '9')) raw2 = ch2 - '0';
861 else if ((ch2 >= 'a') && (ch2 <= 'f')) raw2 = ch2 - 'a' + 10;
862 else if ((ch2 >= 'A') && (ch2 <= 'F')) raw2 = ch2 - 'A' + 10;
865 cap_raw[i] = raw1*16 + raw2;
867 LOGL(LOG_SSENGINE, "[Cap] %s (cap_len=%d)\n", tmpSmackAttribs, cap_len);
874 if (*smack_attr_pos != '\0') {
875 char *acl_mark = "acl_access=0x";
876 int acl_mark_len = strlen(acl_mark);
877 psmack = strstr(smack_attr_pos, acl_mark);
884 tp = strstr(psmack, ":");
885 smack_attr_pos = tp + 1;
886 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
887 memcpy(tmpSmackAttribs, psmack+acl_mark_len,
888 (int)tp - (int)psmack - acl_mark_len);
890 // convert hexadecimal into raw data
891 acl_hex_len = strlen(tmpSmackAttribs);
892 acl_len = acl_hex_len/2;
893 memset(acl_raw, 0x00, sizeof(acl_raw));
894 for (i = 0; i < acl_len; i++) {
895 ch1 = tmpSmackAttribs[i*2];
896 ch2 = tmpSmackAttribs[i*2+1];
897 if ((ch1 >= '0') && (ch1 <= '9')) raw1 = ch1 - '0';
898 else if ((ch1 >= 'a') && (ch1 <= 'f')) raw1 = ch1 - 'a' + 10;
899 else if ((ch1 >= 'A') && (ch1 <= 'F')) raw1 = ch1 - 'A' + 10;
901 if ((ch2 >= '0') && (ch2 <= '9')) raw2 = ch2 - '0';
902 else if ((ch2 >= 'a') && (ch2 <= 'f')) raw2 = ch2 - 'a' + 10;
903 else if ((ch2 >= 'A') && (ch2 <= 'F')) raw2 = ch2 - 'A' + 10;
906 acl_raw[i] = raw1*16 + raw2;
908 LOG("[ACL] %s (acl_len=%d)\n", tmpSmackAttribs, acl_len);
915 // Get Smack value -> Set Smack value
916 if (*smack_attr_pos != '\0') {
917 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_ACCESS);
918 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_EXEC);
919 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_MMAP);
920 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_TRANSMUTE);
922 psmack = strstr(smack_attr_pos, "access=\"");
924 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
925 memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
926 smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
928 smack_value = strtok_r(NULL, "\"", &saveptr);
929 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_ACCESS] smack_value=%s\n", smack_value);
931 ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_ACCESS);
933 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
937 psmack = strstr(smack_attr_pos, "execute=\"");
939 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
940 memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
941 smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
943 smack_value = strtok_r(NULL, "\"", &saveptr);
944 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_EXEC] smack_value=%s\n", smack_value);
946 ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_EXEC);
948 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
952 psmack = strstr(smack_attr_pos, "mmap=\"");
954 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
955 memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
956 smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
958 smack_value = strtok_r(NULL, "\"", &saveptr);
959 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_MMAP] smack_value=%s\n", smack_value);
961 ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_MMAP);
963 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
967 psmack = strstr(smack_attr_pos, "transmute=\"");
969 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
970 memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
971 smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
973 smack_value = strtok_r(NULL, "\"", &saveptr);
974 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_TRANSMUTE] smack_value=%s\n", smack_value);
976 if (strcasecmp(smack_value, "TRUE") == 0)
977 ret = SS_smack_lsetlabel(setFilePath, "1", SMACK_LABEL_TRANSMUTE);
979 ret = SS_smack_lsetlabel(setFilePath, "0", SMACK_LABEL_TRANSMUTE);
981 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
987 // Set UserID,GroupID
988 if (lchown(setFilePath, setUserID, setGroupID)) {
990 LOGL(LOG_SSENGINE, "%s chown error\n", __func__);
991 LOGL(LOG_SSENGINE, "%s setUserID = %d\n", __func__, setUserID);
992 LOGL(LOG_SSENGINE, "%s setGroupID = %d\n", __func__, setGroupID);
993 LOGL(LOG_SSENGINE, "%s chown errno = %d\n", __func__, errno);
999 // mode is always 0777 at symlink file. It doesn't need to call chmod().
1000 if (S_ISLNK(sbuf.st_mode)) {
1001 LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
1002 return S_SS_SUCCESS;
1005 if (chmod(setFilePath, setFileMode)) {
1006 LOGL(LOG_SSENGINE, "%s chmod error\n", __func__);
1007 return E_SS_FAILURE;
1010 if (feature_support_capability) {
1013 if (setxattr(setFilePath, "security.capability", (void*)cap_raw, cap_len, 0) < 0) {
1014 strerror_r(errno, buf, sizeof(buf));
1015 LOGL(LOG_SSENGINE, "cap setxattr() failed: %s\n", buf);
1020 if (setxattr(setFilePath, "system.posix_acl_access", (void*)acl_raw, acl_len, 0) < 0) {
1021 strerror_r(errno, buf, sizeof(buf));
1022 LOGL(LOG_SSENGINE, "Acl setxattr() failed: %s\n", buf);
1024 //LOG("Acl setxattr() :")asfd
1028 //LOGL(LOG_SSENGINE, "%s SUCCESS\n", __func__);
1030 return S_SS_SUCCESS;
1035 SS_GetAvailableFreeSpace(const char *partition_name,
1036 SS_UINT32 *available_flash_size)
1039 char path[MAX_PATH] = { '\0' };
1041 SS_unicode_to_char(partition_name, (char *)path, MAX_PATH - 1);
1042 //LOGL(LOG_SSENGINE, "Enter %s path=%s\n", __func__, path);
1045 //LOGL(LOG_SSENGINE, "path=%s\n", path);
1046 result = statfs(path, &vfs);
1048 LOGE("failed to fstatfs, err : %d errno: %d\n", result, errno);
1052 *available_flash_size = ((long long)vfs.f_bsize * (long long)vfs.f_bavail >= (long long)SIZE_4GB) ? SIZE_4GB : vfs.f_bsize * vfs.f_bavail;
1053 if (*available_flash_size == 0) {
1054 *available_flash_size = 0x80000; //Same as Legecy RB
1055 LOGE("available_flash_size=%u(vfs.f_bsize=%d vfs.f_bavail=%d\n",
1056 (unsigned int)*available_flash_size, (int)vfs.f_bsize, (int)vfs.f_bavail);
1057 return 0; // Same as Legecy RB
1062 #ifdef HEAP_PROFILING
1066 /*******[ Multiprocess API sample implementation ]******/
1067 void *SS_Malloc(SS_UINT32 size)
1069 void *p = malloc(size);
1073 #ifdef HEAP_PROFILING
1075 if (cur_mem > max_mem) {
1077 LOGL(LOG_SSENGINE, "New chunk [%d] assigned making heap [%d]\n", size, cur_mem);
1084 void SS_Free(void *pMemBlock)
1086 #ifdef HEAP_PROFILING
1087 cur_mem -= malloc_usable_size(pMemBlock);
1088 LOGL(LOG_SSENGINE, "Old chunk [%d] removed making heap [%d]\n", malloc_usable_size(pMemBlock), cur_mem);
1093 int SS_get_feature_support_capability(void)
1095 return feature_support_capability;
1098 void SS_set_feature_support_capability(int val)
1100 feature_support_capability = val;