You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

override.cc 7.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. /* ######################################################################
  4. Override
  5. Store the override file.
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include Files /*{{{*/
  9. #include <config.h>
  10. #include <apt-pkg/error.h>
  11. #include <apt-pkg/strutl.h>
  12. #include <utility>
  13. #include <ctype.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include "override.h"
  17. #include <apti18n.h>
  18. /*}}}*/
  19. // Override::ReadOverride - Read the override file /*{{{*/
  20. // ---------------------------------------------------------------------
  21. /* This parses the override file and reads it into the map */
  22. bool Override::ReadOverride(string const &File,bool const &Source)
  23. {
  24. if (File.empty() == true)
  25. return true;
  26. FILE *F = fopen(File.c_str(),"r");
  27. if (F == 0)
  28. return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
  29. char Line[1000];
  30. unsigned long long Counter = 0;
  31. while (fgets(Line,sizeof(Line),F) != 0)
  32. {
  33. Counter++;
  34. Item Itm;
  35. // Silence
  36. for (char *I = Line; *I != 0; I++)
  37. if (*I == '#')
  38. *I = 0;
  39. // Strip space leading up to the package name, skip blank lines
  40. char *Pkg = Line;
  41. for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
  42. if (*Pkg == 0)
  43. continue;
  44. #define APT_FIND_NEXT_FIELD \
  45. for (End++; isspace(*End) != 0 && *End != 0; ++End) \
  46. /* skip spaces */ ; \
  47. Start = End; \
  48. for (; isspace(*End) == 0 && *End != 0; ++End) \
  49. /* find end of word */ ;
  50. #define APT_WARNING_MALFORMED_LINE(FIELD) \
  51. if (*End == 0) \
  52. { \
  53. _error->Warning(_("Malformed override %s line %llu (%s)"),File.c_str(), \
  54. Counter, FIELD ); \
  55. continue; \
  56. } \
  57. *End = 0;
  58. // Find the package and zero..
  59. char *Start;
  60. char *End = Pkg;
  61. for (; isspace(*End) == 0 && *End != 0; End++);
  62. APT_WARNING_MALFORMED_LINE("pkgname");
  63. APT_FIND_NEXT_FIELD;
  64. // Find the priority
  65. if (Source == false)
  66. {
  67. APT_WARNING_MALFORMED_LINE("priority");
  68. Itm.Priority = Start;
  69. APT_FIND_NEXT_FIELD;
  70. }
  71. // Find the Section
  72. APT_WARNING_MALFORMED_LINE("section");
  73. Itm.FieldOverride["Section"] = Start;
  74. // Source override files only have the two columns
  75. if (Source == true)
  76. {
  77. Mapping[Pkg] = Itm;
  78. continue;
  79. }
  80. // Find the =>
  81. for (End++; isspace(*End) != 0 && *End != 0; End++);
  82. if (*End != 0)
  83. {
  84. Start = End;
  85. for (; *End != 0 && (End[0] != '=' || End[1] != '>'); End++);
  86. if (*End == 0 || strlen(End) < 4)
  87. {
  88. Itm.OldMaint = "*";
  89. Itm.NewMaint = _strstrip(Start);
  90. }
  91. else
  92. {
  93. *End = 0;
  94. Itm.OldMaint = _strstrip(Start);
  95. End += 3;
  96. Itm.NewMaint = _strstrip(End);
  97. }
  98. }
  99. Mapping[Pkg] = Itm;
  100. }
  101. if (ferror(F))
  102. _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
  103. fclose(F);
  104. return true;
  105. }
  106. /*}}}*/
  107. // Override::ReadExtraOverride - Read the extra override file /*{{{*/
  108. // ---------------------------------------------------------------------
  109. /* This parses the extra override file and reads it into the map */
  110. bool Override::ReadExtraOverride(string const &File,bool const &/*Source*/)
  111. {
  112. if (File.empty() == true)
  113. return true;
  114. FILE *F = fopen(File.c_str(),"r");
  115. if (F == 0)
  116. return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
  117. char Line[1000];
  118. unsigned long long Counter = 0;
  119. while (fgets(Line,sizeof(Line),F) != 0)
  120. {
  121. Counter++;
  122. // Silence
  123. for (char *I = Line; *I != 0; I++)
  124. if (*I == '#')
  125. *I = 0;
  126. // Strip space leading up to the package name, skip blank lines
  127. char *Pkg = Line;
  128. for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
  129. if (Pkg == 0)
  130. continue;
  131. // Find the package and zero..
  132. char *End = Pkg;
  133. for (; isspace(*End) == 0 && *End != 0; End++);
  134. if (*End == 0)
  135. {
  136. _error->Warning(_("Malformed override %s line %llu #1"),File.c_str(),
  137. Counter);
  138. continue;
  139. }
  140. *End = 0;
  141. // Find the field
  142. for (End++; isspace(*End) != 0 && *End != 0; End++);
  143. char *Field = End;
  144. for (; isspace(*End) == 0 && *End != 0; End++);
  145. if (*End == 0)
  146. {
  147. _error->Warning(_("Malformed override %s line %llu #2"),File.c_str(),
  148. Counter);
  149. continue;
  150. }
  151. *End = 0;
  152. // Find the field value
  153. for (End++; isspace(*End) != 0 && *End != 0; End++);
  154. char *Value = End;
  155. for (; *End != 0; End++);
  156. for (; isspace(*(End-1)) && End > Value; End--);
  157. if (End == Value)
  158. {
  159. _error->Warning(_("Malformed override %s line %llu #3"),File.c_str(),
  160. Counter);
  161. continue;
  162. }
  163. *End = 0;
  164. Mapping[Pkg].FieldOverride[Field] = Value;
  165. }
  166. if (ferror(F))
  167. _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
  168. fclose(F);
  169. return true;
  170. }
  171. /*}}}*/
  172. // Override::GetItem - Get a architecture specific item /*{{{*/
  173. // ---------------------------------------------------------------------
  174. /* Returns a override item for the given package and the given architecture.
  175. * Treats "all" special
  176. */
  177. Override::Item* Override::GetItem(string const &Package, string const &Architecture)
  178. {
  179. map<string,Item>::const_iterator I = Mapping.find(Package);
  180. map<string,Item>::iterator J = Mapping.find(Package + "/" + Architecture);
  181. if (I == Mapping.end() && J == Mapping.end())
  182. {
  183. return 0;
  184. }
  185. Item *result = new Item;
  186. if (I == Mapping.end()) *result = J->second;
  187. else
  188. {
  189. *result = I->second;
  190. if (J != Mapping.end())
  191. {
  192. Item *R = &J->second;
  193. if (R->Priority != "") result->Priority = R->Priority;
  194. if (R->OldMaint != "") result->OldMaint = R->OldMaint;
  195. if (R->NewMaint != "") result->NewMaint = R->NewMaint;
  196. for (map<string,string>::const_iterator foI = R->FieldOverride.begin();
  197. foI != R->FieldOverride.end(); ++foI)
  198. {
  199. result->FieldOverride[foI->first] = foI->second;
  200. }
  201. }
  202. }
  203. return result;
  204. }
  205. // Override::Item::SwapMaint - Swap the maintainer field if necessary /*{{{*/
  206. // ---------------------------------------------------------------------
  207. /* Returns the new maintainer string after evaluating the rewriting rule. If
  208. there is a rule but it does not match then the empty string is returned,
  209. also if there was no rewrite rule the empty string is returned. Failed
  210. indicates if there was some kind of problem while rewriting. */
  211. string Override::Item::SwapMaint(string const &Orig,bool &Failed)
  212. {
  213. Failed = false;
  214. // Degenerate case..
  215. if (NewMaint.empty() == true)
  216. return OldMaint;
  217. if (OldMaint == "*")
  218. return NewMaint;
  219. /* James: ancient, eliminate it, however it is still being used in the main
  220. override file. Thus it persists.*/
  221. #if 1
  222. // Break OldMaint up into little bits on double slash boundaries.
  223. string::const_iterator End = OldMaint.begin();
  224. while (1)
  225. {
  226. string::const_iterator Start = End;
  227. for (; End < OldMaint.end() &&
  228. (End + 3 >= OldMaint.end() || End[0] != ' ' ||
  229. End[1] != '/' || End[2] != '/'); ++End);
  230. if (stringcasecmp(Start,End,Orig.begin(),Orig.end()) == 0)
  231. return NewMaint;
  232. if (End >= OldMaint.end())
  233. break;
  234. // Skip the divider and white space
  235. for (; End < OldMaint.end() && (*End == '/' || *End == ' '); ++End);
  236. }
  237. #else
  238. if (stringcasecmp(OldMaint.begin(),OldMaint.end(),Orig.begin(),Orig.end()) == 0)
  239. return NewMaint;
  240. #endif
  241. Failed = true;
  242. return string();
  243. }
  244. /*}}}*/