debversion.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: debversion.cc,v 1.3 2001/05/07 05:14:53 jgg Exp $
  4. /* ######################################################################
  5. Debian Version - Versioning system for Debian
  6. This implements the standard Debian versioning system.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #define APT_COMPATIBILITY 986
  11. #ifdef __GNUG__
  12. #pragma implementation "apt-pkg/debversion.h"
  13. #endif
  14. #include <apt-pkg/debversion.h>
  15. #include <apt-pkg/pkgcache.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. /*}}}*/
  19. debVersioningSystem debVS;
  20. // debVS::debVersioningSystem - Constructor /*{{{*/
  21. // ---------------------------------------------------------------------
  22. /* */
  23. debVersioningSystem::debVersioningSystem()
  24. {
  25. Label = "Standard .deb";
  26. }
  27. /*}}}*/
  28. // StrToLong - Convert the string between two iterators to a long /*{{{*/
  29. // ---------------------------------------------------------------------
  30. /* */
  31. static unsigned long StrToLong(const char *begin,const char *end)
  32. {
  33. char S[40];
  34. char *I = S;
  35. for (; begin != end && I < S + 40;)
  36. *I++ = *begin++;
  37. *I = 0;
  38. return strtoul(S,0,10);
  39. }
  40. /*}}}*/
  41. // debVS::CmpFragment - Compare versions /*{{{*/
  42. // ---------------------------------------------------------------------
  43. /* This compares a fragment of the version. Dpkg has a really short
  44. version of this, but it is uh.. interesting to grok. */
  45. int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
  46. const char *B,const char *BEnd)
  47. {
  48. if (A >= AEnd && B >= BEnd)
  49. return 0;
  50. if (A >= AEnd)
  51. return -1;
  52. if (B >= BEnd)
  53. return 1;
  54. /* Iterate over the whole string
  55. What this does is to spilt the whole string into groups of
  56. numeric and non numeric portions. For instance:
  57. a67bhgs89
  58. Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
  59. 2.7.2-linux-1
  60. Has '2', '.', '7', '.' ,'-linux-','1' */
  61. const char *lhs = A;
  62. const char *rhs = B;
  63. while (lhs != AEnd && rhs != BEnd)
  64. {
  65. // Starting points
  66. const char *Slhs = lhs;
  67. const char *Srhs = rhs;
  68. // Compute ending points were we have passed over the portion
  69. bool Digit = (isdigit(*lhs) > 0?true:false);
  70. for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
  71. for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
  72. if (Digit == true)
  73. {
  74. // If the lhs has a digit and the rhs does not then <
  75. if (rhs - Srhs == 0)
  76. return -1;
  77. // Generate integers from the strings.
  78. unsigned long Ilhs = StrToLong(Slhs,lhs);
  79. unsigned long Irhs = StrToLong(Srhs,rhs);
  80. if (Ilhs != Irhs)
  81. {
  82. if (Ilhs > Irhs)
  83. return 1;
  84. return -1;
  85. }
  86. }
  87. else
  88. {
  89. // They are equal length so do a straight text compare
  90. for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
  91. {
  92. if (*Slhs != *Srhs)
  93. {
  94. /* We need to compare non alpha chars as higher than alpha
  95. chars (a < !) */
  96. int lc = *Slhs;
  97. int rc = *Srhs;
  98. if (isalpha(lc) == 0) lc += 256;
  99. if (isalpha(rc) == 0) rc += 256;
  100. if (lc > rc)
  101. return 1;
  102. return -1;
  103. }
  104. }
  105. // If the lhs is shorter than the right it is 'less'
  106. if (lhs - Slhs < rhs - Srhs)
  107. return -1;
  108. // If the lhs is longer than the right it is 'more'
  109. if (lhs - Slhs > rhs - Srhs)
  110. return 1;
  111. }
  112. }
  113. // The strings must be equal
  114. if (lhs == AEnd && rhs == BEnd)
  115. return 0;
  116. // lhs is shorter
  117. if (lhs == AEnd)
  118. return -1;
  119. // rhs is shorter
  120. if (rhs == BEnd)
  121. return 1;
  122. // Shouldnt happen
  123. return 1;
  124. }
  125. /*}}}*/
  126. // debVS::CmpVersion - Comparison for versions /*{{{*/
  127. // ---------------------------------------------------------------------
  128. /* This fragments the version into E:V-R triples and compares each
  129. portion separately. */
  130. int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
  131. const char *B,const char *BEnd)
  132. {
  133. // Strip off the epoch and compare it
  134. const char *lhs = A;
  135. const char *rhs = B;
  136. for (;lhs != AEnd && *lhs != ':'; lhs++);
  137. for (;rhs != BEnd && *rhs != ':'; rhs++);
  138. if (lhs == AEnd)
  139. lhs = A;
  140. if (rhs == BEnd)
  141. rhs = B;
  142. // Compare the epoch
  143. int Res = CmpFragment(A,lhs,B,rhs);
  144. if (Res != 0)
  145. return Res;
  146. // Skip the :
  147. if (lhs != A)
  148. lhs++;
  149. if (rhs != B)
  150. rhs++;
  151. // Find the last -
  152. const char *dlhs = AEnd-1;
  153. const char *drhs = BEnd-1;
  154. for (;dlhs > lhs && *dlhs != '-'; dlhs--);
  155. for (;drhs > rhs && *drhs != '-'; drhs--);
  156. if (dlhs == lhs)
  157. dlhs = AEnd;
  158. if (drhs == rhs)
  159. drhs = BEnd;
  160. // Compare the main version
  161. Res = CmpFragment(lhs,dlhs,rhs,drhs);
  162. if (Res != 0)
  163. return Res;
  164. // Skip the -
  165. if (dlhs != lhs)
  166. dlhs++;
  167. if (drhs != rhs)
  168. drhs++;
  169. return CmpFragment(dlhs,AEnd,drhs,BEnd);
  170. }
  171. /*}}}*/
  172. // debVS::CheckDep - Check a single dependency /*{{{*/
  173. // ---------------------------------------------------------------------
  174. /* This simply preforms the version comparison and switch based on
  175. operator. If DepVer is 0 then we are comparing against a provides
  176. with no version. */
  177. bool debVersioningSystem::CheckDep(const char *PkgVer,
  178. int Op,const char *DepVer)
  179. {
  180. if (DepVer == 0 || DepVer[0] == 0)
  181. return true;
  182. if (PkgVer == 0 || PkgVer[0] == 0)
  183. return false;
  184. // Perform the actual comparision.
  185. int Res = CmpVersion(PkgVer,DepVer);
  186. switch (Op & 0x0F)
  187. {
  188. case pkgCache::Dep::LessEq:
  189. if (Res <= 0)
  190. return true;
  191. break;
  192. case pkgCache::Dep::GreaterEq:
  193. if (Res >= 0)
  194. return true;
  195. break;
  196. case pkgCache::Dep::Less:
  197. if (Res < 0)
  198. return true;
  199. break;
  200. case pkgCache::Dep::Greater:
  201. if (Res > 0)
  202. return true;
  203. break;
  204. case pkgCache::Dep::Equals:
  205. if (Res == 0)
  206. return true;
  207. break;
  208. case pkgCache::Dep::NotEquals:
  209. if (Res != 0)
  210. return true;
  211. break;
  212. }
  213. return false;
  214. }
  215. /*}}}*/
  216. // debVS::UpstreamVersion - Return the upstream version string /*{{{*/
  217. // ---------------------------------------------------------------------
  218. /* This strips all the debian specific information from the version number */
  219. string debVersioningSystem::UpstreamVersion(const char *Ver)
  220. {
  221. // Strip off the bit before the first colon
  222. const char *I = Ver;
  223. for (; *I != 0 && *I != ':'; I++);
  224. if (*I == ':')
  225. Ver = I + 1;
  226. // Chop off the trailing -
  227. I = Ver;
  228. unsigned Last = strlen(Ver);
  229. for (; *I != 0; I++)
  230. if (*I == '-')
  231. Last = I - Ver;
  232. return string(Ver,Last);
  233. }
  234. /*}}}*/