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