Tizen 2.1 base
[platform/core/base/rpm-installer.git] / backend / src / core / rpm-installer-core.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 /* System Include files */
24 #include <stdbool.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <sys/wait.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <wait.h>
35 #include <regex.h>
36 #include <pthread.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 #include <rpmlib.h>
40 #include <header.h>
41 #include <rpmts.h>
42 #include <rpmdb.h>
43
44 /* SLP include files */
45 #include "rpm-installer.h"
46 #include "rpm-installer-util.h"
47 #include "db-util.h"
48
49 #define QUERY_PACKAGE           "/usr/bin/query_rpm_package.sh"
50 #define RPM_PKG_INFO            "/var/rpmpkg.info"
51
52 struct pkgfile_info_t {
53         char *pkg_filename;
54         char *pkg_type;
55 };
56 typedef struct pkgfile_info_t pkgfile_info;
57
58 extern char *gpkgname;
59 extern int do_upgrade;
60 static int __ri_xsystem_with_dup(char *pkgid, int fd);
61 static int __ri_recursive_delete_dir(char *dirname);
62
63 static int __ri_recursive_delete_dir(char *dirname)
64 {
65         DIR *dp;
66         struct dirent *ep;
67         char abs_filename[FILENAME_MAX];
68         struct stat stFileInfo;
69         dp = opendir(dirname);
70         if (dp != NULL) {
71                 while (ep = readdir(dp)) {
72                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
73                                  ep->d_name);
74                         if (lstat(abs_filename, &stFileInfo) < 0)
75                                 perror(abs_filename);
76                         if (S_ISDIR(stFileInfo.st_mode)) {
77                                 if (strcmp(ep->d_name, ".") &&
78                                     strcmp(ep->d_name, "..")) {
79                                         __ri_recursive_delete_dir(abs_filename);
80                                         remove(abs_filename);
81                                 }
82                         } else {
83                                 remove(abs_filename);
84                         }
85                 }
86                 (void)closedir(dp);
87         } else {
88                 _d_msg(DEBUG_ERR, "Couldn't open the directory\n");
89                 return RPM_INSTALLER_ERR_CLEAR_DATA_FAILED;
90         }
91
92         return RPM_INSTALLER_SUCCESS;
93 }
94
95 pkginfo *_rpm_installer_get_pkgfile_info(char *pkgfile)
96 {
97         int i;
98         int ret = 0;
99         rpmts ts;
100         rpmtd td;
101         FD_t fd;
102         rpmRC rc;
103         Header hdr = NULL;
104         rpmVSFlags vsflags = 0;
105         pkginfo *info = NULL;
106         if (pkgfile == NULL)
107                 return NULL;
108         info = malloc(sizeof(pkginfo));
109         if (info == NULL) {
110                 _d_msg(DEBUG_ERR, "Malloc Failed\n");
111                 return NULL;
112         }
113         ts = rpmtsCreate();
114         td = rpmtdNew();
115         hdr = headerNew();
116
117         fd = Fopen(pkgfile, "r.ufdio");
118         if ((!fd) || Ferror(fd)) {
119                 _d_msg(DEBUG_ERR, "Failed to open package file (%s)\n", Fstrerror(fd));
120                 if (fd) {
121                         Fclose(fd);
122                 }
123                 free(info);
124                 info = NULL;
125                 goto err;
126         }
127
128         vsflags |= _RPMVSF_NODIGESTS;
129         vsflags |= _RPMVSF_NOSIGNATURES;
130         vsflags |= RPMVSF_NOHDRCHK;
131         (void) rpmtsSetVSFlags(ts, vsflags);
132
133         rc = rpmReadPackageFile(ts, fd, pkgfile, &hdr);
134         if (rc != RPMRC_OK) {
135                 _d_msg(DEBUG_ERR, "Could not read package file\n");
136                 free(info);
137                 info = NULL;
138                 goto err;
139         }
140         Fclose(fd);
141         /*Name*/
142         headerGet(hdr, RPMTAG_NAME, td, HEADERGET_MINMEM);
143         strncpy(info->package_name, rpmtdGetString(td), sizeof(info->package_name) - 1);
144         _d_msg(DEBUG_INFO, "Package Name : %s\n", info->package_name);
145         rpmtdReset(td);
146         /*Version*/
147         headerGet(hdr, RPMTAG_VERSION, td, HEADERGET_MINMEM);
148         strncpy(info->version, rpmtdGetString(td), sizeof(info->version) - 1);
149         _d_msg(DEBUG_INFO, "Version : %s\n", info->version);
150         rpmtdReset(td);
151
152
153 err:
154         rpmtdFreeData(td);
155         rpmtdFree(td);
156         headerFree(hdr);
157         rpmtsFree(ts);
158         return info;
159
160 }
161
162 pkginfo *_rpm_installer_get_pkgname_info(char *pkgid)
163 {
164         rpmts ts = NULL;
165         Header hdr = NULL;
166         int found = 0;
167         rpmdbMatchIterator mi;
168         rpmtd tn, tv;
169         rpmRC rc;
170         pkginfo *info = NULL;
171         if (pkgid == NULL)
172                 return NULL;
173         info = malloc(sizeof(pkginfo));
174         if (info == NULL) {
175                 _d_msg(DEBUG_ERR, "Malloc Failed\n");
176                 return NULL;
177         }
178
179         tn = rpmtdNew();
180         tv = rpmtdNew();
181         ts = rpmtsCreate();
182
183         mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
184         while (NULL != (hdr = rpmdbNextIterator(mi))) {
185
186                 hdr = headerLink(hdr);
187                 rc = headerGet(hdr, RPMTAG_NAME, tn, HEADERGET_MINMEM);
188                 if (strcmp(pkgid, rpmtdGetString(tn)) == 0) {
189                         found = 1;
190                         break;
191                 } else {
192                         rpmtdReset(tn);
193                         headerFree(hdr);
194                 }
195
196         }
197
198         if (found == 0) {
199                 _d_msg(DEBUG_ERR, "Package not found in DB\n");
200                 free(info);
201                 info = NULL;
202                 goto err;
203         }
204         /*Name */
205         headerGet(hdr, RPMTAG_NAME, tn, HEADERGET_MINMEM);
206         strncpy(info->package_name, rpmtdGetString(tn),
207                 sizeof(info->package_name)-1);
208         _d_msg(DEBUG_INFO, "Package Name : %s\n", info->package_name);
209         /*Version */
210         headerGet(hdr, RPMTAG_VERSION, tv, HEADERGET_MINMEM);
211         strncpy(info->version, rpmtdGetString(tv), sizeof(info->version)-1);
212         _d_msg(DEBUG_INFO, "Version : %s\n", info->version);
213
214
215  err:
216         headerFree(hdr);
217         rpmtdFreeData(tn);
218         rpmtdFree(tn);
219         rpmtdFreeData(tv);
220         rpmtdFree(tv);
221         rpmdbFreeIterator(mi);
222         rpmtsFree(ts);
223
224         return info;
225
226 }
227
228 #if 0
229
230 static int __ri_xsystem_with_dup(char *pkgname, int fd)
231 {
232         int pid;
233         int status = 0;
234         const char *argv[] = { QUERY_PACKAGE, pkgname, NULL };
235         pid = fork();
236         switch (pid) {
237         case -1:
238                 perror("fork failed");
239                 return -1;
240         case 0:         /* child */
241                 close(1);
242                 close(2);
243                 dup(fd);
244                 dup(fd);        /* dup called twice to create copy of fd 1 and fd 2 */
245                 execvp(argv[0], (char *const *)argv);
246                 exit(-1);
247         default:                /*parent */
248                 break;
249         }
250         if (waitpid(pid, &status, 0) == -1) {
251                 perror("waitpid failed");
252                 return -1;
253         }
254         if (WIFSIGNALED(status)) {
255                 perror("signal");
256                 printf("sig no. %d\n", WTERMSIG(status));
257                 return -1;
258         }
259         if (!WIFEXITED(status)) {
260                 perror("should not happen");
261                 return -1;
262         }
263
264         return WEXITSTATUS(status);
265 }
266
267 pkginfo *_rpm_installer_get_pkg_info(char *pkgname)
268 {
269         pkginfo *info = NULL;
270         int err = 0;
271         int fd = -1;
272         FILE *fp = NULL;
273         char *line = NULL;
274         size_t len = 0;
275         ssize_t read;
276         char *saveptr = NULL;
277         char *tok = NULL;
278
279         if (pkgname == NULL)
280                 return NULL;
281
282         fd = open(RPM_PKG_INFO, O_CREAT | O_RDWR, 0644);
283         if (fd == -1) {
284                 _d_msg(DEBUG_ERR, "open failed\n");
285                 return NULL;
286         }
287
288         err = __ri_xsystem_with_dup(pkgname, fd);
289         _d_msg(DEBUG_INFO,
290                "[_rpm_installer_get_pkg_info] _xsystem returns %d\n", err);
291         if (err == 1) {
292                 _d_msg(DEBUG_INFO,
293                        "[_rpm_installer_get_pkg_info] "
294                        "Package Not installed \n");
295                 close(fd);
296                 return NULL;
297         } else if (err == 2) {
298                 _d_msg(DEBUG_INFO,
299                        "[_rpm_installer_get_pkg_info] "
300                        "package already install\n");
301                 info = malloc(sizeof(pkginfo));
302                 if (info == NULL) {
303                         _d_msg(DEBUG_ERR, "Malloc Failed\n");
304                         close(fd);
305                         return NULL;
306                 }
307                 memset(info, 0x00, sizeof(pkginfo));
308                 close(fd);
309                 fp = fopen(RPM_PKG_INFO, "r");
310                 if (fp == NULL) {
311                         _d_msg(DEBUG_ERR, "fopen failed\n");
312                         return NULL;
313                 }
314
315                 /* Now open file and get pkgname and version */
316                 while ((read = getline(&line, &len, fp)) != -1) {
317                         int len = strlen(line);
318                         line[len - 1] = '\0';
319
320                         _d_msg(DEBUG_INFO, "line[%s]\n", line);
321
322                         tok = strtok_r(line, " ", &saveptr);    /*Name */
323                         if (tok && strncmp(tok, "Name", 4) == 0) {
324                                 /* : */
325                                 tok = strtok_r(NULL, " ", &saveptr);
326                                 /* <name> */
327                                 tok = strtok_r(NULL, " ", &saveptr);
328                                 if (tok) {
329                                         strncpy(info->package_name, tok,
330                                                 sizeof(info->package_name));
331                                 }
332                         } else if (tok && strncmp(tok, "Version", 7) == 0) {
333                                 /* : */
334                                 tok = strtok_r(NULL, " ", &saveptr);
335                                 /* <version> */
336                                 tok = strtok_r(NULL, " ", &saveptr);
337                                 if (tok) {
338                                         strncpy(info->version, tok,
339                                                 sizeof(info->version));
340                                 }
341                                 break;
342                         } else
343                                 continue;
344                 }
345                 if (line) {
346                         free(line);
347                         line = NULL;
348                 }
349                 fclose(fp);
350                 remove(RPM_PKG_INFO);
351                 return info;
352
353         } else {
354                 _d_msg(DEBUG_ERR,
355                        "[_rpm_installer_get_pkg_info] "
356                        "_xsystem returns error = %d\n", err);
357                 close(fd);
358                 return NULL;
359         }
360         remove(RPM_PKG_INFO);
361         return info;
362
363 }
364
365 #endif
366
367 int _rpm_installer_package_install(char *pkgfilepath, bool forceinstall,
368                                    char *installoptions)
369 {
370         int err = 0;
371         if (forceinstall == true && installoptions == NULL)
372                 return RPM_INSTALLER_ERR_WRONG_PARAM;
373         pkginfo *info = NULL;
374         pkginfo *tmpinfo = NULL;
375         /*Check to see if the package is already installed or not
376            If it is installed, compare the versions. If the current version
377            is higher than the installed version, upgrade it automatically
378            else ask for user confirmation before downgrading */
379
380         info = _rpm_installer_get_pkgfile_info(pkgfilepath);
381         if (info == NULL) {
382                 /* failed to get pkg info */
383                 return RPM_INSTALLER_ERR_UNKNOWN;
384         }
385
386         _ri_set_backend_state_info(GOT_PACKAGE_INFO_SUCCESSFULLY);
387         if (gpkgname) {
388                 free(gpkgname);
389                 gpkgname = NULL;
390         }
391         gpkgname = strdup(info->package_name);
392
393         tmpinfo = _rpm_installer_get_pkgname_info(info->package_name);
394         if (tmpinfo == NULL) {
395                 /* package is not installed. Go for installation. */
396                 if (info) {
397                         free(info);
398                         info = NULL;
399                 }
400                 err = _rpm_install_pkg(pkgfilepath, installoptions);
401                 if (err != 0) {
402                         _d_msg(DEBUG_ERR,
403                                "install complete with error(%d)\n", err);
404                         return err;
405                 } else {
406                         _ri_set_backend_state_info(REQUEST_COMPLETED);
407                         return RPM_INSTALLER_SUCCESS;
408                 }
409         } else if (strcmp(info->version, tmpinfo->version) > 0) {
410                 /*upgrade */
411                 err = _rpm_upgrade_pkg(pkgfilepath, "--force");
412                 if (err != 0) {
413                         _d_msg(DEBUG_ERR,
414                                "upgrade complete with error(%d)\n", err);
415                         if (info) {
416                                 free(info);
417                                 info = NULL;
418                         }
419                         if (tmpinfo) {
420                                 free(tmpinfo);
421                                 tmpinfo = NULL;
422                         }
423                         return err;
424                 } else {
425                         _ri_set_backend_state_info(REQUEST_COMPLETED);
426                         if (info) {
427                                 free(info);
428                                 info = NULL;
429                         }
430                         if (tmpinfo) {
431                                 free(tmpinfo);
432                                 tmpinfo = NULL;
433                         }
434                         return RPM_INSTALLER_SUCCESS;
435                 }
436         } else if (strcmp(info->version, tmpinfo->version) < 0) {
437                 /*show popup and confirm from user */
438                 switch (do_upgrade) {
439                 case -1:
440                         _ri_set_backend_state_info(REQUEST_PENDING);
441                         if (info) {
442                                 free(info);
443                                 info = NULL;
444                         }
445                         if (tmpinfo) {
446                                 free(tmpinfo);
447                                 tmpinfo = NULL;
448                         }
449                         return RPM_INSTALLER_ERR_NEED_USER_CONFIRMATION;
450                 case 0:
451                         /*return */
452                         if (info) {
453                                 free(info);
454                                 info = NULL;
455                         }
456                         if (tmpinfo) {
457                                 free(tmpinfo);
458                                 tmpinfo = NULL;
459                         }
460                         _ri_set_backend_state_info(REQUEST_COMPLETED);
461                         return RPM_INSTALLER_ERR_PACKAGE_NOT_UPGRADED;
462                 case 1:
463                         /*continue with downgrade */
464                         _ri_set_backend_state_info
465                             (GOT_PACKAGE_INFO_SUCCESSFULLY);
466                         err = _rpm_upgrade_pkg(pkgfilepath, "--force");
467                         if (err != 0) {
468                                 _d_msg(DEBUG_ERR,
469                                        "upgrade complete with error(%d)\n",
470                                        err);
471                                 if (info) {
472                                         free(info);
473                                         info = NULL;
474                                 }
475                                 if (tmpinfo) {
476                                         free(tmpinfo);
477                                         tmpinfo = NULL;
478                                 }
479                                 return err;
480                         }
481                         _ri_set_backend_state_info(REQUEST_COMPLETED);
482                         if (info) {
483                                 free(info);
484                                 info = NULL;
485                         }
486                         if (tmpinfo) {
487                                 free(tmpinfo);
488                                 tmpinfo = NULL;
489                         }
490                         return RPM_INSTALLER_SUCCESS;
491
492                 }
493
494         } else {
495                 /*same package. Reinstall it. Manifest should be parsed again */
496                 err = _rpm_upgrade_pkg(pkgfilepath, "--force");
497                 if (err != 0) {
498                         _d_msg(DEBUG_ERR,
499                                "upgrade complete with error(%d)\n", err);
500                         if (info) {
501                                 free(info);
502                                 info = NULL;
503                         }
504                         if (tmpinfo) {
505                                 free(tmpinfo);
506                                 tmpinfo = NULL;
507                         }
508                         return err;
509                 } else {
510                         _ri_set_backend_state_info(REQUEST_COMPLETED);
511                         if (info) {
512                                 free(info);
513                                 info = NULL;
514                         }
515                         if (tmpinfo) {
516                                 free(tmpinfo);
517                                 tmpinfo = NULL;
518                         }
519                         return RPM_INSTALLER_SUCCESS;
520                 }
521         }
522         if (info) {
523                 free(info);
524                 info = NULL;
525         }
526         if (tmpinfo) {
527                 free(tmpinfo);
528                 tmpinfo = NULL;
529         }
530         return RPM_INSTALLER_SUCCESS;
531
532 }
533
534 int _rpm_installer_package_uninstall(char *pkgid)
535 {
536         int ret = 0;
537         pkginfo *tmppkginfo = _rpm_installer_get_pkgname_info(pkgid);
538         if (tmppkginfo == NULL)
539                 return RPM_INSTALLER_ERR_PACKAGE_NOT_INSTALLED;
540         if (tmppkginfo) {
541                 free(tmppkginfo);
542                 tmppkginfo = NULL;
543         }
544 #ifndef SEND_PKGPATH
545         if (gpkgname) {
546                 free(gpkgname);
547                 gpkgname = NULL;
548         }
549         gpkgname = strdup(pkgid);
550         _ri_broadcast_status_notification(pkgid, "start", "uninstall");
551         _ri_broadcast_status_notification(pkgid, "command", "Uninstall");
552 #endif
553         _ri_set_backend_state_info(GOT_PACKAGE_INFO_SUCCESSFULLY);
554         ret = _rpm_uninstall_pkg(pkgid);
555
556         _ri_set_backend_state_info(REQUEST_COMPLETED);
557
558         return ret;
559 }
560
561 int _rpm_installer_clear_private_data(char *pkgid)
562 {
563         if (pkgid == NULL)
564                 return RPM_INSTALLER_ERR_WRONG_PARAM;
565         char dir_path[256] = { '\0' };
566         int ret = -1;
567         snprintf(dir_path, 255, "/opt/usr/apps/%s/data/", pkgid);
568         ret = __ri_recursive_delete_dir(dir_path);
569         return ret;
570 }