Rename delta-ua directory to upgrade-apply-deltafs and delta.ua binary to upgrade...
[platform/core/system/upgrade.git] / src / upgrade-apply-deltafs / engine / SS_FSUpdate.c
1 /*
2  * upgrade-apply-deltafs
3  *
4  * Copyright (c) 2017 - 2022 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         if (path == 0) {
105                 LOGL(LOG_SSENGINE, "Bad path param value \n");
106                 return -E_SS_BAD_PARAMS;
107         }
108
109         if (path[0] == '\0') {
110                 LOGL(LOG_SSENGINE, "Path empty \n");
111                 return -E_SS_FILENAMELENERROR;
112         }
113
114         char input_path[MAX_PATH] = {'\0'};
115         char temppath[MAX_PATH] = {'\0'};
116
117         strncpy(input_path, path, MAX_PATH - 1);
118
119         if (input_path[0] == '/') {
120                 temppath[0] = '/';
121         }
122
123         char *path_token;
124         char *path_pos = input_path;
125
126         int temppath_current_len = (temppath[0] == '/');
127
128         while((path_token = strtok_r(path_pos, "/", &path_pos))) {
129
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;
133
134                 int mkd_res = mkdir(temppath, mode);
135
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;
139                 }
140
141                 if(temppath_current_len < (MAX_PATH - 1)) {
142                         strncat(temppath, "/", 1);
143                 }
144         }
145         return 0;
146 }
147
148 long
149 SS_CopyFile(const char *strFromPath, const char *strToPath)
150 {
151         int fd1, fd2;
152         int readCount = 0, writeCount = 0;
153         char buf[1 << 15];      // copy 32KB wise
154         int ret = 0;
155
156         char path1[MAX_PATH] = { '\0' };
157         char path2[MAX_PATH] = { '\0' };
158
159         if (!strFromPath || !strToPath) {
160                 LOGE("NULL file name find. Abort.\n");
161                 return -1;
162         }
163
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);
166
167         //LOGL(LOG_SSENGINE, "%s -> %s \n", path1, path2);
168
169         fd1 = open(path1, O_RDONLY);
170         if (fd1 < 0)
171                 return E_SS_OPENFILE_ONLYR;
172         ret = SS_OpenFile(strToPath, ONLY_W, (long *)&fd2);
173         if (ret != S_SS_SUCCESS || fd2 < 0) {
174                 close(fd1);
175                 LOGE(" SS_OpenFile fail leaved path1:%s | path2:%s\n", path1, path1);
176                 return E_SS_WRITE_ERROR;
177         }
178
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,
183                                         writeCount);
184                         ret = E_SS_WRITE_ERROR;
185                         break;
186                 }
187         }
188
189         close(fd1);
190         fsync(fd2);
191         close(fd2);
192         //LOGL(LOG_INFO, " leaved path1:%s | path2:%s\n", path1, path2);
193
194         return ret;
195 }
196
197 long SS_DeleteFile(const char *strPath)
198 {
199         char path[MAX_PATH] = { '\0' };
200         int ret = 0;
201
202         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
203         //LOGL(LOG_SSENGINE, "%s\n", path);
204         ret = unlink(path);
205         if (ret == 0)
206                 return S_SS_SUCCESS;
207
208         LOGE("failed to delete path [%s] unlink value: %d, errno: %d\n", path, ret, errno);
209         if (ret < 0 && errno == ENOENT)
210                 return S_SS_SUCCESS;
211         return E_SS_DELETEFILE;
212 }
213
214 int SS_unlink_cbf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
215 {
216         int rv = remove(fpath);//returns zero on success and -1 on failure
217
218         if (rv) {
219                 perror(fpath);
220                 LOGE("path : %s, remove value: %d, errno: %d\n", fpath, rv, errno);
221         }
222         return rv;
223 }
224 long SS_DeleteFolder(const char *strPath)
225 {
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;
228 }
229
230 long SS_CreateFolder(const char *strPath)
231 {
232         mode_t mode = 0;
233         int ret = 0;
234         char path[MAX_PATH] = { '\0' };
235
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 */ ;
246
247         LOGL(LOG_SSENGINE, "%s, mode:0x%x\n", path, mode);
248
249         ret = mkdir(path, mode);
250
251         if (ret == 0 || ((ret == -1) && (errno == EEXIST))) {
252                 return S_SS_SUCCESS;
253         } else if ((ret == -1) && (errno == ENOENT)) {  //maybe multi directory problem
254                 //do//Recursive Function
255                 //{
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.
259                         if (ret == 0)
260                                 return S_SS_SUCCESS;
261                         else
262                                 return E_SS_FAILURE;
263                 } else {
264                         return E_SS_FAILURE;
265                 }
266                 //}
267                 //while(ret != 0);
268
269         } else {
270                 return E_SS_FAILURE;
271         }
272 }
273
274 mode_t SS_get_mode(E_RW_TYPE wFlag)
275 {
276         switch (wFlag) {
277         case ONLY_R:
278                 //LOGL(LOG_SSENGINE, " RDONLY \n");
279                 return O_RDONLY;
280         case ONLY_W:
281                 //LOGL(LOG_SSENGINE, " WRONLY \n");
282                 return O_WRONLY | O_CREAT;
283         case BOTH_RW:
284                 //LOGL(LOG_SSENGINE, " RDWR \n");
285                 return O_RDWR | O_CREAT;
286         default:
287                 //LOGL(LOG_SSENGINE, " Unknown \n");
288                 return 0;
289         }
290 }
291
292 long
293 SS_OpenFile(const char *strPath, E_RW_TYPE wFlag, long *pwHandle)
294 {
295         mode_t mode;
296         char path[MAX_PATH] = { '\0' };
297
298         SS_unicode_to_char((const char *)strPath, (char *)path, MAX_PATH - 1);
299
300         mode = SS_get_mode(wFlag);
301         //LOGL(LOG_SSENGINE, "Path:%s  wFlag:%d  Mode:%d\n", path, wFlag, mode);
302
303         if (mode & O_CREAT) {
304                 //LOGL(LOG_SSENGINE, " open() S_IRWXU\n");
305                 *pwHandle = open(path, mode, S_IRWXU);
306         } else {
307                 //LOGL(LOG_SSENGINE, " open() %d\n", mode);
308                 *pwHandle = open(path, mode);
309         }
310         if (*pwHandle == -1) {
311                 *pwHandle = 0;
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;
316                 }
317
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' };
322                         int i = 0;
323                         //copy the full file path to directory path variable
324                         while (path[i] != '\0') {
325                                 dir[i] = path[i];
326                                 i++;
327                         }
328                         LOGL(LOG_SSENGINE, " copy dir[]=%s\n", dir);
329                         //search for the last '/' char
330                         while (dir[i--] != '/') ;
331                         dir[i + 1] = '\0';
332
333                         SS_char_to_unicode((const char *)dir,
334                                         (char *)dirShort, MAX_PATH - 1);
335
336                         if (SS_CreateFolder(dirShort)) {
337                                 LOGE(" Fail create folder, Leave SS_OpenFile\n");
338                                 return E_SS_OPENFILE_WRITE;
339                         }
340
341                         *pwHandle = open(path, mode);
342                         if (*pwHandle == -1) {
343                                 *pwHandle = 0;
344                                 LOGE(" After successful creating folder, fail open() with error %d\n", errno);
345                                 return E_SS_OPENFILE_WRITE;
346                         }
347                 } else {
348                         LOG(" fail open() *pwHandle:%ld\n", *pwHandle);
349                         return E_SS_OPENFILE_WRITE;
350                 }
351         }
352
353         //LOGL(LOG_SSENGINE, " Successful open() *pwHandle:%ld\n", *pwHandle);
354
355         return S_SS_SUCCESS;
356 }
357
358 long SS_CloseFile(long wHandle)
359 {
360         int ret = 0;
361         LOGL(LOG_SSENGINE, "wHandle = %ld\n", wHandle);
362
363         if (wHandle) {
364                 ret = fsync(wHandle);
365                 if (ret < 0) {
366                         LOG(" fsync Failed with return value: %d\n", ret);
367                         return E_SS_WRITE_ERROR;
368                 }
369                 LOG(" fsync after write: %d\n", ret);
370                 ret = close(wHandle);
371         }
372
373         if (ret == 0)
374                 return S_SS_SUCCESS;
375
376         return E_SS_CLOSEFILE_ERROR;
377 }
378
379 long
380 SS_WriteFile(long wHandle,
381                 SS_UINT32 dwPosition,
382                 unsigned char *pbBuffer, SS_UINT32 dwSize)
383 {
384         int ret = 0;
385
386         LOGL(LOG_SSENGINE, "Handle:%ld , Pos:%u , Size: %u\n", wHandle,
387                         dwPosition, dwSize);
388
389         ret = lseek(wHandle, dwPosition, SEEK_SET);
390         if (ret < 0) {
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;
394         }
395
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;
402         }
403         LOGL(LOG_SSENGINE, "leave Bytes Write: %d\n", ret);
404
405         return S_SS_SUCCESS;
406 }
407
408 long SS_MoveFile(const char *strFromPath, const char *strToPath)
409 {
410         int ret = 0;
411         struct stat sbuf;
412         char path1[MAX_PATH] = { '\0' };
413         char path2[MAX_PATH] = { '\0' };
414
415         if (!strFromPath || !strToPath)
416                 return -1;      //should never happen
417
418         SS_unicode_to_char(strFromPath, (char *)path1, MAX_PATH - 1);
419         SS_unicode_to_char(strToPath, (char *)path2, MAX_PATH - 1);
420
421         LOGL(LOG_INFO, "entered path1:%s | path2:%s\n", path1, path2);
422         ret = stat(path1, &sbuf);
423         if (ret < 0) {
424                         LOGE("stat failed with return value: %d errno: %d\n",  ret, errno);
425                         return E_SS_FAILURE;
426         }
427         ret = rename(path1, path2);
428         if (ret < 0) {
429                 LOGL(LOG_INFO, "rename fail with code [%d], try to create dir if errno is 2\n", errno);
430                 if (errno == 2) {
431                         char * file_name = strrchr(path2, '/');
432                         *file_name = '\0';
433                         SS_create_dir(path2, 0755);
434                         *file_name = '/';
435                         ret = rename(path1, path2);
436                         if (ret < 0) {
437                                 LOGE("Move failed, error code [%d]\n", errno);
438                                 return E_SS_WRITE_ERROR;
439                         }
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;
446                         }
447                         ret = unlink(path1);
448                         if (ret != 0) {
449                                 LOGE("failed to unlink [%s] code [%d]\n", path1, errno);
450                                 return E_SS_WRITE_ERROR;
451                         }
452                 } else {
453                         LOGE("Move failed, error code [%d]\n", errno);
454                         return E_SS_WRITE_ERROR;
455                 }
456         }
457         LOGL(LOG_INFO, "leaved path1:%s | path2:%s\n", path1, path2);
458         return S_SS_SUCCESS;
459 }
460
461 long
462 SS_ReadFile(long wHandle,
463             SS_UINT32 dwPosition,
464             unsigned char *pbBuffer, SS_UINT32 dwSize)
465 {
466         int ret = 0;
467
468 #if 0
469         LOG(" %s: Handle:%ld , Pos:%u , Size: %u", __func__, wHandle,
470                dwPosition, dwSize);
471 #endif
472         ret = lseek(wHandle, dwPosition, SEEK_SET);
473         if (ret < 0) {
474                 LOGE("Handle:%ld , Pos:%u , Size: %u\n", wHandle, dwPosition,
475                      dwSize);
476                 LOGE("lseek failed with return value: %d\n", ret);
477                 return E_SS_READ_ERROR;
478         }
479         ret = read(wHandle, pbBuffer, dwSize);
480         if (ret < 0) {
481                 LOGE("Handle:%ld , Pos:%u , Size: %u\n", wHandle, dwPosition,
482                      dwSize);
483                 LOGE("read failed with return value: %d\n", ret);
484                 return E_SS_READ_ERROR;
485         }
486
487         if (ret != dwSize && ((ret + dwPosition) != (unsigned long)SS_GetFileSize(wHandle)))
488                 return E_SS_READ_ERROR;
489
490         pbBuffer[ret] = '\0';
491 #if 0
492         LOGL(LOG_DEBUG, "Bytes Read: %d\n", ret);
493 #endif
494         return S_SS_SUCCESS;
495 }
496
497 long SS_GetFileSize(long wHandle)
498 {
499         int ret = 0;
500
501
502         ret = lseek(wHandle, 0, SEEK_END);
503
504         if (ret == -1) {
505                 LOGE(" lseek errno: %d\n", errno);
506                 return E_SS_READFILE_SIZE;
507         }
508         LOGL(LOG_SSENGINE, "handle=%d  Returning Size = %ld(0x%x)\n",
509                 (int)wHandle, (long int)ret, ret);
510
511         return ret;
512 }
513
514 long SS_Unlink(char *pLinkName)
515 {
516         int ret = 0;
517         char path[MAX_PATH] = { '\0' };
518         //enumFileType fileType = FT_REGULAR_FILE;
519
520
521         SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
522
523         ret = unlink(path);
524         if (ret < 0 && errno != ENOENT) {
525                 LOGE("unlink failed with return value: %d\n", ret);
526                 return E_SS_FAILURE;
527         }
528         LOGL(LOG_SSENGINE, "unlink with return value: %d\n", ret);
529
530         return S_SS_SUCCESS;
531 }
532
533 long
534 SS_VerifyLinkReference(char *pLinkName, char *pReferenceFileName)
535 {
536         int ret = 0;
537         char path[MAX_PATH] = { '\0' };
538         char linkedpath[MAX_PATH] = { '\0' };
539         char refpath[MAX_PATH] = { '\0' };
540
541
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);
544
545         ret = readlink(path, linkedpath, MAX_PATH);
546         if (ret < 0) {
547                 LOGE("readlink failed with return value: %d\n", ret);
548                 return E_SS_FAILURE;
549         }
550
551         if ((memcmp(&linkedpath, &refpath, ret)) != 0) {
552                 LOGE("not same linked path\n");
553                 return E_SS_FAILURE;
554         }
555         LOGL(LOG_SSENGINE, "same linked path\n");
556
557         return S_SS_SUCCESS;
558 }
559
560 long
561 SS_Link(void *pbUserData, char *pLinkName, char *pReferenceFileName)
562 {
563         int ret = 0;
564         char sympath[MAX_PATH] = { '\0' };
565         char refpath[MAX_PATH] = { '\0' };
566         //enumFileType fileType = FT_SYMBOLIC_LINK;
567         struct stat sbuf;
568
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);
571
572         ret = symlink(refpath, sympath);
573         if (ret != 0) {
574                 LOGE(" symlink failed with return value: %d, errno: %d\n", ret, errno);
575
576                 if (errno == EEXIST) {
577                         ret = lstat(sympath, &sbuf);
578                         LOGL(LOG_SSENGINE, "symlink LSTAT with return value: %d\n", ret);
579                         if (ret >= 0) {
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);
584                                         }
585                                 }
586                         if (SS_VerifyLinkReference(pLinkName
587                                 , pReferenceFileName) == S_SS_SUCCESS) {
588                                 return S_SS_SUCCESS;
589                         } else {
590                                 return E_SS_FAILURE;
591                         }
592                 } else if (errno == ENOENT) {//to handle cases where new symlink points to a new symlink yet to be created
593                         return errno;
594                 } else {
595                         return E_SS_FAILURE;
596                 }
597         }
598         //LOGL(LOG_SSENGINE, "symlink with return value: %d\n", ret);
599
600         return S_SS_SUCCESS;
601 }
602
603 long
604 SS_HardLink(char *hardLinkName, char *referenceName)
605 {
606         int ret = 0;
607         char hardpath[MAX_PATH] = { '\0' };
608         char refpath[MAX_PATH] = { '\0' };
609
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);
612
613         ret = link(refpath, hardpath);
614         if (ret != 0) {
615                 LOGE("Linking failed for hardlink %s with errno: %d\n", hardpath, errno);
616                 return E_SS_FAILURE;
617         }
618         return S_SS_SUCCESS;
619 }
620
621 long SS_GetFileType(char *pLinkName, enumFileType * fileType)
622 {
623         int ret = 0;
624         char path[MAX_PATH] = { '\0' };
625         struct stat sbuf;
626
627         //LOGL(LOG_SSENGINE, "\n");
628         SS_unicode_to_char((const char *)pLinkName, (char *)path, MAX_PATH - 1);
629
630         ret = lstat(path, &sbuf);
631         if (ret < 0) {
632                 ret = stat(path, &sbuf);
633                 if (ret < 0) {
634                         LOGE("stat failed with return value: %d errno: %d\n",
635                              ret, errno);
636                         *fileType = FT_MISSING;
637                         return S_SS_SUCCESS;
638                 }
639         }
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));
643
644         if (S_ISLNK(sbuf.st_mode)) {
645                 //LOGL(LOG_SSENGINE, " stat->st_mode = symbolic link file\n");
646                 *fileType = FT_SYMBOLIC_LINK;
647                 return S_SS_SUCCESS;
648         }
649
650         if (S_ISREG(sbuf.st_mode)) {
651                 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
652                 *fileType = FT_REGULAR_FILE;
653                 return S_SS_SUCCESS;
654         }
655
656         if (S_ISDIR(sbuf.st_mode)) {
657                 //LOGL(LOG_SSENGINE, " stat->st_mode = regular file\n");
658                 *fileType = FT_FOLDER;
659                 return S_SS_SUCCESS;
660         }
661         LOGE("failed to lstat, err : %d\n", ret);
662         return E_SS_FAILURE;
663 }
664
665 static inline char *SS_get_xattr_name(enum smack_label_type type)
666 {
667         switch (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";
680         default:
681                 /* Should not reach this point */
682                 return NULL;
683         }
684 }
685
686 int SS_smack_lsetlabel(const char *path, const char *label, enum smack_label_type type)
687 {
688         if (path == NULL) {
689                 LOGE("Path is NULL\n");
690                 return -1;
691         }
692
693         char *xattr_name = SS_get_xattr_name(type);
694         if (xattr_name == NULL) {
695                 LOGE("Failed get xattr name\n");
696                 return -1;
697         }
698
699         /* Check validity of labels for LABEL_TRANSMUTE */
700         if (type == SMACK_LABEL_TRANSMUTE && label != NULL) {
701                 if (!strncmp(label, "0", strlen("0"))) {
702                         label = NULL;
703                 } else if (!strncmp(label, "1", strlen("0"))) {
704                         label = "TRUE";
705                 } else {
706                         return -1;
707                 }
708         }
709
710         if (label == NULL || label[0] == '\0') {
711                 return lremovexattr(path, xattr_name);
712         } else {
713                 int len = strnlen(label, SMACK_LABEL_LEN + 1);
714                 if (len > SMACK_LABEL_LEN) {
715                         return -1;
716                 }
717                 return lsetxattr(path, xattr_name, label, len, 0);
718         }
719 }
720
721 /*!
722  *******************************************************************************
723  * Set file attributes.<p>
724  *
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)
731  *
732  * \param       pbUserData              Optional opaque data-structure to pass to IPL
733  *                                                      functions
734  * \param       ui16pFilePath   File path
735  * \param       ui32AttribSize  Size of \a ui8pAttribs
736  * \param       ui8pAttribs             Attributes to set
737  *
738  * \return      S_SS_SUCCESS on success or &lt; 0 on error
739  *******************************************************************************
740  */
741
742 long SS_SetFileAttributes(const char *ui16pFilePath,
743                           const SS_UINT32 ui32AttribSize,
744                           const unsigned char *ui8pAttribs)
745 {
746         static char tmpAttribs[512];
747         static char tmpSmackAttribs[512];
748         char *tp;
749         char *endstr;
750         char *saveptr;
751         char *smack_value, *psmack;
752         uid_t setUserID = 0;
753         gid_t setGroupID = 0;
754         mode_t setFileMode = 0;
755         const char attrDelim[2] = ":";
756
757         char setFilePath[MAX_PATH] = { '\0' };
758         struct stat sbuf;
759         int ret = 0;
760         char *smack_attr_pos = NULL;
761         int has_cap = 0;
762         char cap_raw[100];
763         int cap_len;
764         /*ACL */
765         int has_acl = 0;
766         char acl_raw[256];
767         int acl_len;
768
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");
777                 return S_SS_SUCCESS;
778         }
779
780         SS_unicode_to_char((const char *)ui16pFilePath, (char *)setFilePath, MAX_PATH - 1);
781
782         ret = lstat(setFilePath, &sbuf);
783         if (ret < 0) {
784                 ret = stat(setFilePath, &sbuf);
785                 if (ret < 0) {
786                         LOGL(LOG_SSENGINE, " stat failed with return value: %d\n", ret);
787                         return E_SS_FAILURE;
788                 } else {
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.
792                                 }
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");
797                 }
798
799                 LOGL(LOG_SSENGINE, "ui16pFilePath = %s\n", setFilePath);
800                 LOGL(LOG_SSENGINE, "ui32AttribSize = %u\n", ui32AttribSize);
801                 LOGL(LOG_SSENGINE, "ui8pAttribs = %s\n", ui8pAttribs);
802
803         }
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);
808
809         // Get FileMode
810         if (tp != NULL) {
811                 smack_attr_pos += strlen(tp);
812                 smack_attr_pos++;
813                 setFileMode = strtol(tp, &endstr, 8);
814                 tp = strtok_r(NULL, attrDelim, &saveptr);
815         }
816         // Get UserID
817         if (tp != NULL) {
818                 smack_attr_pos += strlen(tp);
819                 smack_attr_pos++;
820                 setUserID = (uid_t) strtol(tp, &endstr, 10);
821                 tp = strtok_r(NULL, attrDelim, &saveptr);
822         }
823         // Get GroupID
824         if (tp != NULL) {
825                 smack_attr_pos += strlen(tp);
826                 smack_attr_pos++;
827                 setGroupID = (gid_t) strtol(tp, &endstr, 10);
828         }
829
830         if (feature_support_capability) {
831                 // Get Capability
832                 has_cap = 0;
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);
837                         if (psmack) {
838                                 int cap_hex_len;
839                                 int i;
840                                 char ch1, ch2;
841                                 int raw1, raw2;
842
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);
848
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;
859                                         else raw1 = 0;
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;
863                                         else raw2 = 0;
864
865                                         cap_raw[i] = raw1*16 + raw2;
866                                 }
867                                 LOGL(LOG_SSENGINE, "[Cap] %s (cap_len=%d)\n", tmpSmackAttribs, cap_len);
868                                 has_cap = 1;
869                         }
870
871                 }
872                 // Get ACL
873                 has_acl = 0;
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);
878                         if (psmack) {
879                                 int acl_hex_len;
880                                 int i;
881                                 char ch1, ch2;
882                                 int raw1, raw2;
883
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);
889
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;
900                                         else raw1 = 0;
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;
904                                         else raw2 = 0;
905
906                                         acl_raw[i] = raw1*16 + raw2;
907                                 }
908                                 LOG("[ACL] %s (acl_len=%d)\n", tmpSmackAttribs, acl_len);
909                                 has_acl = 1;
910                         }
911
912                 }
913         }
914
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);
921
922                 psmack = strstr(smack_attr_pos, "access=\"");
923                 if (psmack) {
924                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
925                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
926                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
927                         if (smack_value) {
928                                 smack_value = strtok_r(NULL, "\"", &saveptr);
929                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_ACCESS] smack_value=%s\n", smack_value);
930                                 if (smack_value) {
931                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_ACCESS);
932                                         if (ret < 0)
933                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
934                                 }
935                         }
936                 }
937                 psmack = strstr(smack_attr_pos, "execute=\"");
938                 if (psmack) {
939                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
940                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
941                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
942                         if (smack_value) {
943                                 smack_value = strtok_r(NULL, "\"", &saveptr);
944                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_EXEC] smack_value=%s\n", smack_value);
945                                 if (smack_value) {
946                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_EXEC);
947                                         if (ret < 0)
948                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
949                                 }
950                         }
951                 }
952                 psmack = strstr(smack_attr_pos, "mmap=\"");
953                 if (psmack) {
954                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
955                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
956                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
957                         if (smack_value) {
958                                 smack_value = strtok_r(NULL, "\"", &saveptr);
959                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_MMAP] smack_value=%s\n", smack_value);
960                                 if (smack_value) {
961                                         ret = SS_smack_lsetlabel(setFilePath, smack_value, SMACK_LABEL_MMAP);
962                                         if (ret < 0)
963                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
964                                 }
965                         }
966                 }
967                 psmack = strstr(smack_attr_pos, "transmute=\"");
968                 if (psmack) {
969                         memset(tmpSmackAttribs, 0x0, sizeof(tmpSmackAttribs));
970                         memcpy(tmpSmackAttribs, psmack, sizeof(tmpSmackAttribs) - 1);
971                         smack_value = strtok_r(tmpSmackAttribs, "\"", &saveptr);
972                         if (smack_value) {
973                                 smack_value = strtok_r(NULL, "\"", &saveptr);
974                                 //LOGL(LOG_SSENGINE, "[SMACK_LABEL_TRANSMUTE] smack_value=%s\n", smack_value);
975                                 if (smack_value) {
976                                         if (strcasecmp(smack_value, "TRUE") == 0)
977                                                 ret = SS_smack_lsetlabel(setFilePath, "1", SMACK_LABEL_TRANSMUTE);
978                                         else
979                                                 ret = SS_smack_lsetlabel(setFilePath, "0", SMACK_LABEL_TRANSMUTE);
980                                         if (ret < 0)
981                                                 LOGL(LOG_SSENGINE, "SS_smack_lsetlabel() failed\n");
982                                 }
983                         }
984                 }
985         }
986
987         // Set UserID,GroupID
988         if (lchown(setFilePath, setUserID, setGroupID)) {
989                 // debug start
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);
994                 // debug end
995
996                 return E_SS_FAILURE;
997         }
998
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;
1003         }
1004
1005         if (chmod(setFilePath, setFileMode)) {
1006                 LOGL(LOG_SSENGINE,  "%s chmod error\n", __func__);
1007                 return E_SS_FAILURE;
1008         }
1009
1010         if (feature_support_capability) {
1011                 char buf[256];
1012                 if (has_cap)  {
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);
1016                         }
1017                 }
1018
1019                 if (has_acl)  {
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);
1023                         }
1024                         //LOG("Acl setxattr() :")asfd
1025                 }
1026         }
1027
1028         //LOGL(LOG_SSENGINE,  "%s SUCCESS\n", __func__);
1029
1030         return S_SS_SUCCESS;
1031 }
1032
1033 /* vrm functions */
1034 long
1035 SS_GetAvailableFreeSpace(const char *partition_name,
1036                          SS_UINT32 *available_flash_size)
1037 {
1038         int result = 0;
1039         char path[MAX_PATH] = { '\0' };
1040
1041         SS_unicode_to_char(partition_name, (char *)path, MAX_PATH - 1);
1042         //LOGL(LOG_SSENGINE, "Enter %s path=%s\n", __func__, path);
1043         struct statfs vfs;
1044
1045         //LOGL(LOG_SSENGINE, "path=%s\n", path);
1046         result = statfs(path, &vfs);
1047         if (result < 0) {
1048                 LOGE("failed to fstatfs, err : %d errno: %d\n", result, errno);
1049                 return -1;
1050         }
1051
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
1058         }
1059         return 0;
1060 }
1061
1062 #ifdef HEAP_PROFILING
1063         int max_mem;
1064         int cur_mem;
1065 #endif
1066 /*******[ Multiprocess API sample implementation ]******/
1067 void *SS_Malloc(SS_UINT32 size)
1068 {
1069         void *p = malloc(size);
1070
1071         if (p)
1072                 memset(p, 0, size);
1073 #ifdef HEAP_PROFILING
1074         cur_mem += size;
1075         if (cur_mem > max_mem) {
1076                 max_mem = cur_mem;
1077                 LOGL(LOG_SSENGINE, "New chunk [%d] assigned making heap [%d]\n", size, cur_mem);
1078         }
1079 #endif
1080
1081         return p;
1082 }
1083
1084 void SS_Free(void *pMemBlock)
1085 {
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);
1089 #endif
1090         if (pMemBlock)
1091                 free(pMemBlock);
1092 }
1093 int SS_get_feature_support_capability(void)
1094 {
1095         return feature_support_capability;
1096 }
1097
1098 void SS_set_feature_support_capability(int val)
1099 {
1100         feature_support_capability = val;
1101 }