]> git.saurik.com Git - apt.git/blob - apt-pkg/versionmatch.cc
Ensure the memory buffer is 0'd
[apt.git] / apt-pkg / versionmatch.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: versionmatch.cc,v 1.4 2001/05/22 06:20:06 jgg Exp $
4 /* ######################################################################
5
6 Version Matching
7
8 This module takes a matching string and a type and locates the version
9 record that satisfies the constraint described by the matching string.
10
11 ##################################################################### */
12 /*}}}*/
13 // Include Files /*{{{*/
14 #ifdef __GNUG__
15 #pragma implementation "apt-pkg/versionmatch.h"
16 #endif
17 #include <apt-pkg/versionmatch.h>
18
19 #include <apt-pkg/strutl.h>
20 #include <apt-pkg/error.h>
21
22 #include <stdio.h>
23 #include <ctype.h>
24 /*}}}*/
25
26 // VersionMatch::pkgVersionMatch - Constructor /*{{{*/
27 // ---------------------------------------------------------------------
28 /* Break up the data string according to the selected type */
29 pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
30 {
31 if (Type == None || Data.length() < 1)
32 return;
33
34 // Cut up the version representation
35 if (Type == Version)
36 {
37 if (Data.end()[-1] == '*')
38 {
39 VerPrefixMatch = true;
40 VerStr = string(Data,0,Data.length()-1);
41 }
42 else
43 VerStr = Data;
44 return;
45 }
46
47 if (Type == Release)
48 {
49 // All empty = match all
50 if (Data == "*")
51 return;
52
53 // Are we a simple specification?
54 string::const_iterator I = Data.begin();
55 for (; I != Data.end() && *I != '='; I++);
56 if (I == Data.end())
57 {
58 // Temporary
59 if (isdigit(Data[0]))
60 RelVerStr = Data;
61 else
62 RelArchive = Data;
63
64 if (RelVerStr.end()[-1] == '*')
65 {
66 RelVerPrefixMatch = true;
67 RelVerStr = string(RelVerStr.begin(),RelVerStr.end()-1);
68 }
69 return;
70 }
71
72 char Spec[300];
73 char *Fragments[20];
74 snprintf(Spec,sizeof(Spec),"%s",Data.c_str());
75 if (TokSplitString(',',Spec,Fragments,
76 sizeof(Fragments)/sizeof(Fragments[0])) == false)
77 {
78 Type = None;
79 return;
80 }
81
82 for (unsigned J = 0; Fragments[J] != 0; J++)
83 {
84 if (strlen(Fragments[J]) < 3)
85 continue;
86
87 if (stringcasecmp(Fragments[J],Fragments[J]+2,"v=") == 0)
88 RelVerStr = Fragments[J]+2;
89 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"o=") == 0)
90 RelOrigin = Fragments[J]+2;
91 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"a=") == 0)
92 RelArchive = Fragments[J]+2;
93 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"l=") == 0)
94 RelLabel = Fragments[J]+2;
95 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"c=") == 0)
96 RelComponent = Fragments[J]+2;
97 }
98
99 if (RelVerStr.end()[-1] == '*')
100 {
101 RelVerPrefixMatch = true;
102 RelVerStr = string(RelVerStr.begin(),RelVerStr.end()-1);
103 }
104 return;
105 }
106
107 if (Type == Origin)
108 {
109 OrSite = Data;
110 return;
111 }
112 }
113 /*}}}*/
114 // VersionMatch::MatchVer - Match a version string with prefixing /*{{{*/
115 // ---------------------------------------------------------------------
116 /* */
117 bool pkgVersionMatch::MatchVer(const char *A,string B,bool Prefix)
118 {
119 const char *Ab = A;
120 const char *Ae = Ab + strlen(A);
121
122 // Strings are not a compatible size.
123 if ((unsigned)(Ae - Ab) != B.length() && Prefix == false ||
124 (unsigned)(Ae - Ab) < B.length())
125 return false;
126
127 // Match (leading?)
128 if (stringcasecmp(B,Ab,Ab + B.length()) == 0)
129 return true;
130
131 return false;
132 }
133 /*}}}*/
134 // VersionMatch::Find - Locate the best match for the select type /*{{{*/
135 // ---------------------------------------------------------------------
136 /* */
137 pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg)
138 {
139 pkgCache::VerIterator Ver = Pkg.VersionList();
140 for (; Ver.end() == false; Ver++)
141 {
142 if (Type == Version)
143 {
144 if (MatchVer(Ver.VerStr(),VerStr,VerPrefixMatch) == true)
145 return Ver;
146 continue;
147 }
148
149 for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; VF++)
150 if (FileMatch(VF.File()) == true)
151 return Ver;
152 }
153
154 // This will be Ended by now.
155 return Ver;
156 }
157 /*}}}*/
158 // VersionMatch::FileMatch - Match against an index file /*{{{*/
159 // ---------------------------------------------------------------------
160 /* This matcher checks against the release file and the origin location
161 to see if the constraints are met. */
162 bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
163 {
164 if (Type == Release)
165 {
166 /* cout << RelVerStr << ',' << RelOrigin << ',' << RelArchive << ',' << RelLabel << endl;
167 cout << File.Version() << ',' << File.Origin() << ',' << File.Archive() << ',' << File.Label() << endl;*/
168
169 if (RelVerStr.empty() == true && RelOrigin.empty() == true &&
170 RelArchive.empty() == true && RelLabel.empty() == true &&
171 RelComponent.empty() == true)
172 return false;
173
174 if (RelVerStr.empty() == false)
175 if (File->Version == 0 ||
176 MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false)
177 return false;
178 if (RelOrigin.empty() == false)
179 if (File->Origin == 0 ||
180 stringcasecmp(RelOrigin,File.Origin()) != 0)
181 return false;
182 if (RelArchive.empty() == false)
183 {
184 if (File->Archive == 0 ||
185 stringcasecmp(RelArchive,File.Archive()) != 0)
186 return false;
187 }
188 if (RelLabel.empty() == false)
189 if (File->Label == 0 ||
190 stringcasecmp(RelLabel,File.Label()) != 0)
191 return false;
192 if (RelComponent.empty() == false)
193 if (File->Component == 0 ||
194 stringcasecmp(RelComponent,File.Component()) != 0)
195 return false;
196 return true;
197 }
198
199 if (Type == Origin)
200 {
201 if (OrSite.empty() == false)
202 if (File->Site == 0 ||
203 OrSite != File.Site())
204 return false;
205 return true;
206 }
207
208 return false;
209 }
210 /*}}}*/