]> git.saurik.com Git - apt.git/blob - cmdline/debfile.cc
add apt-extracttemplates to the list of files for apt-utils
[apt.git] / cmdline / debfile.cc
1 #include <stdio.h>
2 #include <apt-pkg/tagfile.h>
3 #include <apt-pkg/extracttar.h>
4 #include <apt-pkg/arfile.h>
5 #include <apt-pkg/pkgcache.h>
6
7 #include "debfile.h"
8
9 pkgCache *DebFile::Cache = 0;
10
11 DebFile::DebFile(const char *debfile)
12 : File(debfile, FileFd::ReadOnly), Control(0), Package(0), Version(0), DepVer(0), PreDepVer(0), DepOp(0), PreDepOp(0), Config(0), Template(0), Which(None)
13 {
14 }
15
16 DebFile::~DebFile()
17 {
18 delete [] Control;
19 delete [] Config;
20 delete [] Template;
21 }
22
23 char *DebFile::GetInstalledVer(const char *package)
24 {
25 char *ver = 0;
26
27 pkgCache::PkgIterator Pkg = Cache->FindPkg(package);
28 if (Pkg.end() == false)
29 {
30 pkgCache::VerIterator V = Pkg.CurrentVer();
31 if (V.end() == false)
32 {
33 ver = strdup(V.VerStr());
34 }
35 }
36
37 return ver;
38 }
39
40 bool DebFile::Go()
41 {
42 ARArchive AR(File);
43 const ARArchive::Member *Member = AR.FindMember("control.tar.gz");
44 if (Member == 0)
45 {
46 fprintf(stderr, "This is not a valid DEB archive.\n");
47 return false;
48 }
49
50 if (File.Seek(Member->Start) == false)
51 {
52 return false;
53 }
54
55 ExtractTar Tar(File, Member->Size);
56 return Tar.Go(*this);
57 }
58
59 bool DebFile::DoItem(Item &I, int &Fd)
60 {
61 if (strcmp(I.Name, "control") == 0)
62 {
63 delete [] Control;
64 Control = new char[I.Size+1];
65 Control[I.Size] = 0;
66 Which = IsControl;
67 ControlLen = I.Size;
68 // make it call the Process method below. this is so evil
69 Fd = -2;
70 }
71 else if (strcmp(I.Name, "config") == 0)
72 {
73 delete [] Config;
74 Config = new char[I.Size+1];
75 Config[I.Size] = 0;
76 Which = IsConfig;
77 Fd = -2;
78 }
79 else if (strcmp(I.Name, "templates") == 0)
80 {
81 delete [] Template;
82 Template = new char[I.Size+1];
83 Template[I.Size] = 0;
84 Which = IsTemplate;
85 Fd = -2;
86 }
87 else
88 {
89 Fd = -1;
90 }
91 return true;
92 }
93
94 bool DebFile::Process(Item &I, const unsigned char *data,
95 unsigned long size, unsigned long pos)
96 {
97 switch (Which)
98 {
99 case IsControl:
100 memcpy(Control + pos, data, size);
101 break;
102 case IsConfig:
103 memcpy(Config + pos, data, size);
104 break;
105 case IsTemplate:
106 memcpy(Template + pos, data, size);
107 break;
108 default: /* throw it away */ ;
109 }
110 return true;
111 }
112
113 bool DebFile::ParseInfo()
114 {
115 if (Control == NULL) return false;
116 pkgTagSection Section;
117 Section.Scan(Control, ControlLen);
118
119 const char *pkgtmp = Section.FindS("Package").c_str();
120 Package = CopyString(pkgtmp, strlen(pkgtmp));
121 Version = GetInstalledVer(Package);
122
123 const char *Start, *Stop;
124 if (Section.Find("Depends", Start, Stop) == true)
125 {
126 while (1)
127 {
128 char *P = 0, *V = 0;
129 unsigned int Op;
130 Start = ParseDepends(Start, Stop, P, V, Op);
131 if (Start == 0) return false;
132 if (strcmp(P, "debconf") == 0)
133 {
134 DepVer = V;
135 DepOp = Op;
136 delete[] P;
137 break;
138 }
139 else
140 {
141 delete[] P;
142 delete[] V;
143 }
144 if (Start == Stop) break;
145 }
146 }
147
148 if (Section.Find("Pre-Depends", Start, Stop) == true)
149 {
150 while (1)
151 {
152 char *P = 0, *V = 0;
153 unsigned int Op;
154 Start = ParseDepends(Start, Stop, P, V, Op);
155 if (Start == 0) return false;
156 if (strcmp(P, "debconf") == 0)
157 {
158 PreDepVer = V;
159 PreDepOp = Op;
160 delete[] P;
161 break;
162 }
163 else
164 {
165 delete[] P;
166 delete[] V;
167 }
168 if (Start == Stop) break;
169 }
170 }
171
172 return true;
173 }
174
175 char *DebFile::CopyString(const char *start, unsigned int len)
176 {
177 char *s = new char[len + 1];
178 s[len] = 0;
179 memcpy(s, start, len);
180 return s;
181 }
182
183 const char *DebFile::ParseDepends(const char *Start,const char *Stop,
184 char *&Package, char *&Ver,
185 unsigned int &Op)
186 {
187 // Strip off leading space
188 for (;Start != Stop && isspace(*Start) != 0; Start++);
189
190 // Parse off the package name
191 const char *I = Start;
192 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
193 *I != ',' && *I != '|'; I++);
194
195 // Malformed, no '('
196 if (I != Stop && *I == ')')
197 return 0;
198
199 if (I == Start)
200 return 0;
201
202 // Stash the package name
203 Package = CopyString(Start, I - Start);
204
205 // Skip white space to the '('
206 for (;I != Stop && isspace(*I) != 0 ; I++);
207
208 // Parse a version
209 if (I != Stop && *I == '(')
210 {
211 // Skip the '('
212 for (I++; I != Stop && isspace(*I) != 0 ; I++);
213 if (I + 3 >= Stop)
214 return 0;
215
216 // Determine the operator
217 switch (*I)
218 {
219 case '<':
220 I++;
221 if (*I == '=')
222 {
223 I++;
224 Op = pkgCache::Dep::LessEq;
225 break;
226 }
227
228 if (*I == '<')
229 {
230 I++;
231 Op = pkgCache::Dep::Less;
232 break;
233 }
234
235 // < is the same as <= and << is really Cs < for some reason
236 Op = pkgCache::Dep::LessEq;
237 break;
238
239 case '>':
240 I++;
241 if (*I == '=')
242 {
243 I++;
244 Op = pkgCache::Dep::GreaterEq;
245 break;
246 }
247
248 if (*I == '>')
249 {
250 I++;
251 Op = pkgCache::Dep::Greater;
252 break;
253 }
254
255 // > is the same as >= and >> is really Cs > for some reason
256 Op = pkgCache::Dep::GreaterEq;
257 break;
258
259 case '=':
260 Op = pkgCache::Dep::Equals;
261 I++;
262 break;
263
264 // HACK around bad package definitions
265 default:
266 Op = pkgCache::Dep::Equals;
267 break;
268 }
269
270 // Skip whitespace
271 for (;I != Stop && isspace(*I) != 0; I++);
272 Start = I;
273 for (;I != Stop && *I != ')'; I++);
274 if (I == Stop || Start == I)
275 return 0;
276
277 // Skip trailing whitespace
278 const char *End = I;
279 for (; End > Start && isspace(End[-1]); End--);
280
281 Ver = CopyString(Start, End - Start);
282 I++;
283 }
284 else
285 {
286 Ver = CopyString("", 0);
287 Op = pkgCache::Dep::NoOp;
288 }
289
290 // Skip whitespace
291 for (;I != Stop && isspace(*I) != 0; I++);
292
293 if (I != Stop && *I == '|')
294 Op |= pkgCache::Dep::Or;
295
296 if (I == Stop || *I == ',' || *I == '|')
297 {
298 if (I != Stop)
299 for (I++; I != Stop && isspace(*I) != 0; I++);
300 return I;
301 }
302
303 return 0;
304 }