dotnettool: Add --rm-app-profile <app_id> option
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / dotnettool.cc
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "utils.h"
18 #include "ni_common.h"
19 #include "tac_common.h"
20 #include "multi_target_resolver.h"
21 #include "log.h"
22
23 #include <vector>
24 #include <cstring>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <sys/time.h>
28 #include <app_common.h>
29
30 void DisplayUsage() {
31         _SOUT(
32                 "\n"
33                 "Dotnet Tool Version: 1.0\n"
34                 "\n"
35                 "Commands:\n"
36                 "       -h, --help                - Show this help message\n"
37                 "       --ni-system               - Create NI under System DLLs\n"
38                 "       --ni-dll                  - Create NI for DLL\n"
39                 "       --ni-pkg                  - Create NI for package\n"
40                 "       --ni-ro-pkg               - Create NI for read-only package\n"
41                 "       --ni-dir                  - Create NI for directory\n"
42                 "       --ni-reset-system         - Remove System NI files\n"
43                 "       --ni-reset-pkg            - Remove App NI files\n"
44                 "       --ni-reset-dir            - Remove NI for directory\n"
45                 "       --ni-regen-all-app        - Re-generate All App NI files\n"
46                 "       --ni-regen-all-ro-app     - Re-generate All read-only type App NI files\n"
47                 "       --tac-regen-all           - Re-generate All TAC files\n"
48                 "       --tac-restore-db          - Restore TAC Database\n"
49                 "       --tac-disable-pkg         - Disable TAC for package\n"
50                 "       --tac-enable-pkg          - Enable TAC for package\n"
51                 "       --ibc-dir                 - Specify a directory containing IBC files\n"
52                 "       --resolve-all-app         - Remove unused multi-targeting files of all apps\n"
53                 "                                   (this option is used for FOTA script or test)\n"
54                 "       --rm-app-profile          - Remove application profile for all users\n"
55                 "                                   (this option should be run as root)\n"
56                 "\n"
57                 "Options:\n"
58                 "       --r2r                     - Generate a Ready-To-Run image (disable: /FragileNonVersionable)\n"
59                 "       --compatibility           - Compatibility mode for older versions of crossgen\n"
60                 "                                   (replaces /r with /Trusted_Platform_Assemblies)\n"
61                 "       --verbose                 - Display verbose information\n"
62                 "       --instrument              - Generate an instrumented image for profiling (enable: /Tuning)\n"
63                 "\n"
64                 "Usage: dotnettool [options] [command] [arguments]\n"
65                 "\n"
66                 "Example:\n"
67                 "1. Create native image for dlls and exes under platform directories\n"
68                 "   # dotnettool --ni-system\n"
69                 "2. Create native image for dll\n"
70                 "   # dotnettool --ni-dll /usr/bin/Tizen.Runtime.dll\n"
71                 "3. Create native image under the package's bin and lib directory\n"
72                 "   # dotnettool --ni-pkg org.tizen.FormsGallery\n"
73                 "4. Regenerate native images for all installed .net packages with ready-to-run option\n"
74                 "   # dotnettool --r2r --ni-regen-all-app\n"
75                 "5. Create native image for dll based on the IBC data\n"
76                 "   # dotnettool --ibc-dir /tmp/ibcdata/ --ni-dll /usr/bin/Tizen.Runtime.dll\n"
77                 "6. Remove profile for package\n"
78                 "   # dotnettool --rm-app-profile org.tizen.FormsGallery\n"
79                 "\n");
80 }
81
82 int main(int argc, char* argv[])
83 {
84         argc--;
85         argv++;
86
87         long starttime;
88         long endtime;
89         struct timeval tv;
90         gettimeofday(&tv, NULL);
91         starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
92
93         if (argc <= 0) {
94                 DisplayUsage();
95                 return -1;
96         }
97
98         //sh-3.2# dotnettool --[r2r|compatibility|instrument|verbose]
99         DWORD flags = 0;
100         std::vector<std::string> args;
101         for (char** it = argv; it != argv+argc; it++) {
102                 if (!strncmp(*it, "-?", 2) || !strncmp(*it, "-h", 2) || !strncmp(*it, "--help", 6)) {
103                         DisplayUsage();
104                         return 0;
105                 } else if (!strncmp(*it, "--r2r", 5)) {
106                         flags |= NI_FLAGS_ENABLER2R;
107                 } else if (!strncmp(*it, "--compatibility", 15)) {
108                         flags |= NI_FLAGS_COMPATIBILITY;
109                 } else if (!strncmp(*it, "--instrument", 12)) {
110                         flags |= NI_FLAGS_INSTRUMENT;
111                 } else if (!strncmp(*it, "--verbose", 9)) {
112                         flags |= NI_FLAGS_VERBOSE;
113                 } else {
114                         args.push_back(*it);
115                 }
116         }
117
118         //sh-3.2# dotnettool --ibc-dir [ibcDirectory]
119         for (auto it = args.begin(); it != args.end(); ) {
120                 if (*it == "--ibc-dir") {
121                         it = args.erase(it);
122
123                         std::string ibcFilePath = std::string(*it);
124                         if (!isDirectory(ibcFilePath)) {
125                                 _SERR("IBC path is missing or not exist");
126                                 return -1;
127                         }
128
129                         setenv("COMPlus_IBCFileDir", const_cast<char *>(ibcFilePath.c_str()), 1);
130                         setenv("COMPlus_UseIBCFile", const_cast<char *>("1"), 1);
131                         it = args.erase(it);
132                 } else {
133                         ++it;
134                 }
135         }
136
137         if (initNICommon() != NI_ERROR_NONE) {
138                 return -1;
139         }
140
141         std::vector<std::string>::iterator it = args.begin();
142         std::string cmd = std::string(*it);
143         it = args.erase(it);
144
145         //sh-3.2# dotnettool --ni-system
146         if (cmd == "--ni-system") {
147                 int ret = createNIPlatform(flags);
148                 if (ret != NI_ERROR_NONE) {
149                         _SERR("Failed to generate system NI");
150                 }
151         }
152         //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
153         else if (cmd == "--ni-dll") {
154                 if (args.size() < 1) {
155                         _SERR("DLL path is missing");
156                 }
157                 while (it != args.end()) {
158                         std::string dll = std::string(*it);
159                         int ret = createNIDll(dll, flags);
160                         if (ret != NI_ERROR_NONE) {
161                                 _SERR("Failed to generate NI file [%s]", dll.c_str());
162                                 break;
163                         }
164                         it = args.erase(it);
165                 }
166         }
167         //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
168         else if (cmd == "--ni-pkg") {
169                 if (args.size() < 1) {
170                         _SERR("Package name is missing");
171                 }
172                 while (it != args.end()) {
173                         std::string pkg = std::string(*it);
174                         if (isReadOnlyApp(pkg)) {
175                                 _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());
176                         } else {
177                                 // if there is AOTed dlls under package root, that is skiped.
178                                 int ret = createNIUnderPkgRoot(pkg, flags);
179                                 if (ret != NI_ERROR_NONE) {
180                                         _SERR("Failed to generate app NI [%s]", pkg.c_str());
181                                         break;
182                                 }
183                         }
184                         it = args.erase(it);
185                 }
186         }
187         //sh-3.2# dotnettool --ni-ro-pkg [pkgId] [pkgId] ...
188         else if (cmd == "--ni-ro-pkg") {
189                 if (args.size() < 1) {
190                         _SERR("Package name is missing");
191                 }
192                 flags |= NI_FLAGS_READONLY_APP;
193                 while (it != args.end()) {
194                         std::string pkg = std::string(*it);
195                         if (isReadOnlyApp(pkg)) {
196                                 // if there is AOTed dlls under package root, that is skiped.
197                                 int ret = createNIUnderPkgRoot(pkg, flags);
198                                 if (ret != NI_ERROR_NONE) {
199                                         _SERR("Failed to generate read-only app NI [%s]", pkg.c_str());
200                                         break;
201                                 }
202                         } else {
203                                 _SERR("Skip to generate app NI. Try to create NI for package [%s]\n# dotnettool --ni-pkg %s", pkg.c_str(), pkg.c_str());
204                         }
205                         it = args.erase(it);
206                 }
207         }
208         //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
209         else if (cmd == "--ni-dir") {
210                 if (args.size() < 1) {
211                         _SERR("Directory path is missing");
212                 }
213                 while (it != args.end()) {
214                         const std::string dir = std::string(*it);
215                         int ret = createNIUnderDirs(dir, flags);
216                         if (ret != NI_ERROR_NONE) {
217                                 _SERR("Failed to generate NI directory");
218                                 break;
219                         }
220                         it = args.erase(it);
221                 }
222         }
223         //sh-3.2# dotnettool --ni-reset-system
224         else if (cmd == "--ni-reset-system") {
225                 removeNIPlatform();
226         }
227         //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
228         else if (cmd == "--ni-reset-pkg") {
229                 if (args.size() < 1) {
230                         _SERR("Package name is missing");
231                 }
232                 while (it != args.end()) {
233                         std::string pkg = std::string(*it);
234                         int ret = removeNIUnderPkgRoot(pkg);
235                         if (ret != NI_ERROR_NONE) {
236                                 _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
237                                 break;
238                         }
239                         it = args.erase(it);
240                 }
241         }
242         //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
243         else if (cmd == "--ni-reset-dir") {
244                 if (args.size() < 1) {
245                         _SERR("Directory path is missing");
246                 }
247                 while (it != args.end()) {
248                         const std::string dir = std::string(*it);
249                         removeNIUnderDirs(dir);
250                         it = args.erase(it);
251                 }
252         }
253         //sh-3.2# dotnettool --ni-regen-all-app
254         else if (cmd == "--ni-regen-all-app") {
255                 int ret = regenerateAppNI(flags);
256                 if (ret != NI_ERROR_NONE) {
257                         _SERR("Failed to regenerate all app NI");
258                 }
259         }
260         //sh-3.2# dotnettool --ni-regen-readonly-app
261         else if (cmd == "--ni-regen-all-ro-app") {
262                 flags |= NI_FLAGS_READONLY_APP;
263                 int ret = regenerateAppNI(flags);
264                 if (ret != NI_ERROR_NONE) {
265                         _SERR("Failed to regenerate read-only app NI");
266                 }
267         }
268         //sh-3.2# dotnettool --tac-regen-all
269         else if (cmd == "--tac-regen-all") {
270                 int ret = regenerateTACNI(flags);
271                 if (ret != NI_ERROR_NONE) {
272                         _SERR("Failed to regenerate all TAC");
273                 }
274         }
275         //sh-3.2# dotnettool --tac-restore-db
276         else if (cmd == "--tac-restore-db") {
277                 int ret = tac_restoreDB();
278                 if (ret != TAC_ERROR_NONE) {
279                         _SERR("Failed to restore TAC db");
280                 }
281                 ret = tlc_restoreDB();
282                 if (ret != TAC_ERROR_NONE) {
283                         _SERR("Failed to restore TLC db");
284                 }
285         }
286         //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
287         else if (cmd == "--tac-enable-pkg") {
288                 if (args.size() < 1) {
289                         _SERR("Package name is missing");
290                 }
291                 while (it != args.end()) {
292                         std::string pkg = std::string(*it);
293                         int ret = enableTACPackage(pkg);
294                         if (ret != TAC_ERROR_NONE) {
295                                 _SERR("Failed to enable tac [%s]", pkg.c_str());
296                                 break;
297                         }
298                         it = args.erase(it);
299                 }
300         }
301         //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
302         else if (cmd == "--tac-disable-pkg") {
303                 if (args.size() < 1) {
304                         _SERR("Package name is missing");
305                 }
306                 while (it != args.end()) {
307                         std::string pkg = std::string(*it);
308                         int ret = disableTACPackage(pkg);
309                         if (ret != TAC_ERROR_NONE) {
310                                 _SERR("Failed to disable tac [%s]", pkg.c_str());
311                                 break;
312                         }
313                         it = args.erase(it);
314                 }
315         }
316         //sh-3.2# dotnettool --resolve-all-app
317         else if (cmd == "--resolve-all-app") {
318                 int ret = resolveAllApps();
319                 if (ret != 0) {
320                         _SERR("Failed to remove unused multi-targeting files");
321                 }
322         }
323         //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
324         else if (cmd == "--rm-app-profile") {
325                 if (args.size() < 1) {
326                         fprintf(stderr, "Package name is missing\n");
327                 }
328                 while (it != args.end()) {
329                         std::string pkg = std::string(*it);
330                         setenv("AUL_APPID", pkg.c_str(), 1);
331                         char *localDataPath = app_get_data_path(); // /root/apps_rw/<app_id>/data/
332                         if (localDataPath != NULL) {
333                                 char *home = getenv("HOME"); // /root
334                                 std::string rmCMD = std::string("rm -f /home/*");
335                                 rmCMD.append(localDataPath + strlen(home)); // rm /home/*/apps_rw/<app_id>/data/
336                                 rmCMD.append(PROFILE_BASENAME); // rm /home/*/apps_rw/<app_id>/data/.__tizen_specific_profile_data
337                                 system(rmCMD.c_str());
338                                 free(localDataPath);
339                         } else {
340                                 fprintf(stderr, "Application not found [%s], skip to remove profile\n", pkg.c_str());
341                         }
342                         it = args.erase(it);
343                 }
344         }
345         else {
346                 _SERR("Unknown option [%s]", cmd.c_str());
347                 DisplayUsage();
348         }
349
350         finalizeNICommon();
351
352         gettimeofday(&tv, NULL);
353         endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
354         _SOUT("\nSpend time for dotnettool is [%d]ms", (int)(endtime - starttime));
355
356         return 0;
357 }