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