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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: copy.cc,v 1.7.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
Copy URI - This method takes a uri like a file: uri and copies it
to the destination file.
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#include <config.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/acquire-method.h>
#include <apt-pkg/error.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/configuration.h>
#include <string>
#include <sys/stat.h>
#include <sys/time.h>
#include <apti18n.h>
/*}}}*/
class CopyMethod : public pkgAcqMethod
{
virtual bool Fetch(FetchItem *Itm);
void CalculateHashes(FetchResult &Res);
public:
CopyMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {};
};
void CopyMethod::CalculateHashes(FetchResult &Res)
{
// For gzip indexes we need to look inside the gzip for the hash
// We can not use the extension here as its not used in partial
// on a IMS hit
FileFd::OpenMode OpenMode = FileFd::ReadOnly;
if (_config->FindB("Acquire::GzipIndexes", false) == true)
OpenMode = FileFd::ReadOnlyGzip;
Hashes Hash;
FileFd Fd(Res.Filename, OpenMode);
Hash.AddFD(Fd);
Res.TakeHashes(Hash);
}
// CopyMethod::Fetch - Fetch a file /*{{{*/
// ---------------------------------------------------------------------
/* */
bool CopyMethod::Fetch(FetchItem *Itm)
{
// this ensures that relative paths work in copy
std::string File = Itm->Uri.substr(Itm->Uri.find(':')+1);
// Stat the file and send a start message
struct stat Buf;
if (stat(File.c_str(),&Buf) != 0)
return _error->Errno("stat",_("Failed to stat"));
// Forumulate a result and send a start message
FetchResult Res;
Res.Size = Buf.st_size;
Res.Filename = Itm->DestFile;
Res.LastModified = Buf.st_mtime;
Res.IMSHit = false;
URIStart(Res);
// when the files are identical, just compute the hashes
if(File == Itm->DestFile)
{
CalculateHashes(Res);
URIDone(Res);
return true;
}
// just calc the hashes if the source and destination are identical
if (File == Itm->DestFile)
{
CalculateHashes(Res);
URIDone(Res);
return true;
}
// See if the file exists
FileFd From(File,FileFd::ReadOnly);
FileFd To(Itm->DestFile,FileFd::WriteAtomic);
To.EraseOnFailure();
if (_error->PendingError() == true)
{
To.OpFail();
return false;
}
// Copy the file
if (CopyFile(From,To) == false)
{
To.OpFail();
return false;
}
From.Close();
To.Close();
// Transfer the modification times
struct timeval times[2];
times[0].tv_sec = Buf.st_atime;
times[1].tv_sec = Buf.st_mtime;
times[0].tv_usec = times[1].tv_usec = 0;
if (utimes(Res.Filename.c_str(), times) != 0)
return _error->Errno("utimes",_("Failed to set modification time"));
CalculateHashes(Res);
URIDone(Res);
return true;
}
/*}}}*/
int main()
{
setlocale(LC_ALL, "");
CopyMethod Mth;
return Mth.Run();
}
|