Remove the commented code
[platform/core/dotnet/launcher.git] / NativeLauncher / installer-plugin / prefer_nuget_cache_plugin.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 "log.h"
18 #include "ni_common.h"
19 #include "utils.h"
20 #include "db_manager.h"
21
22 #include <cstring>
23 #include <fstream>
24 #include <sstream>
25 #include <vector>
26 #include <boost/filesystem.hpp>
27 #include <glib.h>
28 #include <json/json.h>
29 #include <pkgmgr-info.h>
30 #include <pkgmgr_installer_info.h>
31 #include <openssl/sha.h>
32
33 #ifdef  LOG_TAG
34 #undef  LOG_TAG
35 #endif
36 #define LOG_TAG "DOTNET_INSTALLER_PLUGIN"
37
38 #define __XSTR(x) #x
39 #define __STR(x) __XSTR(x)
40 static const char* __TAC_DIR = __STR(TAC_DIR);
41 #undef __STR
42 #undef __XSTR
43
44 typedef struct Metadata {
45         const char *key;
46         const char *value;
47 } Metadata;
48
49 std::vector<std::string> nugetPackagesAssembliesSha;
50 std::vector<std::string> tacDB;
51 std::vector<std::string> createDirectories;
52 std::vector<std::string> updateTac;
53 std::string status = "";
54 std::string rootPath;
55 std::string execName;
56 std::string binPath;
57 bool isCreateDirectory = false;
58 static sqlite3 *tac_db = NULL;
59
60 bool metadataCheck(GList *list)
61 {
62         GList *tag = NULL;
63         Metadata *mdInfo = NULL;
64         tag = g_list_first(list);
65         mdInfo = (Metadata*)tag->data;
66         if (strcmp(mdInfo->key, TAC_METADATA_KEY) == 0 && strcmp(mdInfo->value, METADATA_VALUE) == 0) {
67                 _DBG("Prefer nuget cache set TRUE");
68                 NiCommonOption option = {std::string(), std::string(), std::string()};
69                 if (initNICommon(&option) < 0) {
70                         _ERR("Fail to initialize NI Common");
71                         return false;
72                 }
73                 return true;
74         }
75         return false;
76 }
77
78 bool appTypeCheck(std::string pkgId)
79 {
80         uid_t uid = 0;
81         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
82                 _ERR("Failed to get UID");
83                 return false;
84         }
85
86         pkgmgrinfo_pkginfo_h handle;
87         int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
88         if (ret != PMINFO_R_OK) {
89                 _ERR("Failed to get pkg info");
90                 return false;
91         }
92
93         bool isDotnetAppType = false;
94         auto dotnetAppCounter = [] (pkgmgrinfo_appinfo_h handle, void *userData) -> int {
95                 char* type = nullptr;
96                 bool* dotnet = static_cast<bool*>(userData);
97                 if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK) {
98                         _ERR("Failed to get app type : %s", type);
99                         return -1;
100                 }
101                 if (strcmp(type, "dotnet") == 0) {
102                         *dotnet = true;
103                 }
104                 return 0;
105         };
106
107         if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnetAppCounter, &isDotnetAppType, uid) != PMINFO_R_OK) {
108                 _ERR("Failed to get list of app in pkg : %s", pkgId.c_str());
109                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
110                 return false;
111         }
112
113         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
114         return isDotnetAppType;
115 }
116
117 void SHA256(std::string path, char outputBuffer[65])
118 {
119         FILE *file = fopen(path.c_str(), "rb");
120         if (!file) {
121                 return;
122         }
123
124         unsigned char hash[SHA256_DIGEST_LENGTH];
125         SHA256_CTX sha256;
126         SHA256_Init(&sha256);
127         int bytesRead = 0;
128         const int bufSize = 32768;
129         char *buffer = (char*)malloc(bufSize);
130         if (!buffer) {
131                 fclose(file);
132                 return;
133         }
134
135         while ((bytesRead = fread(buffer, 1, bufSize, file))) {
136                 SHA256_Update(&sha256, buffer, bytesRead);
137         }
138         SHA256_Final(hash, &sha256);
139         for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
140                 sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
141         }
142         outputBuffer[64] = 0;
143
144         fclose(file);
145         free(buffer);
146 }
147
148 int depsJsonParser()
149 {
150         std::string deps_json_name = execName.substr(0, execName.rfind(".dll")) + ".deps.json";
151         std::string deps_json_path = concatPath(rootPath, deps_json_name);
152         if (bf::exists(deps_json_path)) {
153                 std::ifstream ifs(deps_json_path);
154                 Json::CharReaderBuilder reader;
155                 Json::Value root;
156                 std::string error;
157                 if (ifs.is_open()) {
158                         if (!Json::parseFromStream(reader, ifs, &root, &error)) {
159                                 _ERR("Failed to parse of deps.json");
160                                 ifs.close();
161                                 return -1;
162                         }
163                         const Json::Value runtimeTargetName = root["runtimeTarget"]["name"];
164                         const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()];
165                         for (auto& nuget : nugetPackages.getMemberNames()) {
166                                 if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) != NULL ||
167                                         strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) != NULL ||
168                                         strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) != NULL ||
169                                         strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) != NULL) {
170                                         continue;
171                                 } else {
172                                         const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"];
173                                         if (assemblies != Json::nullValue) {
174                                                 const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"];
175                                                 bool isDependency = false;
176                                                 for (auto& dependency : dependencies.getMemberNames()) {
177                                                         if (strstr(dependency.c_str(), TIZEN_DOTNET_NUGET) != NULL ||
178                                                                 strstr(dependency.c_str(), NET_STANDARD_LIBRARY_NUGET) != NULL) {
179                                                                 continue;
180                                                         } else {
181                                                                 isDependency = true;
182                                                         }
183                                                 }
184                                                 if (!isDependency) {
185                                                         tacDB.push_back(nuget);
186                                                         _INFO("Nuget package : %s", nuget.c_str());
187                                                         for (auto& assembly : assemblies.getMemberNames()) {
188                                                                 std::string assembly_name = assembly.substr(assembly.rfind('/') + 1);
189                                                                 char buffer[65] = {0};
190                                                                 SHA256(concatPath(binPath, assembly_name), buffer);
191                                                                 nugetPackagesAssembliesSha.push_back(nuget + "/" + assembly_name + "/" + buffer);
192                                                                 _INFO("Assembly / SHA256 : %s / %s", assembly_name.c_str(), buffer);
193                                                         }
194                                                 }
195                                         }
196                                 }
197                         }
198                         ifs.close();
199                 }
200         }
201         return 0;
202 }
203
204 int createSymlink(std::string tac_version_dir, std::string np)
205 {
206         uid_t uid = 0;
207         std::string tac_dir = concatPath(binPath, TAC_SYMLINK_SUB_DIR);
208         if (!createDir(tac_dir)) {
209                 _INFO("Cannot create directory: %s", tac_dir.c_str());
210                 return -1;
211         }
212
213         for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
214                 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind('/'));
215                 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind('/'));
216                 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind('/') + 1);
217                 if (!strcmp(nuget_package.c_str(), np.c_str())) {
218                         if (bf::exists(concatPath(binPath, assembly))) {
219                                 if (isCreateDirectory) {
220                                         if (!copyFile(concatPath(binPath, assembly), concatPath(tac_version_dir, assembly))) {
221                                                 _ERR("Failed to copy of %s", assembly.c_str());
222                                                 return -1;
223                                         }
224                                 }
225                                 if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
226                                         _ERR("Failed to get UID");
227                                         return -1;
228                                 }
229                                 bf::create_symlink(concatPath(tac_version_dir, assembly), concatPath(tac_dir, assembly));
230                                 if (lchown(concatPath(tac_dir, assembly).c_str(), uid, 0)) {
231                                         _ERR("Failed to change owner of: %s", concatPath(tac_dir, assembly).c_str());
232                                         return -1;
233                                 }
234                                 if (!removeFile(concatPath(binPath, assembly))) {
235                                         _ERR("Failed to remove of %s", assembly.c_str());
236                                         return -1;
237                                 }
238                         }
239                 }
240         }
241         return 0;
242 }
243
244 extern "C" int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgId, const char *appId, GList *list)
245 {
246         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_INSTALL =====]");
247         _INFO("PackageID : %s", pkgId);
248
249         if (!appTypeCheck(std::string(pkgId))) {
250                 _INFO("App type is not dotnet");
251                 return 0;
252         }
253         if (getExecName(std::string(pkgId), execName) < 0) {
254                 return 0;
255         }
256         if (getRootPath(std::string(pkgId), rootPath) < 0) {
257                 return 0;
258         } else {
259                 binPath = concatPath(rootPath, "bin");
260         }
261         if (metadataCheck(list)) {
262                 if (depsJsonParser() < 0) {
263                         return 0;
264                 }
265         }
266
267         status = "install";
268         tac_db = dbCreate(TAC_APP_LIST_DB);
269         if (tac_db) {
270                 if (!dbOpen(tac_db, TAC_APP_LIST_DB)) {
271                         _ERR("Sqlite open error");
272                         return 0;
273                 }
274         } else {
275                 _ERR("Sqlite create error");
276                 return 0;
277         }
278
279         if (tacDB.empty()) {
280                 _ERR("Not exist .deps.json file");
281                 return 0;
282         }
283
284         for (auto& np : tacDB) {
285                 std::string tac_name = np.substr(0, np.find('/'));
286                 std::string tac_version = np.substr(np.rfind('/') + 1);
287                 _INFO("TAC name : %s", tac_name.c_str());
288                 _INFO("TAC version : %s", tac_version.c_str());
289
290                 std::string tac_version_dir = concatPath(__TAC_DIR, np);
291                 std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO);
292                 isCreateDirectory = false;
293                 if (!bf::exists(tac_version_dir)) {
294                         _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
295                         if (!createDir(tac_version_dir)) {
296                                 _ERR("Cannot create directory: %s", tac_version_dir.c_str());
297                                 return 0;
298                         }
299                         isCreateDirectory = true;
300                         createDirectories.push_back(tac_version_dir);
301                         std::ofstream ofs(sha256_info, std::ios::app);
302                         int assembly_count = 0;
303                         for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
304                                 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind('/'));
305                                 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind('/'));
306                                 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind('/') + 1);
307                                 std::string sha = npAssemblySha.substr(npAssemblySha.rfind('/') + 1);
308                                 if (!strcmp(nuget_package.c_str(), np.c_str())) {
309                                         ofs << assembly << ";" << sha << std::endl;
310                                         assembly_count++;
311                                 }
312                         }
313                         ofs << assembly_count << std::endl;
314                         ofs.close();
315
316                         if (createSymlink(tac_version_dir, np) < 0) {
317                                 _ERR("Failed to create symlink");
318                                 return -1;
319                         }
320                         std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
321                                         "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
322                         dbInsert(tac_db, TAC_APP_LIST_DB, sql);
323                 } else {
324                         _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
325                         int compare_count = 0;
326                         int assembly_count = 0;
327                         std::string sha256_count = "0";
328                         for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
329                                 std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind('/'));
330                                 std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind('/'));
331                                 std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind('/') + 1);
332                                 std::string sha = npAssemblySha.substr(npAssemblySha.rfind('/') + 1);
333                                 if (!strcmp(nuget_package.c_str(), np.c_str())) {
334                                         assembly_count++;
335                                         std::ifstream ifs(sha256_info);
336                                         std::string get_str;
337                                         if (ifs.is_open()) {
338                                                 while (getline(ifs, get_str)) {
339                                                         if (!strcmp(get_str.c_str(), (assembly + ";" + sha).c_str())) {
340                                                                 compare_count++;
341                                                         }
342                                                         sha256_count = get_str;
343                                                 }
344                                                 ifs.close();
345                                         }
346                                 }
347                         }
348                         if (!strcmp(std::to_string(assembly_count).c_str(), std::to_string(compare_count).c_str()) &&
349                                 !strcmp(std::to_string(assembly_count).c_str(), sha256_count.c_str())) {
350                                 _INFO("Same nuget : %s", tac_name.c_str());
351                                 if (createSymlink(tac_version_dir, np) < 0) {
352                                         _ERR("Failed to create symlink");
353                                         return -1;
354                                 }
355                                 std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
356                                                 "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
357                                 dbInsert(tac_db, TAC_APP_LIST_DB, sql);
358                         } else {
359                                 _INFO("Different nuget : %s", tac_name.c_str());
360                         }
361                 }
362                 if (!bf::exists(sha256_info)) {
363                         if(!removeAll(tac_version_dir)) {
364                                 _ERR("Failed to remove of %s", tac_version_dir.c_str());
365                         }
366                 }
367         }
368         return 0;
369 }
370
371 static int sqliteCb(void *count, int argc, char **argv, char **colName) {
372         int *c = (int*)count;
373         *c = atoi(argv[0]);
374         return 0;
375 }
376
377 int updateTacDB(const char *pkgId)
378 {
379         for (auto& unp : updateTac) {
380                 int count = -1;
381                 if (tac_db) {
382                         if (!dbOpen(tac_db, TAC_APP_LIST_DB)) {
383                                 _ERR("Sqlite open error");
384                                 return -1;
385                         }
386                 } else {
387                         _ERR("Sqlite create error");
388                         return -1;
389                 }
390                 std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE NUGET = '" + unp + "';";
391                 int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL);
392                 if (ret != SQLITE_OK) {
393                         _ERR("Sqlite select error");
394                         return -1;
395                 }
396                 if (count == 0) {
397                         std::string tac_version_dir_prev = concatPath(__TAC_DIR, unp);
398                         std::string tac_version_dir_backup = tac_version_dir_prev + ".bck";
399                         if (!copyDir(tac_version_dir_prev, tac_version_dir_backup)) {
400                                 _ERR("Failed to copy of %s to %s", tac_version_dir_prev.c_str(), tac_version_dir_backup.c_str());
401                                 return -1;
402                         }
403                         if (!removeAll(tac_version_dir_prev)) {
404                                 _ERR("Failed to remove of %s", tac_version_dir_prev.c_str());
405                                 return -1;
406                         }
407                 }
408         }
409         return 0;
410 }
411
412 extern "C" int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgId, const char *appId, GList *list)
413 {
414         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UPGRADE =====]");
415         _INFO("PackageID : %s", pkgId);
416
417         if (!appTypeCheck(std::string(pkgId))) {
418                 _INFO("App type is not dotnet");
419                 return 0;
420         }
421         if (getExecName(std::string(pkgId), execName) < 0) {
422                 return 0;
423         }
424         if (getRootPath(std::string(pkgId), rootPath) < 0) {
425                 return 0;
426         } else {
427                 binPath = concatPath(rootPath, "bin");
428         }
429         if (!strcmp("removed", status.c_str())) {
430                 _INFO("Skipped to parse of deps.json");
431         } else {
432                 if (metadataCheck(list)) {
433                         if (depsJsonParser() < 0) {
434                                 return 0;
435                         }
436                 }
437         }
438
439         status = "update";
440         tac_db = dbCreate(TAC_APP_LIST_DB);
441         if (tac_db) {
442                 if (!dbOpen(tac_db, TAC_APP_LIST_DB)) {
443                         _ERR("Sqlite open error");
444                         return 0;
445                 }
446         } else {
447                 _ERR("Sqlite create error");
448                 return 0;
449         }
450
451         std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
452         updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql);
453
454         if (tacDB.empty()) {
455                 sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
456                 dbDelete(tac_db, TAC_APP_LIST_DB, sql);
457                 if (updateTacDB(pkgId) < 0) {
458                         return -1;
459                 }
460         } else {
461                 for (auto& np : tacDB) {
462                         std::string tac_name = np.substr(0, np.find('/'));
463                         std::string tac_version = np.substr(np.rfind('/') + 1);
464                         _INFO("TAC name : %s", tac_name.c_str());
465                         _INFO("TAC version : %s", tac_version.c_str());
466
467                         std::string tac_version_dir = concatPath(__TAC_DIR, np);
468                         std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO);
469                         isCreateDirectory = false;
470                         if (!bf::exists(tac_version_dir)) {
471                                 _INFO("Create tac_version_dir [%s]", tac_version_dir.c_str());
472                                 if (!createDir(tac_version_dir)) {
473                                         _ERR("Cannot create directory: %s", tac_version_dir.c_str());
474                                         return 0;
475                                 }
476                                 isCreateDirectory = true;
477                                 createDirectories.push_back(tac_version_dir);
478                                 std::ofstream ofs2(sha256_info, std::ios::app);
479                                 int assembly_count = 0;
480                                 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
481                                         std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind('/'));
482                                         std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind('/'));
483                                         std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind('/') + 1);
484                                         std::string sha = npAssemblySha.substr(npAssemblySha.rfind('/') + 1);
485                                         if (!strcmp(nuget_package.c_str(), np.c_str())) {
486                                                 ofs2 << assembly << ";" << sha << std::endl;
487                                                 assembly_count++;
488                                         }
489                                 }
490                                 ofs2 << assembly_count << std::endl;
491                                 ofs2.close();
492                                 if (createSymlink(tac_version_dir, np) < 0) {
493                                         _ERR("Failed to create symlink");
494                                         return -1;
495                                 }
496
497                                 int count = -1;
498                                 sql = "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';";
499                                 int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL);
500                                 if (ret != SQLITE_OK) {
501                                         _ERR("Sqlite select error");
502                                         return -1;
503                                 }
504                                 if (count == 1) {
505                                         sql = "UPDATE TAC SET NAME = '" + tac_name + "', VERSION = '" + tac_version + "', NUGET = '" + np + "' WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';";
506                                         dbUpdate(tac_db, TAC_APP_LIST_DB, sql);
507                                 } else if (count == 0) {
508                                         sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
509                                                 "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
510                                         dbInsert(tac_db, TAC_APP_LIST_DB, sql);
511                                 }
512                         } else {
513                                 _INFO("Exists tac_version_dir [%s]", tac_version_dir.c_str());
514                                 int compare_count = 0;
515                                 int assembly_count = 0;
516                                 std::string sha256_count = "0";
517                                 for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
518                                         std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind('/'));
519                                         std::string nuget_package = nuget_package_assembly.substr(0, nuget_package_assembly.rfind('/'));
520                                         std::string assembly = nuget_package_assembly.substr(nuget_package_assembly.rfind('/') + 1);
521                                         std::string sha = npAssemblySha.substr(npAssemblySha.rfind('/') + 1);
522                                         if (!strcmp(nuget_package.c_str(), np.c_str())) {
523                                                 assembly_count++;
524                                                 std::ifstream ifs2(sha256_info);
525                                                 std::string get_str;
526                                                 if (ifs2.is_open()) {
527                                                         while (getline(ifs2, get_str)) {
528                                                                 if (!strcmp(get_str.c_str(), (assembly + ";" + sha).c_str())) {
529                                                                         compare_count++;
530                                                                 }
531                                                                 sha256_count = get_str;
532                                                         }
533                                                         ifs2.close();
534                                                 }
535                                         }
536                                 }
537
538                                 if (!strcmp(std::to_string(assembly_count).c_str(), std::to_string(compare_count).c_str()) &&
539                                         !strcmp(std::to_string(assembly_count).c_str(), sha256_count.c_str())) {
540                                         _INFO("Same nuget : %s", tac_name.c_str());
541                                         if (createSymlink(tac_version_dir, np) < 0) {
542                                                 _ERR("Failed to create symlink");
543                                                 return -1;
544                                         }
545
546                                         int count = -1;
547                                         std::string sql = "SELECT COUNT(NUGET) FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';";
548                                         int ret = sqlite3_exec(tac_db, sql.c_str(), sqliteCb, &count, NULL);
549                                         if (ret != SQLITE_OK) {
550                                                 _ERR("Sqlite select error");
551                                                 return -1;
552                                         }
553                                         if (count == 1) {
554                                                 sql = "UPDATE TAC SET NAME = '" + tac_name + "', VERSION = '" + tac_version + "', NUGET = '" + np + "' WHERE PKGID = '" + std::string(pkgId) + "' AND NAME = '" + tac_name + "';";
555                                                 dbUpdate(tac_db, TAC_APP_LIST_DB, sql);
556                                         } else if (count == 0) {
557                                                 sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
558                                                         "VALUES ('" + std::string(pkgId) + "', '" + np + "', '" + tac_name + "', '" + tac_version + "');";
559                                                 dbInsert(tac_db, TAC_APP_LIST_DB, sql);
560                                         }
561                                 } else {
562                                         _INFO("Different nuget : %s", tac_name.c_str());
563                                 }
564                         }
565                         if (!bf::exists(sha256_info)) {
566                                 if(!removeAll(tac_version_dir)) {
567                                         _ERR("Failed to remove of %s", tac_version_dir.c_str());
568                                 }
569                         }
570                 }
571                 for (auto& unp : updateTac) {
572                         bool isExits = false;
573                         for (auto& np : tacDB) {
574                                 if (!strcmp(unp.c_str(), np.c_str())) {
575                                         isExits = true;
576                                         break;
577                                 }
578                         }
579
580                         if (!isExits) {
581                                 std::string sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "' AND NUGET = '" + unp + "';";
582                                 dbDelete(tac_db, TAC_APP_LIST_DB, sql);
583                         }
584                 }
585                 if (updateTacDB(pkgId) < 0) {
586                         return -1;
587                 }
588         }
589         return 0;
590 }
591
592 extern "C" int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgId, const char *appId, GList *list)
593 {
594         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNINSTALL =====]");
595         _INFO("PackageID : %s", pkgId);
596
597         status = "uninstall";
598         tac_db = dbCreate(TAC_APP_LIST_DB);
599         if (tac_db) {
600                 if (!dbOpen(tac_db, TAC_APP_LIST_DB)) {
601                         _ERR("Sqlite open error");
602                         return 0;
603                 }
604         } else {
605                 _ERR("Sqlite create error");
606                 return 0;
607         }
608
609         std::string sql = "SELECT * FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
610         updateTac = dbSelect(tac_db, TAC_APP_LIST_DB, sql);
611
612         sql = "DELETE FROM TAC WHERE PKGID = '" + std::string(pkgId) + "';";
613         dbDelete(tac_db, TAC_APP_LIST_DB, sql);
614
615         if (updateTacDB(pkgId) < 0) {
616                 return -1;
617         }
618         return 0;
619 }
620
621 extern "C" int PKGMGR_MDPARSER_PLUGIN_REMOVED(const char *pkgId, const char *appId, GList *list)
622 {
623         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_REMOVED =====]");
624         _INFO("PackageID : %s", pkgId);
625
626         status = "removed";
627
628         return PKGMGR_MDPARSER_PLUGIN_UPGRADE(pkgId, appId, list);
629 }
630
631 void cleanStep(std::string tac)
632 {
633         std::string current_tac = concatPath(__TAC_DIR, tac.substr(0, tac.find('/')));
634         for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
635                 if (bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) {
636                         if (!removeAll(bck.path().string())) {
637                                 _ERR("Failed to remove of %s", bck.path().c_str());
638                         }
639                         break;
640                 }
641         }
642
643         bool isExist = false;
644         for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
645                 if (bf::exists(bck.path()) && bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") == NULL) {
646                         isExist = true;
647                         break;
648                 }
649         }
650         if (!isExist) {
651                 if (!removeAll(current_tac)) {
652                         _ERR("Failed to remove of %s", current_tac.c_str());
653                 }
654         }
655 }
656
657 void install_Clean()
658 {
659         return;
660 }
661
662 void unInstall_Clean()
663 {
664         for (auto& unp : updateTac) {
665                 cleanStep(unp);
666         }
667 }
668
669 void update_Clean()
670 {
671         if (!tacDB.empty()) {
672                 for (auto& np : tacDB) {
673                         cleanStep(np);
674                 }
675         }
676         unInstall_Clean();
677 }
678
679 extern "C" int PKGMGR_MDPARSER_PLUGIN_CLEAN(const char *pkgId, const char *appId, GList *list)
680 {
681         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_CLEAN =====]");
682         _INFO("PackageID : %s", pkgId);
683
684         if (tac_db) {
685                 dbClose(tac_db);
686                 tac_db = NULL;
687         }
688         if (!strcmp("install", status.c_str())) {
689                 install_Clean();
690         } else if (!strcmp("update", status.c_str())) {
691                 update_Clean();
692         } else if (!strcmp("uninstall", status.c_str())) {
693                 unInstall_Clean();
694         }
695         return 0;
696 }
697
698 void undoStep(std::string tac)
699 {
700         std::string current_tac = concatPath(__TAC_DIR, tac.substr(0, tac.find('/')));
701         for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
702                 if (bf::is_directory(bck.path()) && strstr(bck.path().c_str(), ".bck") != NULL) {
703                         if (!moveFile(bck.path(), bck.path().string().substr(0, bck.path().string().rfind(".bck")))) {
704                                 _ERR("Failed to move %s to %s",
705                                         bck.path().c_str(), bck.path().string().substr(0, bck.path().string().rfind(".bck")).c_str());
706                         }
707                         break;
708                 }
709         }
710 }
711
712 void install_Undo()
713 {
714         for (auto& cd : createDirectories) {
715                 if (!removeAll(cd)) {
716                         _ERR("Failed to remove of %s", cd.c_str());
717                 }
718         }
719 }
720
721 void unInstall_Undo()
722 {
723         for (auto& unp : updateTac) {
724                 undoStep(unp);
725         }
726 }
727
728 void update_Undo()
729 {
730         install_Undo();
731         if (!tacDB.empty()) {
732                 for (auto& np : tacDB) {
733                         undoStep(np);
734                 }
735         }
736         unInstall_Undo();
737 }
738
739 extern "C" int PKGMGR_MDPARSER_PLUGIN_UNDO(const char *pkgId, const char *appId, GList *list)
740 {
741         _DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]");
742         _INFO("PackageID : %s", pkgId);
743
744         if (tac_db) {
745                 dbRollback(tac_db);
746                 tac_db = NULL;
747         }
748         if (!strcmp("install", status.c_str())) {
749                 install_Undo();
750         } else if (!strcmp("update", status.c_str())) {
751                 update_Undo();
752         } else if (!strcmp("uninstall", status.c_str())) {
753                 unInstall_Undo();
754         }
755         return 0;
756 }