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