Fix build warning
[platform/core/system/libtota.git] / ss_engine / SS_FSUpdate.c
1 /*
2  * tota-ua
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #define _XOPEN_SOURCE 600
20 #define _POSIX_C_SOURCE 200809L
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <sys/vfs.h>
27 #include <sys/types.h>
28 #include <stdarg.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <sys/wait.h>
33
34 #include <ftw.h>
35 #include <sys/xattr.h>
36 #include "SS_Common.h"
37
38 #include "fota_common.h"
39 #include "ua_types.h"
40
41 static int feature_support_capability;
42
43 enum smack_label_type {
44         SMACK_LABEL_ACCESS,
45         SMACK_LABEL_EXEC,
46         SMACK_LABEL_MMAP,
47         SMACK_LABEL_TRANSMUTE,
48         SMACK_LABEL_IPIN,
49         SMACK_LABEL_IPOUT,
50 };
51
52 #define SMACK_LABEL_LEN 255
53
54 /************************************************************
55  *                     common functions
56  ************************************************************/
57 void SS_create_dir(char *pathname, int mode)
58 {
59         char *p;
60         int r;
61
62         /* Strip trailing '/' */
63         if (pathname[strlen(pathname) - 1] == '/')
64                 pathname[strlen(pathname) - 1] = '\0';
65
66         /* Try creating the directory. */
67         r = mkdir(pathname, mode);
68
69         if (r != 0) {
70                 /* On failure, try creating parent directory. */
71                 p = strrchr(pathname, '/');
72                 if (p != NULL) {
73                         *p = '\0';
74                         SS_create_dir(pathname, 0755);
75                         *p = '/';
76                         r = mkdir(pathname, mode);
77                 }
78         }
79         if (r != 0) {
80                 if (r != EEXIST && r != -1)
81                         LOG("Could not create directory [%s] Error[%d]\n", pathname, r);
82         }
83 }
84
85
86 void SS_unicode_to_char(const char *src, char *dest, int size)
87 {
88         if (src == NULL)
89                 return;
90
91         strncpy(dest, src, size);
92 }
93
94 void SS_char_to_unicode(const char *src, char *dest, int size)
95 {
96         if (src == NULL)
97                 return;
98
99         strncpy(dest, src, size);
100 }
101
102 long SS_recursive_folder_creater(const char *path, const mode_t mode)
103 {
104         int ret = 0;
105         int offset = 0;
106         char temppath[MAX_PATH] = { '\0' };
107
108         LOGL(LOG_SSENGINE, "path: %s\n", path);
109
110         if ((offset = strlen(path)) == 0) // For counting back until the '/' delimiter
111                 return -1;      //if from some reason we got to the end return error!!!.
112
113         while (path[offset] != '/')     // get to the next '/' place
114                 offset--;
115
116         strncpy(temppath, path, offset);        // copy one depth below till and without the char '/'
117         LOGL(LOG_SSENGINE, " temppath: %s\n", temppath);
118         ret = mkdir(temppath, mode);
119         LOGL(LOG_SSENGINE, " mkdir result: %d errno: %d\n", ret, errno);
120
121         if (ret == 0 || ((ret == -1) && (errno == EEXIST))) {
122                 return 0;       //meaning the depth creation is success.
123         } else if ((ret == -1) && (errno == ENOENT)) {
124                 if ((ret = SS_recursive_folder_creater(temppath, mode)) == 0)
125                         ret = mkdir(temppath, mode);
126                 return ret;
127         } else {
128                 return -1;
129         }
130 }
131
132 long
133 SS_CopyFile(const char *strFromPath, const char *strToPath)
134 {
135         int fd1, fd2;
136         int readCount = 0, writeCount = 0;
137         char buf[1 << 15];      // copy 32KB wise
138         int ret = 0;
139
140         char path1[MAX_PATH] = { '\0' };
141         char path2[MAX_PATH] = { '\0' };
142
143         if (!strFromPath || !strToPath) {
144                 LOGE("NULL file name find. Abort.\n");
145                 return -1;
146         }
147
148         SS_unicode_to_char((const char *)strFromPath, (char *)path1, MAX_PATH - 1);
149         SS_unicode_to_char((const char *)strToPath, (char *)path2, MAX_PATH - 1);
150
151         //LOGL(LOG_SSENGINE, "%s -> %s \n", path1, path2);
152
153         fd1 = open(path1, O_RDONLY);
154         if (fd1 < 0)
155                 return E_SS_OPENFILE_ONLYR;
156         ret = SS_OpenFile(strToPath, ONLY_W, (long *)&fd2);
157         if (ret != S_SS_SUCCESS || fd2 < 0) {
158                 close(fd1);
159                 LOGE(" SS_OpenFile fail leaved path1:%s | path2:%s\n", path1, path1);
160                 return E_SS_WRITE_ERROR;
161         }
162
163         while ((readCount = read(fd1, buf, sizeof(buf))) > 0) {
164                 writeCount = write(fd2, buf, readCount);
165                 if (writeCount != readCount) {
166                         LOGE(" read %d, but write %d, abort.\n", readCount,
167                                         writeCount);
168                         ret = E_SS_WRITE_ERROR;
169                         break;
170                 }
171         }
172
173         close(fd1);
174         fsync(fd2);
175         close(fd2);
176         //LOGL(LOG_INFO, " leaved path1:%s | path2:%s\n", path1, path2);
177
178         return ret;
179 }
180
181 long SS_DeleteFile(const char *strPath)
182 {
183         char path[MAX_PATH] = { '\0' };
184         int ret = 0;
185
186         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
187         //LOGL(LOG_SSENGINE, "%s\n", path);
188         ret = unlink(path);
189         if (ret == 0)
190                 return S_SS_SUCCESS;
191
192         LOGE("failed to delete path [%s] unlink value: %d, errno: %d\n", path, ret, errno);
193         if (ret < 0 && errno == ENOENT)
194                 return S_SS_SUCCESS;
195         return E_SS_DELETEFILE;
196 }
197
198 int SS_unlink_cbf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
199 {
200         int rv = remove(fpath);//returns zero on success and -1 on failure
201
202         if (rv) {
203                 perror(fpath);
204                 LOGE("path : %s, remove value: %d, errno: %d\n", fpath, rv, errno);
205         }
206         return rv;
207 }
208 long SS_DeleteFolder(const char *strPath)
209 {
210         //runs till either tree is exhausted or when unlink_cbf returns non zero value.
211         return ((long)nftw(strPath, SS_unlink_cbf, 64, FTW_DEPTH | FTW_PHYS) == 0) ? S_SS_SUCCESS : E_SS_FAILURE;
212 }
213
214 long SS_DeleteFolderEmpty(const char *strPath)
215 {
216
217         int ret = 0;
218         char path[MAX_PATH] = { '\0' };
219
220         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
221         //LOGL(LOG_SSENGINE, "%s\n", path);
222         ret = rmdir(path);
223         if ((ret == 0)
224             || ((ret < 0) && ((errno == ENOENT) || (errno == ENOTEMPTY)))) {
225                 LOGL(LOG_SSENGINE, "rmdir value: %d, errno: %d\n", ret, errno);
226                 return S_SS_SUCCESS;
227         }
228         LOGE("rmdir value: %d, errno: %d\n", ret, errno);
229         return E_SS_FAILURE;
230 }
231
232 long SS_CreateFolder(const char *strPath)
233 {
234         mode_t mode = 0;
235         int ret = 0;
236         char path[MAX_PATH] = { '\0' };
237
238         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
239         mode = S_IRUSR /*Read by owner */  |
240                 S_IWUSR /*Write by owner */  |
241                 S_IXUSR /*Execute by owner */  |
242                 S_IRGRP /*Read by group */  |
243                 S_IWGRP /*Write by group */  |
244                 S_IXGRP /*Execute by group */  |
245                 S_IROTH /*Read by others */  |
246                 S_IWOTH /*Write by others */  |
247                 S_IXOTH /*Execute by others */ ;
248
249         LOGL(LOG_SSENGINE, "%s, mode:0x%x\n", path, mode);
250
251         ret = mkdir(path, mode);
252
253         if (ret == 0 || ((ret == -1) && (errno == EEXIST))) {
254                 return S_SS_SUCCESS;
255         } else if ((ret == -1) && (errno == ENOENT)) {  //maybe multi directory problem
256                 //do//Recursive Function
257                 //{
258                 ret = SS_recursive_folder_creater(path, mode);
259                 if (ret == S_SS_SUCCESS) {
260                         ret = mkdir(path, mode);        //After creating all the depth Directories we try to create the Original one again.
261                         if (ret == 0)
262                                 return S_SS_SUCCESS;
263                         else
264                                 return E_SS_FAILURE;
265                 } else {
266                         return E_SS_FAILURE;
267                 }
268                 //}
269                 //while(ret != 0);
270
271         } else {
272                 return E_SS_FAILURE;
273         }
274 }
275
276 mode_t SS_get_mode(E_RW_TYPE wFlag)
277 {
278         switch (wFlag) {
279         case ONLY_R:
280                 //LOGL(LOG_SSENGINE, " RDONLY \n");
281                 return O_RDONLY;
282         case ONLY_W:
283                 //LOGL(LOG_SSENGINE, " WRONLY \n");
284                 return O_WRONLY | O_CREAT;
285         case BOTH_RW:
286                 //LOGL(LOG_SSENGINE, " RDWR \n");
287                 return O_RDWR | O_CREAT;
288         default:
289                 //LOGL(LOG_SSENGINE, " Unknown \n");
290                 return 0;
291         }
292 }
293
294 long
295 SS_OpenFile(const char *strPath, E_RW_TYPE wFlag, long *pwHandle)
296 {
297         mode_t mode;
298         char path[MAX_PATH] = { '\0' };
299
300         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
301
302         mode = SS_get_mode(wFlag);
303         //LOGL(LOG_SSENGINE, "Path:%s  wFlag:%d  Mode:%d\n", path, wFlag, mode);
304
305         if (mode & O_CREAT) {
306                 //LOGL(LOG_SSENGINE, " open() S_IRWXU\n");
307                 *pwHandle = open(path, mode, S_IRWXU);
308         } else {
309                 //LOGL(LOG_SSENGINE, " open() %d\n", mode);
310                 *pwHandle = open(path, mode);
311         }
312         if (*pwHandle == -1) {
313                 *pwHandle = 0;
314                 LOGE(" First open() with error %d\n", errno);
315                 if (wFlag == ONLY_R) {
316                         LOGE(" error in ONLY_R return E_SS_OPENFILE_ONLYR\n");
317                         return E_SS_OPENFILE_ONLYR;
318                 }
319
320                 //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)
321                 if ((wFlag != ONLY_R) && (errno == ENOENT)) {
322                         char dir[MAX_PATH] = { '\0' };
323                         char dirShort[MAX_PATH] = { '\0' };
324                         int i = 0;
325                         //copy the full file path to directory path variable
326                         while (path[i] != '\0') {
327                                 dir[i] = path[i];
328                                 i++;
329                         }
330                         LOGL(LOG_SSENGINE, " copy dir[]=%s\n", dir);
331                         //search for the last '/' char
332                         while (dir[i--] != '/') ;
333                         dir[i + 1] = '\0';
334
335                         SS_char_to_unicode((const char *)dir,
336                                         (char *)dirShort, MAX_PATH - 1);
337
338                         if (SS_CreateFolder(dirShort)) {
339                                 LOGE(" Fail create folder, Leave SS_OpenFile\n");
340                                 return E_SS_OPENFILE_WRITE;
341                         }
342
343                         *pwHandle = open(path, mode);
344                         if (*pwHandle == -1) {
345                                 *pwHandle = 0;
346                                 LOGE(" After successful creating folder, fail open() with error %d\n", errno);
347                                 return E_SS_OPENFILE_WRITE;
348                         }
349                 } else {
350                         LOG(" fail open() *pwHandle:%ld\n", *pwHandle);
351                         return E_SS_OPENFILE_WRITE;
352                 }
353         }
354
355         //LOGL(LOG_SSENGINE, " Successful open() *pwHandle:%ld\n", *pwHandle);
356
357         return S_SS_SUCCESS;
358 }
359
360 long SS_ResizeFile(long wHandle, SS_UINT32 dwSize)
361 {
362         int ret = 0;
363
364         LOGL(LOG_SSENGINE, "handle %ld, dwSize %d\n", wHandle, errno);
365
366         if (wHandle)
367                 ret = ftruncate(wHandle, dwSize);
368         else
369                 ret = E_SS_RESIZEFILE;
370
371         LOGL(LOG_SSENGINE, "ret %d handle %ld %d\n", ret, wHandle, errno);
372
373         return ret;
374 }
375
376 long SS_CloseFile(long wHandle)
377 {
378         int ret = 0;
379         LOGL(LOG_SSENGINE, "wHandle = %ld\n", wHandle);
380
381         if (wHandle) {
382                 ret = fsync(wHandle);
383                 if (ret < 0) {
384                         LOG(" fsync Failed with return value: %d\n", ret);
385                         return E_SS_WRITE_ERROR;
386                 }
387                 LOG(" fsync after write: %d\n", ret);
388                 ret = close(wHandle);
389         }
390
391         if (ret == 0)
392                 return S_SS_SUCCESS;
393
394         return E_SS_CLOSEFILE_ERROR;
395 }
396
397 long
398 SS_WriteFile(long wHandle,
399                 SS_UINT32 dwPosition,
400                 unsigned char *pbBuffer, SS_UINT32 dwSize)
401 {
402         int ret = 0;
403
404         LOGL(LOG_SSENGINE, "Handle:%ld , Pos:%u , Size: %u\n", wHandle,
405                         dwPosition, dwSize);
406
407         ret = lseek(wHandle, dwPosition, SEEK_SET);
408         if (ret < 0) {
409                 LOGE(" lseek failed with return value: %d\n", ret);
410                 LOGL(LOG_SSENGINE, "lseek errno=%d\n", errno);
411                 return E_SS_WRITE_ERROR;
412         }
413
414         ret = write(wHandle, pbBuffer, dwSize);
415         if (ret < 0 || ret != dwSize) {
416                 LOGE(" Failed with return value: %d\n", ret);
417                 LOGL(LOG_SSENGINE, "ret=%d, dwSize=%u write errno=%d\n",
418                         ret, (unsigned int)dwSize, errno);
419                 return E_SS_WRITE_ERROR;
420         }
421         LOGL(LOG_SSENGINE, "leave Bytes Write: %d\n", ret);
422
423         return S_SS_SUCCESS;
424 }
425
426 long SS_MoveFile(const char *strFromPath, const char *strToPath)
427 {
428         int ret = 0;
429         struct stat sbuf;
430         char path1[MAX_PATH] = { '\0' };
431         char path2[MAX_PATH] = { '\0' };
432
433         if (!strFromPath || !strToPath)
434                 return -1;      //should never happen
435
436         SS_unicode_to_char(strFromPath, (char *)path1, MAX_PATH - 1);
437         SS_unicode_to_char(strToPath, (char *)path2, MAX_PATH - 1);
438
439         LOGL(LOG_INFO, "entered path1:%s | path2:%s\n", path1, path2);
440         ret = stat(path1, &sbuf);
441         if (ret < 0) {
442                         LOGE("stat failed with return value: %d errno: %d\n",  ret, errno);
443                         return E_SS_FAILURE;
444         }
445         ret = rename(path1, path2);
446         if (ret < 0) {
447                 LOGL(LOG_INFO, "rename fail with code [%d], try to create dir if errno is 2\n", errno);
448                 if (errno == 2) {
449                         char * file_name = strrchr(path2, '/');
450                         *file_name = '\0';
451                         SS_create_dir(path2, 0755);
452                         *file_name = '/';
453                         ret = rename(path1, path2);
454                         if (ret < 0) {
455                                 LOGE("Move failed, error code [%d]", errno);
456                                 return E_SS_WRITE_ERROR;
457                         }
458                 } else if (errno == 18) { //EXDEV 18  /* Cross-device link */
459                         //Moving file across partitions if mount point is different (Extremely rare)
460                         ret = (int)SS_CopyFile(path1, path2);
461                         if (ret != S_SS_SUCCESS) {
462                                 LOGE("failed to copy file [%s] result [%d]\n", path1, ret);
463                                 return E_SS_WRITE_ERROR;
464                         }
465                         ret = unlink(path1);
466                         if (ret != 0) {
467                                 LOGE("failed to unlink [%s] code [%d]\n", path1, errno);
468                                 return E_SS_WRITE_ERROR;
469                         }
470                 } else {
471                         LOGE("Move failed, error code [%d]", errno);
472                         return E_SS_WRITE_ERROR;
473                 }
474         }
475         LOGL(LOG_INFO, "leaved path1:%s | path2:%s\n", path1, path2);
476         return S_SS_SUCCESS;
477 }
478 long SS_SyncFile(long wHandle)
479 {
480         return (-1 == fsync(wHandle)) ? E_SS_FAILURE : S_SS_SUCCESS;
481 }
482
483 long
484 SS_ReadFile(long wHandle,
485             SS_UINT32 dwPosition,
486             unsigned char *pbBuffer, SS_UINT32 dwSize)
487 {
488         int ret = 0;
489
490 #if 0
491         LOG(" %s: Handle:%ld , Pos:%u , Size: %u", __func__, wHandle,
492                dwPosition, dwSize);
493 #endif
494         ret = lseek(wHandle, dwPosition, SEEK_SET);
495         if (ret < 0) {
496                 LOGE("Handle:%ld , Pos:%u , Size: %u", wHandle, dwPosition,
497                      dwSize);
498                 LOGE("lseek failed with return value: %d\n", ret);
499                 return E_SS_READ_ERROR;
500         }
501         ret = read(wHandle, pbBuffer, dwSize);
502         if (ret < 0) {
503                 LOGE("Handle:%ld , Pos:%u , Size: %u", wHandle, dwPosition,
504                      dwSize);
505                 LOGE("read failed with return value: %d\n", ret);
506                 return E_SS_READ_ERROR;
507         }
508
509         if (ret != dwSize && ((ret + dwPosition) != (unsigned long)SS_GetFileSize(wHandle)))
510                 return E_SS_READ_ERROR;
511
512 #if 0
513         LOGL(LOG_DEBUG, "Bytes Read: %d\n", ret);
514 #endif
515         return S_SS_SUCCESS;
516 }
517
518 long SS_GetFileSize(long wHandle)
519 {
520         int ret = 0;
521
522
523         ret = lseek(wHandle, 0, SEEK_END);
524
525         if (ret == -1) {
526                 LOGE(" lseek errno: %d\n", errno);
527                 return E_SS_READFILE_SIZE;
528         }
529         LOGL(LOG_SSENGINE, "handle=%d  Returning Size = %ld(0x%x)\n",
530                 (int)wHandle, (long int)ret, ret);
531
532         return ret;
533 }
534
535 long SS_Unlink(char *pLinkName)
536 {
537         int ret = 0;
538         char path[MAX_PATH] = { '\0' };
539         //enumFileType fileType = FT_REGULAR_FILE;
540
541
542         SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
543
544         ret = unlink(path);
545         if (ret < 0 && errno != ENOENT) {
546                 LOGE("unlink failed with return value: %d\n", ret);
547                 return E_SS_FAILURE;
548         }
549         LOGL(LOG_SSENGINE, "unlink with return value: %d\n", ret);
550
551         return S_SS_SUCCESS;
552 }
553
554 long
555 SS_VerifyLinkReference(char *pLinkName, char *pReferenceFileName)
556 {
557         int ret = 0;
558         char path[MAX_PATH] = { '\0' };
559         char linkedpath[MAX_PATH] = { '\0' };
560         char refpath[MAX_PATH] = { '\0' };
561
562
563         SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
564         SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath, MAX_PATH - 1);
565
566         ret = readlink(path, linkedpath, MAX_PATH);
567         if (ret < 0) {
568                 LOGE("readlink failed with return value: %d\n", ret);
569                 return E_SS_FAILURE;
570         }
571
572         if ((memcmp(&linkedpath, &refpath, ret)) != 0) {
573                 LOGE("not same linked path\n");
574                 return E_SS_FAILURE;
575         }
576         LOGL(LOG_SSENGINE, "same linked path\n");
577
578         return S_SS_SUCCESS;
579 }
580
581 long
582 SS_Link(void *pbUserData, char *pLinkName, char *pReferenceFileName)
583 {
584         int ret = 0;
585         char sympath[MAX_PATH] = { '\0' };
586         char refpath[MAX_PATH] = { '\0' };
587         //enumFileType fileType = FT_SYMBOLIC_LINK;
588         struct stat sbuf;
589
590         SS_unicode_to_char((const char *)pLinkName, (char *)sympath, MAX_PATH - 1);
591         SS_unicode_to_char((const char *)pReferenceFileName, (char *)refpath, MAX_PATH - 1);
592
593         ret = symlink(refpath, sympath);
594         if (ret != 0) {
595                 LOGE(" symlink failed with return value: %d, errno: %d\n", ret, errno);
596
597                 if (errno == EEXIST) {
598                         ret = lstat(sympath, &sbuf);
599                         LOGL(LOG_SSENGINE, "symlink LSTAT with return value: %d\n", ret);
600                         if (ret >= 0) {
601                                         if (S_ISREG(sbuf.st_mode)) {
602                                         LOGL(LOG_SSENGINE, " stat->st_mode = regular file, To be deleted and create a LINK \n");
603                                         SS_DeleteFile(sympath);
604                                         SS_Link(pbUserData, pLinkName, pReferenceFileName);
605                                         }
606                                 }
607                         if (SS_VerifyLinkReference(pLinkName
608                                 , pReferenceFileName) == S_SS_SUCCESS) {
609                                 return S_SS_SUCCESS;
610                         } else {
611                                 return E_SS_FAILURE;
612                         }
613                 } else if (errno == ENOENT) {//to handle cases where new symlink points to a new symlink yet to be created
614                         return errno;
615                 } else {
616                         return E_SS_FAILURE;
617                 }
618         }
619         //LOGL(LOG_SSENGINE, "symlink with return value: %d\n", ret);
620
621         return S_SS_SUCCESS;
622 }
623
624 long SS_GetFileType(char *pLinkName, enumFileType * fileType)
625 {
626         int ret = 0;
627         char path[MAX_PATH] = { '\0' };
628         struct stat sbuf;
629
630         //LOGL(LOG_SSENGINE, "\n");
631         SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
632
633         ret = lstat(path, &sbuf);
634         if (ret < 0) {
635                 ret = stat(path, &sbuf);
636                 if (ret < 0) {
637                         LOGE("stat failed with return value: %d errno: %d\n",
638                              ret, errno);
639                         *fileType = FT_MISSING;
640                         return S_SS_SUCCESS;
641                 }
642         }
643         //LOGL(LOG_SSENGINE, " sbuf.st_mode: %d\n", sbuf.st_mode);
644         //LOGL(LOG_SSENGINE, " S_ISREG(sbuf.st_mode): %d\n", S_ISREG(sbuf.st_mode));
645         //LOGL(LOG_SSENGINE, " S_ISLNK(sbuf.st_mode): %d\n",  S_ISLNK(sbuf.st_mode));
646
647         if (S_ISLNK(sbuf.st_mode)) {
648                 //LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
649                 *fileType = FT_SYMBOLIC_LINK;
650                 return S_SS_SUCCESS;
651         }
652
653         if (S_ISREG(sbuf.st_mode)) {
654                 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
655                 *fileType = FT_REGULAR_FILE;
656                 return S_SS_SUCCESS;
657         }
658
659         if (S_ISDIR(sbuf.st_mode)) {
660                 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
661                 *fileType = FT_FOLDER;
662                 return S_SS_SUCCESS;
663         }
664         LOGE("failed to lstat, err : %d\n", ret);
665         return E_SS_FAILURE;
666 }
667
668 char SS_a2ch(int value)
669 {
670         char set_value = 0;
671
672         LOGL(LOG_SSENGINE, "%d\n", value);
673
674         switch (value) {
675         case '1':
676                 set_value = 0x01;
677                 break;
678         case '2':
679                 set_value = 0x02;
680                 break;
681         case '3':
682                 set_value = 0x03;
683                 break;
684         case '4':
685                 set_value = 0x04;
686                 break;
687         case '5':
688                 set_value = 0x05;
689                 break;
690         case '6':
691                 set_value = 0x06;
692                 break;
693         case '7':
694                 set_value = 0x07;
695                 break;
696         case '8':
697                 set_value = 0x08;
698                 break;
699         case '9':
700                 set_value = 0x09;
701                 break;
702         case '0':
703                 set_value = 0x00;
704                 break;
705         default:
706                 LOGL(LOG_SSENGINE, "Wrong attribute value: %d\n", value);
707
708         }
709         LOGL(LOG_SSENGINE, "SS_a2ch : %c\n", set_value);
710
711         return set_value;
712 }
713
714 void SS_chtoa(int value, char *str)
715 {
716         char *pStr = str;
717
718         LOGL(LOG_SSENGINE, "%d\n", value);
719
720         switch (value) {
721         case 1:
722                 *pStr = '1';
723                 break;
724         case 2:
725                 *pStr = '2';
726                 break;
727         case 3:
728                 *pStr = '3';
729                 break;
730         case 4:
731                 *pStr = '4';
732                 break;
733         case 5:
734                 *pStr = '5';
735                 break;
736         case 6:
737                 *pStr = '6';
738                 break;
739         case 7:
740                 *pStr = '7';
741                 break;
742         case 8:
743                 *pStr = '8';
744                 break;
745         case 9:
746                 *pStr = '9';
747                 break;
748         case 0:
749                 *pStr = '0';
750                 break;
751         default:
752                 LOGL(LOG_SSENGINE, "Wrong attribute value: %d\n", value);
753         }
754 }
755
756 static inline char *SS_get_xattr_name(enum smack_label_type type)
757 {
758         switch (type) {
759         case SMACK_LABEL_ACCESS:
760                 return "security.SMACK64";
761         case SMACK_LABEL_EXEC:
762                 return "security.SMACK64EXEC";
763         case SMACK_LABEL_MMAP:
764                 return "security.SMACK64MMAP";
765         case SMACK_LABEL_TRANSMUTE:
766                 return "security.SMACK64TRANSMUTE";
767         case SMACK_LABEL_IPIN:
768                 return "security.SMACK64IPIN";
769         case SMACK_LABEL_IPOUT:
770                 return "security.SMACK64IPOUT";
771         default:
772                 /* Should not reach this point */
773                 return NULL;
774         }
775 }
776
777 int SS_smack_lsetlabel(const char *path, const char *label, enum smack_label_type type)
778 {
779         if (path == NULL) {
780                 LOGE("Path is NULL\n");
781                 return -1;
782         }
783
784         char *xattr_name = SS_get_xattr_name(type);
785         if (xattr_name == NULL) {
786                 LOGE("Failed get xattr name\n");
787                 return -1;
788         }
789
790         /* Check validity of labels for LABEL_TRANSMUTE */
791         if (type == SMACK_LABEL_TRANSMUTE && label != NULL) {
792                 if (!strncmp(label, "0", strlen("0"))) {
793                         label = NULL;
794                 } else if (!strncmp(label, "1", strlen("0"))) {
795                         label = "TRUE";
796                 } else {
797                         return -1;
798                 }
799         }
800
801         if (label == NULL || label[0] == '\0') {
802                 return lremovexattr(path, xattr_name);
803         } else {
804                 int len = strnlen(label, SMACK_LABEL_LEN + 1);
805                 if (len > SMACK_LABEL_LEN) {
806                         return -1;
807                 }
808                 return lsetxattr(path, xattr_name, label, len, 0);
809         }
810 }
811
812 /*!
813  *******************************************************************************
814  * Set file attributes.<p>
815  *
816  * The file attributes token (\a ui8pAttribs) is defined at generation time.
817  * If attributes are not defined explicitly, they are given the following,
818  * OS-dependent values:
819  * \li  Windows: _foo_ro_ for R/O files, _foo_rw_ for R/W files
820  * \li  Linux: _foo_oooooo:xxxx:yyyy indicating the file mode, uid, and gid
821  *              (uid and gid use capitalized hex digits as required)
822  *
823  * \param       pbUserData              Optional opaque data-structure to pass to IPL
824  *                                                      functions
825  * \param       ui16pFilePath   File path
826  * \param       ui32AttribSize  Size of \a ui8pAttribs
827  * \param       ui8pAttribs             Attributes to set
828  *
829  * \return      S_SS_SUCCESS on success or &lt; 0 on error
830  *******************************************************************************
831  */
832
833 long SS_SetFileAttributes(const char *ui16pFilePath,
834                           const SS_UINT32 ui32AttribSize,
835                           const unsigned char *ui8pAttribs)
836 {
837         static char tmpAttribs[512];
838         static char tmpSmackAttribs[512];
839         char *tp;
840         char *endstr;
841         char *saveptr;
842         char *smack_value, *psmack;
843         uid_t setUserID = 0;
844         gid_t setGroupID = 0;
845         mode_t setFileMode = 0;
846         const char attrDelim[2] = ":";
847
848         char setFilePath[MAX_PATH] = { '\0' };
849         struct stat sbuf;
850         int ret = 0;
851         char *smack_attr_pos = NULL;
852         int has_cap = 0;
853         char cap_raw[100];
854         int cap_len;
855         /*ACL */
856         int has_acl = 0;
857         char acl_raw[256];
858         int acl_len;
859
860         if (NULL == ui16pFilePath) {
861                 LOGL(LOG_SSENGINE, "ui16pFilePath NULL [error]\n");
862                 return E_SS_BAD_PARAMS;
863         } else if (NULL == ui8pAttribs) {
864                 LOGL(LOG_SSENGINE, "ui8pAttribs NULL [error]\n");
865                 return E_SS_BAD_PARAMS;
866         } else if (0 == ui32AttribSize) {
867                 LOGL(LOG_SSENGINE, "ui32AttribSize 0\n");
868                 return S_SS_SUCCESS;
869         }
870
871         SS_unicode_to_char((const char *)ui16pFilePath, (char *)setFilePath, MAX_PATH - 1);
872
873         ret = lstat(setFilePath, &sbuf);
874         if (ret < 0) {
875                 ret = stat(setFilePath, &sbuf);
876                 if (ret < 0) {
877                         LOGL(LOG_SSENGINE, " stat failed with return value: %d\n", ret);
878                         return E_SS_FAILURE;
879                 } else {
880                                 if (S_ISLNK(sbuf.st_mode)) {
881                                         LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
882 //        return S_RB_SUCCESS; // sybolic link should be set mode.
883                                 }
884                                 if (S_ISREG(sbuf.st_mode))
885                                         LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
886                                 if (S_ISDIR(sbuf.st_mode))
887                                         LOGL(LOG_SSENGINE, " stat->st_mode = directory\n");
888                 }
889
890                 LOGL(LOG_SSENGINE, "ui16pFilePath = %s\n", setFilePath);
891                 LOGL(LOG_SSENGINE, "ui32AttribSize = %u\n", ui32AttribSize);
892                 LOGL(LOG_SSENGINE, "ui8pAttribs = %s\n", ui8pAttribs);
893
894         }
895         memset(tmpAttribs, 0x0, sizeof(tmpAttribs));
896         memcpy(tmpAttribs, ui8pAttribs, (size_t) ui32AttribSize-1);
897         smack_attr_pos = tmpAttribs;
898         tp = strtok_r(tmpAttribs, attrDelim, &saveptr);
899
900         // Get FileMode
901         if (tp != NULL) {
902                 smack_attr_pos += strlen(tp);
903                 smack_attr_pos++;
904                 setFileMode = strtol(tp, &endstr, 8);
905                 tp = strtok_r(NULL, attrDelim, &saveptr);
906         }
907         // Get UserID
908         if (tp != NULL) {
909                 smack_attr_pos += strlen(tp);
910                 smack_attr_pos++;
911                 setUserID = (uid_t) strtol(tp, &endstr, 10);
912                 tp = strtok_r(NULL, attrDelim, &saveptr);
913         }
914         // Get GroupID
915         if (tp != NULL) {
916                 smack_attr_pos += strlen(tp);
917                 smack_attr_pos++;
918                 setGroupID = (gid_t) strtol(tp, &endstr, 10);
919         }
920
921         if (feature_support_capability) {
922                 // Get Capability
923                 has_cap = 0;
924                 if (*smack_attr_pos != '\0') {
925                         char *cap_mark = "capability=0x";
926                         int cap_mark_len = strlen(cap_mark);
927                         psmack = strstr(smack_attr_pos, cap_mark);
928                         if (psmack) {
929                                 int cap_hex_len;
930                                 int i;
931                                 char ch1, ch2;
932                                 int raw1, raw2;
933
934                                 tp = strstr(psmack, ":");
935                                 smack_attr_pos = tp + 1;
936                                 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
937                                 memcpy(tmpSmackAttribs, psmack+cap_mark_len,
938                                         (int)tp - (int)psmack - cap_mark_len);
939
940                                 // convert hexadecimal into raw data
941                                 cap_hex_len = strlen(tmpSmackAttribs);
942                                 cap_len = cap_hex_len/2;
943                                 memset(cap_raw, 0x00, sizeof(cap_raw));
944                                 for (i = 0; i < cap_len; i++) {
945                                         ch1 = tmpSmackAttribs[i*2];
946                                         ch2 = tmpSmackAttribs[i*2+1];
947                                         if ((ch1 >= '0') && (ch1 <= '9'))               raw1 = ch1 - '0';
948                                         else if ((ch1 >= 'a') && (ch1 <= 'f'))          raw1 = ch1 - 'a' + 10;
949                                         else if ((ch1 >= 'A') && (ch1 <= 'F'))          raw1 = ch1 - 'A' + 10;
950                                         else raw1 = 0;
951                                         if ((ch2 >= '0') && (ch2 <= '9'))               raw2 = ch2 - '0';
952                                         else if ((ch2 >= 'a') && (ch2 <= 'f'))          raw2 = ch2 - 'a' + 10;
953                                         else if ((ch2 >= 'A') && (ch2 <= 'F'))          raw2 = ch2 - 'A' + 10;
954                                         else raw2 = 0;
955
956                                         cap_raw[i] = raw1*16 + raw2;
957                                 }
958                                 LOGL(LOG_SSENGINE, "[Cap] %s (cap_len=%d)\n", tmpSmackAttribs, cap_len);
959                                 has_cap = 1;
960                         }
961
962                 }
963                 // Get ACL
964                 has_acl = 0;
965                 if (*smack_attr_pos != '\0') {
966                         char *acl_mark = "acl_access=0x";
967                         int acl_mark_len = strlen(acl_mark);
968                         psmack = strstr(smack_attr_pos, acl_mark);
969                         if (psmack) {
970                                 int acl_hex_len;
971                                 int i;
972                                 char ch1, ch2;
973                                 int raw1, raw2;
974
975                                 tp = strstr(psmack, ":");
976                                 smack_attr_pos = tp + 1;
977                                 memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
978                                 memcpy(tmpSmackAttribs, psmack+acl_mark_len,
979                                         (int)tp - (int)psmack - acl_mark_len);
980
981                                 // convert hexadecimal into raw data
982                                 acl_hex_len = strlen(tmpSmackAttribs);
983                                 acl_len = acl_hex_len/2;
984                                 memset(acl_raw, 0x00, sizeof(acl_raw));
985                                 for (i = 0; i < acl_len; i++) {
986                                         ch1 = tmpSmackAttribs[i*2];
987                                         ch2 = tmpSmackAttribs[i*2+1];
988                                         if ((ch1 >= '0') && (ch1 <= '9'))               raw1 = ch1 - '0';
989                                         else if ((ch1 >= 'a') && (ch1 <= 'f'))          raw1 = ch1 - 'a' + 10;
990                                         else if ((ch1 >= 'A') && (ch1 <= 'F'))          raw1 = ch1 - 'A' + 10;
991                                         else raw1 = 0;
992                                         if ((ch2 >= '0') && (ch2 <= '9'))               raw2 = ch2 - '0';
993                                         else if ((ch2 >= 'a') && (ch2 <= 'f'))          raw2 = ch2 - 'a' + 10;
994                                         else if ((ch2 >= 'A') && (ch2 <= 'F'))          raw2 = ch2 - 'A' + 10;
995                                         else raw2 = 0;
996
997                                         acl_raw[i] = raw1*16 + raw2;
998                                 }
999                                 LOG("[ACL] %s (acl_len=%d)\n", tmpSmackAttribs, acl_len);
1000                                 has_acl = 1;
1001                         }
1002
1003                 }
1004         }
1005
1006         // Get Smack value -> Set Smack value
1007         if (*smack_attr_pos != '\0') {
1008                 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_ACCESS);
1009                 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_EXEC);
1010                 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_MMAP);
1011                 SS_smack_lsetlabel(setFilePath, NULL, SMACK_LABEL_TRANSMUTE);
1012
1013                 psmack = strstr(smack_attr_pos, "access=\"");
1014                 if (psmack) {
1015                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
1016                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
1017                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
1018                         if (smack_value) {
1019                                 smack_value = strtok_r(NULL, "\"", &saveptr);
1020                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_ACCESS] smack_value=%s\n", smack_value);
1021                                 if (smack_value) {
1022                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_ACCESS);
1023                                         if (ret < 0)
1024                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
1025                                 }
1026                         }
1027                 }
1028                 psmack = strstr(smack_attr_pos, "execute=\"");
1029                 if (psmack) {
1030                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
1031                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
1032                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
1033                         if (smack_value) {
1034                                 smack_value = strtok_r(NULL, "\"", &saveptr);
1035                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_EXEC] smack_value=%s\n", smack_value);
1036                                 if (smack_value) {
1037                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_EXEC);
1038                                         if (ret < 0)
1039                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
1040                                 }
1041                         }
1042                 }
1043                 psmack = strstr(smack_attr_pos, "mmap=\"");
1044                 if (psmack) {
1045                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
1046                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
1047                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
1048                         if (smack_value) {
1049                                 smack_value = strtok_r(NULL, "\"", &saveptr);
1050                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_MMAP] smack_value=%s\n", smack_value);
1051                                 if (smack_value) {
1052                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_MMAP);
1053                                         if (ret < 0)
1054                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
1055                                 }
1056                         }
1057                 }
1058                 psmack = strstr(smack_attr_pos, "transmute=\"");
1059                 if (psmack) {
1060                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
1061                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
1062                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
1063                         if (smack_value) {
1064                                 smack_value = strtok_r(NULL, "\"", &saveptr);
1065                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_TRANSMUTE] smack_value=%s\n", smack_value);
1066                                 if (smack_value) {
1067                                         if (strcasecmp(smack_value, "TRUE") == 0)
1068                                                 ret = SS_smack_lsetlabel(setFilePath, "1", SMACK_LABEL_TRANSMUTE);
1069                                         else
1070                                                 ret = SS_smack_lsetlabel(setFilePath, "0", SMACK_LABEL_TRANSMUTE);
1071                                         if (ret < 0)
1072                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
1073                                 }
1074                         }
1075                 }
1076         }
1077
1078         // Set UserID,GroupID
1079         if (lchown(setFilePath, setUserID, setGroupID)) {
1080                 // debug start
1081                 LOGL(LOG_SSENGINE,  "%s chown error\n", __func__);
1082                 LOGL(LOG_SSENGINE,  "%s setUserID = %d\n", __func__, setUserID);
1083                 LOGL(LOG_SSENGINE,  "%s setGroupID = %d\n", __func__, setGroupID);
1084                 LOGL(LOG_SSENGINE,  "%s chown errno = %d\n", __func__, errno);
1085                 // debug end
1086
1087                 return E_SS_FAILURE;
1088         }
1089
1090         // mode is always 0777 at symlink file. It doesn't need to call chmod().
1091         if (S_ISLNK(sbuf.st_mode)) {
1092                 LOGL(LOG_SSENGINE,  " stat->st_mode = symbolic link file\n");
1093                 return S_SS_SUCCESS;
1094         }
1095
1096         if (chmod(setFilePath, setFileMode)) {
1097                 LOGL(LOG_SSENGINE,  "%s chmod error\n", __func__);
1098                 return E_SS_FAILURE;
1099         }
1100
1101         if (feature_support_capability) {
1102                 char buf[256];
1103                 if (has_cap)  {
1104                         if (setxattr(setFilePath, "security.capability", (void*)cap_raw, cap_len, 0) < 0) {
1105                                 strerror_r(errno, buf, sizeof(buf));
1106                                 LOGL(LOG_SSENGINE, "cap setxattr() failed: %s\n", buf);
1107                         }
1108                 }
1109
1110                 if (has_acl)  {
1111                         if (setxattr(setFilePath, "system.posix_acl_access", (void*)acl_raw, acl_len, 0) < 0) {
1112                                 strerror_r(errno, buf, sizeof(buf));
1113                                 LOGL(LOG_SSENGINE, "Acl setxattr() failed: %s\n", buf);
1114                         }
1115                         //LOG("Acl setxattr() :")asfd
1116                 }
1117         }
1118
1119         //LOGL(LOG_SSENGINE,  "%s SUCCESS\n", __func__);
1120
1121         return S_SS_SUCCESS;
1122 }
1123
1124
1125 long SS_CompareFileAttributes(void)
1126 {
1127         return S_SS_SUCCESS;
1128 }
1129
1130
1131
1132 #define MAX_INT 0xefffffff
1133
1134 /* vrm functions */
1135 long
1136 SS_GetAvailableFreeSpace(const char *partition_name,
1137                          SS_UINT32 *available_flash_size)
1138 {
1139 //      *available_flash_size = MAX_INT;
1140 /*
1141 #define IDENT_SBL          "sbl"
1142 #define IDENT_PLATFORM     "platform"
1143 #define IDENT_BOOT     "boot"
1144 */
1145         int result = 0;
1146         char path[MAX_PATH] = { '\0' };
1147
1148         SS_unicode_to_char(partition_name, (char *)path, MAX_PATH - 1);
1149         //LOGL(LOG_SSENGINE, "Enter %s path=%s\n", __func__, path);
1150         struct statfs vfs;
1151
1152         //LOGL(LOG_SSENGINE, "path=%s\n", path);
1153         result = statfs(path, &vfs);
1154         if (result < 0) {
1155                 LOGE("failed to fstatfs, err : %d errno: %d\n", result, errno);
1156                 return -1;
1157         }
1158
1159         *available_flash_size = vfs.f_bsize * vfs.f_bavail;
1160         if (*available_flash_size == 0) {
1161                 *available_flash_size = 0x80000; //Same as Legecy RB
1162                 LOGE("available_flash_size=%u(vfs.f_bsize=%d vfs.f_bavail=%d\n",
1163                                 (unsigned int)*available_flash_size, (int)vfs.f_bsize, (int)vfs.f_bavail);
1164                 return 0; // Same as Legecy RB
1165         }
1166         return 0;
1167 }
1168
1169 #ifdef HEAP_PROFILING
1170         int max_mem;
1171         int cur_mem;
1172 #endif
1173 /*******[ Multiprocess API sample implementation ]******/
1174 void *SS_Malloc(SS_UINT32 size)
1175 {
1176         void *p = malloc(size);
1177
1178         if (p)
1179                 memset(p, 0, size);
1180 #ifdef HEAP_PROFILING
1181         cur_mem += size;
1182         if (cur_mem > max_mem) {
1183                 max_mem = cur_mem;
1184                 LOGL(LOG_SSENGINE, "New chunk [%d] assigned making heap [%d]\n", size, cur_mem);
1185         }
1186 #endif
1187
1188         return p;
1189 }
1190
1191 void SS_Free(void *pMemBlock)
1192 {
1193 #ifdef HEAP_PROFILING
1194         cur_mem -= malloc_usable_size(pMemBlock);
1195         LOGL(LOG_SSENGINE, "Old chunk [%d] removed making heap [%d]\n", malloc_usable_size(pMemBlock), cur_mem);
1196 #endif
1197         if (pMemBlock)
1198                 free(pMemBlock);
1199 }
1200
1201 SS_UINT32 SS_GetMaxNumProcess(void)
1202 {
1203         return SAMPLE_PROCS_NUM;
1204 }
1205
1206 void* SS_WaitForProcess(const void *handle, SS_UINT32* process_exit_code)
1207 {
1208         pid_t pid;
1209         *process_exit_code = 0;
1210
1211         // processes
1212         if (handle)
1213                 #ifdef _NOEXEC_
1214                 pid = waitpid((pid_t)handle, (int *)process_exit_code, 0);
1215                 #else
1216                 pid = wait((int*)process_exit_code);
1217                 #endif
1218
1219         else
1220                 pid = wait((int*)process_exit_code);
1221
1222         if (pid < 0)
1223                 return NULL;
1224
1225         if (!WIFEXITED(*process_exit_code)) {
1226                 *process_exit_code = (char)WTERMSIG(*process_exit_code);
1227                 LOG("Wait Error\n");
1228         } else {
1229                 *process_exit_code = (char)WEXITSTATUS(*process_exit_code);
1230         }
1231
1232         return (void*)pid;
1233 }
1234 unsigned long SS_GetMaxProcRamSize(void)
1235 {
1236         return UA_RAM_SIZE;
1237 }
1238
1239 void* SS_RunProcess(void)
1240 {
1241         pid_t child_pid;
1242
1243         #ifdef _NOEXEC_
1244         child_pid = fork();
1245         #else
1246         child_pid = vfork();
1247         #endif
1248
1249         if (child_pid == -1) {
1250                 LOG("Fork failed.\n");
1251                 return (void *)-1;
1252         }
1253
1254         // This is the child
1255         if (child_pid == 0) {
1256                 #ifdef _NOEXEC_
1257                 #ifdef _TIZEN_SSENGINE//bota
1258                 SS_HandleProcessRequest(pbUserData, argc, argv);
1259                 #endif
1260                 LOGL(LOG_SSENGINE, "SS_RunProcess was called - SS_HandleProcessRequest\n");
1261                 exit(0);
1262                 #else
1263
1264                 char **params = NULL;
1265                 int i;
1266
1267                 params = (char **)SS_Malloc((argc+EXTRA_ARGS) *sizeof(char*));
1268                 if (!params) {
1269                         LOG("params allocation failed\n");
1270                         return NULL;
1271                 }
1272                 // prepare child data, as it's forbidden to change data after vfork
1273                 params[0] = strdup(((sample_userdata*)user)->exec_path);
1274                 params[1] = strdup("handle_run_process");
1275                 params[2] = strdup(((sample_userdata*)user)->delta_path);
1276
1277                 for (i = 0; i < argc; i++)
1278                         params[i+EXTRA_ARGS] = strdup(argv[i]);
1279
1280                 // no need to free allocated memory - execv takes care of it
1281                 execv(params[0], (char**)params);
1282                 _exit(-1); // if we're here, execv has failed
1283                 #endif
1284         } else {
1285                 return (void *)child_pid;
1286         }
1287 }
1288
1289 int SS_get_feature_support_capability(void)
1290 {
1291         return feature_support_capability;
1292 }
1293
1294 void SS_set_feature_support_capability(int val)
1295 {
1296         feature_support_capability = val;
1297 }