e6455bc2e33adf3d1a1a6957c121b468928bcc6d
[framework/base/rpm-installer.git] / common / rpm-installer-util.c
1 /*
2  * rpm-installer
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <string.h>
24 #include <stdarg.h>
25 #include <sys/wait.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <wait.h>
29 #include <stdio.h>
30 #include <ctype.h>              /* for isspace () */
31 #include <string.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <dirent.h>
37 #include <sys/statvfs.h>
38
39 #include <syslog.h>
40 #include "rpm-installer-util.h"
41
42 int _ri_get_attribute(xmlTextReaderPtr reader, char *attribute, const char **xml_attribute)
43 {
44         if(xml_attribute == NULL){
45                 _LOGE("@xml_attribute is NULL!!");
46                 return -1;
47         }
48         xmlChar *attrib_val = xmlTextReaderGetAttribute(reader,XMLCHAR(attribute));
49         if(attrib_val)
50                 *xml_attribute = ASCII(attrib_val);
51
52         return 0;
53 }
54
55 void _ri_error_no_to_string(int errnumber, char **errstr)
56 {
57         if (errstr == NULL)
58                 return;
59         switch (errnumber) {
60         case RPM_INSTALLER_SUCCESS:
61                 *errstr = RPM_INSTALLER_SUCCESS_STR;
62                 break;
63         case RPM_INSTALLER_ERR_WRONG_PARAM:
64                 *errstr = RPM_INSTALLER_ERR_WRONG_PARAM_STR;
65                 break;
66         case RPM_INSTALLER_ERR_DBUS_PROBLEM:
67                 *errstr = RPM_INSTALLER_ERR_DBUS_PROBLEM_STR;
68                 break;
69         case RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY:
70                 *errstr = RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY_STR;
71                 break;
72         case RPM_INSTALLER_ERR_PACKAGE_EXIST:
73                 *errstr = RPM_INSTALLER_ERR_PACKAGE_EXIST_STR;
74                 break;
75         case RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED:
76                 *errstr = RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED_STR;
77                 break;
78         case RPM_INSTALLER_ERR_RESOURCE_BUSY:
79                 *errstr = RPM_INSTALLER_ERR_RESOURCE_BUSY_STR;
80                 break;
81         case RPM_INSTALLER_ERR_UNKNOWN:
82                 *errstr = RPM_INSTALLER_ERR_UNKNOWN_STR;
83                 break;
84         case RPM_INSTALLER_ERR_PKG_NOT_FOUND:
85                 *errstr = RPM_INSTALLER_ERR_PKG_NOT_FOUND_STR;
86                 break;
87         case RPM_INSTALLER_ERR_NOT_SUPPOTED_VERSION:
88                 *errstr = RPM_INSTALLER_ERR_NOT_SUPPOTED_VERSION_STR;
89                 break;
90         case RPM_INSTALLER_ERR_NO_RPM_FILE:
91                 *errstr = RPM_INSTALLER_ERR_NO_RPM_FILE_STR;
92                 break;
93         case RPM_INSTALLER_ERR_DB_ACCESS_FAILED:
94                 *errstr = RPM_INSTALLER_ERR_DB_ACCESS_FAILED_STR;
95                 break;
96         case RPM_INSTALLER_ERR_RPM_OPERATION_FAILED:
97                 *errstr = RPM_INSTALLER_ERR_RPM_OPERATION_FAILED_STR;
98                 break;
99         case RPM_INSTALLER_ERR_PACKAGE_NOT_UPGRADED:
100                 *errstr = RPM_INSTALLER_ERR_PACKAGE_NOT_UPGRADED_STR;
101                 break;
102         case RPM_INSTALLER_ERR_RPM_SCRIPT_WRONG_ARGS:
103                 *errstr = RPM_INSTALLER_ERR_RPM_SCRIPT_WRONG_ARGS_STR;
104                 break;
105         case RPM_INSTALLER_ERR_PACKAGE_INSTALLATION_DISABLED:
106                 *errstr = RPM_INSTALLER_ERR_PACKAGE_INSTALLATION_DISABLED_STR;
107                 break;
108         case RPM_INSTALLER_ERR_PACKAGE_UNINSTALLATION_DISABLED:
109                 *errstr = RPM_INSTALLER_ERR_PACKAGE_UNINSTALLATION_DISABLED_STR;
110                 break;
111         case RPM_INSTALLER_ERR_CLEAR_DATA_FAILED:
112                 *errstr = RPM_INSTALLER_ERR_CLEAR_DATA_FAILED_STR;
113                 break;
114         case RPM_INSTALLER_ERR_INTERNAL:
115                 *errstr = RPM_INSTALLER_ERR_INTERNAL_STR;
116                 break;
117         case RPM_INSTALLER_ERR_NO_MANIFEST:
118                 *errstr = RPM_INSTALLER_ERR_NO_MANIFEST_STR;
119                 break;
120         case RPM_INSTALLER_ERR_INVALID_MANIFEST:
121                 *errstr = RPM_INSTALLER_ERR_INVALID_MANIFEST_STR;
122                 break;
123         case RPM_INSTALLER_ERR_SIG_NOT_FOUND:
124                 *errstr = RPM_INSTALLER_ERR_SIG_NOT_FOUND_STR;
125                 break;
126         case RPM_INSTALLER_ERR_SIG_INVALID:
127                 *errstr = RPM_INSTALLER_ERR_SIG_INVALID_STR;
128                 break;
129         case RPM_INSTALLER_ERR_SIG_VERIFICATION_FAILED:
130                 *errstr = RPM_INSTALLER_ERR_SIG_VERIFICATION_FAILED_STR;
131                 break;
132         case RPM_INSTALLER_ERR_ROOT_CERT_NOT_FOUND:
133                 *errstr = RPM_INSTALLER_ERR_ROOT_CERT_NOT_FOUND_STR;
134                 break;
135         case RPM_INSTALLER_ERR_CERT_INVALID:
136                 *errstr = RPM_INSTALLER_ERR_CERT_INVALID_STR;
137                 break;
138         case RPM_INSTALLER_ERR_CERTCHAIN_VERIFICATION_FAILED:
139                 *errstr = RPM_INSTALLER_ERR_CERTCHAIN_VERIFICATION_FAILED_STR;
140                 break;
141         case RPM_INSTALLER_ERR_NO_CONFIG:
142                 *errstr = RPM_INSTALLER_ERR_NO_CONFIG_STR;
143                 break;
144         case RPM_INSTALLER_ERR_INVALID_CONFIG:
145                 *errstr = RPM_INSTALLER_ERR_INVALID_CONFIG_STR;
146                 break;
147         case RPM_INSTALLER_ERR_CMD_NOT_SUPPORTED:
148                 *errstr = RPM_INSTALLER_ERR_CMD_NOT_SUPPORTED_STR;
149                 break;
150         case RPM_INSTALLER_ERR_PRIVILEGE_UNAUTHORIZED:
151                 *errstr = RPM_INSTALLER_ERR_PRIVILEGE_UNAUTHORIZED_STR;
152                 break;
153         case RPM_INSTALLER_ERR_PRIVILEGE_UNKNOWN:
154                 *errstr = RPM_INSTALLER_ERR_PRIVILEGE_UNKNOWN_ERR_STR;
155                 break;
156         case RPM_INSTALLER_ERR_PRIVILEGE_USING_LEGACY_FAILED:
157                 *errstr = RPM_INSTALLER_ERR_PRIVILEGE_USING_LEGACY_FAILED_STR;
158                 break;
159         default:
160                 *errstr = RPM_INSTALLER_ERR_UNKNOWN_STR;
161                 break;
162         }
163 }
164
165 int _ri_string_to_error_no(char *errstr)
166 {
167         int errnumber = RPM_INSTALLER_ERR_UNKNOWN;
168         if (errstr == NULL)
169                 return errnumber;
170
171         if (strcmp(errstr, RPM_INSTALLER_SUCCESS_STR) == 0)
172                 errnumber = RPM_INSTALLER_SUCCESS;
173         else if (strcmp(errstr, RPM_INSTALLER_ERR_WRONG_PARAM_STR) == 0)
174                 errnumber = RPM_INSTALLER_ERR_WRONG_PARAM;
175         else if (strcmp(errstr, RPM_INSTALLER_ERR_DBUS_PROBLEM_STR) == 0)
176                 errnumber = RPM_INSTALLER_ERR_DBUS_PROBLEM;
177         else if (strcmp(errstr, RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY_STR) == 0)
178                 errnumber = RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
179         else if (strcmp(errstr, RPM_INSTALLER_ERR_PACKAGE_EXIST_STR) == 0)
180                 errnumber = RPM_INSTALLER_ERR_PACKAGE_EXIST;
181         else if (strcmp(errstr, RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED_STR)
182                  == 0)
183                 errnumber = RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED;
184         else if (strcmp(errstr, RPM_INSTALLER_ERR_RESOURCE_BUSY_STR) == 0)
185                 errnumber = RPM_INSTALLER_ERR_RESOURCE_BUSY;
186         else if (strcmp(errstr, RPM_INSTALLER_ERR_UNKNOWN_STR) == 0)
187                 errnumber = RPM_INSTALLER_ERR_UNKNOWN;
188         else if (strcmp(errstr, RPM_INSTALLER_ERR_PKG_NOT_FOUND_STR) == 0)
189                 errnumber = RPM_INSTALLER_ERR_PKG_NOT_FOUND;
190         else if (strcmp(errstr, RPM_INSTALLER_ERR_NOT_SUPPOTED_VERSION_STR) ==
191                  0)
192                 errnumber = RPM_INSTALLER_ERR_NOT_SUPPOTED_VERSION;
193         else if (strcmp(errstr, RPM_INSTALLER_ERR_NO_RPM_FILE_STR) == 0)
194                 errnumber = RPM_INSTALLER_ERR_NO_RPM_FILE;
195         else if (strcmp(errstr, RPM_INSTALLER_ERR_DB_ACCESS_FAILED_STR) == 0)
196                 errnumber = RPM_INSTALLER_ERR_DB_ACCESS_FAILED;
197         else if (strcmp(errstr, RPM_INSTALLER_ERR_RPM_OPERATION_FAILED_STR)
198                  == 0)
199                 errnumber = RPM_INSTALLER_ERR_RPM_OPERATION_FAILED;
200         else if (strcmp(errstr, RPM_INSTALLER_ERR_PACKAGE_NOT_UPGRADED_STR) ==
201                  0)
202                 errnumber = RPM_INSTALLER_ERR_PACKAGE_NOT_UPGRADED;
203         else if (strcmp(errstr, RPM_INSTALLER_ERR_RPM_SCRIPT_WRONG_ARGS_STR) ==
204                  0)
205                 errnumber = RPM_INSTALLER_ERR_RPM_SCRIPT_WRONG_ARGS;
206         else if (strcmp(errstr, RPM_INSTALLER_ERR_PACKAGE_INSTALLATION_DISABLED_STR) == 0)
207                 errnumber = RPM_INSTALLER_ERR_PACKAGE_INSTALLATION_DISABLED;
208         else if (strcmp(errstr, RPM_INSTALLER_ERR_PACKAGE_UNINSTALLATION_DISABLED_STR) == 0)
209                 errnumber = RPM_INSTALLER_ERR_PACKAGE_UNINSTALLATION_DISABLED;
210         else if (strcmp(errstr, RPM_INSTALLER_ERR_CLEAR_DATA_FAILED_STR) == 0)
211                 errnumber = RPM_INSTALLER_ERR_CLEAR_DATA_FAILED;
212         else if (strcmp(errstr, RPM_INSTALLER_ERR_INTERNAL_STR) == 0)
213                 errnumber = RPM_INSTALLER_ERR_INTERNAL;
214         else if (strcmp(errstr, RPM_INSTALLER_ERR_NO_MANIFEST_STR) == 0)
215                 errnumber = RPM_INSTALLER_ERR_NO_MANIFEST;
216         else if (strcmp(errstr, RPM_INSTALLER_ERR_INVALID_MANIFEST_STR) == 0)
217                 errnumber = RPM_INSTALLER_ERR_INVALID_MANIFEST;
218         else if (strcmp(errstr, RPM_INSTALLER_ERR_SIG_NOT_FOUND_STR) == 0)
219                 errnumber = RPM_INSTALLER_ERR_SIG_NOT_FOUND;
220         else if (strcmp(errstr, RPM_INSTALLER_ERR_SIG_INVALID_STR) == 0)
221                 errnumber = RPM_INSTALLER_ERR_SIG_INVALID;
222         else if (strcmp(errstr, RPM_INSTALLER_ERR_SIG_VERIFICATION_FAILED_STR) == 0)
223                 errnumber = RPM_INSTALLER_ERR_SIG_VERIFICATION_FAILED;
224         else if (strcmp(errstr, RPM_INSTALLER_ERR_ROOT_CERT_NOT_FOUND_STR) == 0)
225                 errnumber = RPM_INSTALLER_ERR_ROOT_CERT_NOT_FOUND;
226         else if (strcmp(errstr, RPM_INSTALLER_ERR_CERT_INVALID_STR) == 0)
227                 errnumber = RPM_INSTALLER_ERR_CERT_INVALID;
228         else if (strcmp(errstr, RPM_INSTALLER_ERR_CERTCHAIN_VERIFICATION_FAILED_STR) == 0)
229                 errnumber = RPM_INSTALLER_ERR_CERTCHAIN_VERIFICATION_FAILED;
230         else if (strcmp(errstr, RPM_INSTALLER_ERR_NO_CONFIG_STR) == 0)
231                 errnumber = RPM_INSTALLER_ERR_NO_CONFIG;
232         else if (strcmp(errstr, RPM_INSTALLER_ERR_INVALID_CONFIG_STR) == 0)
233                 errnumber = RPM_INSTALLER_ERR_INVALID_CONFIG;
234         else if (strcmp(errstr, RPM_INSTALLER_ERR_CMD_NOT_SUPPORTED_STR) == 0)
235                 errnumber = RPM_INSTALLER_ERR_CMD_NOT_SUPPORTED;
236         else if (strcmp(errstr, RPM_INSTALLER_ERR_PRIVILEGE_UNAUTHORIZED_STR) == 0)
237                 errnumber = RPM_INSTALLER_ERR_PRIVILEGE_UNAUTHORIZED;
238         else if (strcmp(errstr, RPM_INSTALLER_ERR_PRIVILEGE_UNKNOWN_ERR_STR) == 0)
239                 errnumber = RPM_INSTALLER_ERR_PRIVILEGE_UNKNOWN;
240         else if (strcmp(errstr, RPM_INSTALLER_ERR_PRIVILEGE_USING_LEGACY_FAILED_STR) == 0)
241                 errnumber = RPM_INSTALLER_ERR_PRIVILEGE_USING_LEGACY_FAILED;
242         else
243                 errnumber = RPM_INSTALLER_ERR_UNKNOWN;
244
245         return errnumber;
246 }
247
248 int _rpm_delete_dir(char *dirname)
249 {
250         int ret = 0;
251         DIR *dp;
252         struct dirent *ep;
253         char abs_filename[FILENAME_MAX];
254         struct stat stFileInfo;
255
256         if (dirname == NULL) {
257                 _LOGE("dirname is NULL.");
258                 return -1;
259         }
260
261         _LOGD("delete_dir=[%s]", dirname);
262
263         dp = opendir(dirname);
264         if (dp != NULL) {
265                 while ((ep = readdir(dp))) {
266                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep->d_name);
267                         if (lstat(abs_filename, &stFileInfo) < 0) {
268                                 _LOGE("lstat(%s) failed.", abs_filename);
269                                 perror(abs_filename);
270                         }
271
272                         if (S_ISDIR(stFileInfo.st_mode)) {
273                                 if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, "..")) {
274                                         _rpm_delete_dir(abs_filename);
275                                         (void)remove(abs_filename);
276                                 }
277                         } else {
278                                 (void)remove(abs_filename);
279                         }
280                 }
281                 (void)closedir(dp);
282         } else {
283                 _LOGE("opendir(%s) failed.", dirname);
284                 return -1;
285         }
286
287         ret = remove(dirname);
288         if (ret < 0)
289                 _LOGE("remove(%s) failed.", dirname);
290
291         return 0;
292 }
293
294 char* _manifest_to_package(const char* manifest)
295 {
296         char *package;
297
298         if(manifest == NULL) {
299                 _LOGE("manifest is NULL.\n");
300                 return NULL;
301         }
302
303         package = strdup(manifest);
304         if(package == NULL) {
305                 _LOGE("strdup failed.\n");
306                 return NULL;
307         }
308
309         if (!strstr(package, ".xml")) {
310                 _LOGE("%s is not a manifest file\n", manifest);
311                 free(package);
312                 return NULL;
313         }
314
315         return package;
316 }
317
318 /* Extract the basename from the file's path */
319 char *_ri_basename(char *name)
320 {
321         int length;
322         length = name ? strlen(name) : 0;
323         if (!length)
324                 return ".";
325
326         while (--length > 0 && name[length] != '/');
327
328         return length <= 0 ? name : name + length + (name[length] == '/');
329 }
330
331 int _child_element(xmlTextReaderPtr reader, int depth)
332 {
333         int ret = xmlTextReaderRead(reader);
334         int cur = xmlTextReaderDepth(reader);
335         while (ret == 1) {
336
337                 switch (xmlTextReaderNodeType(reader)) {
338                         case XML_READER_TYPE_ELEMENT:
339                                 if (cur == depth + 1)
340                                         return 1;
341                                 break;
342                         case XML_READER_TYPE_TEXT:
343                                 /*text is handled by each function separately*/
344                                 if (cur == depth + 1)
345                                         return 0;
346                                 break;
347                         case XML_READER_TYPE_END_ELEMENT:
348                                 if (cur == depth)
349                                         return 0;
350                                 break;
351                         default:
352                                 if (cur <= depth)
353                                         return 0;
354                                 break;
355                         }
356
357                 ret = xmlTextReaderRead(reader);
358                 cur = xmlTextReaderDepth(reader);
359         }
360         return ret;
361 }
362
363 /*
364 This Function get the package name from the rpm file's path..
365 */
366 int  _get_pkgname_from_rpm_name(char * pkgfile, char **rpm_name){
367
368         char* rpm_file = NULL;
369         char  name[PATH_MAX] = {0};
370         char  temp[PATH_MAX]={0};
371         char *saveptr = NULL;;
372         char *str= NULL;
373         char c ;
374         int ret = RPM_INSTALLER_SUCCESS;
375
376         if(pkgfile == NULL || rpm_name == NULL){
377                 _LOGE("Invalid Parameter!!");
378                 return RPM_INSTALLER_ERR_WRONG_PARAM;
379
380         }
381         _LOGD("RPM path is [%s]",pkgfile);
382
383         /* Get the rpm name from rpm file's path */
384         rpm_file = _ri_basename(pkgfile);
385         _LOGD("RPM name is [%s]",rpm_file);
386
387         if (strlen(rpm_file) < PATH_MAX)
388                 strcpy(name, rpm_file);
389         else {
390                 _LOGE("rpm file path too long[%s]", rpm_file);
391                 ret = -1;
392                 goto end;
393         }
394
395         str = strtok_r(name, "-", &saveptr);
396         if(rpm_file[strlen(name)] != '\0'){
397                 c = rpm_file[strlen(name) + 1];
398         }else{
399                 if(strstr(name,".rpm")){
400                         name[strlen(name)-strlen(".rpm")]='\0';
401                 }
402                 *rpm_name = strdup(name);
403                 if(*rpm_name == NULL){
404                         _LOGE("Malloc failed!!");
405                         ret = RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
406                 }
407                 goto end;
408         }
409
410         while(!isdigit(c)){
411                 memset(temp,'\0',PATH_MAX);
412                 str = strtok_r(NULL, "-", &saveptr);
413                 snprintf(temp,PATH_MAX,"-%s",str);
414                 strncat(name,temp,strlen(temp));
415                 if(rpm_file[strlen(name)] != '\0'){
416                         c = rpm_file[strlen(name) + 1];
417                 }else{
418                         break;
419                 }
420         }
421         if(strstr(name,".rpm")){
422                 name[strlen(name)-strlen(".rpm")]='\0';
423         }
424         *rpm_name = strdup(name);
425         if(*rpm_name == NULL){
426                 _LOGE("Malloc failed!!");
427                 ret = RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
428         }
429
430 end:
431         return ret;
432
433 }
434
435 /*
436 This Function reads the package field from the xml file.
437 */
438 int  _get_package_name_from_xml(char* manifest, char** pkgname){
439
440         const char *val = NULL;
441         const xmlChar *node;
442         xmlTextReaderPtr reader;
443         int ret = PMINFO_R_OK;
444
445         if(manifest == NULL) {
446                 _LOGE("Input argument is NULL\n");
447                 return PMINFO_R_ERROR;
448         }
449
450         if(pkgname == NULL) {
451                 _LOGE("Argument supplied to hold return value is NULL\n");
452                 return PMINFO_R_ERROR;
453         }
454
455         reader = xmlReaderForFile(manifest, NULL, 0);
456
457         if (reader){
458                 if ( _child_element(reader, -1)) {
459                         node = xmlTextReaderConstName(reader);
460                         if (!node) {
461                                 _LOGE("xmlTextReaderConstName value is NULL\n");
462                                 ret =  PMINFO_R_ERROR;
463                                 goto end;
464                         }
465
466                         if (!strcmp(ASCII(node), "manifest")) {
467                                 ret = _ri_get_attribute(reader,"package",&val);
468                                 if(ret != 0){
469                                         _LOGE("@Error in getting attribute value");
470                                         ret = PMINFO_R_ERROR;
471                                         goto end;
472                                 }
473
474                                 if(val){
475                                         *pkgname = strdup(val);
476                                         if(*pkgname == NULL){
477                                                 _LOGE("Malloc Failed!!");
478                                                 ret = PMINFO_R_ERROR;
479                                                 goto end;
480                                         }
481                                 }
482                         } else {
483                                 _LOGE("Unable to create xml reader\n");
484                                 ret =  PMINFO_R_ERROR;
485                         }
486                 }
487         } else {
488                 _LOGE("xmlReaderForFile value is NULL\n");
489                 return PMINFO_R_ERROR;
490         }
491
492 end:
493         xmlFreeTextReader(reader);
494
495         if(val)
496                 free((void*)val);
497
498         return ret;
499 }
500
501 int _ri_recursive_delete_dir(char *dirname)
502 {
503         int ret=0;
504         DIR *dp;
505         struct dirent *ep;
506         char abs_filename[FILENAME_MAX];
507         struct stat stFileInfo;
508         dp = opendir(dirname);
509         if (dp != NULL) {
510                 while ((ep = readdir(dp))) {
511                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
512                                  ep->d_name);
513                         if (lstat(abs_filename, &stFileInfo) < 0)
514                                 perror(abs_filename);
515                         if (S_ISDIR(stFileInfo.st_mode)) {
516                                 if (strcmp(ep->d_name, ".") &&
517                                     strcmp(ep->d_name, "..")) {
518                                         ret=_ri_recursive_delete_dir(abs_filename);
519                                         if(ret < 0)
520                                                 _LOGE("_ri_recursive_delete_dir fail\n");
521
522                                         ret=remove(abs_filename);
523                                         if(ret < 0)
524                                                 _LOGE("remove fail\n");
525                                 }
526                         } else {
527                                 ret = remove(abs_filename);
528                                 if(ret < 0)
529                                         _LOGE("Couldn't remove abs_filename\n");
530                         }
531                 }
532                 (void)closedir(dp);
533         } else {
534                 _LOGE("Couldn't open the directory\n");
535                 if (errno == ENOENT)
536                         return RPM_INSTALLER_SUCCESS;
537                 else
538                         return RPM_INSTALLER_ERR_CLEAR_DATA_FAILED;
539         }
540
541         return RPM_INSTALLER_SUCCESS;
542 }
543
544  int _ri_xsystem(const char *argv[])
545 {
546         int status = 0;
547         pid_t pid;
548         pid = fork();
549         switch (pid) {
550         case -1:
551                 perror("fork failed");
552                 return -1;
553         case 0:
554                 /* child */
555                 execvp(argv[0], (char *const *)argv);
556                 _exit(-1);
557         default:
558                 /* parent */
559                 break;
560         }
561         if (waitpid(pid, &status, 0) == -1) {
562                 perror("waitpid failed");
563                 return -1;
564         }
565         if (WIFSIGNALED(status)) {
566                 perror("signal");
567                 return -1;
568         }
569         if (!WIFEXITED(status)) {
570                 /* shouldn't happen */
571                 perror("should not happen");
572                 return -1;
573         }
574         return WEXITSTATUS(status);
575 }
576 void _ri_remove_wgt_unzip_dir()
577 {
578         if (!access(DIR_RPM_INSTALLER_APPLICATIONS_TEMP, F_OK)) {
579                 _ri_recursive_delete_dir(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
580                 (void)remove(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
581         }
582
583 }
584
585 int _ri_get_available_free_memory(const char *opt_path, unsigned long *free_mem)
586 {
587         struct statvfs buf;
588         int ret = 0;
589         if (opt_path == NULL || free_mem == NULL) {
590                 _LOGE("Invalid input parameter\n");
591                 return -1;
592         }
593         memset((void *)&buf, '\0', sizeof(struct statvfs));
594         ret = statvfs(opt_path, &buf);
595         if (ret) {
596                 _LOGE("Unable to get /opt/usr memory information\n");
597                 return -1;
598         }
599         *free_mem = (buf.f_bfree * buf.f_bsize)/SIZE_KB;
600         return 0;
601 }
602
603
604 unsigned long  _ri_calculate_file_size(const char *filename)
605 {
606         struct stat stFileInfo;
607
608         if (stat(filename, &stFileInfo) < 0) {
609                 perror(filename);
610                 return 0;
611         } else
612                 return (stFileInfo.st_size/SIZE_KB);
613 }
614
615 void _ri_process_config_node(xmlTextReaderPtr reader, pkginfo * info)
616 {
617         const xmlChar *node;
618         const char *pkgid = NULL;
619         const char *version = NULL;
620         node = xmlTextReaderConstName(reader);
621         if (node == NULL) {
622                 return;
623         }
624         if (strcmp(ASCII(node), "widget") == 0) {
625                 if (xmlTextReaderNodeType(reader) == 1) {
626                         if(_ri_get_attribute(reader,"version",&version) != 0){
627                                 _LOGE("@Error while getting the attribute value");
628                                 return;
629                         }
630                                 snprintf(info->version, VERSION_MAX_LEN - 1, "%s", version);
631                                 _LOGD("<version> %s", info->version);
632                 }
633         }
634
635
636         if (strcmp(ASCII(node), "tizen:application") == 0) {
637                 if (xmlTextReaderNodeType(reader) == 1) {
638                         if(_ri_get_attribute(reader,"package",&pkgid) != 0){
639                                 _LOGE("@Error while getting the attribute value");
640                                 return;
641                         }
642                         snprintf(info->package_name, PKG_MAX_LEN - 1, "%s", pkgid);
643                         _LOGD("<package> %s", info->package_name);
644                 }
645         }
646         if(pkgid){
647                 free((void*)pkgid);
648                 pkgid = NULL;
649         }
650
651         if(version){
652                 free((void*)version);
653                 version = NULL;
654         }
655         return;
656
657 }
658
659 int  _ri_stream_config_file(const char* filename, pkginfo *info)
660 {
661         xmlTextReaderPtr reader;
662         int ret = RPM_INSTALLER_SUCCESS;
663
664         _LOGD("Reading config file [%s]",filename);
665         reader = xmlReaderForFile(filename,NULL,0);
666         if (reader != NULL) {
667                 ret = xmlTextReaderRead(reader);
668                 while (ret == 1) {
669                         _ri_process_config_node(reader, info);
670                         ret = xmlTextReaderRead(reader);
671                 }
672                 xmlFreeTextReader(reader);
673                 if (ret != 0) {
674                         _LOGE("%s : failed to parse\n", filename);
675                         ret = RPM_INSTALLER_ERR_INTERNAL;
676                 }
677         } else {
678                 _LOGE("Unable to open %s\n", filename);
679                 ret = RPM_INSTALLER_ERR_INTERNAL;
680         }
681         return ret;
682 }
683
684 unsigned long  _ri_calculate_rpm_size( char* rpm_file)
685 {
686         Header  hdr = NULL;
687         rpmts   ts;
688         rpmtd   td;
689         FD_t    fd;
690         rpmRC   rc;
691         rpmVSFlags vsflags = 0;
692         unsigned long  size = 0;
693
694         /* Initialize rpm */
695         rc = rpmReadConfigFiles(NULL,NULL);
696         if( rc != RPMRC_OK){
697                 _LOGE("\n failed to read RPM configuration files");
698                 return size;
699         }
700         /* Open the rpm file */
701         fd = Fopen(rpm_file, "r.ufdio");
702         if ((!fd) || Ferror(fd)){
703                 _LOGE("\n failed to open %s package file",rpm_file);
704                 if(fd)
705                         Fclose(fd);
706                 return size ;
707         }
708
709         hdr = headerNew();
710         ts = rpmtsCreate();
711         td = rpmtdNew();
712         vsflags |= _RPMVSF_NODIGESTS;
713         vsflags |= _RPMVSF_NOSIGNATURES;
714         vsflags |= RPMVSF_NOHDRCHK;
715         (void)rpmtsSetVSFlags(ts, vsflags);
716
717         rc = rpmReadPackageFile(ts,fd,rpm_file,&hdr);
718         if(rc != RPMRC_OK){
719                 _LOGE("\n Couldn't read rpm package file");
720                 size = 0;
721                 Fclose(fd);
722                 goto err;
723         }
724         headerGet(hdr,RPMTAG_SIZE,td,HEADERGET_MINMEM);
725         size = rpmtdGetNumber(td);
726
727         err:
728         rpmtdFreeData(td);
729         rpmtdFree(td);
730         headerFree(hdr);
731         rpmtsFree(ts);
732
733         return size;
734 }
735
736 unsigned long  _ri_calculate_dir_size(const char *dirname)
737 {
738         static unsigned long  total = 0;
739         unsigned long  size = 0;
740         DIR *dp = NULL;
741         struct dirent *ep = NULL;
742         char abs_filename[FILENAME_MAX] = { 0, };;
743         dp = opendir(dirname);
744         if (dp != NULL) {
745                 while ((ep = readdir(dp)) != NULL) {
746                         struct stat stFileInfo;
747
748                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
749                                  ep->d_name);
750
751                         if (stat(abs_filename, &stFileInfo) < 0)
752                                 perror(abs_filename);
753                         else {
754                                 /* If file is rpm then get the size from rpm header. */
755                                 if(strstr(ep->d_name,".rpm")){
756                                         size = _ri_calculate_rpm_size(abs_filename);
757                                         if( size == 0){
758                                                 _LOGE("\n error in computing the rpm's size");
759                                         }
760                                         total += size;
761                                 }else{
762                                 total += (unsigned long)stFileInfo.st_size;
763                                 }
764
765                                 if (S_ISDIR(stFileInfo.st_mode)) {
766                                         if (strcmp(ep->d_name, ".")
767                                             && strcmp(ep->d_name, "..")) {
768                                                 _ri_calculate_dir_size
769                                                     (abs_filename);
770                                         }
771                                 } else {
772                                         /*Do Nothing */
773                                 }
774                         }
775                 }
776                 (void)closedir(dp);
777         } else {
778                 _LOGE("\n error in opening directory ");
779         }
780         return (total/SIZE_KB);
781 }
782
783
784 /*
785 This function unzip the wgt package.
786 It read and validate the config.xml file.
787 It checks whether the free size avaiable to install this package.
788 */
789
790 int _ri_wgt_package_extract(char *pkgid)
791 {
792         if(pkgid == NULL)
793                 return RPM_INSTALLER_ERR_INTERNAL;
794
795         int ret = RPM_INSTALLER_SUCCESS;
796         const char *argv[5] = { RPM_UNZIP, pkgid, "-d", DIR_RPM_INSTALLER_APPLICATIONS_TEMP, NULL};
797         char config_file_name[PATH_MAX] = {0};
798         pkginfo *info = NULL;
799         unsigned long free_mem = 0;
800         unsigned long reqd_size = 0;
801         mode_t mode = DIR_PERMS;
802
803         /* 1. Delete the temp folder if already present*/
804         if (!access(DIR_RPM_INSTALLER_APPLICATIONS_TEMP, F_OK)) {
805                 _ri_recursive_delete_dir(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
806                 (void)remove(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
807         }
808
809         /* 1.2 Create temp folder */
810         ret = mkdir(DIR_RPM_INSTALLER_APPLICATIONS_TEMP, mode);
811         if (ret != 0) {
812                 _LOGE("Temporary folder creation failed");
813                 return RPM_INSTALLER_ERR_INTERNAL;
814         }
815         /* 1.3 Unzip wgt to temp folder*/
816         ret = _ri_xsystem(argv);
817         if (ret != 0) {
818                 _LOGE("Unzip to Temporary folder failed");
819                 return  RPM_INSTALLER_ERR_INTERNAL;
820         }
821
822         /* Read the config.xml file and get the information*/
823         snprintf(config_file_name,PATH_MAX,"%s/%s", DIR_RPM_INSTALLER_APPLICATIONS_TEMP,WGT_CONFIG);
824         _LOGD("Config File is [%s]",config_file_name);
825         if(access(config_file_name,F_OK)){
826                 /* Return if info config is absent */
827                 _LOGE("No Config File [%s] found\n", config_file_name);
828                 return  RPM_INSTALLER_ERR_NO_CONFIG;
829         }
830         _LOGD("Config File [%s] found\n", config_file_name);
831
832         /*populate pkginfo */
833         info = (pkginfo *)calloc(1, sizeof(pkginfo));
834         if (info == NULL) {
835                 _LOGE("Memory allocation failed");
836                 return  RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
837         }
838
839         /* Parse config file and store the info in pkginfo struct */
840         ret = _ri_stream_config_file(config_file_name,info);
841         if(ret != RPM_INSTALLER_SUCCESS){
842                 _LOGE("Config file's parsing Failed");
843                 if(info){
844                         free(info);
845                         info = NULL;
846                 }
847                 return RPM_INSTALLER_ERR_INTERNAL;
848         }
849
850         /* 3. Validate the pkginfo*/
851         if (strlen(info->package_name) == 0 || strlen(info->version) == 0) {
852                 _LOGE("Package name or version is not found in Config File");
853                 if (info) {
854                         free(info);
855                         info = NULL;
856                 }
857                 return RPM_INSTALLER_ERR_INVALID_CONFIG;
858         }
859
860         /* 4. Check the free memory  in RW partition*/
861         ret = _ri_get_available_free_memory(RPM_INSTALLER_RW_INSTALL_PATH, &free_mem);
862         if (ret<0) {
863                 _LOGE("Error in getting available free memory");
864                 if (info) {
865                         free(info);
866                         info = NULL;
867                 }
868                 return RPM_INSTALLER_ERR_INTERNAL;
869         } else {
870                 /* Compare with size required by package*/
871                 reqd_size = _ri_calculate_dir_size(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
872                 if (reqd_size ==0) {
873                         _LOGE("Error in getting file size");
874                         if (info) {
875                                 free(info);
876                                 info = NULL;
877                         }
878                         return RPM_INSTALLER_ERR_INTERNAL;
879                 } else {
880                         if (reqd_size > free_mem) {
881                                 _LOGE("Not enough memory");
882                                 if (info) {
883                                         free(info);
884                                         info = NULL;
885                                 }
886                                 return  RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
887                         }
888                 }
889         }
890
891         _LOGD("Required size to install pkg is [%lu KB] and available memory is  [%lu KB]",reqd_size,free_mem);
892
893         if (info) {
894                 free(info);
895                 info = NULL;
896         }
897
898         return ret;
899 }
900
901 int _verify_wgt_package_signature_files(void)
902 {
903
904         char buff[PATH_MAX] = {0};
905         int ret = RPM_INSTALLER_SUCCESS;
906         char cwd[PATH_MAX]={0};
907         char *temp = NULL;
908         int visibility = 0;
909
910         temp = getcwd(cwd, PATH_MAX);
911         if ( ( temp == NULL) || (cwd[0] == '\0')) {
912                 _LOGE("@getcwd() failed.\n");
913                 ret = RPM_INSTALLER_ERR_INTERNAL;
914                 goto end;
915         }
916
917         ret = chdir(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
918         if(ret != 0){
919                 _LOGE("Change directory failed!");
920                 goto end;
921         }
922
923         /*Verify the author-signature file */
924         memset(buff, '\0', PATH_MAX);
925         snprintf(buff, PATH_MAX, "%s/%s",DIR_RPM_INSTALLER_APPLICATIONS_TEMP,AUTHOR_SIGNATURE_XML);
926
927         if (access(buff, F_OK) == 0) {
928                 _LOGD("auth-signature.xml found in %s\n", DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
929                 ret = _ri_verify_sig_and_cert(buff, &visibility);
930                 if (ret) {
931                         _LOGE("Failed to verify [%s]\n", buff);
932                         ret = RPM_INSTALLER_ERR_SIG_INVALID;
933                         goto end;
934                 }else{
935                 _LOGD("Successfully verified [%s]\n", buff);
936                 }
937         }
938
939         /*Verify the signature2.xml file */
940         memset(buff, '\0', PATH_MAX);
941         snprintf(buff, PATH_MAX, "%s/%s",DIR_RPM_INSTALLER_APPLICATIONS_TEMP,SIGNATURE2_XML);
942
943         if (access(buff, F_OK) == 0) {
944                 _LOGD("signature2.xml found in %s\n", DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
945                 ret = _ri_verify_sig_and_cert(buff, &visibility);
946                 if (ret) {
947                         _LOGE("Failed to verify [%s]\n", buff);
948                         ret = RPM_INSTALLER_ERR_SIG_INVALID;
949                         goto end;
950                 }else{
951                 _LOGD("Successfully verified [%s]\n", buff);
952                 }
953         }
954
955         /*Verify the signature1.xml file*/
956         memset(buff, '\0', PATH_MAX);
957         snprintf(buff,PATH_MAX,"%s/%s", DIR_RPM_INSTALLER_APPLICATIONS_TEMP,SIGNATURE1_XML);
958
959         if (access(buff, F_OK) == 0) {
960                 _LOGD("signature1.xml found in %s\n", DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
961                 ret = _ri_verify_sig_and_cert(buff, &visibility);
962                 if (ret) {
963                         _LOGE("Failed to verify [%s]\n", buff);
964                         ret = RPM_INSTALLER_ERR_SIG_INVALID;
965                         goto end;
966                 }else{
967                 _LOGD("Successfully verified [%s]\n", buff);
968                 }
969         }
970
971         if(chdir(cwd)){
972                 _LOGE("chdir failed [%s]",strerror(errno));
973                 ret = RPM_INSTALLER_ERR_INTERNAL;
974         }
975
976         end:
977
978                 return ret;
979
980 }
981
982 char* _get_rpm_file_from_wgt_package(char* dirname)
983 {
984
985         DIR *dp = NULL;
986         struct dirent *ep = NULL;
987         char abs_filename[FILENAME_MAX] = { 0, };
988         dp = opendir(dirname);
989         int found = 0;
990         if (dp != NULL) {
991                 while ((ep = readdir(dp)) != NULL) {
992                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
993                                  ep->d_name);
994                         if (strstr(abs_filename,".rpm")!=NULL){
995                                 found = 1;
996                                 break;
997                         }
998                 }
999                 (void)closedir(dp);
1000         }
1001
1002         if(found){
1003                 _LOGD("rpm name is [%s]",abs_filename);
1004                 return strdup(abs_filename);
1005         }
1006
1007         return NULL;
1008
1009 }
1010
1011 /*
1012 This function processes the modified wgt package .
1013 */
1014 int _ri_process_wgt_package(char** pkgid)
1015 {
1016         if(*pkgid == NULL)
1017                 return RPM_INSTALLER_ERR_INTERNAL;
1018
1019         unsigned long free_mem = 0;
1020         unsigned long file_size = 0;
1021         int ret = RPM_INSTALLER_SUCCESS;
1022
1023
1024         /* check memory available*/
1025         ret = _ri_get_available_free_memory(RPM_INSTALLER_RW_INSTALL_PATH, &free_mem);
1026         if (ret<0) {
1027                 _LOGE("Error in getting available free memory");
1028                 return RPM_INSTALLER_ERR_INTERNAL;
1029         } else {
1030                 file_size = _ri_calculate_file_size(*pkgid);
1031                 if (file_size <=0) {
1032                         _LOGE("Error in getting file size");
1033                         return RPM_INSTALLER_ERR_INTERNAL;
1034                 } else {
1035                         if (file_size > free_mem) {
1036                                 _LOGE("Not enough memory");
1037                                 return RPM_INSTALLER_ERR_NOT_ENOUGH_MEMORY;
1038                         }
1039                 }
1040         }
1041
1042         _LOGD("Package file [%s] size is [%lu]KB and free size in RW directory is [%lu]KB",*pkgid,file_size,free_mem);
1043
1044         /* unzip the wgt package */
1045         ret = _ri_wgt_package_extract(*pkgid);
1046         if(ret != RPM_INSTALLER_SUCCESS)
1047                 return ret;
1048
1049         _LOGD("wgt package is extracted to [%s]",DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
1050
1051         ret = _verify_wgt_package_signature_files();
1052         if(ret != RPM_INSTALLER_SUCCESS){
1053                 _LOGE("signature verification [%d]",ret);
1054                 return ret;
1055         }
1056         _LOGD("Verification of wgt package's signature files is done");
1057
1058         if(*pkgid){
1059                 free(*pkgid);
1060                 *pkgid = NULL;
1061         }
1062         /* Change the data->pkgid to the unzipped package's rpm */
1063         *pkgid = _get_rpm_file_from_wgt_package(DIR_RPM_INSTALLER_APPLICATIONS_TEMP);
1064         if(*pkgid == NULL)
1065                 return RPM_INSTALLER_ERR_INTERNAL;
1066         else
1067                 _LOGD("rpm is [%s]",*pkgid);
1068
1069         return RPM_INSTALLER_SUCCESS;
1070 }