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.

store.cc 4.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. /* ######################################################################
  4. Store method - Takes a file URI and stores its content (for which it will
  5. calculate the hashes) in the given destination. The input file will be
  6. extracted based on its file extension (or with the given compressor if
  7. called with one of the compatible symlinks) and potentially recompressed
  8. based on the file extension of the destination filename.
  9. ##################################################################### */
  10. /*}}}*/
  11. // Include Files /*{{{*/
  12. #include <config.h>
  13. #include "aptmethod.h"
  14. #include <apt-pkg/aptconfiguration.h>
  15. #include <apt-pkg/configuration.h>
  16. #include <apt-pkg/error.h>
  17. #include <apt-pkg/fileutl.h>
  18. #include <apt-pkg/hashes.h>
  19. #include <apt-pkg/strutl.h>
  20. #include <string>
  21. #include <vector>
  22. #include <string.h>
  23. #include <sys/stat.h>
  24. #include <sys/time.h>
  25. #include <apti18n.h>
  26. /*}}}*/
  27. class StoreMethod : public aptMethod
  28. {
  29. virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
  30. public:
  31. explicit StoreMethod(std::string &&pProg) : aptMethod(std::move(pProg),"1.2",SingleInstance | SendConfig)
  32. {
  33. SeccompFlags = aptMethod::BASE;
  34. if (Binary != "store")
  35. methodNames.insert(methodNames.begin(), "store");
  36. }
  37. };
  38. static bool OpenFileWithCompressorByName(FileFd &fileFd, std::string const &Filename, unsigned int const Mode, std::string const &Name)
  39. {
  40. if (Name == "store")
  41. return fileFd.Open(Filename, Mode, FileFd::Extension);
  42. std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
  43. std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
  44. for (; compressor != compressors.end(); ++compressor)
  45. if (compressor->Name == Name)
  46. break;
  47. if (compressor == compressors.end())
  48. return _error->Error("Extraction of file %s requires unknown compressor %s", Filename.c_str(), Name.c_str());
  49. return fileFd.Open(Filename, Mode, *compressor);
  50. }
  51. /*}}}*/
  52. bool StoreMethod::Fetch(FetchItem *Itm) /*{{{*/
  53. {
  54. URI Get = Itm->Uri;
  55. std::string Path = Get.Host + Get.Path; // To account for relative paths
  56. FetchResult Res;
  57. Res.Filename = Itm->DestFile;
  58. URIStart(Res);
  59. // Open the source and destination files
  60. FileFd From;
  61. if (_config->FindB("Method::Compress", false) == false)
  62. {
  63. if (OpenFileWithCompressorByName(From, Path, FileFd::ReadOnly, Binary) == false)
  64. return false;
  65. if(From.IsCompressed() && From.FileSize() == 0)
  66. return _error->Error(_("Empty files can't be valid archives"));
  67. }
  68. else
  69. From.Open(Path, FileFd::ReadOnly, FileFd::Extension);
  70. if (From.IsOpen() == false || From.Failed() == true)
  71. return false;
  72. FileFd To;
  73. if (Itm->DestFile != "/dev/null" && Itm->DestFile != Path)
  74. {
  75. if (_config->FindB("Method::Compress", false) == false)
  76. To.Open(Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Atomic, FileFd::Extension);
  77. else if (OpenFileWithCompressorByName(To, Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Empty, Binary) == false)
  78. return false;
  79. if (To.IsOpen() == false || To.Failed() == true)
  80. return false;
  81. To.EraseOnFailure();
  82. }
  83. // Read data from source, generate checksums and write
  84. Hashes Hash(Itm->ExpectedHashes);
  85. bool Failed = false;
  86. Res.Size = 0;
  87. while (1)
  88. {
  89. unsigned char Buffer[4*1024];
  90. unsigned long long Count = 0;
  91. if (!From.Read(Buffer,sizeof(Buffer),&Count))
  92. {
  93. if (To.IsOpen())
  94. To.OpFail();
  95. return false;
  96. }
  97. if (Count == 0)
  98. break;
  99. Res.Size += Count;
  100. Hash.Add(Buffer,Count);
  101. if (To.IsOpen() && To.Write(Buffer,Count) == false)
  102. {
  103. Failed = true;
  104. break;
  105. }
  106. }
  107. From.Close();
  108. To.Close();
  109. if (Failed == true)
  110. return false;
  111. if (TransferModificationTimes(Path.c_str(), Itm->DestFile.c_str(), Res.LastModified) == false)
  112. return false;
  113. // Return a Done response
  114. Res.TakeHashes(Hash);
  115. URIDone(Res);
  116. return true;
  117. }
  118. /*}}}*/
  119. int main(int, char *argv[])
  120. {
  121. return StoreMethod(flNotDir(argv[0])).Run();
  122. }