Create virtual-root directory for VirtualRoot
[platform/framework/native/installer.git] / src / Manager / PermissionManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file        PermissionManager.cpp
19  * @brief       This is the implementation file for %PermissionManager class.
20  */
21
22 #include <stdio.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <unique_ptr.h>
26
27 #include <FBaseUtilStringUtil.h>
28 #include <FIoFile.h>
29 #include <FIoDirectory.h>
30 #include <FBase_StringConverter.h>
31 #include <FIo_FileImpl.h>
32
33 #include "PermissionManager.h"
34 #include "InstallerUtil.h"
35 #include "SmackManager.h"
36 #include "CompatibilityManager.h"
37
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Base::Utility;
41 using namespace Tizen::Io;
42 using namespace Tizen::App;
43
44 PermissionManager::PermissionManager(void)
45 {
46 }
47
48 PermissionManager::~PermissionManager(void)
49 {
50 }
51
52 bool
53 PermissionManager::SetDirectory(InstallationContext* pContext)
54 {
55         result r = E_SUCCESS;
56         bool res = true;
57
58         String destPath;
59         String appRootPath;
60         SmackManager smackManager;
61         smackManager.Construct(pContext);
62
63         appRootPath = pContext->__rootPath;
64         PackageId packageId = pContext->__packageId;
65
66         // appRoot
67         // InstallerUtil::ChangeOwner(appRootPath);
68         InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
69         smackManager.AddLabelDir(packageId, appRootPath, true);
70
71         if (pContext->__isPreloaded == true)
72         {
73                 String preloadedAppPath(PATH_USR_APPS);
74                 preloadedAppPath += L"/";
75                 preloadedAppPath += packageId;
76
77                 smackManager.AddLabelDir(L"_", preloadedAppPath, true);
78         }
79
80         // appRoot/bin
81         destPath = appRootPath + DIR_BIN;
82         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
83         smackManager.AddLabelDir(packageId, destPath);
84
85         // appRoot/info
86         destPath = appRootPath + DIR_INFO;
87         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
88         smackManager.AddLabelDir(packageId, destPath);
89
90         // appRoot/res
91         destPath = appRootPath + DIR_RES;
92         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
93         smackManager.AddLabelDir(packageId, destPath);
94
95         // appRoot/lib
96         destPath = appRootPath + DIR_LIB;
97         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
98         smackManager.AddLabelDir(packageId, destPath);
99
100         // appRoot/shared
101         destPath = appRootPath + DIR_SHARED;
102         if (File::IsFileExist(destPath) == false)
103         {
104                 r = Directory::Create(destPath, false);
105                 TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed");
106         }
107         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
108         smackManager.AddLabelDir(packageId, destPath);
109
110         // appRoot/shared/res
111         destPath = appRootPath + DIR_SHARED_RES;
112         if (File::IsFileExist(destPath) == false)
113         {
114                 String iconPath = appRootPath + DIR_ICONS;
115                 InstallerUtil::CreateSymlink(iconPath, destPath);
116         }
117         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
118         smackManager.AddLabelDir(packageId, destPath);
119
120         // appRoot/shared/data
121         destPath = appRootPath + DIR_SHARED_DATA;
122         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
123         smackManager.AddLabelSharedDir(packageId, destPath);
124
125         // appRoot/shared/trusted
126         destPath = appRootPath + DIR_SHARED_TRUSTED;
127         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
128         smackManager.AddLabelSharedDir(packageId, destPath);
129
130         // appRoot/contents
131         destPath = appRootPath + DIR_CONTENTS;
132         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
133         smackManager.AddLabelDir(packageId, destPath);
134
135         // appRoot/setting
136         destPath = appRootPath + DIR_SETTING;
137         if (File::IsFileExist(destPath) == true)
138         {
139                 String appVersion = pContext->__version;
140                 String srcPath;
141                 String settingXmlPath;
142                 String label = "*";
143                 //String label = packageId;
144                 //label.Append("_setting");
145
146                 srcPath = destPath + L"/setting." + appVersion + L".xml";
147                 settingXmlPath = destPath + L"/setting.xml";
148
149                 InstallerUtil::Remove(settingXmlPath);
150                 InstallerUtil::CreateSymlink(srcPath, settingXmlPath);
151
152                 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
153                 smackManager.AddLabelDir(label, destPath);
154         }
155
156         // appRoot/data
157         destPath = appRootPath + DIR_DATA;
158         if (File::IsFileExist(destPath) == false)
159         {
160                 r = Directory::Create(destPath, false);
161                 TryReturn(!IsFailed(r), false, "Directory::Create() failed");
162         }
163         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
164         smackManager.AddLabelDir(packageId, destPath);
165
166         String apiVersion = pContext->__apiVersion;
167
168         AppLog("------------------------------------------");
169         AppLog("[Tizen::Io] # path = [%ls]", appRootPath.GetPointer());
170         AppLog("[Tizen::Io] # package = [%ls]", packageId.GetPointer());
171         AppLog("[Tizen::Io] # apiVersion = [%ls]", apiVersion.GetPointer());
172
173         if (pContext->__isOspCompat == true)
174         {
175                 AppLog("[Tizen::Io] OSP 2.0 application");
176
177                 res = CompatibilityManager::PrepareDataCaging(appRootPath, packageId);
178                 TryReturn(res == true, false, "[Tizen::Io] CompatibilityManager::PrepareDataCaging() failed.");
179
180                 SetSymLink(pContext);
181         }
182         else
183         {
184                 AppLog("[Tizen::Io] apiVersion is equal to or greater than Tizen 2.0");
185
186                 res = CompatibilityManager::CleanDirectories(appRootPath, packageId);
187                 TryReturn(res == true, false, "[Tizen::Io] CompatibilityManager::CleanDirectories() failed.");
188
189                 res = CompatibilityManager::LinkOspSharePath(appRootPath, packageId);
190                 TryReturn(res == true, false, "[Tizen::Io] CompatibilityManager::LinkOspSharePath() failed.");
191         }
192
193         if (pContext->__isVirtualRoot == true)
194         {
195                 res = CompatibilityManager::PrepareVirtualRoot(appRootPath, packageId);
196                 TryReturn(res == true, false, "[Tizen::Io] CompatibilityManager::PrepareVirtualRoot() failed.");
197         }
198         AppLog("------------------------------------------");
199
200         return true;
201 }
202
203 bool
204 PermissionManager::SetFile(InstallationContext* pContext)
205 {
206         String destPath;
207         String appRootPath = pContext->__rootPath;
208
209         IListT<AppData*>* pAppDataList = pContext->__pAppDataList;
210         TryReturn(pAppDataList, false, "pAppDataList is null");
211
212         for (int i = 0 ; i < pAppDataList->GetCount(); i++)
213         {
214                 AppData* pAppData = null;
215                 pAppDataList->GetAt(i, pAppData);
216                 TryReturn(pAppData, false, "pAppData is null");
217
218                 // set permission(755) to bin file.
219                 destPath = appRootPath + DIR_BIN + L"/" + pAppData->__name + L".exe";
220                 if (File::IsFileExist(destPath) == true)
221                 {
222                         InstallerUtil::ChangeMode(destPath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
223                 }
224         }
225
226         return true;
227 }
228
229 bool
230 PermissionManager::SetSymLink(InstallationContext* pContext)
231 {
232         String oldPath;
233         String newPath;
234         String appRootPath = pContext->__rootPath;
235
236         SmackManager smackManager;
237
238 #if 0
239         oldPath = appRootPath + DIR_RES;
240         newPath = appRootPath + L"/Res";
241         InstallerUtil::CreateSymlink(oldPath, newPath);
242 #else
243         newPath = appRootPath + L"/Res";
244         std::unique_ptr< char[] > pResPath(_StringConverter::CopyToCharArrayN(newPath));
245         int ret = symlink("./res", pResPath.get());
246         smackManager.AddLabelDir(pContext->__packageId, newPath);
247 #endif
248
249 #if 0
250         oldPath = appRootPath + DIR_DATA;
251         newPath = appRootPath + L"/Home";
252         InstallerUtil::CreateSymlink(oldPath, newPath);
253 #else
254         newPath = appRootPath + L"/Home";
255         std::unique_ptr< char[] > pHomePath(_StringConverter::CopyToCharArrayN(newPath));
256         ret = symlink("./data", pHomePath.get());
257         smackManager.AddLabelDir(pContext->__packageId, newPath);
258 #endif
259
260         oldPath = appRootPath + DIR_RES + L"/screen-size-normal";
261         newPath = appRootPath + L"/Res/ScreenSize-Normal";
262         InstallerUtil::CreateSymlink(oldPath, newPath);
263
264         oldPath = appRootPath + DIR_RES + L"/screen-density-high";
265         newPath = appRootPath + L"/Res/ScreenDensity-High";
266         InstallerUtil::CreateSymlink(oldPath, newPath);
267
268         oldPath = appRootPath + DIR_RES + L"/screen-density-middle";
269         newPath = appRootPath + L"/Res/ScreenDensity-Middle";
270         InstallerUtil::CreateSymlink(oldPath, newPath);
271
272         oldPath = appRootPath + DIR_RES + L"/screen-density-low";
273         newPath = appRootPath + L"/Res/ScreenDensity-Low";
274         InstallerUtil::CreateSymlink(oldPath, newPath);
275
276         return true;
277 }
278
279 bool
280 PermissionManager::CopyForRds(InstallationContext* pContext, IList* pFileList, bool& isInstallRequired)
281 {
282         TryReturn(pFileList, false, "pFileList is null.");
283
284         for (int idx = 0; idx < pFileList->GetCount(); idx++)
285         {
286                 String* pFilePath = static_cast<String *>(pFileList->GetAt(idx));
287                 TryReturn(pFilePath, false, "pFilePath is null.");
288
289                 String srcFile = DIR_APPLICATIONS_TMP;
290                 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
291                 String destFile = pContext->__rootPath + L"/" + *pFilePath;
292
293                 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
294
295                 int pos = 0;
296                 result r = E_SUCCESS;
297                 String destDir;
298
299                 if (destFile.EndsWith(L"/") == true)
300                 {
301                         destDir = destFile;
302                         if (File::IsFileExist(destDir) == false)
303                         {
304                                 Directory::Create(destDir, true);
305                         }
306                         continue;
307                 }
308                 else
309                 {
310                         r = destFile.LastIndexOf(L'/', destFile.GetLength() -1, pos);
311                         if (IsFailed(r) == true)
312                         {
313                                 AppLog("destFile is invalid[%ls]", destFile.GetPointer());
314                                 continue;
315                         }
316                         destFile.SubString(0, pos, destDir);
317                 }
318
319                 if (File::IsFileExist(destDir) == false)
320                 {
321                         Directory::Create(destDir, true);
322                 }
323                 InstallerUtil::Remove(destFile);
324                 r = File::Copy(srcFile, destFile, true);
325                 if (IsFailed(r) == true)
326                 {
327                         AppLog("File::Copy() failed. [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
328                         continue;
329                 }
330
331                 if (*pFilePath == L"info/manifest.xml")
332                 {
333                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
334                         isInstallRequired = true;
335                 }
336                 else if (pFilePath->StartsWith("setting/setting", 0) == true)
337                 {
338                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
339                         isInstallRequired = true;
340                 }
341         }
342
343         return true;
344 }
345
346 bool
347 PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
348 {
349         String destPath;
350         String appRootPath;
351         SmackManager smackManager;
352         smackManager.Construct(pContext);
353
354         appRootPath = pContext->__rootPath;
355         PackageId packageId = pContext->__packageId;
356
357         // appRoot
358         InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
359         smackManager.AddLabelDir(packageId, appRootPath, true);
360
361         // appRoot/bin
362         destPath = appRootPath + DIR_BIN;
363         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
364         smackManager.AddLabelDir(packageId, destPath);
365
366         // appRoot/info
367         destPath = appRootPath + DIR_INFO;
368         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
369         smackManager.AddLabelDir(packageId, destPath);
370
371         // appRoot/res
372         destPath = appRootPath + DIR_RES;
373         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
374         smackManager.AddLabelDir(packageId, destPath);
375
376         // appRoot/lib
377         destPath = appRootPath + DIR_LIB;
378         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
379         smackManager.AddLabelDir(packageId, destPath);
380
381         // appRoot/shared
382         destPath = appRootPath + DIR_SHARED;
383         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
384         smackManager.AddLabelDir(packageId, destPath);
385
386         // appRoot/shared/res
387         destPath = appRootPath + DIR_SHARED_RES;
388         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
389         smackManager.AddLabelSharedDir(packageId, destPath);
390
391         // appRoot/shared/data
392         destPath = appRootPath + DIR_SHARED_DATA;
393         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
394         smackManager.AddLabelSharedDir(packageId, destPath);
395
396         // appRoot/shared/trusted
397         destPath = appRootPath + DIR_SHARED_TRUSTED;
398         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
399         smackManager.AddLabelSharedDir(packageId, destPath);
400
401         // appRoot/setting
402         destPath = appRootPath + DIR_SETTING;
403         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
404         smackManager.AddLabelDir(packageId, destPath);
405
406         // appRoot/data
407         destPath = appRootPath + DIR_DATA;
408         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
409         smackManager.AddLabelDir(packageId, destPath);
410
411         return true;
412 }
413
414 #if 0
415 bool
416 PermissionManager::ApplyPermission(InstallationContext* pContext, const IList* pFileList)
417 {
418         TryReturn(pContext, false, "pContext is null");
419         TryReturn(pFileList, false, "pFileList is null");
420
421         // dir | type | owner | mode | smack
422         static RdsPermssions perms[] =
423         {
424                 {"res",                         PERM_DIR_RES,                           PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
425                 {"data",                        PERM_DIR_DATA,                          PERM_OWNER_APP,         PERM_BASE,                                              PERM_SMACK_0},
426                 {"bin",                         PERM_DIR_BIN,                           PERM_OWNER_ROOT,        (PERM_BASE | PERM_EXECUTE),             PERM_SMACK_0},
427                 {"info",                        PERM_DIR_INFO,                          PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
428                 {"lib",                         PERM_DIR_LIB,                           PERM_OWNER_ROOT,        (PERM_BASE | PERM_EXECUTE),             PERM_SMACK_0},
429                 {"setting",                     PERM_DIR_SETTING,                       PERM_OWNER_ROOT,        (PERM_BASE | PERM_WRITE),               PERM_SMACK_0},
430                 {"shared/res",          PERM_DIR_SHARED_RES,            PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
431                 {"shared/data",         PERM_DIR_SHARED_DATA,           PERM_OWNER_APP,         PERM_BASE,                                              PERM_SMACK_0},
432                 {"shared/trusted",      PERM_DIR_SHARED_TRUSTED,        PERM_OWNER_APP,         PERM_BASE,                                              PERM_SMACK_0},
433                 {"shared",                      PERM_DIR_SHARED,                        PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
434                 {"author",                      PERM_DIR_ROOT,                          PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
435                 {"signature",           PERM_DIR_ROOT,                          PERM_OWNER_ROOT,        PERM_BASE,                                              PERM_SMACK_0},
436         };
437
438         static int permCount = sizeof(perms) / sizeof(RdsPermssions);
439         bool isInstallRequired = false;
440         SmackManager smackManager;
441         smackManager.Construct(pContext);
442
443         for (int i = 0; i < pFileList->GetCount(); i++)
444         {
445                 const String *pFilePath = static_cast<const String *>(pFileList->GetAt(i));
446                 TryReturn(pFilePath, false, "pFilePath is null");
447
448                 AppLog("pFilePath=(%ls)", pFilePath->GetPointer());
449
450                 int permIdx = 0;
451                 for (permIdx = 0; permIdx < permCount; permIdx++)
452                 {
453                         if (pFilePath->StartsWith(perms[permIdx].pDir, 0) == true)
454                         {
455                                 if (perms[permIdx].dirType == PERM_DIR_INFO)
456                                 {
457                                         if (*pFilePath == L"info/manifest.xml")
458                                         {
459                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
460                                                 isInstallRequired = true;
461                                         }
462                                 }
463                                 else if (perms[permIdx].dirType == PERM_DIR_SETTING)
464                                 {
465                                         if (pFilePath->StartsWith("setting/setting", 0) == true)
466                                         {
467                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
468                                                 isInstallRequired = true;
469                                         }
470                                 }
471
472                                 AppLog("dirType=(%d), owner=(%d), mode=(%d), smack=(%d)",
473                                                 perms[permIdx].dirType, perms[permIdx].ownerIndex, perms[permIdx].modeIndex, perms[permIdx].smackIndex);
474
475                                 String srcFile = DIR_APPLICATIONS_TMP;
476                                 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
477                                 String destFile = pContext->__rootPath + L"/" + *pFilePath;
478
479                                 AppLog("copy file: from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
480                                 File::Copy(srcFile, destFile, false);
481
482                                 bool isAppOwner = false;
483                                 if (perms[permIdx].ownerIndex == PERM_OWNER_APP)
484                                 {
485                                         isAppOwner = true;
486                                 }
487
488                                 String destPath;
489                                 if (perms[permIdx].dirType != PERM_DIR_ROOT)
490                                 {
491                                         destPath = pContext->__rootPath + L"/" + perms[permIdx].pDir;
492                                         InstallerUtil::ChangeDirectoryPermission(destPath, perms[permIdx].modeIndex, isAppOwner);
493                                 }
494                                 else
495                                 {
496                                         destPath = pContext->__rootPath + L"/" + *pFilePath;
497                                         InstallerUtil::ChangeMode(*pFilePath, perms[permIdx].modeIndex);
498                                 }
499                                 smackManager.AddLabelSharedDir(pContext->__packageId, destPath);
500
501                                 break;
502                         }
503                 }
504         }
505
506         return true;
507 }
508 #endif
509
510