allow rpm to custom systemd installation
[platform/upstream/rpm.git] / lib / rpmprob.c
1 /**
2  * \file lib/rpmps.c
3  */
4
5 #include "system.h"
6
7 #include <inttypes.h>
8 #include <stdlib.h>
9
10 #include <rpm/rpmstring.h>
11 #include <rpm/rpmprob.h>
12
13 #include "debug.h"
14
15 struct rpmProblem_s {
16     char * pkgNEVR;
17     char * altNEVR;
18     fnpyKey key;
19     rpmProblemType type;
20     char * str1;
21     uint64_t num1;
22     int nrefs;
23 };
24
25 static rpmProblem rpmProblemUnlink(rpmProblem prob);
26
27 rpmProblem rpmProblemCreate(rpmProblemType type,
28                             const char * pkgNEVR, fnpyKey key,
29                             const char * altNEVR,
30                             const char * str, uint64_t number)
31 {
32     rpmProblem p = xcalloc(1, sizeof(*p));
33
34     p->type = type;
35     p->key = key;
36     p->num1 = number;
37
38     p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
39     p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
40     p->str1 = (str ? xstrdup(str) : NULL);
41
42     return rpmProblemLink(p);
43 }
44
45 rpmProblem rpmProblemFree(rpmProblem prob)
46 {
47     if (prob == NULL) return NULL;
48
49     if (prob->nrefs > 1) {
50         return rpmProblemUnlink(prob);
51     }
52     prob->pkgNEVR = _free(prob->pkgNEVR);
53     prob->altNEVR = _free(prob->altNEVR);
54     prob->str1 = _free(prob->str1);
55     free(prob);
56     return NULL;
57 }
58
59 rpmProblem rpmProblemLink(rpmProblem prob)
60 {
61     if (prob) {
62         prob->nrefs++;
63     }
64     return prob;
65 }
66
67 static rpmProblem rpmProblemUnlink(rpmProblem prob)
68 {
69     if (prob) {
70         prob->nrefs--;
71     }
72     return NULL;
73 }
74
75 const char * rpmProblemGetPkgNEVR(rpmProblem p)
76 {
77     return (p->pkgNEVR);
78 }
79
80 const char * rpmProblemGetAltNEVR(rpmProblem p)
81 {
82     return (p->altNEVR);
83 }
84
85 fnpyKey rpmProblemGetKey(rpmProblem p)
86 {
87     return (p->key);
88 }
89
90 rpmProblemType rpmProblemGetType(rpmProblem p)
91 {
92     return (p->type);
93 }
94
95 const char * rpmProblemGetStr(rpmProblem p)
96 {
97     return (p->str1);
98 }
99
100 rpm_loff_t rpmProblemGetDiskNeed(rpmProblem p)
101 {
102     return (p->num1);
103 }
104
105 char * rpmProblemString(rpmProblem prob)
106 {
107     const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
108     const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
109     const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
110     char * buf = NULL;
111
112     switch (prob->type) {
113     case RPMPROB_BADARCH:
114         rasprintf(&buf, _("package %s is intended for a %s architecture"),
115                 pkgNEVR, str1);
116         break;
117     case RPMPROB_BADOS:
118         rasprintf(&buf, _("package %s is intended for a %s operating system"),
119                 pkgNEVR, str1);
120         break;
121     case RPMPROB_PKG_INSTALLED:
122         rasprintf(&buf, _("package %s is already installed"), pkgNEVR);
123         break;
124     case RPMPROB_BADRELOCATE:
125         rasprintf(&buf, _("path %s in package %s is not relocatable"),
126                 str1, pkgNEVR);
127         break;
128     case RPMPROB_NEW_FILE_CONFLICT:
129         rasprintf(&buf, 
130                 _("file %s conflicts between attempted installs of %s and %s"),
131                 str1, pkgNEVR, altNEVR);
132         break;
133     case RPMPROB_FILE_CONFLICT:
134         rasprintf(&buf,
135             _("file %s from install of %s conflicts with file from package %s"),
136                 str1, pkgNEVR, altNEVR);
137         break;
138     case RPMPROB_OLDPACKAGE:
139         rasprintf(&buf,
140                 _("package %s (which is newer than %s) is already installed"),
141                 altNEVR, pkgNEVR);
142         break;
143     case RPMPROB_DISKSPACE:
144         rasprintf(&buf,
145             _("installing package %s needs %" PRIu64 "%cB on the %s filesystem"),
146                 pkgNEVR,
147                 prob->num1 > (1024*1024)
148                     ? (prob->num1 + 1024 * 1024 - 1) / (1024 * 1024)
149                     : (prob->num1 + 1023) / 1024,
150                 prob->num1 > (1024*1024) ? 'M' : 'K',
151                 str1);
152         break;
153     case RPMPROB_DISKNODES:
154         rasprintf(&buf,
155             _("installing package %s needs %" PRIu64 " inodes on the %s filesystem"),
156                 pkgNEVR, prob->num1, str1);
157         break;
158     case RPMPROB_REQUIRES:
159         rasprintf(&buf, _("%s is needed by %s%s"),
160                   prob->str1, (prob->num1 ? _("(installed) ") : ""), altNEVR);
161         break;
162     case RPMPROB_CONFLICT:
163         rasprintf(&buf, _("%s conflicts with %s%s"),
164                   prob->str1, (prob->num1 ? _("(installed) ") : ""), altNEVR);
165         break;
166     case RPMPROB_OBSOLETES:
167         rasprintf(&buf, _("%s is obsoleted by %s%s"),
168                   prob->str1, (prob->num1 ? _("(installed) ") : ""), altNEVR);
169         break;
170     default:
171         rasprintf(&buf,
172                 _("unknown error %d encountered while manipulating package %s"),
173                 prob->type, pkgNEVR);
174         break;
175     }
176
177     return buf;
178 }
179
180 static int cmpStr(const char *s1, const char *s2)
181 {
182     if (s1 == s2) return 0;
183     if (s1 && s2) return strcmp(s1, s2);
184     return 1;
185 }
186
187 int rpmProblemCompare(rpmProblem ap, rpmProblem bp)
188 {
189     if (ap == bp)
190         return 0;
191     if (ap == NULL || bp == NULL)
192         return 1;
193     if (ap->type != bp->type)
194         return 1;
195     if (ap->key != bp->key)
196         return 1;
197     if (ap->num1 != bp->num1)
198         return 1;
199     if (cmpStr(ap->pkgNEVR, bp->pkgNEVR))
200         return 1;
201     if (cmpStr(ap->altNEVR, bp->altNEVR))
202         return 1;
203     if (cmpStr(ap->str1, bp->str1))
204         return 1;
205
206     return 0;
207 }