File: copy.cc

package info (click to toggle)
apt 3.1.12
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,736 kB
  • sloc: cpp: 71,048; sh: 31,750; xml: 5,553; perl: 217; python: 197; ansic: 191; makefile: 41
file content (110 lines) | stat: -rw-r--r-- 3,011 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// -*- mode: cpp; mode: fold -*-
// Description								/*{{{*/
/* ######################################################################

   Copy URI - This method takes a uri like a file: uri and copies it
   to the destination file.
   
   ##################################################################### */
									/*}}}*/
// Include Files							/*{{{*/
#include <config.h>

#include "aptmethod.h"
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/strutl.h>

#include <string>
#include <sys/stat.h>
#include <sys/time.h>

#include <apti18n.h>
									/*}}}*/

class CopyMethod final : public aptMethod
{
   bool URIAcquire(std::string const &Message, FetchItem *Itm) override;

   public:
   CopyMethod() : aptMethod("copy", "1.0", SingleInstance | SendConfig | SendURIEncoded)
   {
      SeccompFlags = aptMethod::BASE;
   }
};

// CopyMethod::Fetch - Fetch a file					/*{{{*/
bool CopyMethod::URIAcquire(std::string const &Message, FetchItem *Itm)
{
   struct FileCopyType {
      std::string name;
      struct stat stat{};
      explicit FileCopyType(std::string &&file) noexcept : name{std::move(file)} {}
   };
   std::vector<FileCopyType> files;
   // this ensures that relative paths work
   files.emplace_back(DecodeSendURI(Itm->Uri.substr(Itm->Uri.find(':')+1)));
   for (auto const &AltPath : VectorizeString(LookupTag(Message, "Alternate-Paths"), '\n'))
      files.emplace_back(CombineWithAlternatePath(flNotFile(files[0].name), DecodeSendURI(AltPath)));
   files.erase(std::remove_if(files.begin(), files.end(), [](auto &file)
			      { return stat(file.name.c_str(), &file.stat) != 0; }),
	       files.end());
   if (files.empty())
      return _error->Errno("copy-stat", _("Failed to stat"));

   // Forumulate a result and send a start message
   FetchResult Res;
   Res.Filename = Itm->DestFile;
   Res.IMSHit = false;

   for (auto const &File : files)
   {
      Res.Size = File.stat.st_size;
      Res.LastModified = File.stat.st_mtime;

      // just calc the hashes if the source and destination are identical
      if (Itm->DestFile == "/dev/null" || File.name == Itm->DestFile)
      {
	 URIStart(Res);
	 CalculateHashes(Itm, Res);
	 URIDone(Res);
	 return true;
      }

      FileFd From(File.name, FileFd::ReadOnly);
      FileFd To(Itm->DestFile, FileFd::WriteAtomic);
      To.EraseOnFailure();
      if (not From.IsOpen() || not To.IsOpen())
	 continue;

      // Copy the file
      URIStart(Res);
      if (not CopyFile(From, To))
      {
	 To.OpFail();
	 continue;
      }
      From.Close();
      To.Close();

      CalculateHashes(Itm, Res);
      if (not Itm->ExpectedHashes.empty() && Itm->ExpectedHashes != Res.Hashes)
	 continue;

      if (not TransferModificationTimes(File.name.c_str(), Res.Filename.c_str(), Res.LastModified))
	 continue;

      URIDone(Res);
      return true;
   }

   return false;
}
									/*}}}*/

int main()
{
   return CopyMethod().Run();
}