When creating a target image or developing platform, "/usr/apps" which is the RO area, is mounted as RW.
In this case, if we perform AOTC for apps installed under /usr/apps,
NI files should be created under /usr/apps/, not "/opt/usr/dotnet".
So, combine options into one, and create NI files under /opt/usr/dotnet only if package directory is mounted as RO.
#define NI_FLAGS_APPNI 0x0002
#define NI_FLAGS_COMPATIBILITY 0x0004
#define NI_FLAGS_VERBOSE 0x0008
-#define NI_FLAGS_READONLY_APP 0x0010
+#define NI_FLAGS_APP_UNDER_RO_AREA 0x0010
#define NI_FLAGS_INSTRUMENT 0x1000
typedef std::function<void (std::string)> afterCreate;
std::string changeExtension(const std::string& path, const std::string& from, const std::string& to);
/**
- * @brief check the package is 'readonly' or not
- * @param[in] package id
+ * @brief check the path is 'readonly' or not
+ * @param[in] path
* @return bool package readonly value
*/
-bool isReadOnlyApp(const std::string& pkgId);
+bool isReadOnlyArea(const std::string& path);
/**
* @brief split path with ":" delimiter and put that in the vector
" --ni-system - Create NI under System DLLs\n"
" --ni-dll - Create NI for DLL\n"
" --ni-pkg - Create NI for package\n"
- " --ni-ro-pkg - Create NI for read-only package\n"
+ " (If package is installed under RO area, NI files are generated under RW area)\n"
" --ni-dir - Create NI for directory\n"
" --ni-reset-system - Remove System NI files\n"
" --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"
}
while (it != args.end()) {
std::string pkg = std::string(*it);
- if (isReadOnlyApp(pkg)) {
- _SERR("Skip to generate app NI. Try to create NI for read-only package [%s]\n# dotnettool --ni-ro-pkg %s", pkg.c_str(), pkg.c_str());
- } else {
- // if there is AOTed dlls under package root, that is skiped.
- int ret = createNIUnderPkgRoot(pkg, flags);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to generate app NI [%s]", pkg.c_str());
- break;
- }
- }
- it = args.erase(it);
- }
- }
- //sh-3.2# dotnettool --ni-ro-pkg [pkgId] [pkgId] ...
- else if (cmd == "--ni-ro-pkg") {
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- flags |= NI_FLAGS_READONLY_APP;
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- if (isReadOnlyApp(pkg)) {
- // if there is AOTed dlls under package root, that is skiped.
- int ret = createNIUnderPkgRoot(pkg, flags);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to generate read-only app NI [%s]", pkg.c_str());
- break;
- }
- } else {
- _SERR("Skip to generate app NI. Try to create NI for package [%s]\n# dotnettool --ni-pkg %s", pkg.c_str(), pkg.c_str());
+ int ret = createNIUnderPkgRoot(pkg, flags);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to generate app NI [%s]", pkg.c_str());
+ break;
}
it = args.erase(it);
}
_SERR("Failed to regenerate all app NI");
}
}
- //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) {
- _SERR("Failed to regenerate read-only app NI");
- }
- }
//sh-3.2# dotnettool --tac-regen-all
else if (cmd == "--tac-regen-all") {
int ret = regenerateTACNI(flags);
prevPath = getBaseName(absDllPath);
niDirPath = concatPath(prevPath, APP_NI_SUB_DIR);
- if (flags & NI_FLAGS_READONLY_APP) {
+ if (flags & NI_FLAGS_APP_UNDER_RO_AREA) {
niDirPath = replaceAll(niDirPath, getBaseName(__pm->getAppRootPath()), __READ_ONLY_APP_UPDATE_DIR);
+ _SERR("App is installed in RO area. So, create NI files in RW area(%s).", niDirPath.c_str());
+ _ERR("App is installed in RO area. So, create NI files in RW area(%s).", niDirPath.c_str());
}
if (!isDirectory(niDirPath)) {
return -1;
}
- bool readOnlyApp = isReadOnlyApp(pkgId);
-
- // read-only and readonly flag set
- if (readOnlyApp && (*pFlags & NI_FLAGS_READONLY_APP)) {
- _SERR("try to regenerate read-only pkg [%s]", pkgId);
- }
- // not read-only and readonly flag does not set
- else if (!readOnlyApp && !(*pFlags & NI_FLAGS_READONLY_APP)) {
- if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) {
- _SERR("Failed to remove previous dlls from [%s]", pkgId);
- return -1;
- }
- }
- // skip regeneration
- else {
- _SERR("skip regeneration. pkg-type(read-only) doesnot match the configuration [%s]", pkgId);
- return 0;
- }
-
if (createNIUnderPkgRoot(pkgId, *pFlags) != NI_ERROR_NONE) {
_SERR("Failed to generate NI file [%s]", pkgId);
return -1;
flags |= NI_FLAGS_APPNI;
+ if (isReadOnlyArea(rootPath)) {
+ flags |= NI_FLAGS_APP_UNDER_RO_AREA;
+ } else {
+ flags &= ~NI_FLAGS_APP_UNDER_RO_AREA;
+ ni_error_e err = removeNIUnderPkgRoot(pkgId);
+ if (err != NI_ERROR_NONE) {
+ _SERR("Failed to remove previous dlls from [%s]", pkgId.c_str());
+ return err;
+ }
+ }
+
// create native image under bin and lib directory
// tac directory is skipped in the createNIUnderDirs.
return createNIUnderDirs(__pm->getAppPaths(), flags);
#include <sys/smack.h>
#include <sys/prctl.h>
#include <openssl/sha.h>
+#include <mntent.h>
#include <cstdlib>
#include <cstring>
return metadataValue;
}
-bool isReadOnlyApp(const std::string& pkgId)
+bool isReadOnlyArea(const std::string& path)
{
- bool readOnly = false;
- int ret = 0;
- uid_t uid = 0;
+ FILE *f = NULL;
+ struct mntent *m = NULL;
- 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);
+ // "/opt/usr" is mounted to "RW" only
+ if (path.find("/opt/usr") != std::string::npos) {
+ return false;
}
- if (ret != PMINFO_R_OK) {
- return readOnly;
+ // check whether "/" is mounted to RO or not
+ f = setmntent("/proc/mounts", "r");
+ if (!f) {
+ // return true for fail case to generate NI files under RW area.
+ return true;
}
- ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readOnly);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return readOnly;
+ while((m = getmntent(f))) {
+ if (m->mnt_dir != NULL && strcmp(m->mnt_dir, "/") == 0 &&
+ m->mnt_opts != NULL && strstr(m->mnt_opts, "ro,") != NULL) {
+ endmntent(f);
+ return true;
+ }
}
+ endmntent(f);
+ return false;
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-
- return readOnly;
}
std::string getBaseName(const std::string& path)
if tpk_path == None:
return f"FAIL : Get the tpk path for {sln_name}"
+ cmd(f"shell mount -o remount,rw /")
+
raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
if "1 file(s) pushed. 0 file(s) skipped." in raw:
cmd(f"shell install_preload_pkg")
- cmd(f"shell dotnettool --ni-regen-all-ro-app")
+ cmd(f"shell mount -o remount,ro /")
+
+ cmd(f"shell dotnettool --ni-regen-all-app")
raw = subprocess.run((f"sdb -s {serial} shell pkginfo --metadata-flt").split(), stdout=subprocess.PIPE, input=f"http://tizen.org/metadata/prefer_dotnet_aot\ntrue\n", encoding="utf-8").stdout
lines = [l for l in raw.splitlines() if "appid" in l]
if tpk_path == None:
return f"FAIL : Get the tpk path for {sln_name}"
+ cmd(f"shell mount -o remount,rw /")
raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
if "1 file(s) pushed. 0 file(s) skipped." in raw:
cmd(f"shell install_preload_pkg")
+ cmd(f"shell mount -o remount,ro /")
pkg_id = f"org.tizen.example.Launcher_TC_TOOL_09.Tizen"
if exist(f"{root_path}/bin/.native_image"):
return "FAIL : The .native_image folder not should exist"
- cmd(f"shell dotnettool --ni-ro-pkg {pkg_id}")
+ cmd(f"shell dotnettool --ni-pkg {pkg_id}")
if not exist(f"{DOTNET_DIR}apps/{pkg_id}/bin/.native_image"):
return "FAIL : The .native_image folder should exist"