From: 조웅석/Common Platform Lab(SR)/Principal Engineer/삼성전자 Date: Thu, 24 Dec 2020 00:52:44 +0000 (+0900) Subject: Support regen-app-ni for read-only app (#301) X-Git-Tag: submit/tizen/20201224.021710~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1ced14b73b97a630815fc200da6c8c15f5363f9a;p=platform%2Fcore%2Fdotnet%2Flauncher.git Support regen-app-ni for read-only app (#301) When a partial update of tizenfx occurs, native image files of application created with FNV option must be regenerated. However, it is not possible with the current implementation to replace the native-image files of the app installed in the read-only area like the preload app. To solve this problem, add a functionality that creates new native images under /opt/usr/dotnet/apps, when creating a new native image files of read-only app. --- diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt index c344aab..fc67894 100644 --- a/NativeLauncher/CMakeLists.txt +++ b/NativeLauncher/CMakeLists.txt @@ -51,6 +51,10 @@ IF(DEFINED DOTNET_DIR) SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DDOTNET_DIR=${DOTNET_DIR}") ENDIF(DEFINED DOTNET_DIR) +IF(DEFINED READ_ONLY_APP_UPDATE_DIR) + SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DREAD_ONLY_APP_UPDATE_DIR=${READ_ONLY_APP_UPDATE_DIR}") +ENDIF(DEFINED READ_ONLY_APP_UPDATE_DIR) + IF(DEFINED USE_DEFAULT_BASE_ADDR) SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DUSE_DEFAULT_BASE_ADDR") ENDIF(DEFINED USE_DEFAULT_BASE_ADDR) diff --git a/NativeLauncher/inc/ni_common.h b/NativeLauncher/inc/ni_common.h index bdaba44..944448a 100644 --- a/NativeLauncher/inc/ni_common.h +++ b/NativeLauncher/inc/ni_common.h @@ -30,6 +30,7 @@ #define NI_FLAGS_APPNI 0x0002 #define NI_FLAGS_COMPATIBILITY 0x0004 #define NI_FLAGS_VERBOSE 0x0008 +#define NI_FLAGS_READONLY_APP 0x0010 #define NI_FLAGS_INSTRUMENT 0x1000 typedef std::function afterCreate; @@ -59,15 +60,15 @@ void finalizeNICommon(); /** * @brief create native images for platform DLLs (.NETCore + TizenFX) - * @param[i] flags additional flags for the image generator + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e createNIPlatform(DWORD flags); /** * @brief create a native image for a single DLL - * @param[i] dllPath path to input DLL - * @param[i] flags additional flags for the image generator + * @param[in] dllPath path to input DLL + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e createNIDll(const std::string& dllPath, DWORD flags); @@ -75,16 +76,16 @@ ni_error_e createNIDll(const std::string& dllPath, DWORD flags); /** * @brief create native images for all DLLs under directories - * @param[i] rootPaths paths to directories - * @param[i] flags additional flags for the image generator + * @param[in] rootPaths paths to directories + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e createNIUnderDirs(const std::string& rootPaths, DWORD flags); /** * @brief create native images for all DLLs in a package - * @param[i] pkgId package ID - * @param[i] flags additional flags for the image generator + * @param[in] pkgId package ID + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e createNIUnderPkgRoot(const std::string& pkgId, DWORD flags); @@ -96,27 +97,27 @@ void removeNIPlatform(); /** * @brief remove native images under directories - * @param[i] rootPaths paths to directories + * @param[in] rootPaths paths to directories */ void removeNIUnderDirs(const std::string& rootPaths); /** * @brief remove native images of a package - * @param[i] pkgId package ID + * @param[in] pkgId package ID * @return ni_error_e */ ni_error_e removeNIUnderPkgRoot(const std::string& pkgId); /** * @brief regenerate native images of all installed applications - * @param[i] flags additional flags for the image generator + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e regenerateAppNI(DWORD flags); /** * @brief regenerate native image of TAC for all shared assembly. - * @param[i] flags additional flags for the image generator + * @param[in] flags additional flags for the image generator * @return ni_error_e */ ni_error_e regenerateTACNI(DWORD flags); diff --git a/NativeLauncher/inc/path_manager.h b/NativeLauncher/inc/path_manager.h index 3de0d7b..38ca327 100644 --- a/NativeLauncher/inc/path_manager.h +++ b/NativeLauncher/inc/path_manager.h @@ -69,8 +69,8 @@ public: /** * @brief Add platform assemblies paths. The TPA(Trusted-Platform-Assembly) is generated based on this paths - * @param[i] paths the paths to be added - * @param[i] isHighPriority if true, paths are added in front of the current list, otherwise added at the end of the list + * @param[in] paths the paths to be added + * @param[in] isHighPriority if true, paths are added in front of the current list, otherwise added at the end of the list */ void addPlatformAssembliesPaths(const std::string& paths, bool isHighPriority = false); @@ -78,67 +78,74 @@ public: * @brief Set application root path. * All application related paths ("bin", "lib", ".tac_symlink", ".native_image") are generated based on it. * A temporary path (/proc/self/fd/[fd]) is used if this function is never called. - * @param[i] rootPath application root path + * @param[in] rootPath application root path */ void setAppRootPath(const std::string& rootPath); /** * @brief Get runtime path which contains coreclr and corefx - * @return[i] runtime path + * @return runtime path */ const std::string& getRuntimePath(); /** * @brief Get tizenfx path which contains tizenfx - * @return[i] runtime path + * @return runtime path */ const std::string& getTizenFXPath(); /** * @brief Get platform assemblies paths - * @return[i] return path vector + * @return return path vector */ const std::vector& getPlatformAssembliesPaths(); /** * @brief Get application root path * @see setAppRootPath() - * @return[i] system paths + * @return system paths */ const std::string& getAppRootPath(); /** * @brief Get the path of .tac_symlink of application - * @return[i] .tac_symlink path + * @return .tac_symlink path */ const std::string& getAppTacPath(); /** * @brief Get the list of directories where the assemlies of this application exist - * @return[i] the list(":" seperated) of paths to probe in for an assembly + * @return the list(":" seperated) of paths to probe in for an assembly */ const std::string& getAppPaths(); /** * @brief Get the list of directories where the native image of this application exist - * @return[i] the list(":" seperated) of paths to probe in for an native image + * @return the list(":" seperated) of paths to probe in for an native image */ const std::string& getAppNIPaths(); /** * @brief Get the list of directories where the native libraries of this application exist - * @return[i] the list(":" seperated) of paths the loader should probe when looking for native libraries + * @return the list(":" seperated) of paths the loader should probe when looking for native libraries */ const std::string& getNativeDllSearchingPaths(); private: - // update application related path (bin, lib, tac_symlink, native_image) - void updateAppRelatedPath(const std::string& appRootPath); + /** + * @brief Update application related path (bin, lib, tac_symlink, native_image) + * In most cases, appRootPath and appNIRootPath are the same. + * Apps installed in read-only storage may have a different appNIRootPath. + * @param[in] root path of application. (APP_PATH is geneated based on root path) + * @param[in] root path for native image (APP_NI_PATH is generated based on on ni root path ) + */ + void updateAppRelatedPath(const std::string& appRootPath, const std::string& appNIRootPath); private: std::vector platformAssembliesPaths; std::string systemPaths; std::string appRootPath; + std::string appNIRootPath; std::string runtimePath; std::string tizenfxPath; std::string appPaths; @@ -146,6 +153,7 @@ private: std::string nativeDllSearchingPaths; std::string appTacPath; int rootFD; + int niRootFD; }; #endif /* __DLL_PATH_MANAGER_H__ */ diff --git a/NativeLauncher/inc/tac_common.h b/NativeLauncher/inc/tac_common.h index a97eb70..17e2441 100644 --- a/NativeLauncher/inc/tac_common.h +++ b/NativeLauncher/inc/tac_common.h @@ -37,14 +37,14 @@ tac_error_e tac_restoreDB(); /** * @brief disable tac feature. - * @param[i] pkgId package ID + * @param[in] pkgId package ID * @return tac_error_e */ tac_error_e disableTACPackage(const std::string& pkgId); /** * @brief enable tac feature. - * @param[i] pkgId package ID + * @param[in] pkgId package ID * @return tac_error_e */ tac_error_e enableTACPackage(const std::string& pkgId); diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h index dc4d6c4..505fba9 100644 --- a/NativeLauncher/inc/utils.h +++ b/NativeLauncher/inc/utils.h @@ -44,21 +44,21 @@ enum FSFlag : int { * @brief concat path with PATH_SEPARATOR * @param[in] destination path * @param[in] source path - * return std::string result path + * @return std::string result path */ std::string concatPath(const std::string& path1, const std::string& path2); /** * @brief get canonicalized absolute Path * @param[in] source path - * return std::string result path + * @return std::string result path */ std::string getAbsolutePath(const std::string& path); /** * @brief get the directory of file * @param[in] source path - * return std::string result path + * @return std::string result path */ std::string getBaseName(const std::string& path); @@ -67,28 +67,28 @@ std::string getBaseName(const std::string& path); * @param[in] original string * @param[in] pattern to match * @param[in] replacement string - * return std::string the modified string + * @return std::string the modified string */ std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace); /** * @brief get root path * @param[in] package id - * return std::string root path + * @return std::string root path */ std::string getRootPath(const std::string& pkgId); /** * @brief get exec name * @param[in] package id - * return std::string exec name + * @return std::string exec name */ std::string getExecName(const std::string& pkgId); /** * @brief get app type * @param[in] package id - * return std::string app type + * @return std::string app type */ std::string getAppType(const std::string& pkgId); @@ -96,10 +96,17 @@ std::string getAppType(const std::string& pkgId); * @brief get metadata value * @param[in] package id * @param[in] metadata key - * return std::string metadata value + * @return std::string metadata value */ std::string getMetadataValue(const std::string& pkgId, const std::string& key); +/** + * @brief check the package is 'readonly' or not + * @param[in] package id + * @return bool package readonly value + */ +bool isReadOnlyApp(const std::string& pkgId); + /** * @brief split path with ":" delimiter and put that in the vector * @param[in] source path diff --git a/NativeLauncher/tool/dotnettool.cc b/NativeLauncher/tool/dotnettool.cc index c5d5af2..83f0b6a 100644 --- a/NativeLauncher/tool/dotnettool.cc +++ b/NativeLauncher/tool/dotnettool.cc @@ -40,6 +40,7 @@ void DisplayUsage() { " --ni-reset-pkg - Remove App NI files\n" " --ni-reset-dir - Remove NI for directory\n" " --ni-regen-all-app - Re-generate All App NI files\n" + " --ni-regen-all-ro-app - Re-generate All read-only type App NI files\n" " --tac-regen-all - Re-generate All TAC files\n" " --tac-restore-db - Restore TAC Database\n" " --tac-disable-pkg - Disable TAC for package\n" @@ -224,6 +225,14 @@ int main(int argc, char* argv[]) fprintf(stderr, "Failed to regenerate all app NI\n"); } } + //sh-3.2# dotnettool --ni-regen-readonly-app + else if (cmd == "--ni-regen-all-ro-app") { + flags |= NI_FLAGS_READONLY_APP; + int ret = regenerateAppNI(flags); + if (ret != NI_ERROR_NONE) { + fprintf(stderr, "Failed to regenerate read-only app NI\n"); + } + } //sh-3.2# dotnettool --tac-regen-all else if (cmd == "--tac-regen-all") { int ret = regenerateTACNI(flags); diff --git a/NativeLauncher/tool/ni_common.cc b/NativeLauncher/tool/ni_common.cc index db1eab6..1a8f894 100644 --- a/NativeLauncher/tool/ni_common.cc +++ b/NativeLauncher/tool/ni_common.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include "ni_common.h" #include "db_manager.h" @@ -60,6 +61,7 @@ static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR); #endif static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH); static const char* __DOTNET_DIR = __STR(DOTNET_DIR); +static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR); #ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT static const char* __SYSTEM_BASE_FILE = __STR(SYSTEM_BASE_FILE); @@ -97,32 +99,67 @@ static std::string getNIFilePath(const std::string& dllPath) return niPath; } -static std::string getAppNIFilePath(const std::string& niPath) +/** + * @brief create the directory including parents directory, and + * copy ownership and smack labels to the created directory. + * @param[in] target directory path + * @param[in] source directory path to get ownership and smack label + * @return if directory created successfully, return true otherwise false + */ +static bool createDirsAndCopyOwnerShip(std::string& target_path, const std::string& source) +{ + struct stat st; + mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + + for (std::string::iterator iter = target_path.begin(); iter != target_path.end();) { + std::string::iterator newIter = std::find(iter, target_path.end(), '/'); + std::string newPath = std::string(target_path.begin(), newIter); + + if (!newPath.empty()) { + if (stat(newPath.c_str(), &st) != 0) { + if (mkdir(newPath.c_str(), mode) != 0 && errno != EEXIST) { + fprintf(stderr, "Fail to create app ni directory (%s)\n", newPath.c_str()); + return false; + } + if (!source.empty()) { + copySmackAndOwnership(source, newPath); + } + } else { + if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "Fail. path is not a dir (%s)\n", newPath.c_str()); + return false; + } + } + } + iter = newIter; + if(newIter != target_path.end()) { + ++iter; + } + } + + return true; +} + +static std::string getAppNIFilePath(const std::string& absDllPath, DWORD flags) { - std::string fileName; std::string niDirPath; std::string prevPath; - size_t index = niPath.find_last_of("/"); - if (index != std::string::npos) { - prevPath = niPath.substr(0, index); - fileName = niPath.substr(index + 1, niPath.length()); - } else { - prevPath = "."; - fileName = niPath; - } - + prevPath = getBaseName(absDllPath); niDirPath = concatPath(prevPath, APP_NI_SUB_DIR); - if (!isFile(niDirPath)) { - if (mkdir(niDirPath.c_str(), 0755) == 0) { - copySmackAndOwnership(prevPath, niDirPath); - } else { - fprintf(stderr, "Fail to create app ni directory (%s)\n", niDirPath.c_str()); + if (flags & NI_FLAGS_READONLY_APP) { + niDirPath = replaceAll(niDirPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR); + } + + if (!isDirectory(niDirPath)) { + if (!createDirsAndCopyOwnerShip(niDirPath, prevPath)) { + niDirPath = prevPath; + fprintf(stderr, "fail to create dir (%s)\n", niDirPath.c_str()); } } - return concatPath(niDirPath, fileName); + return getNIFilePath(concatPath(niDirPath, getFileName(absDllPath))); } static bool checkNIExistence(const std::string& path) @@ -255,18 +292,20 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat } std::string absDllPath = getAbsolutePath(dllPath); - std::string absNIPath = getNIFilePath(dllPath); + std::string absNIPath; + + bool isAppNI = flags & NI_FLAGS_APPNI; + if (isAppNI && strstr(absDllPath.c_str(), __DOTNET_DIR) == NULL) { + absNIPath = getAppNIFilePath(absDllPath, flags); + } else { + absNIPath = getNIFilePath(absDllPath); + } if (absNIPath.empty()) { fprintf(stderr, "Fail to get ni file name\n"); return NI_ERROR_UNKNOWN; } - bool isAppNI = flags & NI_FLAGS_APPNI; - if (isAppNI && strstr(absNIPath.c_str(), __DOTNET_DIR) == NULL) { - absNIPath = getAppNIFilePath(absNIPath); - } - #ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT uintptr_t baseAddr = 0; @@ -388,9 +427,23 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) return -1; } - if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) { - fprintf(stderr, "Failed to remove previous dlls from [%s]\n", pkgId); - return -1; + bool readOnlyApp = isReadOnlyApp(pkgId); + + // read-only and readonly flag set + if (readOnlyApp && (*pFlags & NI_FLAGS_READONLY_APP)) { + fprintf(stderr, "try to regenerate read-only pkg [%s]\n", pkgId); + } + // not rad-only and readonly flag doesnot set + else if (!readOnlyApp && !(*pFlags & NI_FLAGS_READONLY_APP)) { + if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to remove previous dlls from [%s]\n", pkgId); + return -1; + } + } + // skip regeneration + else { + fprintf(stderr, "skip regeneration. pkg-type(read-only) doesnot match the configuration [%s]\n", pkgId); + return 0; } if (createNIUnderPkgRoot(pkgId, *pFlags) != NI_ERROR_NONE) { diff --git a/NativeLauncher/tool/tac_common.cc b/NativeLauncher/tool/tac_common.cc index eed13a2..9335325 100644 --- a/NativeLauncher/tool/tac_common.cc +++ b/NativeLauncher/tool/tac_common.cc @@ -32,6 +32,7 @@ #define __XSTR(x) #x #define __STR(x) __XSTR(x) static const char* __DOTNET_DIR = __STR(DOTNET_DIR); +static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR); #undef __STR #undef __XSTR @@ -45,15 +46,16 @@ static void cleanupDirectory() std::vector removeNuget; try { for (auto& nuget : bf::recursive_directory_iterator(__DOTNET_DIR)) { - bool isExist = false; std::string nugetPath = nuget.path().string(); + if (!bf::is_directory(nugetPath) || + nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos || + nugetPath.find(__READ_ONLY_APP_UPDATE_DIR) != std::string::npos) { + continue; + } + + bool isExist = false; for (auto& restore : restore_nuget) { - if (!bf::is_directory(nugetPath) || nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos) { - isExist = true; - break; - } - if (!strcmp(nugetPath.c_str(), restore.c_str()) || - !strcmp(nugetPath.c_str(), restore.substr(0, restore.rfind('/')).c_str())) { + if (nugetPath == restore || nugetPath == getBaseName(restore)) { isExist = true; break; } diff --git a/NativeLauncher/util/path_manager.cc b/NativeLauncher/util/path_manager.cc index ee456f3..ae89ca2 100644 --- a/NativeLauncher/util/path_manager.cc +++ b/NativeLauncher/util/path_manager.cc @@ -36,6 +36,8 @@ static const char* __TIZEN_API_PATH_KEY = "db/dotnet/tizen_api_path"; static const char* __DEVICE_API_DIR = __STR(DEVICE_API_DIR); static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR); static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR); +static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR); + #undef __STR #undef __XSTR @@ -52,19 +54,23 @@ static std::string getExtraNativeLibDirs(const std::string& appRoot) return candidate; } -void PathManager::updateAppRelatedPath(const std::string& appRootPath) +void PathManager::updateAppRelatedPath(const std::string& appRootPath, const std::string& appNIRootPath) { std::string appBinPath = concatPath(appRootPath, "bin"); std::string appLibPath = concatPath(appRootPath, "lib"); + std::string appNIBinPath = concatPath(concatPath(appNIRootPath, "bin"), APP_NI_SUB_DIR); + std::string appNILibPath = concatPath(concatPath(appNIRootPath, "lib"), APP_NI_SUB_DIR); + appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR); appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath; - appNIPaths = concatPath(appBinPath, APP_NI_SUB_DIR) + ":" + concatPath(appLibPath, APP_NI_SUB_DIR) + ":"+ appTacPath; - nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + appBinPath + ":" + appLibPath + ":" + getExtraNativeLibDirs(appRootPath); + appNIPaths = appNIBinPath + ":" + appNILibPath + ":"+ appTacPath; + nativeDllSearchingPaths = runtimePath + ":" + __NATIVE_LIB_DIR + ":" + appBinPath + ":" + appLibPath + ":" + getExtraNativeLibDirs(appRootPath); } PathManager::PathManager() : - rootFD(-1) + rootFD(-1), + niRootFD(-1) { // set runtime path runtimePath = getAbsolutePath(__RUNTIME_DIR); @@ -89,8 +95,16 @@ PathManager::PathManager() : throw std::ios_base::failure("Fail to open /proc/self"); } + // set temporal application root path for native image + niRootFD = open("/proc/self", O_DIRECTORY); + if (niRootFD < 0) { + _ERR("Failed to open /proc/self"); + throw std::ios_base::failure("Fail to open /proc/self"); + } + appRootPath = std::string("/proc/self/fd/") + std::to_string(rootFD); - updateAppRelatedPath(appRootPath); + appNIRootPath = std::string("/proc/self/fd/") + std::to_string(niRootFD); + updateAppRelatedPath(appRootPath, appNIRootPath); _INFO("Path manager created successfully"); } @@ -122,16 +136,33 @@ void PathManager::addPlatformAssembliesPaths(const std::string& paths, bool isHi void PathManager::setAppRootPath(const std::string& rootPath) { + appRootPath = getAbsolutePath(rootPath); + + // check readonly update directory eixst or not + std::string niRootPath = replaceAll(appRootPath, getBaseName(appRootPath), __READ_ONLY_APP_UPDATE_DIR); + if (isDirectory(niRootPath)) { + appNIRootPath = getAbsolutePath(niRootPath); + } else { + appNIRootPath = appRootPath; + } + // override root path for application launch mode (candidate / standalone mode) if (rootFD >= 0) { - int tmpFD = open(rootPath.c_str(), O_DIRECTORY); + int tmpFD = open(appRootPath.c_str(), O_DIRECTORY); dup3(tmpFD, rootFD, O_CLOEXEC); if (tmpFD >= 0) close(tmpFD); } - appRootPath = getAbsolutePath(rootPath); - updateAppRelatedPath(appRootPath); + // override ni root path + if (niRootFD >= 0) { + int tmpFD = open(appNIRootPath.c_str(), O_DIRECTORY); + dup3(tmpFD, niRootFD, O_CLOEXEC); + if (tmpFD >= 0) + close(tmpFD); + } + + updateAppRelatedPath(appRootPath, appNIRootPath); } const std::string& PathManager::getRuntimePath() diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc index 0dd7777..00cb0c8 100644 --- a/NativeLauncher/util/utils.cc +++ b/NativeLauncher/util/utils.cc @@ -236,6 +236,39 @@ std::string getMetadataValue(const std::string& pkgId, const std::string& key) return metadataValue; } +bool isReadOnlyApp(const std::string& pkgId) +{ + bool readOnly = false; + int ret = 0; + uid_t uid = 0; + + if (pkgmgr_installer_info_get_target_uid(&uid) < 0) { + _ERR("Failed to get UID"); + return readOnly; + } + + pkgmgrinfo_pkginfo_h handle; + if (uid == 0) { + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle); + } else { + ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle); + } + + if (ret != PMINFO_R_OK) { + return readOnly; + } + + ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readOnly); + if (ret != PMINFO_R_OK) { + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return readOnly; + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + + return readOnly; +} + std::string getBaseName(const std::string& path) { auto pos = path.find_last_of(PATH_SEPARATOR); diff --git a/dotnet-launcher.manifest b/dotnet-launcher.manifest index e14cc1f..71d0ad6 100644 --- a/dotnet-launcher.manifest +++ b/dotnet-launcher.manifest @@ -4,6 +4,7 @@ + diff --git a/packaging/dotnet-launcher.spec b/packaging/dotnet-launcher.spec index 80685dc..1db30cd 100644 --- a/packaging/dotnet-launcher.spec +++ b/packaging/dotnet-launcher.spec @@ -58,6 +58,7 @@ Requires(preun): /usr/bin/systemctl %define _install_plugin_dir /etc/package-manager/parserlib %define _native_lib_dir /usr/share/dotnet.tizen/lib %define _dotnet_dir /opt/usr/dotnet +%define _readonly_app_update_dir /opt/usr/dotnet/apps %define _system_base_addr_file /opt/usr/dotnet.system.base.addr %define _ibc_data_dir /usr/share/dotnet.tizen/ibcdata @@ -127,6 +128,7 @@ cmake \ -DINSTALL_MDPLUGIN_DIR=%{_install_mdplugin_dir} \ -DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \ -DDOTNET_DIR=%{_dotnet_dir} \ + -DREAD_ONLY_APP_UPDATE_DIR=%{_readonly_app_update_dir} \ -DVERSION=%{version} \ -DNATIVE_LIB_DIR=%{_native_lib_dir} \ %ifarch %{arm} aarch64 @@ -149,6 +151,7 @@ mv Managed/Tizen.Runtime/bin/Release/Tizen.Runtime.dll %{buildroot}%{_framework_ mv Managed/Tizen.Runtime/bin/Release/Tizen.Runtime.pdb %{buildroot}%{_framework_dir} mkdir -p %{buildroot}%{_dotnet_dir} +mkdir -p %{buildroot}%{_readonly_app_update_dir} mkdir -p %{buildroot}%{_native_lib_dir} ln -sf %{_libdir}/libsqlite3.so.0 %{buildroot}%{_native_lib_dir}/libsqlite3.so @@ -201,6 +204,7 @@ chsmack -a User /usr/bin/dotnet-nui-loader /usr/share/parser-plugins/dotnet-launcher.info %{_framework_dir}/Tizen.Runtime.dll %{_dotnet_dir} +%{_readonly_app_update_dir} %{_ibc_data_dir} %{_tizen_preload_dir} %{_rw_update_scripts_dir}/%{_rw_dotnet_update_script}