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.

tagfile.cc 20 KiB

* merged changes from the conference Patches applied: * apt@arch.ubuntu.com/apt--experimental--0.6--base-0 tag of apt@arch.ubuntu.com/apt--MAIN--0--patch-1190 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-1 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-2 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-3 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-4 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-5 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-6 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-7 Merge working copy of v0.6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-8 0.6.0 is headed for experimental, not unstable * apt@arch.ubuntu.com/apt--experimental--0.6--patch-9 Date * apt@arch.ubuntu.com/apt--experimental--0.6--patch-10 Update LIB_APT_PKG_MAJOR * apt@arch.ubuntu.com/apt--experimental--0.6--patch-11 - Fix a heap corruption bug in pkgSrcRecords::pkgSrcRec... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-12 Resynch * apt@arch.ubuntu.com/apt--experimental--0.6--patch-13 * Merge apt 0.5.17 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-14 * Rearrange Release file authentication code to be more... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-15 * Convert distribution "../project/experimental" to "ex... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-16 Merge 1.11 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-17 Merge 1.7 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-18 Merge 1.10 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-19 * Make a number of Release file errors into warnings; f... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-20 * Add space between package names when multiple unauthe... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-21 * Provide apt-key with a secret keyring and a trustdb, ... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-22 * Fix typo in apt-key(8) (standard input is '-', not '/') * apt@arch.ubuntu.com/apt--experimental--0.6--patch-23 0.6.2 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-24 Resynch * apt@arch.ubuntu.com/apt--experimental--0.6--patch-25 * Fix MetaIndexURI for flat ("foo/") sources * apt@arch.ubuntu.com/apt--experimental--0.6--patch-26 0.6.3 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-27 * Use the top-level Release file in LoadReleaseInfo, ra... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-28 0.6.4 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-29 Clarify * apt@arch.ubuntu.com/apt--experimental--0.6--patch-30 * Move the authentication check into a separate functio... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-31 * Fix display of unauthenticated packages when they are... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-32 * Move the authentication check into a separate functio... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-33 * Restore the ugly hack I removed from indexRecords::Lo... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-34 0.6.6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-35 * Forgot to revert part of the changes to tagfile in 0.... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-36 * Add a config option and corresponding command line option * apt@arch.ubuntu.com/apt--experimental--0.6--patch-37 0.6.8 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-38 hopefully avoid more segfaults * apt@arch.ubuntu.com/apt--experimental--0.6--patch-39 XXX * apt@arch.ubuntu.com/apt--experimental--0.6--patch-40 * Another tagfile workaround * apt@arch.ubuntu.com/apt--experimental--0.6--patch-41 * Use "Codename" (woody, sarge, etc.) to supply the val... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-42 * Support IMS requests of Release.gpg and Release * apt@arch.ubuntu.com/apt--experimental--0.6--patch-43 * Have pkgAcquireIndex calculate an MD5 sum if one is n... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-44 * Merge 0.5.18 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-45 apt (0.6.13) experimental; urgency=low * apt@arch.ubuntu.com/apt--experimental--0.6--patch-46 0.6.13 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-47 Merge 0.5.20 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-48 The source list works a bit differently in 0.6; fix the... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-49 * s/Debug::Acquire::gpg/&v/ * apt@arch.ubuntu.com/apt--experimental--0.6--patch-50 * Honor the [vendor] syntax in sources.list again (thou... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-51 * Don't ship vendors.list(5) since it isn't used yet * apt@arch.ubuntu.com/apt--experimental--0.6--patch-52 * Revert change from 0.6.10; it was right in the first ... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-53 * Fix some cases where the .gpg file could be left in p... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-54 Print a warning if gnupg is not installed * apt@arch.ubuntu.com/apt--experimental--0.6--patch-55 * Handle more IMS stuff correctly * apt@arch.ubuntu.com/apt--experimental--0.6--patch-56 0.6.17 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-57 * Merge 0.5.21 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-58 * Add new Debian Archive Automatic Signing Key to the d... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-59 0.6.18 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-60 * Merge 0.5.22 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-61 * Convert apt-key(8) to docbook XML * apt@arch.ubuntu.com/apt--experimental--0.6--patch-62 Merge 0.5.23 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-63 Remove bogus partial 0.5.22 changelog entry * apt@arch.ubuntu.com/apt--experimental--0.6--patch-64 Make the auth warning a bit less redundant * apt@arch.ubuntu.com/apt--experimental--0.6--patch-65 * Merge 0.5.24 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-66 * Make the unauthenticated packages prompt more intuiti... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-67 Merge 0.5.25 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-68 * Remove obsolete pkgIterator::TargetVer() (Closes: #230159) * apt@arch.ubuntu.com/apt--experimental--0.6--patch-69 * Reverse test in CheckAuth to match new prompt (Closes... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-70 Update version * apt@arch.ubuntu.com/apt--experimental--0.6--patch-71 Fix backwards sense of CheckAuth prompt * apt@arch.ubuntu.com/apt--experimental--0.6--patch-72 0.6.24 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-73 Close bug * apt@arch.ubuntu.com/apt--experimental--0.6--patch-74 * Fix handling of two-part sources for sources.list deb... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-75 0.6.25 * apt@packages.debian.org/apt--authentication--0--base-0 tag of apt@arch.ubuntu.com/apt--experimental--0.6--patch-75 * apt@packages.debian.org/apt--authentication--0--patch-1 Michael Vogt's merge of apt--experimental--0 onto apt--main--0 * apt@packages.debian.org/apt--authentication--0--patch-2 Merge from apt--main--0 * apt@packages.debian.org/apt--authentication--0--patch-3 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-4 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-5 Update version number in configure.in * apt@packages.debian.org/apt--authentication--0--patch-6 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-7 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-8 Merge from mvo's branch * apt@packages.debian.org/apt--authentication--0--patch-9 Merge from mvo's tree * apt@packages.debian.org/apt--authentication--0--patch-10 Merge from mvo * apt@packages.debian.org/apt--authentication--0--patch-11 Fix permissions AGAIN * apt@packages.debian.org/apt--bzip2-debs--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-30 * apt@packages.debian.org/apt--bzip2-debs--0--patch-1 Create baz branch * apt@packages.debian.org/apt--bzip2-debs--0--patch-2 Implement data.tar.bz2 support * apt@packages.debian.org/apt--main--0--patch-30 Fix changelog * apt@packages.debian.org/apt--main--0--patch-31 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-32 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-33 Use baz instead of tla * apt@packages.debian.org/apt--main--0--patch-34 Merge bzip2-debs branch * apt@packages.debian.org/apt--main--0--patch-35 Fix changelog * apt@packages.debian.org/apt--main--0--patch-36 untagged-source precious * apt@packages.debian.org/apt--main--0--patch-37 Add .arch-inventory files * apt@packages.debian.org/apt--main--0--patch-38 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-39 Merge apt--authentication--0 * apt@packages.debian.org/apt--main--0--patch-40 Merge misc-abi-changes * apt@packages.debian.org/apt--main--0--patch-41 Merge from mvo * apt@packages.debian.org/apt--misc-abi-changes--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-16 * apt@packages.debian.org/apt--misc-abi-changes--0--patch-1 Fix apt-get -s remove to not display the candidate version * apt@packages.debian.org/apt--misc-abi-changes--0--patch-2 Merge from main * apt@packages.debian.org/apt--misc-abi-changes--0--patch-3 Use pid_t throughout to hold process IDs * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--base-0 tag of michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-12 * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--patch-1 * star-merged matt's changes (bz2 support for data-members in debs) * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--patch-2 * ignore errors when a Packages.bz2/Sources.bz2 can't be found and try with Packages.gz/Sources.gz again * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-34 * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-1 * merged matt's tree (with all those apt-authentication changes) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-2 don't display a error if a bzip2 package can not be downloaded, just ignore (Ign) it * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-3 * "chmod 755 cmdline/apt-key", changed version to 0.6.27ubuntu1 * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-4 * fix for a stupid merge error (from 0.5->0.6) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-5 * unstable should really be hoary * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-6 * stronger dependencies for libapt-pkg-dev (depends on the source version of apt and apt-watch now) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-7 * distro really should be hoary, not unstable :/ * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-8 * documented the "--allow-unauthenticated" switch * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-1 tag of apt@packages.debian.org/apt--authentication--0--base-0 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-2 merged "tla apply-delta -A foo@ apt@arch.ubuntu.com/apt--MAIN--0--patch-1190 apt@arch.ubuntu.com/apt--MAIN--0--patch-1343" and cleaned up conflicts * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-3 * missing bits from the merge added * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-4 * star-merged with apt@packages.debian.org/apt--main--0 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-5 * tree-synced to the apt--authentication tree * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-6 * use the ubuntu-key in this version * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-7 * imported the patches from mdz * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-8 * apt-get update --print-uris works now as before (fallback to 0.5.x behaviour) * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-9 * fix for the "if any source unauthenticated, all other sources are unauthenticated too" problem * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-10 * reworked the "--print-uris" patch. it no longer uses: "APT::Get::Print-URIs" in the library * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-11 * version of the library set to 3.6 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-12 * changelog finallized, will upload to people.ubuntulinux.org/~mvo/apt-authentication * michael.vogt@canonical.com--2004/apt--main-authentication--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-22 * michael.vogt@canonical.com--2004/apt--main-authentication--0--patch-1 * star-merge from apt--experimental--0.6 * michael.vogt@canonical.com--2004/apt--main-authentication--0--patch-2 * compile failure fix for methods/http.cc, po-file fixes
17 years ago
15 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: tagfile.cc,v 1.37.2.2 2003/12/31 16:02:30 mdz Exp $
  4. /* ######################################################################
  5. Fast scanner for RFC-822 type header information
  6. This uses a rotating buffer to load the package information into.
  7. The scanner runs over it and isolates and indexes a single section.
  8. ##################################################################### */
  9. /*}}}*/
  10. // Include Files /*{{{*/
  11. #include<config.h>
  12. #include <apt-pkg/tagfile.h>
  13. #include <apt-pkg/error.h>
  14. #include <apt-pkg/strutl.h>
  15. #include <apt-pkg/fileutl.h>
  16. #include <string>
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <apti18n.h>
  20. /*}}}*/
  21. using std::string;
  22. class pkgTagFilePrivate
  23. {
  24. public:
  25. pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Buffer(NULL),
  26. Start(NULL), End(NULL),
  27. Done(false), iOffset(0),
  28. Size(Size)
  29. {
  30. }
  31. FileFd &Fd;
  32. char *Buffer;
  33. char *Start;
  34. char *End;
  35. bool Done;
  36. unsigned long long iOffset;
  37. unsigned long long Size;
  38. };
  39. // TagFile::pkgTagFile - Constructor /*{{{*/
  40. // ---------------------------------------------------------------------
  41. /* */
  42. pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size)
  43. {
  44. /* The size is increased by 4 because if we start with the Size of the
  45. filename we need to try to read 1 char more to see an EOF faster, 1
  46. char the end-pointer can be on and maybe 2 newlines need to be added
  47. to the end of the file -> 4 extra chars */
  48. Size += 4;
  49. d = new pkgTagFilePrivate(pFd, Size);
  50. if (d->Fd.IsOpen() == false)
  51. d->Start = d->End = d->Buffer = 0;
  52. else
  53. d->Buffer = (char*)malloc(sizeof(char) * Size);
  54. if (d->Buffer == NULL)
  55. d->Done = true;
  56. else
  57. d->Done = false;
  58. d->Start = d->End = d->Buffer;
  59. d->iOffset = 0;
  60. if (d->Done == false)
  61. Fill();
  62. }
  63. /*}}}*/
  64. // TagFile::~pkgTagFile - Destructor /*{{{*/
  65. // ---------------------------------------------------------------------
  66. /* */
  67. pkgTagFile::~pkgTagFile()
  68. {
  69. free(d->Buffer);
  70. delete d;
  71. }
  72. /*}}}*/
  73. // TagFile::Offset - Return the current offset in the buffer /*{{{*/
  74. unsigned long pkgTagFile::Offset()
  75. {
  76. return d->iOffset;
  77. }
  78. /*}}}*/
  79. // TagFile::Resize - Resize the internal buffer /*{{{*/
  80. // ---------------------------------------------------------------------
  81. /* Resize the internal buffer (double it in size). Fail if a maximum size
  82. * size is reached.
  83. */
  84. bool pkgTagFile::Resize()
  85. {
  86. // fail is the buffer grows too big
  87. if(d->Size > 1024*1024+1)
  88. return false;
  89. return Resize(d->Size * 2);
  90. }
  91. bool pkgTagFile::Resize(unsigned long long const newSize)
  92. {
  93. unsigned long long const EndSize = d->End - d->Start;
  94. // get new buffer and use it
  95. char* newBuffer = (char*)realloc(d->Buffer, sizeof(char) * newSize);
  96. if (newBuffer == NULL)
  97. return false;
  98. d->Buffer = newBuffer;
  99. d->Size = newSize;
  100. // update the start/end pointers to the new buffer
  101. d->Start = d->Buffer;
  102. d->End = d->Start + EndSize;
  103. return true;
  104. }
  105. /*}}}*/
  106. // TagFile::Step - Advance to the next section /*{{{*/
  107. // ---------------------------------------------------------------------
  108. /* If the Section Scanner fails we refill the buffer and try again.
  109. * If that fails too, double the buffer size and try again until a
  110. * maximum buffer is reached.
  111. */
  112. bool pkgTagFile::Step(pkgTagSection &Tag)
  113. {
  114. while (Tag.Scan(d->Start,d->End - d->Start) == false)
  115. {
  116. if (Fill() == false)
  117. return false;
  118. if(Tag.Scan(d->Start,d->End - d->Start))
  119. break;
  120. if (Resize() == false)
  121. return _error->Error(_("Unable to parse package file %s (1)"),
  122. d->Fd.Name().c_str());
  123. }
  124. d->Start += Tag.size();
  125. d->iOffset += Tag.size();
  126. Tag.Trim();
  127. return true;
  128. }
  129. /*}}}*/
  130. // TagFile::Fill - Top up the buffer /*{{{*/
  131. // ---------------------------------------------------------------------
  132. /* This takes the bit at the end of the buffer and puts it at the start
  133. then fills the rest from the file */
  134. bool pkgTagFile::Fill()
  135. {
  136. unsigned long long EndSize = d->End - d->Start;
  137. unsigned long long Actual = 0;
  138. memmove(d->Buffer,d->Start,EndSize);
  139. d->Start = d->Buffer;
  140. d->End = d->Buffer + EndSize;
  141. if (d->Done == false)
  142. {
  143. // See if only a bit of the file is left
  144. unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1);
  145. if (d->Fd.Read(d->End, dataSize, &Actual) == false)
  146. return false;
  147. if (Actual != dataSize)
  148. d->Done = true;
  149. d->End += Actual;
  150. }
  151. if (d->Done == true)
  152. {
  153. if (EndSize <= 3 && Actual == 0)
  154. return false;
  155. if (d->Size - (d->End - d->Buffer) < 4)
  156. return true;
  157. // Append a double new line if one does not exist
  158. unsigned int LineCount = 0;
  159. for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--)
  160. if (*E == '\n')
  161. LineCount++;
  162. if (LineCount < 2)
  163. {
  164. if ((unsigned)(d->End - d->Buffer) >= d->Size)
  165. Resize(d->Size + 3);
  166. for (; LineCount < 2; LineCount++)
  167. *d->End++ = '\n';
  168. }
  169. return true;
  170. }
  171. return true;
  172. }
  173. /*}}}*/
  174. // TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/
  175. // ---------------------------------------------------------------------
  176. /* This jumps to a pre-recorded file location and reads the record
  177. that is there */
  178. bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
  179. {
  180. // We are within a buffer space of the next hit..
  181. if (Offset >= d->iOffset && d->iOffset + (d->End - d->Start) > Offset)
  182. {
  183. unsigned long long Dist = Offset - d->iOffset;
  184. d->Start += Dist;
  185. d->iOffset += Dist;
  186. return Step(Tag);
  187. }
  188. // Reposition and reload..
  189. d->iOffset = Offset;
  190. d->Done = false;
  191. if (d->Fd.Seek(Offset) == false)
  192. return false;
  193. d->End = d->Start = d->Buffer;
  194. if (Fill() == false)
  195. return false;
  196. if (Tag.Scan(d->Start, d->End - d->Start) == true)
  197. return true;
  198. // This appends a double new line (for the real eof handling)
  199. if (Fill() == false)
  200. return false;
  201. if (Tag.Scan(d->Start, d->End - d->Start) == false)
  202. return _error->Error(_("Unable to parse package file %s (2)"),d->Fd.Name().c_str());
  203. return true;
  204. }
  205. /*}}}*/
  206. // pkgTagSection::pkgTagSection - Constructor /*{{{*/
  207. // ---------------------------------------------------------------------
  208. /* */
  209. pkgTagSection::pkgTagSection()
  210. : Section(0), TagCount(0), d(NULL), Stop(0)
  211. {
  212. memset(&Indexes, 0, sizeof(Indexes));
  213. memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
  214. }
  215. /*}}}*/
  216. // TagSection::Scan - Scan for the end of the header information /*{{{*/
  217. // ---------------------------------------------------------------------
  218. /* This looks for the first double new line in the data stream.
  219. It also indexes the tags in the section. */
  220. bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
  221. {
  222. const char *End = Start + MaxLength;
  223. Stop = Section = Start;
  224. memset(AlphaIndexes,0,sizeof(AlphaIndexes));
  225. if (Stop == 0)
  226. return false;
  227. TagCount = 0;
  228. while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
  229. {
  230. TrimRecord(true,End);
  231. // this can happen when TrimRecord trims away the entire Record
  232. // (e.g. because it just contains comments)
  233. if(Stop == End)
  234. return true;
  235. // Start a new index and add it to the hash
  236. if (isspace(Stop[0]) == 0)
  237. {
  238. Indexes[TagCount++] = Stop - Section;
  239. AlphaIndexes[AlphaHash(Stop,End)] = TagCount;
  240. }
  241. Stop = (const char *)memchr(Stop,'\n',End - Stop);
  242. if (Stop == 0)
  243. return false;
  244. for (; Stop+1 < End && Stop[1] == '\r'; Stop++)
  245. /* nothing */
  246. ;
  247. // Double newline marks the end of the record
  248. if (Stop+1 < End && Stop[1] == '\n')
  249. {
  250. Indexes[TagCount] = Stop - Section;
  251. TrimRecord(false,End);
  252. return true;
  253. }
  254. Stop++;
  255. }
  256. return false;
  257. }
  258. /*}}}*/
  259. // TagSection::TrimRecord - Trim off any garbage before/after a record /*{{{*/
  260. // ---------------------------------------------------------------------
  261. /* There should be exactly 2 newline at the end of the record, no more. */
  262. void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End)
  263. {
  264. if (BeforeRecord == true)
  265. return;
  266. for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++);
  267. }
  268. /*}}}*/
  269. // TagSection::Trim - Trim off any trailing garbage /*{{{*/
  270. // ---------------------------------------------------------------------
  271. /* There should be exactly 1 newline at the end of the buffer, no more. */
  272. void pkgTagSection::Trim()
  273. {
  274. for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--);
  275. }
  276. /*}}}*/
  277. // TagSection::Exists - return True if a tag exists /*{{{*/
  278. bool pkgTagSection::Exists(const char* const Tag)
  279. {
  280. unsigned int tmp;
  281. return Find(Tag, tmp);
  282. }
  283. /*}}}*/
  284. // TagSection::Find - Locate a tag /*{{{*/
  285. // ---------------------------------------------------------------------
  286. /* This searches the section for a tag that matches the given string. */
  287. bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
  288. {
  289. unsigned int Length = strlen(Tag);
  290. unsigned int I = AlphaIndexes[AlphaHash(Tag)];
  291. if (I == 0)
  292. return false;
  293. I--;
  294. for (unsigned int Counter = 0; Counter != TagCount; Counter++,
  295. I = (I+1)%TagCount)
  296. {
  297. const char *St;
  298. St = Section + Indexes[I];
  299. if (strncasecmp(Tag,St,Length) != 0)
  300. continue;
  301. // Make sure the colon is in the right place
  302. const char *C = St + Length;
  303. for (; isspace(*C) != 0; C++);
  304. if (*C != ':')
  305. continue;
  306. Pos = I;
  307. return true;
  308. }
  309. Pos = 0;
  310. return false;
  311. }
  312. /*}}}*/
  313. // TagSection::Find - Locate a tag /*{{{*/
  314. // ---------------------------------------------------------------------
  315. /* This searches the section for a tag that matches the given string. */
  316. bool pkgTagSection::Find(const char *Tag,const char *&Start,
  317. const char *&End) const
  318. {
  319. unsigned int Length = strlen(Tag);
  320. unsigned int I = AlphaIndexes[AlphaHash(Tag)];
  321. if (I == 0)
  322. return false;
  323. I--;
  324. for (unsigned int Counter = 0; Counter != TagCount; Counter++,
  325. I = (I+1)%TagCount)
  326. {
  327. const char *St;
  328. St = Section + Indexes[I];
  329. if (strncasecmp(Tag,St,Length) != 0)
  330. continue;
  331. // Make sure the colon is in the right place
  332. const char *C = St + Length;
  333. for (; isspace(*C) != 0; C++);
  334. if (*C != ':')
  335. continue;
  336. // Strip off the gunk from the start end
  337. Start = C;
  338. End = Section + Indexes[I+1];
  339. if (Start >= End)
  340. return _error->Error("Internal parsing error");
  341. for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
  342. for (; isspace(End[-1]) != 0 && End > Start; End--);
  343. return true;
  344. }
  345. Start = End = 0;
  346. return false;
  347. }
  348. /*}}}*/
  349. // TagSection::FindS - Find a string /*{{{*/
  350. // ---------------------------------------------------------------------
  351. /* */
  352. string pkgTagSection::FindS(const char *Tag) const
  353. {
  354. const char *Start;
  355. const char *End;
  356. if (Find(Tag,Start,End) == false)
  357. return string();
  358. return string(Start,End);
  359. }
  360. /*}}}*/
  361. // TagSection::FindI - Find an integer /*{{{*/
  362. // ---------------------------------------------------------------------
  363. /* */
  364. signed int pkgTagSection::FindI(const char *Tag,signed long Default) const
  365. {
  366. const char *Start;
  367. const char *Stop;
  368. if (Find(Tag,Start,Stop) == false)
  369. return Default;
  370. // Copy it into a temp buffer so we can use strtol
  371. char S[300];
  372. if ((unsigned)(Stop - Start) >= sizeof(S))
  373. return Default;
  374. strncpy(S,Start,Stop-Start);
  375. S[Stop - Start] = 0;
  376. char *End;
  377. signed long Result = strtol(S,&End,10);
  378. if (S == End)
  379. return Default;
  380. return Result;
  381. }
  382. /*}}}*/
  383. // TagSection::FindULL - Find an unsigned long long integer /*{{{*/
  384. // ---------------------------------------------------------------------
  385. /* */
  386. unsigned long long pkgTagSection::FindULL(const char *Tag, unsigned long long const &Default) const
  387. {
  388. const char *Start;
  389. const char *Stop;
  390. if (Find(Tag,Start,Stop) == false)
  391. return Default;
  392. // Copy it into a temp buffer so we can use strtoull
  393. char S[100];
  394. if ((unsigned)(Stop - Start) >= sizeof(S))
  395. return Default;
  396. strncpy(S,Start,Stop-Start);
  397. S[Stop - Start] = 0;
  398. char *End;
  399. unsigned long long Result = strtoull(S,&End,10);
  400. if (S == End)
  401. return Default;
  402. return Result;
  403. }
  404. /*}}}*/
  405. // TagSection::FindFlag - Locate a yes/no type flag /*{{{*/
  406. // ---------------------------------------------------------------------
  407. /* The bits marked in Flag are masked on/off in Flags */
  408. bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
  409. unsigned long Flag) const
  410. {
  411. const char *Start;
  412. const char *Stop;
  413. if (Find(Tag,Start,Stop) == false)
  414. return true;
  415. return FindFlag(Flags, Flag, Start, Stop);
  416. }
  417. bool const pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
  418. char const* Start, char const* Stop)
  419. {
  420. switch (StringToBool(string(Start, Stop)))
  421. {
  422. case 0:
  423. Flags &= ~Flag;
  424. return true;
  425. case 1:
  426. Flags |= Flag;
  427. return true;
  428. default:
  429. _error->Warning("Unknown flag value: %s",string(Start,Stop).c_str());
  430. return true;
  431. }
  432. return true;
  433. }
  434. /*}}}*/
  435. // TFRewrite - Rewrite a control record /*{{{*/
  436. // ---------------------------------------------------------------------
  437. /* This writes the control record to stdout rewriting it as necessary. The
  438. override map item specificies the rewriting rules to follow. This also
  439. takes the time to sort the feild list. */
  440. /* The order of this list is taken from dpkg source lib/parse.c the fieldinfos
  441. array. */
  442. static const char *iTFRewritePackageOrder[] = {
  443. "Package",
  444. "Essential",
  445. "Status",
  446. "Priority",
  447. "Section",
  448. "Installed-Size",
  449. "Maintainer",
  450. "Original-Maintainer",
  451. "Architecture",
  452. "Source",
  453. "Version",
  454. "Revision", // Obsolete
  455. "Config-Version", // Obsolete
  456. "Replaces",
  457. "Provides",
  458. "Depends",
  459. "Pre-Depends",
  460. "Recommends",
  461. "Suggests",
  462. "Conflicts",
  463. "Breaks",
  464. "Conffiles",
  465. "Filename",
  466. "Size",
  467. "MD5Sum",
  468. "SHA1",
  469. "SHA256",
  470. "SHA512",
  471. "MSDOS-Filename", // Obsolete
  472. "Description",
  473. 0};
  474. static const char *iTFRewriteSourceOrder[] = {"Package",
  475. "Source",
  476. "Binary",
  477. "Version",
  478. "Priority",
  479. "Section",
  480. "Maintainer",
  481. "Original-Maintainer",
  482. "Build-Depends",
  483. "Build-Depends-Indep",
  484. "Build-Conflicts",
  485. "Build-Conflicts-Indep",
  486. "Architecture",
  487. "Standards-Version",
  488. "Format",
  489. "Directory",
  490. "Files",
  491. 0};
  492. /* Two levels of initialization are used because gcc will set the symbol
  493. size of an array to the length of the array, causing dynamic relinking
  494. errors. Doing this makes the symbol size constant */
  495. const char **TFRewritePackageOrder = iTFRewritePackageOrder;
  496. const char **TFRewriteSourceOrder = iTFRewriteSourceOrder;
  497. bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
  498. TFRewriteData *Rewrite)
  499. {
  500. unsigned char Visited[256]; // Bit 1 is Order, Bit 2 is Rewrite
  501. for (unsigned I = 0; I != 256; I++)
  502. Visited[I] = 0;
  503. // Set new tag up as necessary.
  504. for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
  505. {
  506. if (Rewrite[J].NewTag == 0)
  507. Rewrite[J].NewTag = Rewrite[J].Tag;
  508. }
  509. // Write all all of the tags, in order.
  510. for (unsigned int I = 0; Order[I] != 0; I++)
  511. {
  512. bool Rewritten = false;
  513. // See if this is a field that needs to be rewritten
  514. for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
  515. {
  516. if (strcasecmp(Rewrite[J].Tag,Order[I]) == 0)
  517. {
  518. Visited[J] |= 2;
  519. if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0)
  520. {
  521. if (isspace(Rewrite[J].Rewrite[0]))
  522. fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  523. else
  524. fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  525. }
  526. Rewritten = true;
  527. break;
  528. }
  529. }
  530. // See if it is in the fragment
  531. unsigned Pos;
  532. if (Tags.Find(Order[I],Pos) == false)
  533. continue;
  534. Visited[Pos] |= 1;
  535. if (Rewritten == true)
  536. continue;
  537. /* Write out this element, taking a moment to rewrite the tag
  538. in case of changes of case. */
  539. const char *Start;
  540. const char *Stop;
  541. Tags.Get(Start,Stop,Pos);
  542. if (fputs(Order[I],Output) < 0)
  543. return _error->Errno("fputs","IO Error to output");
  544. Start += strlen(Order[I]);
  545. if (fwrite(Start,Stop - Start,1,Output) != 1)
  546. return _error->Errno("fwrite","IO Error to output");
  547. if (Stop[-1] != '\n')
  548. fprintf(Output,"\n");
  549. }
  550. // Now write all the old tags that were missed.
  551. for (unsigned int I = 0; I != Tags.Count(); I++)
  552. {
  553. if ((Visited[I] & 1) == 1)
  554. continue;
  555. const char *Start;
  556. const char *Stop;
  557. Tags.Get(Start,Stop,I);
  558. const char *End = Start;
  559. for (; End < Stop && *End != ':'; End++);
  560. // See if this is a field that needs to be rewritten
  561. bool Rewritten = false;
  562. for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
  563. {
  564. if (stringcasecmp(Start,End,Rewrite[J].Tag) == 0)
  565. {
  566. Visited[J] |= 2;
  567. if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0)
  568. {
  569. if (isspace(Rewrite[J].Rewrite[0]))
  570. fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  571. else
  572. fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  573. }
  574. Rewritten = true;
  575. break;
  576. }
  577. }
  578. if (Rewritten == true)
  579. continue;
  580. // Write out this element
  581. if (fwrite(Start,Stop - Start,1,Output) != 1)
  582. return _error->Errno("fwrite","IO Error to output");
  583. if (Stop[-1] != '\n')
  584. fprintf(Output,"\n");
  585. }
  586. // Now write all the rewrites that were missed
  587. for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
  588. {
  589. if ((Visited[J] & 2) == 2)
  590. continue;
  591. if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0)
  592. {
  593. if (isspace(Rewrite[J].Rewrite[0]))
  594. fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  595. else
  596. fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
  597. }
  598. }
  599. return true;
  600. }
  601. /*}}}*/