install: add duplicate case of beginning index
[sdk/emulator/qemu.git] / tizen / src / util / extra_pkgs_install.c
1 /*
2  * Emulator Extra Package Installation Utility
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact:
7  *  Jinhyung choi   <jinhyung2.choi@samsung.com>
8  *  Sangho Park     <sangho1206.park@samsung.com>
9  *  YeongKyoon Lee  <yeongkyoon.lee@samsung.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <dirent.h>
34
35 #include "qemu/osdep.h"
36 #include "qemu-common.h"
37 #include "qemu/queue.h"
38
39 #include "hw/virtio/maru_virtio_evdi.h"
40
41 #include "extra_pkgs_install.h"
42 #include "emul_state.h"
43 #include "debug_ch.h"
44
45 MULTI_DEBUG_CHANNEL(qemu, pkgs);
46
47 /* FIXME: getting add-on path */
48 static char *get_addon_path(void)
49 {
50 #ifndef CONFIG_WIN32
51     const char *parent = "../../../";
52     const char *separator = "/";
53 #else
54     const char *parent = "..\\..\\..\\";
55     const char *separator = "\\";
56 #endif
57
58     int ret = 0;
59
60     const char *profile_name = get_profile_name();
61     if (!profile_name) {
62         return NULL;
63     }
64
65     char *extra_path = (char *)malloc(MAX_PKG_LIST);
66     if (!extra_path) {
67         LOG_SEVERE("cannot alloc extra_path.\n");
68         return NULL;
69     }
70
71     ret = sprintf(extra_path, "%s%s%s%s%s%s%s",
72             get_bin_path(), parent, profile_name, separator,
73             IMAGE_DIRECTORY, separator, ADDON_DIRECTORY);
74     if (ret < 0) {
75         LOG_SEVERE("ADDON PATH composition is failed.\n");
76     }
77
78     LOG_INFO("ADDON PATH: %s\n", extra_path);
79
80     return extra_path;
81 }
82
83 static void add_addon_pkgs_name(char *pkgs, char *name)
84 {
85     if (strlen(pkgs) == 0) {
86         strcpy(pkgs, name);
87     } else {
88         sprintf(pkgs, "%s, %s", pkgs, name);
89     }
90 }
91
92 static void send_to_emuld(char *addon, char *pkgs)
93 {
94     int ret = 0;
95     int data_len = 0;
96     int action = 1;
97     char data[MAX_PKG_LIST + MAX_PATH_PKG_LIST];
98
99     memset(data, 0, sizeof(data));
100     sprintf(data, "%s, %s", addon, pkgs);
101
102     data_len = strlen(data) + 1;
103     int sndlen = 14 + data_len;
104     char *sndbuf = (char *) g_malloc0(sndlen);
105     if (!sndbuf) {
106         LOG_SEVERE("Failed to alloc emuld message\n");
107         return;
108     }
109
110     memcpy(sndbuf, CMD_PKG, 7);
111     memcpy(sndbuf + 10, &data_len, 2);
112     memcpy(sndbuf + 13, &action, 1);
113     memcpy(sndbuf + 14, data, data_len);
114
115     LOG_TRACE("sndbuf data: %s\n", sndbuf + 14);
116
117     ret = send_to_evdi(route_ij, sndbuf, sndlen);
118     if (ret < 0) {
119         LOG_SEVERE("Failed to send emuld message\n");
120     }
121 }
122
123 #ifdef CONFIG_WIN32
124 static char *strcasestr(const char *haystack, const char *needle)
125 {
126     size_t length_needle;
127     size_t length_haystack;
128     size_t i;
129
130     if (!haystack || !needle) {
131         return NULL;
132     }
133
134     length_needle = strnlen(needle, MAX_PKG_LIST);
135     length_haystack = strnlen(haystack, MAX_PKG_LIST);
136
137     for (i = 0; i < length_haystack; i++) {
138         size_t j;
139         for (j = 0; j < length_needle; j++) {
140             unsigned char c1;
141             unsigned char c2;
142
143             c1 = haystack[i+j];
144             c2 = needle[j];
145             if (toupper(c1) != toupper(c2)) {
146                 goto next;
147             }
148         }
149         return (char *) haystack + i;
150     next:
151         ;
152     }
153
154     return NULL;
155 }
156 #endif /* CONFIG_WIN32 */
157
158 void epi_init(void)
159 {
160     int pkg_count = 0;
161     char sub_addon_path[512];
162     DIR *main_dir = NULL;
163     DIR *sub_dir = NULL;
164     struct dirent *dir_entry = NULL;
165     struct dirent *sub_dir_entry = NULL;
166     char addon[MAX_PATH_PKG_LIST];
167     char pkgs[MAX_PKG_LIST];
168     char pkg_list[MAX_PKG_LIST];
169     char *ext;
170     char *addon_path = get_addon_path();
171
172     if (!addon_path) {
173         return;
174     }
175
176     main_dir = opendir(addon_path);
177     if (!main_dir) {
178         LOG_INFO("Add-on Directory is empty. No package install is required.\n");
179         return;
180     }
181
182     memset(pkg_list, 0, sizeof(pkg_list));
183
184     while ((dir_entry = readdir(main_dir))) {
185         if ((strncasecmp(dir_entry->d_name, ".", 1) != 0) &&
186             (strncasecmp(dir_entry->d_name, "..", 2) != 0)) {
187             LOG_TRACE("reading addon directory: %s\n", dir_entry->d_name);
188
189             memset(sub_addon_path, 0, 512);
190             memset(addon, 0, sizeof(addon));
191             memset(pkgs, 0, sizeof(pkgs));
192
193             strcpy(addon, dir_entry->d_name);
194
195 #ifndef CONFIG_WIN32
196             sprintf(sub_addon_path, "%s/%s", addon_path, dir_entry->d_name);
197 #else
198             sprintf(sub_addon_path, "%s\\%s", addon_path, dir_entry->d_name);
199 #endif
200             sub_dir = opendir(sub_addon_path);
201             if (!sub_dir) {
202                 LOG_SEVERE("Add-on sub Directory open failed.");
203                 continue;
204             }
205             while ((sub_dir_entry = readdir(sub_dir))) {
206                 if ((strncasecmp(sub_dir_entry->d_name, ".", 1) != 0) &&
207                     (strncasecmp(sub_dir_entry->d_name, "..", 2) != 0)) {
208                     if (strlen(sub_dir_entry->d_name) <= 4) {
209                         continue;
210                     }
211
212                     ext = &sub_dir_entry->d_name[strlen(sub_dir_entry->d_name) - 4];
213                     if (strcmp(EXT_RPM, ext)) {
214                         continue;
215                     }
216                     char* checkDup = strcasestr(pkg_list, sub_dir_entry->d_name);
217                     if (checkDup != NULL) {
218                         if (checkDup == pkg_list) {
219                             LOG_INFO("duplicated package : %s\n", sub_dir_entry->d_name);
220                             continue;
221                         }
222                         checkDup--;
223                         if (*checkDup == ' ') {
224                             LOG_INFO("duplicated package: %s\n", sub_dir_entry->d_name);
225                             continue;
226                         }
227                     }
228
229                     pkg_count++;
230                     add_addon_pkgs_name(pkgs, sub_dir_entry->d_name);
231                     add_addon_pkgs_name(pkg_list, sub_dir_entry->d_name);
232                     LOG_TRACE("reading addon sub directory: %s\n", sub_dir_entry->d_name);
233                 }
234             }
235
236             LOG_INFO("pkgs: %s, %s\n", addon, pkgs);
237
238             if (pkg_count == 0) {
239                 LOG_INFO("pkgs addon %s is empty. skip!\n", addon);
240             } else {
241                 /* send to emuld */
242                 send_to_emuld(addon, pkgs);
243             }
244
245             closedir(sub_dir);
246             pkg_count = 0;
247         }
248     }
249
250     closedir(main_dir);
251     free(addon_path);
252
253     LOG_INFO("pkg_list: %s\n", pkg_list);
254 }