arfile.cc 4.2 KB

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