]> git.saurik.com Git - apt.git/blame - methods/store.cc
Add apt-pkg/tagfile-keys.cc to the gitignore file
[apt.git] / methods / store.cc
CommitLineData
92173b19
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
92173b19
AL
3/* ######################################################################
4
9bd2313a
DK
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
92173b19
AL
11 ##################################################################### */
12 /*}}}*/
13// Include Files /*{{{*/
ea542140
DK
14#include <config.h>
15
0ec6b98b 16#include <apt-pkg/configuration.h>
453b82a3
DK
17#include <apt-pkg/error.h>
18#include <apt-pkg/fileutl.h>
63b1700f 19#include <apt-pkg/hashes.h>
453b82a3
DK
20#include <apt-pkg/strutl.h>
21#include <apt-pkg/aptconfiguration.h>
23e64f6d 22#include "aptmethod.h"
92173b19 23
453b82a3 24#include <string.h>
92173b19 25#include <sys/stat.h>
246bbb61 26#include <sys/time.h>
453b82a3
DK
27#include <string>
28#include <vector>
29
d77559ac 30#include <apti18n.h>
92173b19
AL
31 /*}}}*/
32
9bd2313a 33class StoreMethod : public aptMethod
92173b19 34{
3b302846 35 virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
9983999d 36
23e64f6d 37 public:
9983999d 38
30060442
DK
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 }
23e64f6d 44};
63b1700f 45
9bd2313a 46static bool OpenFileWithCompressorByName(FileFd &fileFd, std::string const &Filename, unsigned int const Mode, std::string const &Name)
92173b19 47{
9bd2313a
DK
48 if (Name == "store")
49 return fileFd.Open(Filename, Mode, FileFd::Extension);
d6bbcaad
DK
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)
9bd2313a 54 if (compressor->Name == Name)
d6bbcaad
DK
55 break;
56 if (compressor == compressors.end())
9bd2313a
DK
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 /*}}}*/
63bool 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);
d6bbcaad 71
63b1700f 72 // Open the source and destination files
af9e40c9 73 FileFd From;
0ec6b98b
DK
74 if (_config->FindB("Method::Compress", false) == false)
75 {
30060442 76 if (OpenFileWithCompressorByName(From, Path, FileFd::ReadOnly, Binary) == false)
9bd2313a 77 return false;
479f6fa4 78 if(From.IsCompressed() && From.FileSize() == 0)
0ec6b98b 79 return _error->Error(_("Empty files can't be valid archives"));
0ec6b98b
DK
80 }
81 else
9bd2313a 82 From.Open(Path, FileFd::ReadOnly, FileFd::Extension);
af9e40c9
DK
83 if (From.IsOpen() == false || From.Failed() == true)
84 return false;
85
86 FileFd To;
9bd2313a 87 if (Itm->DestFile != "/dev/null" && Itm->DestFile != Path)
af9e40c9
DK
88 {
89 if (_config->FindB("Method::Compress", false) == false)
9bd2313a 90 To.Open(Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Atomic, FileFd::Extension);
30060442 91 else if (OpenFileWithCompressorByName(To, Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Empty, Binary) == false)
9bd2313a 92 return false;
af9e40c9
DK
93
94 if (To.IsOpen() == false || To.Failed() == true)
95 return false;
96 To.EraseOnFailure();
0ec6b98b 97 }
0ec6b98b 98
127e6df3 99 // Read data from source, generate checksums and write
9224ce3d 100 Hashes Hash(Itm->ExpectedHashes);
63b1700f 101 bool Failed = false;
af9e40c9 102 Res.Size = 0;
9bd2313a 103 while (1)
63b1700f
AL
104 {
105 unsigned char Buffer[4*1024];
650faab0 106 unsigned long long Count = 0;
9bd2313a 107
127e6df3 108 if (!From.Read(Buffer,sizeof(Buffer),&Count))
63b1700f 109 {
af9e40c9
DK
110 if (To.IsOpen())
111 To.OpFail();
127e6df3 112 return false;
63b1700f 113 }
63b1700f
AL
114 if (Count == 0)
115 break;
af9e40c9 116 Res.Size += Count;
127e6df3 117
63b1700f 118 Hash.Add(Buffer,Count);
af9e40c9 119 if (To.IsOpen() && To.Write(Buffer,Count) == false)
2204bd80 120 {
678bc33e
AL
121 Failed = true;
122 break;
9bd2313a 123 }
63b1700f 124 }
9bd2313a 125
127e6df3 126 From.Close();
246bbb61 127 To.Close();
9ce3cfc9 128
63b1700f
AL
129 if (Failed == true)
130 return false;
9ce3cfc9 131
34651385
DK
132 if (TransferModificationTimes(Path.c_str(), Itm->DestFile.c_str(), Res.LastModified) == false)
133 return false;
9ce3cfc9 134
93bf083d 135 // Return a Done response
a7c835af 136 Res.TakeHashes(Hash);
63b1700f 137
93bf083d 138 URIDone(Res);
93bf083d
AL
139 return true;
140}
141 /*}}}*/
142
65512241 143int main(int, char *argv[])
93bf083d 144{
8b79c94a 145 return StoreMethod(flNotDir(argv[0])).Run();
92173b19 146}