arfile.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: arfile.cc,v 1.5 2003/02/10 00:36:12 doogie Exp $
  4. /* ######################################################################
  5. AR File - Handle an 'AR' archive
  6. AR Archives have plain text headers at the start of each file
  7. section. The headers are aligned on a 2 byte boundry.
  8. Information about the structure of AR files can be found in ar(5)
  9. on a BSD system, or in the binutils source.
  10. ##################################################################### */
  11. /*}}}*/
  12. // Include Files /*{{{*/
  13. #ifdef __GNUG__
  14. #pragma implementation "apt-pkg/arfile.h"
  15. #endif
  16. #include <apti18n.h>
  17. #include <apt-pkg/arfile.h>
  18. #include <apt-pkg/strutl.h>
  19. #include <apt-pkg/error.h>
  20. #include <stdlib.h>
  21. /*}}}*/
  22. struct ARArchive::MemberHeader
  23. {
  24. char Name[16];
  25. char MTime[12];
  26. char UID[6];
  27. char GID[6];
  28. char Mode[8];
  29. char Size[10];
  30. char Magic[2];
  31. };
  32. // ARArchive::ARArchive - Constructor /*{{{*/
  33. // ---------------------------------------------------------------------
  34. /* */
  35. ARArchive::ARArchive(FileFd &File) : List(0), File(File)
  36. {
  37. LoadHeaders();
  38. }
  39. /*}}}*/
  40. // ARArchive::~ARArchive - Destructor /*{{{*/
  41. // ---------------------------------------------------------------------
  42. /* */
  43. ARArchive::~ARArchive()
  44. {
  45. while (List != 0)
  46. {
  47. Member *Tmp = List;
  48. List = List->Next;
  49. delete Tmp;
  50. }
  51. }
  52. /*}}}*/
  53. // ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
  54. // ---------------------------------------------------------------------
  55. /* AR files are structured with a 8 byte magic string followed by a 60
  56. byte plain text header then the file data, another header, data, etc */
  57. bool ARArchive::LoadHeaders()
  58. {
  59. signed long Left = File.Size();
  60. // Check the magic byte
  61. char Magic[8];
  62. if (File.Read(Magic,sizeof(Magic)) == false)
  63. return false;
  64. if (memcmp(Magic,"!<arch>\012",sizeof(Magic)) != 0)
  65. return _error->Error(_("Invalid archive signature"));
  66. Left -= sizeof(Magic);
  67. // Read the member list
  68. while (Left > 0)
  69. {
  70. MemberHeader Head;
  71. if (File.Read(&Head,sizeof(Head)) == false)
  72. return _error->Error(_("Error reading archive member header"));
  73. Left -= sizeof(Head);
  74. // Convert all of the integer members
  75. Member *Memb = new Member();
  76. if (StrToNum(Head.MTime,Memb->MTime,sizeof(Head.MTime)) == false ||
  77. StrToNum(Head.UID,Memb->UID,sizeof(Head.UID)) == false ||
  78. StrToNum(Head.GID,Memb->GID,sizeof(Head.GID)) == false ||
  79. StrToNum(Head.Mode,Memb->Mode,sizeof(Head.Mode),8) == false ||
  80. StrToNum(Head.Size,Memb->Size,sizeof(Head.Size)) == false)
  81. {
  82. delete Memb;
  83. return _error->Error(_("Invalid archive member header"));
  84. }
  85. // Check for an extra long name string
  86. if (memcmp(Head.Name,"#1/",3) == 0)
  87. {
  88. char S[300];
  89. unsigned long Len;
  90. if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
  91. Len >= strlen(S))
  92. {
  93. delete Memb;
  94. return _error->Error(_("Invalid archive member header"));
  95. }
  96. if (File.Read(S,Len) == false)
  97. return false;
  98. S[Len] = 0;
  99. Memb->Name = S;
  100. Memb->Size -= Len;
  101. Left -= Len;
  102. }
  103. else
  104. {
  105. unsigned int I = sizeof(Head.Name) - 1;
  106. for (; Head.Name[I] == ' '; I--);
  107. Memb->Name = string(Head.Name,0,I+1);
  108. }
  109. // Account for the AR header alignment
  110. unsigned Skip = Memb->Size % 2;
  111. // Add it to the list
  112. Memb->Next = List;
  113. List = Memb;
  114. Memb->Start = File.Tell();
  115. if (File.Skip(Memb->Size + Skip) == false)
  116. return false;
  117. if (Left < (signed)(Memb->Size + Skip))
  118. return _error->Error(_("Archive is too short"));
  119. Left -= Memb->Size + Skip;
  120. }
  121. if (Left != 0)
  122. return _error->Error(_("Failed to read the archive headers"));
  123. return true;
  124. }
  125. /*}}}*/
  126. // ARArchive::FindMember - Find a name in the member list /*{{{*/
  127. // ---------------------------------------------------------------------
  128. /* Find a member with the given name */
  129. const ARArchive::Member *ARArchive::FindMember(const char *Name) const
  130. {
  131. const Member *Res = List;
  132. while (Res != 0)
  133. {
  134. if (Res->Name == Name)
  135. return Res;
  136. Res = Res->Next;
  137. }
  138. return 0;
  139. }
  140. /*}}}*/