]> git.saurik.com Git - apt-legacy.git/blob - methods/gzip.cc
Many fixes for Name, Section, and mDNSResponder.
[apt-legacy.git] / methods / gzip.cc
1 extern "C" {
2 #include <mach-o/nlist.h>
3 }
4
5 // -*- mode: cpp; mode: fold -*-
6 // Description /*{{{*/
7 // $Id: gzip.cc,v 1.17.2.1 2004/01/16 18:58:50 mdz Exp $
8 /* ######################################################################
9
10 GZip method - Take a file URI in and decompress it into the target
11 file.
12
13 ##################################################################### */
14 /*}}}*/
15 // Include Files /*{{{*/
16 #include <apt-pkg/fileutl.h>
17 #include <apt-pkg/error.h>
18 #include <apt-pkg/acquire-method.h>
19 #include <apt-pkg/strutl.h>
20 #include <apt-pkg/hashes.h>
21
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #include <utime.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <apti18n.h>
28 /*}}}*/
29
30 const char *Prog;
31
32 class GzipMethod : public pkgAcqMethod
33 {
34 virtual bool Fetch(FetchItem *Itm);
35
36 public:
37
38 GzipMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {};
39 };
40
41
42 // GzipMethod::Fetch - Decompress the passed URI /*{{{*/
43 // ---------------------------------------------------------------------
44 /* */
45 bool GzipMethod::Fetch(FetchItem *Itm)
46 {
47 URI Get = Itm->Uri;
48 string Path = Get.Host + Get.Path; // To account for relative paths
49
50 string GzPathOption = "Dir::bin::"+string(Prog);
51
52 FetchResult Res;
53 Res.Filename = Itm->DestFile;
54 URIStart(Res);
55
56 // Open the source and destination files
57 FileFd From(Path,FileFd::ReadOnly);
58
59 // if the file is empty, just rename it and return
60 if(From.Size() == 0)
61 {
62 rename(Path.c_str(), Itm->DestFile.c_str());
63 return true;
64 }
65
66 int GzOut[2];
67 if (pipe(GzOut) < 0)
68 return _error->Errno("pipe",_("Couldn't open pipe for %s"),Prog);
69
70 // Fork gzip
71 pid_t Process = ExecFork();
72 if (Process == 0)
73 {
74 close(GzOut[0]);
75 dup2(From.Fd(),STDIN_FILENO);
76 dup2(GzOut[1],STDOUT_FILENO);
77 From.Close();
78 close(GzOut[1]);
79 SetCloseExec(STDIN_FILENO,false);
80 SetCloseExec(STDOUT_FILENO,false);
81
82 const char *Args[3];
83 string Tmp = _config->Find(GzPathOption,Prog);
84 Args[0] = Tmp.c_str();
85 Args[1] = "-d";
86 Args[2] = 0;
87 execvp(Args[0],(char **)Args);
88 _exit(100);
89 }
90 From.Close();
91 close(GzOut[1]);
92
93 FileFd FromGz(GzOut[0]); // For autoclose
94 FileFd To(Itm->DestFile,FileFd::WriteEmpty);
95 To.EraseOnFailure();
96 if (_error->PendingError() == true)
97 return false;
98
99 // Read data from gzip, generate checksums and write
100 Hashes Hash;
101 bool Failed = false;
102 while (1)
103 {
104 unsigned char Buffer[4*1024];
105 unsigned long Count;
106
107 Count = read(GzOut[0],Buffer,sizeof(Buffer));
108 if (Count < 0 && errno == EINTR)
109 continue;
110
111 if (Count < 0)
112 {
113 _error->Errno("read", _("Read error from %s process"),Prog);
114 Failed = true;
115 break;
116 }
117
118 if (Count == 0)
119 break;
120
121 Hash.Add(Buffer,Count);
122 if (To.Write(Buffer,Count) == false)
123 {
124 Failed = true;
125 FromGz.Close();
126 break;
127 }
128 }
129
130 // Wait for gzip to finish
131 if (ExecWait(Process,_config->Find(GzPathOption,Prog).c_str(),false) == false)
132 {
133 To.OpFail();
134 return false;
135 }
136
137 To.Close();
138
139 if (Failed == true)
140 return false;
141
142 // Transfer the modification times
143 struct stat Buf;
144 if (stat(Path.c_str(),&Buf) != 0)
145 return _error->Errno("stat",_("Failed to stat"));
146
147 struct utimbuf TimeBuf;
148 TimeBuf.actime = Buf.st_atime;
149 TimeBuf.modtime = Buf.st_mtime;
150 if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0)
151 return _error->Errno("utime",_("Failed to set modification time"));
152
153 if (stat(Itm->DestFile.c_str(),&Buf) != 0)
154 return _error->Errno("stat",_("Failed to stat"));
155
156 // Return a Done response
157 Res.LastModified = Buf.st_mtime;
158 Res.Size = Buf.st_size;
159 Res.TakeHashes(Hash);
160
161 URIDone(Res);
162
163 return true;
164 }
165 /*}}}*/
166
167 int main(int argc, char *argv[])
168 {
169 struct nlist nl[2];
170 memset(nl, 0, sizeof(nl));
171 nl[0].n_un.n_name = "_useMDNSResponder";
172 nlist("/usr/lib/libc.dylib", nl);
173 if (nl[0].n_type != N_UNDF)
174 *(int *) nl[0].n_value = 0;
175
176 setlocale(LC_ALL, "");
177
178 GzipMethod Mth;
179
180 Prog = strrchr(argv[0],'/');
181 Prog++;
182
183 return Mth.Run();
184 }