]>
git.saurik.com Git - apt.git/blob - methods/rred.cc
ab73398f512d9b66a84d7ca8f2c8440aae65aaab
1 #include <apt-pkg/fileutl.h>
2 #include <apt-pkg/error.h>
3 #include <apt-pkg/acquire-method.h>
4 #include <apt-pkg/strutl.h>
5 #include <apt-pkg/hashes.h>
16 class RredMethod
: public pkgAcqMethod
18 virtual bool Fetch(FetchItem
*Itm
);
22 RredMethod() : pkgAcqMethod("1.1",SingleInstance
| SendConfig
) {};
26 #define BUF_SIZE (1024)
29 #define MODE_CHANGED 0
30 #define MODE_DELETED 1
38 // XXX someone better go out and understand the error reporting/handling here...
39 int ed_rec(FILE *ed_cmds
, FILE *in_file
, FILE *out_file
, int line
,
40 char *buffer
, unsigned int bufsize
, Hashes
*hash
) {
48 /* get the current command and parse it*/
49 if (fgets(buffer
, bufsize
, ed_cmds
) == NULL
) {
52 startline
= strtol(buffer
, &idx
, 10);
53 if (startline
< line
) {
58 stopline
= strtol(idx
, &idx
, 10);
66 else if (*idx
== 'a') {
69 else if (*idx
== 'd') {
75 /* get the current position */
77 /* if this is add or change then go to the next full stop */
78 if ((mode
== MODE_CHANGED
) || (mode
== MODE_ADDED
)) {
80 fgets(buffer
, bufsize
, ed_cmds
);
81 while ((strlen(buffer
) == (bufsize
- 1))
82 && (buffer
[bufsize
- 2] != '\n')) {
83 fgets(buffer
, bufsize
, ed_cmds
);
86 } while (strncmp(buffer
, ".", 1) != 0);
88 /* do the recursive call */
89 line
= ed_rec(ed_cmds
, in_file
, out_file
, line
, buffer
, bufsize
,
96 fseek(ed_cmds
, pos
, SEEK_SET
);
97 /* first wind to the current position */
98 if (mode
!= MODE_ADDED
) {
101 while (line
< startline
) {
102 fgets(buffer
, bufsize
, in_file
);
103 written
= fwrite(buffer
, 1, strlen(buffer
), out_file
);
104 hash
->Add((unsigned char*)buffer
, written
);
105 while ((strlen(buffer
) == (bufsize
- 1))
106 && (buffer
[bufsize
- 2] != '\n')) {
107 fgets(buffer
, bufsize
, in_file
);
108 written
= fwrite(buffer
, 1, strlen(buffer
), out_file
);
109 hash
->Add((unsigned char*)buffer
, written
);
113 /* include from ed script */
114 if ((mode
== MODE_ADDED
) || (mode
== MODE_CHANGED
)) {
116 fgets(buffer
, bufsize
, ed_cmds
);
117 if (strncmp(buffer
, ".", 1) != 0) {
118 written
= fwrite(buffer
, 1, strlen(buffer
), out_file
);
119 hash
->Add((unsigned char*)buffer
, written
);
120 while ((strlen(buffer
) == (bufsize
- 1))
121 && (buffer
[bufsize
- 2] != '\n')) {
122 fgets(buffer
, bufsize
, ed_cmds
);
123 written
= fwrite(buffer
, 1, strlen(buffer
), out_file
);
124 hash
->Add((unsigned char*)buffer
, written
);
132 /* ignore the corresponding number of lines from input */
133 if ((mode
== MODE_DELETED
) || (mode
== MODE_CHANGED
)) {
134 while (line
< stopline
) {
135 fgets(buffer
, bufsize
, in_file
);
136 while ((strlen(buffer
) == (bufsize
- 1))
137 && (buffer
[bufsize
- 2] != '\n')) {
138 fgets(buffer
, bufsize
, in_file
);
146 int ed_file(FILE *ed_cmds
, FILE *in_file
, FILE *out_file
, Hashes
*hash
) {
147 char buffer
[BUF_SIZE
];
151 /* we do a tail recursion to read the commands in the right order */
152 result
= ed_rec(ed_cmds
, in_file
, out_file
, 0, buffer
, BUF_SIZE
,
155 /* read the rest from infile */
157 while (fgets(buffer
, BUF_SIZE
, in_file
) != NULL
) {
158 written
= fwrite(buffer
, 1, strlen(buffer
), out_file
);
159 hash
->Add((unsigned char*)buffer
, written
);
163 // XXX better error handling
164 fprintf(stderr
, "Error: %i\n", result
);
171 // XXX do we need modification times as well?
172 bool RredMethod::Fetch(FetchItem
*Itm
)
175 string Path
= Get
.Host
+ Get
.Path
; // To account for relative paths
176 // Path contains the filename to patch
178 Res
.Filename
= Itm
->DestFile
;
180 // Res.Filename the destination filename
182 // Open the source and destination files (the d'tor of FileFd will do
183 // the cleanup/closing of the fds)
184 FileFd
From(Path
,FileFd::ReadOnly
);
185 FileFd
Patch(Path
+".ed",FileFd::ReadOnly
);
186 FileFd
To(Itm
->DestFile
,FileFd::WriteEmpty
);
188 if (_error
->PendingError() == true)
192 FILE* fFrom
= fdopen(From
.Fd(), "r");
193 FILE* fPatch
= fdopen(Patch
.Fd(), "r");
194 FILE* fTo
= fdopen(To
.Fd(), "w");
195 // now do the actual patching
196 if (ed_file(fPatch
, fFrom
, fTo
, &Hash
) != ED_OK
) {
200 // write out the result
208 // Transfer the modification times
210 if (stat(Path
.c_str(),&Buf
) != 0)
211 return _error
->Errno("stat",_("Failed to stat"));
213 struct utimbuf TimeBuf
;
214 TimeBuf
.actime
= Buf
.st_atime
;
215 TimeBuf
.modtime
= Buf
.st_mtime
;
216 if (utime(Itm
->DestFile
.c_str(),&TimeBuf
) != 0)
217 return _error
->Errno("utime",_("Failed to set modification time"));
219 if (stat(Itm
->DestFile
.c_str(),&Buf
) != 0)
220 return _error
->Errno("stat",_("Failed to stat"));
223 Res
.LastModified
= Buf
.st_mtime
;
224 Res
.Size
= Buf
.st_size
;
225 Res
.TakeHashes(Hash
);
232 int main(int argc
, char *argv
[])
236 Prog
= strrchr(argv
[0],'/');