debversion.cc 6.7 KB

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