* limitations under the License.
*/
-#include "log.h"
#include "utils.h"
-#include "db_manager.h"
#include "ni_common.h"
#include "tac_common.h"
+#include "profile_common.h"
+#include "privilege_common.h"
+#include "multi_target_resolver.h"
+#include "log.h"
-#include <algorithm>
-#include <cstdio>
-#include <cstring>
-#include <fstream>
#include <vector>
+#include <cstring>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <app_common.h>
-#include <pkgmgr-info.h>
-#include <pkgmgr_installer_info.h>
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
-
-std::vector<std::string> getCmdArgs(char** begin, char** end)
-{
- std::vector<std::string> list;
- for (char** itr = begin+1; itr != end; itr++) {
- if (strncmp(*itr, "--", 2) != 0) {
- list.push_back(*itr);
- }
- }
- return list;
-}
-
-static void help(const char *argv0)
-{
- const char* helpDesc =
- "Usage: %s [args] <root paths or pkg name>\n"
- " --help - Display this screen\n"
- " --ni-system - Create NI under System DLLs\n"
- " --ni-dll - Create NI for DLL\n"
- " --ni-pkg - Create NI for package\n"
- " --ni-pkg-dll - Create NI for DLL in package\n"
- " --ni-dir - Create NI for directory\n"
- " --r2r - Use ready-to-run option (default: FNV)\n"
- " (This option should be used with other options)\n"
- " --ni-reset-system - Remove System NI files\n"
- " --ni-reset-pkg - Remove App NI files\n"
- " --ni-regen-all-app - Re-generate All 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"
- " --tac-enable-pkg - Enable TAC for package\n"
+void DisplayUsage() {
+ _SOUT(
+ "\n"
+ "Dotnet Tool Version: 1.0\n"
+ "\n"
+ "Commands:\n"
+ " -h, --help - Show this help message\n"
+ " --ni-system - Create NI under System DLLs\n"
+ " --ni-dll - Create NI for DLL\n"
+ " --ni-pkg - Create NI for 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"
+ " --tac-regen-all - Re-generate All TAC files\n"
+ " --tac-restore-db - Restore TAC Database\n"
+ " --tac-disable-pkg - Disable TAC for package\n"
+ " --tac-enable-pkg - Enable TAC for package\n"
+ " --resolve-all-app - Remove unused multi-targeting files of all apps\n"
+ " (this option is used for FOTA script or test)\n"
+ " --rm-app-profile - Remove application profile of given packages for all users\n"
+ " (this option should be run as root)\n"
+ " --rm-all-app-profile - Remove application profile of all packages for all users\n"
+ " (this option should be run as root)\n"
+ " --check-all-app-privilege - Chcek application privilege of all package\n"
+ " (this option should be run as root)\n"
+ "\n"
+ "Options:\n"
+ " --mibc - Specify Mibc files. Sepatated with ':'.\n"
+ " --verbose - Display verbose information\n"
+ " --inputbubble - Compile input assemblies into one bubble with the assemblies described at --inputbubbleref option\n"
+ " Note!: If you do not have an accurate understanding of Bubble, do not use this option.\n"
+ " All assemblies in the bubble must be guaranteed to be compiled to the native image before execution.\n"
+ " If an uncompiled assembly is included in the bubble during execution, an unknown error may occur.\n"
+ " If --inputbubbleref option doesnot be set, only input files are included to bubble. \n"
+ " --inputbubbleref - Input bubble reference file(s) to be added to bubble (used with --inputbubble option)\n"
+ " --ref - Reference file(s) for compilation\n"
+ " (system paths are set automatically.)\n"
+ " --no-pipeline - Compile the dlls individually\n"
+ " --print-cmd - Print command and options\n"
+ " --skip-ro-app - Skip re-generate NI for apps installed RO area\n"
+ " (This option works with --ni-regen-all-app only)\n"
+ " --rm-origin-after-ni - Remove original dll after creating native image\n"
+ " Note!: App ATOC options(--ni-pkg, --ni-regen-all-app, --tac-regen-all) cannot be used with --rm-origin-after-ni option.\n"
+ " (Use only for assemblies that will not be AOTed again afterward.)"
+ "\n"
+ "Usage: dotnettool [options] [command] [arguments]\n"
"\n"
"Example:\n"
"1. Create native image for dlls and exes under platform directories\n"
- " # %s --ni-system\n"
+ " # dotnettool --ni-system\n"
"2. Create native image for dll\n"
- " # %s --ni-dll /usr/bin/Tizen.Runtime.dll\n"
+ " # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
"3. Create native image under the package's bin and lib directory\n"
- " # %s --ni-pkg org.tizen.FormsGallery\n"
- "4. Regenerate native images for all installed .net packages with ready-to-run option\n"
- " # %s --r2r --ni-regen-all-app\n\n";
- printf(helpDesc, argv0, argv0, argv0, argv0, argv0);
+ " # dotnettool --ni-pkg org.tizen.FormsGallery\n"
+ "4. Regenerate native images for all installed .net packages\n"
+ " # dotnettool --ni-regen-all-app\n"
+ "5. Create native image for dll based on the Mibc data\n"
+ " # dotnettool --mibc /tmp/ibcdata/in.mibc --ni-dll /usr/bin/Tizen.Runtime.dll\n"
+ "6. Remove profile for package\n"
+ " # dotnettool --rm-app-profile org.tizen.FormsGallery\n"
+ "\n");
}
int main(int argc, char* argv[])
{
- bool pkgMode = false;
- bool dllMode = false;
- bool dirMode = false;
- bool rmPkgMode = false;
- bool enableR2R = false;
- bool pkgDllMode = false;
- bool disableTacMode = false;
- bool enableTacMode = false;
-
- NiCommonOption option = {std::string(), std::string(), std::string()};
- if (initNICommon(&option) != NI_ERROR_NONE) {
- fprintf(stderr, "Fail to initialize NI Common\n");
+ argc--;
+ argv++;
+
+ long starttime;
+ long endtime;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
+
+ if (argc <= 0) {
+ DisplayUsage();
+ return -1;
+ }
+
+ NIOption* opt = getNIOption();
+ if (opt == nullptr) {
+ _SERR("Fail to create option structure.");
return -1;
}
- if (cmdOptionExists(argv, argv+argc, "--r2r")) {
- enableR2R = true;
- }
-
- if (cmdOptionExists(argv, argv+argc, "--help")) {
- help(argv[0]);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-system")) {
- createNiPlatform(enableR2R);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-dll")) {
- dllMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg")) {
- pkgMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-dir")) {
- dirMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-system")) {
- removeNiPlatform();
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-reset-pkg")) {
- rmPkgMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-pkg-dll")) {
- pkgDllMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--ni-regen-all-app")) {
- regenerateAppNI(enableR2R);
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-regen-all")) {
- regenerateTAC();
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-restore-db")) {
- restoreTACDB();
- return 0;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-disable-pkg")) {
- disableTacMode = true;
- } else if (cmdOptionExists(argv, argv+argc, "--tac-enable-pkg")) {
- enableTacMode = true;
- } else {
- help(argv[0]);
- return 0;
- }
-
- std::vector<std::string> args = getCmdArgs(argv, argv+argc);
-
- if (args.size() < 1) {
- if (pkgMode || rmPkgMode || disableTacMode || enableTacMode) {
- fprintf(stderr, "Package name is missed\n");
- } else if (dllMode) {
- fprintf(stderr, "DLL path is missed\n");
- }
- help(argv[0]);
- return 1;
- } else if (args.size() < 2) {
- if (pkgDllMode) {
- fprintf(stderr, "Package name or DLL path is missed\n");
- help(argv[0]);
- return 1;
- }
- }
-
- if (pkgMode) {
- for (const std::string pkg : args) {
- // if there is AOTed dlls under package root, that is skiped.
- int ret = createNiUnderPkgRoot(pkg, enableR2R);
- if (ret == NI_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to generate NI file [%s]\n", pkg.c_str());
- return -1;
+ std::vector<std::string> args;
+ for (int i = 0; i < argc; ++i) {
+ std::string arg = argv[i];
+
+ if ((arg == "-?") || (arg == "-h") || (arg == "--h")) {
+ DisplayUsage();
+ return 0;
+ } else if (arg == "--verbose") {
+ opt->flags |= NI_FLAGS_VERBOSE;
+ } else if (arg == "--inputbubble") {
+ opt->flags |= NI_FLAGS_INPUT_BUBBLE;
+ } else if (arg == "--no-pipeline") {
+ opt->flags |= NI_FLAGS_NO_PIPELINE;
+ } else if (arg == "--print-cmd") {
+ opt->flags |= NI_FLAGS_PRINT_CMD;
+ } else if (arg == "--skip-ro-app") {
+ opt->flags |= NI_FLAGS_SKIP_RO_APP;
+ } else if (arg == "--rm-origin-after-ni") {
+ opt->flags |= NI_FLAGS_RM_ORIGIN_AFTER_NI;
+ } else if (arg == "--mibc") {
+ ++i;
+ if (i >= argc) {
+ _SOUT("File path containing Mibc files should be followed for --mibc option");
+ DisplayUsage();
+ return 0;
+ }
+
+ opt->flags |= NI_FLAGS_MIBC;
+
+ std::vector<std::string> paths;
+ splitPath(std::string(argv[i]), paths);
+ for (const auto &path : paths) {
+ if (!isFile(path) || isDirectory(path)) {
+ _SERR("Mibc file path is missing or does not exist");
+ return -1;
+ }
+ opt->mibcPath.push_back(path);
}
- ret = createTACPackage(pkg);
- if (ret == TAC_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkg.c_str());
- return -1;
+ } else if (arg == "--inputbubbleref") {
+ ++i;
+ if (i >= argc) {
+ _SOUT("Path for references should be followed for --inputbubbleref option");
+ DisplayUsage();
+ return 0;
}
+
+ opt->flags |= NI_FLAGS_INPUT_BUBBLE_REF;
+
+ std::vector<std::string> files;
+ splitPath(std::string(argv[i]), files);
+ for (const auto &f : files) {
+ opt->inputBubbleRefFiles.push_back(f);
+ }
+ } else if (arg == "--ref") {
+ ++i;
+ if (i >= argc) {
+ _SOUT("Path for references should be followed for --ref option");
+ DisplayUsage();
+ return 0;
+ }
+
+ std::vector<std::string> files;
+ splitPath(std::string(argv[i]), files);
+ for (const auto &f : files) {
+ opt->refFiles.push_back(f);
+ }
+ } else {
+ args.push_back(arg);
}
- } else if (pkgDllMode) {
- int ret = createNiDllUnderPkgRoot(args[0], args[1], enableR2R);
- if (ret == NI_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", args[0].c_str());
- return -1;
- } else if (ret == NI_ERROR_ALREADY_EXIST) {
- // skip for already exist case
- return -1;
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to generate NI file [%s]\n", args[1].c_str());
+ }
+
+ if (args.size() == 0) {
+ _SERR("The command is missing");
+ DisplayUsage();
+ return -1;
+ }
+
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE_REF && !(opt->flags & NI_FLAGS_INPUT_BUBBLE)) {
+ _SERR("--inputbubbleref option should be used with --inputbubble option");
+ DisplayUsage();
+ return -1;
+ }
+
+ if (initNICommon() != NI_ERROR_NONE) {
+ return -1;
+ }
+
+ std::vector<std::string>::iterator it = args.begin();
+ std::string cmd = std::string(*it);
+ it = args.erase(it);
+
+ //sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
+ if (cmd == "--ni-system") {
+ std::string inputs;
+ while (it != args.end()) {
+ const std::string dir = std::string(*it);
+ inputs = inputs + ":" + dir;
+ it = args.erase(it);
+ }
+ int ret = createNIPlatform(inputs, opt);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to generate system NI");
+ }
+ }
+ //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
+ else if (cmd == "--ni-dll") {
+ if (args.size() < 1) {
+ _SERR("DLL path is missing");
+ }
+ std::vector<std::string> inputs;
+ while (it != args.end()) {
+ std::string dll = std::string(*it);
+ inputs.push_back(dll);
+ opt->refFiles.push_back(dll);
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ opt->inputBubbleRefFiles.push_back(dll);
+ }
+ it = args.erase(it);
+ }
+
+ for (auto &dll : inputs) {
+ int ret = createNIDll(dll, opt);
+ if (ret != NI_ERROR_NONE && ret != NI_ERROR_ALREADY_EXIST) {
+ _SERR("Failed to generate NI file [%s]", dll.c_str());
+ break;
+ }
+ }
+ }
+ //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--ni-pkg") {
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
return -1;
}
- } else if (rmPkgMode) {
- for (const std::string pkg : args) {
- int ret = removeNiUnderPkgRoot(pkg);
- if (ret == NI_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to remove dlls for given package [%s]\n", pkg.c_str());
- return -1;
+
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ int ret = createNIUnderPkgRoot(pkg, opt);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to generate app NI [%s]", pkg.c_str());
+ break;
}
- ret = resetTACPackage(pkg);
- if (ret == TAC_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkg.c_str());
- return -1;
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
+ else if (cmd == "--ni-dir") {
+ if (args.size() < 1) {
+ _SERR("Directory path is missing");
+ }
+ std::string dir;
+ while (it != args.end()) {
+ if (!dir.empty()) {
+ dir += std::string(":");
}
+ dir += std::string(*it);
+ it = args.erase(it);
+ }
+ if (createNIUnderDirs(dir, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate NI directory");
}
- } else if (dllMode) {
- // donot return error code for generation failure.
- // we have to run crossgen for all input dlls.
- for (const std::string dll : args) {
- int ret = createNiDll(dll, enableR2R);
- if (ret == NI_ERROR_ALREADY_EXIST) {
- // skip for already exist case
- } else if (ret != NI_ERROR_NONE) {
- fprintf(stderr, "Failed to generate NI file [%s]\n", dll.c_str());
+ }
+ //sh-3.2# dotnettool --ni-reset-system
+ else if (cmd == "--ni-reset-system") {
+ removeNIPlatform();
+ }
+ //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--ni-reset-pkg") {
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ int ret = removeNIUnderPkgRoot(pkg);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
+ break;
}
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
+ else if (cmd == "--ni-reset-dir") {
+ if (args.size() < 1) {
+ _SERR("Directory path is missing");
+ }
+ while (it != args.end()) {
+ const std::string dir = std::string(*it);
+ removeNIUnderDirs(dir);
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --ni-regen-all-app
+ else if (cmd == "--ni-regen-all-app") {
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return -1;
+ }
+
+ int ret = regenerateAppNI(opt);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to regenerate all app NI");
}
- } else if (dirMode) {
- createNiUnderDirs(args.data(), args.size(), enableR2R);
- } else if (disableTacMode) {
- for (const std::string pkg : args) {
+ }
+ //sh-3.2# dotnettool --tac-regen-all
+ else if (cmd == "--tac-regen-all") {
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return -1;
+ }
+
+ int ret = regenerateTACNI(opt);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Failed to regenerate all TAC");
+ }
+ }
+ //sh-3.2# dotnettool --tac-restore-db
+ else if (cmd == "--tac-restore-db") {
+ int ret = tac_restoreDB();
+ if (ret != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TAC db");
+ }
+ ret = tlc_restoreDB();
+ if (ret != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TLC db");
+ }
+ }
+ //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--tac-enable-pkg") {
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ int ret = enableTACPackage(pkg);
+ if (ret != TAC_ERROR_NONE) {
+ _SERR("Failed to enable tac [%s]", pkg.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+ }
+ //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--tac-disable-pkg") {
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
int ret = disableTACPackage(pkg);
- if (ret == TAC_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to disable tac [%s]\n", pkg.c_str());
- return -1;
+ if (ret != TAC_ERROR_NONE) {
+ _SERR("Failed to disable tac [%s]", pkg.c_str());
+ break;
}
+ it = args.erase(it);
}
- } else if (enableTacMode) {
- for (const std::string pkg : args) {
- int ret = enableTACPackage(pkg);
- if (ret == TAC_ERROR_INVALID_PACKAGE) {
- fprintf(stderr, "Failed to get root path from [%s]\n", pkg.c_str());
- return -1;
- } else if (ret != TAC_ERROR_NONE) {
- fprintf(stderr, "Failed to enable tac [%s]\n", pkg.c_str());
- return -1;
+ }
+ //sh-3.2# dotnettool --resolve-all-app
+ else if (cmd == "--resolve-all-app") {
+ int ret = resolveAllApps();
+ if (ret != 0) {
+ _SERR("Failed to remove unused multi-targeting files");
+ }
+ }
+ //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
+ else if (cmd == "--rm-app-profile") {
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (removeAppProfileData(pkg) != PROFILE_ERROR_NONE) {
+ _SERR("Failed to remove [%s] profile data", pkg.c_str());
}
+ it = args.erase(it);
}
}
+ //sh-3.2# dotnettool --rm-all-app-profile
+ else if (cmd == "--rm-all-app-profile") {
+ removeAllAppProfileData();
+ }
+ //sh-3.2# dotnettool --check-all-app-privilege
+ else if (cmd == "--check-all-app-privilege") {
+ checkAllAppPrivilege();
+ }
+ else {
+ _SERR("Unknown option [%s]", cmd.c_str());
+ DisplayUsage();
+ }
+
+ finalizeNICommon();
+
+ gettimeofday(&tv, NULL);
+ endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
+ _SOUT("\nSpend time for dotnettool is [%d]ms", (int)(endtime - starttime));
+
return 0;
}