arfile.cc 4.3 KB

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