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.
 
 
 
 
 
 

161 lines
4.3 KiB

  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. /* ######################################################################
  4. AR File - Handle an 'AR' archive
  5. AR Archives have plain text headers at the start of each file
  6. section. The headers are aligned on a 2 byte boundary.
  7. Information about the structure of AR files can be found in ar(5)
  8. on a BSD system, or in the binutils source.
  9. ##################################################################### */
  10. /*}}}*/
  11. // Include Files /*{{{*/
  12. #include <config.h>
  13. #include <apt-pkg/arfile.h>
  14. #include <apt-pkg/error.h>
  15. #include <apt-pkg/fileutl.h>
  16. #include <apt-pkg/strutl.h>
  17. #include <string>
  18. #include <string.h>
  19. #include <sys/types.h>
  20. #include <apti18n.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. off_t 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 %s"), Head.Name);
  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 >= sizeof(S))
  92. {
  93. delete Memb;
  94. return _error->Error(_("Invalid archive member header"));
  95. }
  96. if (File.Read(S,Len) == false)
  97. {
  98. delete Memb;
  99. return false;
  100. }
  101. S[Len] = 0;
  102. Memb->Name = S;
  103. Memb->Size -= Len;
  104. Left -= Len;
  105. }
  106. else
  107. {
  108. unsigned int I = sizeof(Head.Name) - 1;
  109. for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--);
  110. Memb->Name = std::string(Head.Name,I+1);
  111. }
  112. // Account for the AR header alignment
  113. off_t Skip = Memb->Size % 2;
  114. // Add it to the list
  115. Memb->Next = List;
  116. List = Memb;
  117. Memb->Start = File.Tell();
  118. if (File.Skip(Memb->Size + Skip) == false)
  119. return false;
  120. if (Left < (off_t)(Memb->Size + Skip))
  121. return _error->Error(_("Archive is too short"));
  122. Left -= Memb->Size + Skip;
  123. }
  124. if (Left != 0)
  125. return _error->Error(_("Failed to read the archive headers"));
  126. return true;
  127. }
  128. /*}}}*/
  129. // ARArchive::FindMember - Find a name in the member list /*{{{*/
  130. // ---------------------------------------------------------------------
  131. /* Find a member with the given name */
  132. const ARArchive::Member *ARArchive::FindMember(const char *Name) const
  133. {
  134. const Member *Res = List;
  135. while (Res != 0)
  136. {
  137. if (Res->Name == Name)
  138. return Res;
  139. Res = Res->Next;
  140. }
  141. return 0;
  142. }
  143. /*}}}*/