Fixed the segmentation fault in dotnettool (#437)
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / dotnettool.cc
index ffb52ca..4343b49 100644 (file)
@@ -17,6 +17,8 @@
 #include "utils.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"
 
@@ -47,18 +49,33 @@ void DisplayUsage() {
                "       --tac-restore-db          - Restore TAC Database\n"
                "       --tac-disable-pkg         - Disable TAC for package\n"
                "       --tac-enable-pkg          - Enable TAC for package\n"
-               "       --ibc-dir                 - Specify a directory containing IBC files\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 for all users\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"
-               "       --r2r                     - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n"
-               "       --compatibility           - Compatibility mode for older versions of crossgen\n"
-               "                                   (replaces /r with /Trusted_Platform_Assemblies)\n"
+               "       --mibc                    - Specify Mibc files. Sepatated with ':'.\n"
                "       --verbose                 - Display verbose information\n"
-               "       --instrument              - Generate an instrumented image for profiling (enable: /Tuning)\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"
@@ -69,10 +86,10 @@ void DisplayUsage() {
                "   # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
                "3. Create native image under the package's bin and lib directory\n"
                "   # dotnettool --ni-pkg org.tizen.FormsGallery\n"
-               "4. Regenerate native images for all installed .net packages with ready-to-run option\n"
-               "   # dotnettool --r2r --ni-regen-all-app\n"
-               "5. Create native image for dll based on the IBC data\n"
-               "   # dotnettool --ibc-dir /tmp/ibcdata/ --ni-dll /usr/bin/Tizen.Runtime.dll\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");
@@ -94,45 +111,95 @@ int main(int argc, char* argv[])
                return -1;
        }
 
-       //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
-       DWORD flags = 0;
+       NIOption* opt = getNIOption();
+       if (opt == nullptr) {
+               _SERR("Fail to create option structure.");
+               return -1;
+       }
+
        std::vector<std::string> args;
-       for (char** it = argv; it != argv+argc; it++) {
-               if (!strncmp(*it, "-?", 2) || !strncmp(*it, "-h", 2) || !strncmp(*it, "--help", 6)) {
+       for (int i = 0; i < argc; ++i) {
+               std::string arg = argv[i];
+
+               if ((arg == "-?") || (arg == "-h") || (arg == "--h")) {
                        DisplayUsage();
                        return 0;
-               } else if (!strncmp(*it, "--r2r", 5)) {
-                       flags |= NI_FLAGS_ENABLER2R;
-               } else if (!strncmp(*it, "--compatibility", 15)) {
-                       flags |= NI_FLAGS_COMPATIBILITY;
-               } else if (!strncmp(*it, "--instrument", 12)) {
-                       flags |= NI_FLAGS_INSTRUMENT;
-               } else if (!strncmp(*it, "--verbose", 9)) {
-                       flags |= NI_FLAGS_VERBOSE;
-               } else {
-                       args.push_back(*it);
-               }
-       }
+               } 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;
+                       }
 
-       //sh-3.2# dotnettool --ibc-dir [ibcDirectory]
-       for (auto it = args.begin(); it != args.end(); ) {
-               if (*it == "--ibc-dir") {
-                       it = args.erase(it);
+                       opt->flags |= NI_FLAGS_MIBC;
 
-                       std::string ibcFilePath = std::string(*it);
-                       if (!isDirectory(ibcFilePath)) {
-                               _SERR("IBC path is missing or not exist");
-                               return -1;
+                       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);
+                       }
+               } else if (arg == "--inputbubbleref") {
+                       ++i;
+                       if (i >= argc) {
+                               _SOUT("Path for references should be followed for --inputbubbleref option");
+                               DisplayUsage();
+                               return 0;
                        }
 
-                       setenv("COMPlus_IBCFileDir", const_cast<char *>(ibcFilePath.c_str()), 1);
-                       setenv("COMPlus_UseIBCFile", const_cast<char *>("1"), 1);
-                       it = args.erase(it);
+                       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 {
-                       ++it;
+                       args.push_back(arg);
                }
        }
 
+       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;
        }
@@ -141,9 +208,15 @@ int main(int argc, char* argv[])
        std::string cmd = std::string(*it);
        it = args.erase(it);
 
-       //sh-3.2# dotnettool --ni-system
+       //sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
        if (cmd == "--ni-system") {
-               int ret = createNIPlatform(flags);
+               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");
                }
@@ -153,24 +226,39 @@ int main(int argc, char* argv[])
                if (args.size() < 1) {
                        _SERR("DLL path is missing");
                }
+               std::vector<std::string> inputs;
                while (it != args.end()) {
                        std::string dll = std::string(*it);
-                       int ret = createNIDll(dll, flags);
-                       if (ret != NI_ERROR_NONE) {
+                       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;
                        }
-                       it = args.erase(it);
                }
        }
        //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;
+               }
+
                if (args.size() < 1) {
                        _SERR("Package name is missing");
                }
                while (it != args.end()) {
                        std::string pkg = std::string(*it);
-                       int ret = createNIUnderPkgRoot(pkg, flags);
+                       int ret = createNIUnderPkgRoot(pkg, opt);
                        if (ret != NI_ERROR_NONE) {
                                _SERR("Failed to generate app NI [%s]", pkg.c_str());
                                break;
@@ -183,15 +271,17 @@ int main(int argc, char* argv[])
                if (args.size() < 1) {
                        _SERR("Directory path is missing");
                }
+               std::string dir;
                while (it != args.end()) {
-                       const std::string dir = std::string(*it);
-                       int ret = createNIUnderDirs(dir, flags);
-                       if (ret != NI_ERROR_NONE) {
-                               _SERR("Failed to generate NI directory");
-                               break;
+                       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");
+               }
        }
        //sh-3.2# dotnettool --ni-reset-system
        else if (cmd == "--ni-reset-system") {
@@ -225,14 +315,26 @@ int main(int argc, char* argv[])
        }
        //sh-3.2# dotnettool --ni-regen-all-app
        else if (cmd == "--ni-regen-all-app") {
-               int ret = regenerateAppNI(flags);
+               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");
                }
        }
        //sh-3.2# dotnettool --tac-regen-all
        else if (cmd == "--tac-regen-all") {
-               int ret = regenerateTACNI(flags);
+               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");
                }
@@ -288,25 +390,24 @@ int main(int argc, char* argv[])
        //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
        else if (cmd == "--rm-app-profile") {
                if (args.size() < 1) {
-                       fprintf(stderr, "Package name is missing\n");
+                       _SERR("Package name is missing");
                }
                while (it != args.end()) {
                        std::string pkg = std::string(*it);
-                       setenv("AUL_APPID", pkg.c_str(), 1);
-                       char *localDataPath = app_get_data_path(); // /root/apps_rw/<app_id>/data/
-                       if (localDataPath != NULL) {
-                               char *home = getenv("HOME"); // /root
-                               std::string rmCMD = std::string("rm -f /home/*");
-                               rmCMD.append(localDataPath + strlen(home)); // rm /home/*/apps_rw/<app_id>/data/
-                               rmCMD.append(PROFILE_BASENAME); // rm /home/*/apps_rw/<app_id>/data/.__tizen_specific_profile_data
-                               system(rmCMD.c_str());
-                               free(localDataPath);
-                       } else {
-                               fprintf(stderr, "Application not found [%s], skip to remove profile\n", pkg.c_str());
+                       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();