]> git.saurik.com Git - apt.git/blob - methods/gzip.cc
Stable acquire code
[apt.git] / methods / gzip.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: gzip.cc,v 1.2 1998/10/26 07:11:53 jgg Exp $
4 /* ######################################################################
5
6 GZip method - Take a file URI in and decompress it into the target
7 file.
8
9 ##################################################################### */
10 /*}}}*/
11 // Include Files /*{{{*/
12 #include <apt-pkg/fileutl.h>
13 #include <apt-pkg/error.h>
14 #include <apt-pkg/configuration.h>
15 #include <apt-pkg/acquire-worker.h>
16 #include <strutl.h>
17
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <utime.h>
21 #include <wait.h>
22 #include <stdio.h>
23 /*}}}*/
24
25 // Fail - Generate a failure message /*{{{*/
26 // ---------------------------------------------------------------------
27 /* */
28 void Fail(string URI)
29 {
30 string Err = "Undetermined Error";
31 if (_error->empty() == false)
32 _error->PopMessage(Err);
33
34 printf("400 URI Failure\n"
35 "URI: %s\n"
36 "Message: %s\n\n",URI.c_str(),Err.c_str());
37 _error->Discard();
38 }
39 /*}}}*/
40
41 int main()
42 {
43 setlinebuf(stdout);
44 SetNonBlock(STDIN_FILENO,true);
45
46 printf("100 Capabilities\n"
47 "Version: 1.0\n"
48 "Pipeline: true\n"
49 "Send-Config: true\n\n");
50
51 vector<string> Messages;
52 while (1)
53 {
54 if (WaitFd(STDIN_FILENO) == false ||
55 ReadMessages(STDIN_FILENO,Messages) == false)
56 return 0;
57
58 while (Messages.empty() == false)
59 {
60 string Message = Messages.front();
61 Messages.erase(Messages.begin());
62
63 // Fetch the message number
64 char *End;
65 int Number = strtol(Message.c_str(),&End,10);
66 if (End == Message.c_str())
67 {
68 cerr << "Malformed message!" << endl;
69 return 100;
70 }
71
72 // 601 configuration message
73 if (Number == 601)
74 {
75 pkgInjectConfiguration(Message,*_config);
76 continue;
77 }
78
79 // 600 URI Fetch message
80 if (Number != 600)
81 continue;
82
83 // Grab the URI bit
84 string URI = LookupTag(Message,"URI");
85 string Target = LookupTag(Message,"Filename");
86
87 // Grab the filename
88 string::size_type Pos = URI.find(':');
89 if (Pos == string::npos)
90 {
91 _error->Error("Invalid message");
92 Fail(URI);
93 continue;
94 }
95 string File = string(URI,Pos+1);
96
97 // Start the reply message
98 string Result = "201 URI Done";
99 Result += "\nURI: " + URI;
100 Result += "\nFileName: " + Target;
101
102 // See if the file exists
103 FileFd From(File,FileFd::ReadOnly);
104 FileFd To(Target,FileFd::WriteEmpty);
105 To.EraseOnFailure();
106 if (_error->PendingError() == true)
107 {
108 Fail(URI);
109 continue;
110 }
111
112 // Fork gzip
113 int Process = fork();
114 if (Process < 0)
115 {
116 _error->Errno("fork","Couldn't fork gzip");
117 Fail(URI);
118 continue;
119 }
120
121 // The child
122 if (Process == 0)
123 {
124 dup2(From.Fd(),STDIN_FILENO);
125 dup2(To.Fd(),STDOUT_FILENO);
126 From.Close();
127 To.Close();
128 SetCloseExec(STDIN_FILENO,false);
129 SetCloseExec(STDOUT_FILENO,false);
130
131 const char *Args[3];
132 Args[0] = _config->Find("Dir::bin::gzip","gzip").c_str();
133 Args[1] = "-d";
134 Args[2] = 0;
135 execvp(Args[0],(char **)Args);
136 exit(100);
137 }
138 From.Close();
139
140 // Wait for gzip to finish
141 int Status;
142 if (waitpid(Process,&Status,0) != Process)
143 {
144 To.OpFail();
145 _error->Errno("wait","Waiting for gzip failed");
146 Fail(URI);
147 continue;
148 }
149
150 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
151 {
152 To.OpFail();
153 _error->Error("gzip failed, perhaps the disk is full or the directory permissions are wrong.");
154 Fail(URI);
155 continue;
156 }
157
158 To.Close();
159
160 // Transfer the modification times
161 struct stat Buf;
162 if (stat(File.c_str(),&Buf) != 0)
163 {
164 _error->Errno("stat","Failed to stat");
165 Fail(URI);
166 continue;
167 }
168 struct utimbuf TimeBuf;
169 TimeBuf.actime = Buf.st_atime;
170 TimeBuf.modtime = Buf.st_mtime;
171 if (utime(Target.c_str(),&TimeBuf) != 0)
172 {
173 _error->Errno("utime","Failed to set modification time");
174 Fail(URI);
175 continue;
176 }
177
178 // Send the message
179 Result += "\n\n";
180 if (write(STDOUT_FILENO,Result.begin(),Result.length()) !=
181 (signed)Result.length())
182 return 100;
183 }
184 }
185
186 return 0;
187 }