arfile.cc 4.3 KB

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