]> cygwin.com Git - cygwin-apps/setup.git/blame - ini.cc
* CHANGES: Update.
[cygwin-apps/setup.git] / ini.cc
CommitLineData
23c9e63c 1/*
eb20d728 2 * Copyright (c) 2000,2007 Red Hat, Inc.
23c9e63c
DD
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16/* The purpose of this file is to get and parse the setup.ini file
17 from the mirror site. A few support routines for the bison and
18 flex parsers are provided also. We check to see if this setup.ini
19 is older than the one we used last time, and if so, warn the user. */
20
b24c88b3
RC
21#if 0
22static const char *cvsid =
23 "\n%%% $Id$\n";
24#endif
8507f105 25
2b734ec7
MB
26#include "ini.h"
27
946198be 28#include "csu_util/rfc1738.h"
2b734ec7
MB
29#include "csu_util/version_compare.h"
30
31#include "setup_version.h"
23c9e63c 32#include "win32.h"
a77b6167 33#include "LogSingleton.h"
23c9e63c
DD
34
35#include <stdio.h>
b11b49f3 36#include <stdlib.h>
23c9e63c 37#include <stdarg.h>
ab57ceaa 38#include <process.h>
23c9e63c 39
23c9e63c 40#include "resource.h"
23c9e63c
DD
41#include "state.h"
42#include "geturl.h"
43#include "dialog.h"
44#include "msg.h"
a351e48c 45#include "mount.h"
de6a1a64 46#include "site.h"
de6a1a64 47#include "find.h"
b401ef47 48#include "IniParseFindVisitor.h"
67829ce0 49#include "IniParseFeedback.h"
23c9e63c 50
b24c88b3 51#include "io_stream.h"
eb20d728 52#include "io_stream_memory.h"
b24c88b3 53
ab57ceaa 54#include "threebar.h"
58ee6135 55
076654e7 56#include "IniDBBuilderPackage.h"
3272d625 57#include "compress.h"
072fb49a 58#include "Exception.h"
b92028a4 59
ab57ceaa
RC
60extern ThreeBarProgressPage Progress;
61
23c9e63c 62unsigned int setup_timestamp = 0;
fd93eff9 63std::string ini_setup_version;
23c9e63c 64
0af2d779 65extern int yyparse ();
b11b49f3
DD
66/*extern int yydebug;*/
67
67829ce0
RC
68class GuiParseFeedback : public IniParseFeedback
69{
70public:
aa1e3b4d
RC
71 GuiParseFeedback () : lastpct (0)
72 {
73 Progress.SetText2 ("");
74 Progress.SetText3 ("");
75 Progress.SetText4 ("Progress:");
76 }
77 virtual void progress(unsigned long const pos, unsigned long const max)
78 {
79 if (!max)
80 /* length not known or eof */
81 return;
82 if (lastpct == 100)
83 /* rounding down should mean this only ever fires once */
84 lastpct = 0;
85 if (pos * 100 / max > lastpct)
86 {
87 lastpct = pos * 100 / max;
eb20d728
BD
88 /* log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
89 << " bytes of ini file read)" << endLog; */
aa1e3b4d
RC
90 }
91 Progress.SetBar1(pos, max);
92 }
fd93eff9 93 virtual void iniName (const std::string& name)
aa1e3b4d 94 {
fd93eff9 95 Progress.SetText1 (("Parsing ini file \"" + name + "\"").c_str());
aa1e3b4d 96 }
fd93eff9 97 virtual void babble(const std::string& message)const
67829ce0 98 {
a77b6167 99 log (LOG_BABBLE) << message << endLog;
67829ce0 100 }
fd93eff9 101 virtual void warning (const std::string& message)const
67829ce0 102 {
d2a3615c 103 MessageBox (0, message.c_str(), "Warning", 0);
67829ce0 104 }
fd93eff9 105 virtual void error(const std::string& message)const
67829ce0 106 {
eb20d728 107 MessageBox (0, message.c_str(), "Parse Errors", 0);
67829ce0
RC
108 }
109 virtual ~ GuiParseFeedback ()
110 {
aa1e3b4d 111 Progress.SetText4("Package:");
67829ce0 112 }
aa1e3b4d 113private:
b4cf6208 114 unsigned int lastpct;
67829ce0
RC
115};
116
de6a1a64 117static int
ab57ceaa 118do_local_ini (HWND owner)
de6a1a64 119{
67829ce0
RC
120 GuiParseFeedback myFeedback;
121 IniDBBuilderPackage findBuilder(myFeedback);
122 IniParseFindVisitor myVisitor (findBuilder, local_dir, myFeedback);
b401ef47
RC
123 Find (local_dir).accept(myVisitor);
124 setup_timestamp = myVisitor.timeStamp();
2b734ec7 125 ini_setup_version = myVisitor.version();
b401ef47 126 return myVisitor.iniCount();
de6a1a64
RC
127}
128
129static int
ab57ceaa 130do_remote_ini (HWND owner)
de6a1a64
RC
131{
132 size_t ini_count = 0;
67829ce0
RC
133 GuiParseFeedback myFeedback;
134 IniDBBuilderPackage aBuilder(myFeedback);
eb20d728
BD
135 io_stream *ini_file;
136
137 /* FIXME: Get rid of this io_stream pointer travesty. The need to
138 explicily delete these things is ridiculous. */
aa1e3b4d 139
3bac26a1
RC
140 for (SiteList::const_iterator n = site_list.begin();
141 n != site_list.end(); ++n)
dd3f7f9b 142 {
eb20d728
BD
143
144 /* First try to fetch the .bz2 compressed ini file. */
145 current_ini_name = n->url + "/" + SETUP_BZ2_FILENAME;
146 if ((ini_file = get_url_to_membuf (current_ini_name, owner)))
3272d625 147 {
eb20d728
BD
148 /* Decompress the entire file in memory right now. This has the
149 advantage that input_stream->get_size() will work during parsing
150 and we'll have an accurate status bar. Also, we can't seek
151 bz2 streams, so when it comes time to write out a local cached
152 copy of the .ini file below, we'd otherwise have to delete this
153 stream and uncompress it again from the start, which is wasteful.
154 The current uncompresed size of the .ini file as of 2007 is less
155 than 600 kB, so this is not a great deal of memory. */
156 io_stream *bz2_stream = compress::decompress (ini_file);
157 if (!bz2_stream)
158 {
159 /* This isn't a valid bz2 file. */
160 delete ini_file;
161 ini_file = NULL;
162 }
163 else
164 {
165 io_stream *uncompressed = new io_stream_memory ();
166
167 if (io_stream::copy (bz2_stream, uncompressed) != 0 ||
168 bz2_stream->error () == EIO)
169 {
170 /* There was a problem decompressing bz2. */
171 delete bz2_stream;
172 delete uncompressed;
173 delete ini_file;
174 ini_file = NULL;
175 log (LOG_PLAIN) <<
176 "Warning: Problem encountered while uncompressing " <<
177 current_ini_name << " - possibly truncated or corrupt bzip2"
178 " file. Retrying with uncompressed version." << endLog;
179 }
180 else
181 {
182 delete bz2_stream;
183 delete ini_file;
184 ini_file = uncompressed;
185 ini_file->seek (0, IO_SEEK_SET);
186 }
187 }
188 }
189
190 if (!ini_file)
191 {
192 /* Try to look for a plain .ini file because one of the following
193 happened above:
194 - there was no .bz2 file found on the mirror.
195 - the .bz2 file didn't look like a valid bzip2 file.
196 - there was an error during bzip2 decompression. */
197 current_ini_name = n->url + "/" + SETUP_INI_FILENAME;
198 ini_file = get_url_to_membuf (current_ini_name, owner);
3272d625 199 }
de6a1a64
RC
200
201 if (!ini_file)
202 {
5072c0bb 203 note (owner, IDS_SETUPINI_MISSING, SETUP_INI_FILENAME, n->url.c_str());
de6a1a64
RC
204 continue;
205 }
206
eb20d728 207 myFeedback.iniName (current_ini_name);
3bac26a1 208 aBuilder.parse_mirror = n->url;
aa1e3b4d 209 ini_init (ini_file, &aBuilder, myFeedback);
de6a1a64
RC
210
211 /*yydebug = 1; */
212
eb20d728
BD
213 if (yyparse () || yyerror_count > 0)
214 myFeedback.error (yyerror_messages);
de6a1a64
RC
215 else
216 {
217 /* save known-good setup.ini locally */
fd93eff9 218 const std::string fp = "file://" + local_dir + "/" +
3bac26a1 219 rfc1738_escape_part (n->url) +
5072c0bb 220 "/" + SETUP_INI_FILENAME;
de6a1a64 221 io_stream::mkpath_p (PATH_TO_FILE, fp);
eb20d728 222 if (io_stream *out = io_stream::open (fp, "wb"))
de6a1a64 223 {
eb20d728
BD
224 ini_file->seek (0, IO_SEEK_SET);
225 if (io_stream::copy (ini_file, out) != 0)
ea36e064 226 io_stream::remove (fp);
eb20d728 227 delete out;
de6a1a64 228 }
5e0464a1 229 ++ini_count;
dd3f7f9b 230 }
67829ce0 231 if (aBuilder.timestamp > setup_timestamp)
b92028a4 232 {
67829ce0 233 setup_timestamp = aBuilder.timestamp;
2b734ec7 234 ini_setup_version = aBuilder.version;
b92028a4 235 }
3272d625 236 delete ini_file;
dd3f7f9b 237 }
de6a1a64
RC
238 return ini_count;
239}
240
d9f4a2ba 241static bool
ab57ceaa 242do_ini_thread (HINSTANCE h, HWND owner)
de6a1a64
RC
243{
244 size_t ini_count = 0;
245 if (source == IDC_SOURCE_CWD)
ab57ceaa 246 ini_count = do_local_ini (owner);
de6a1a64 247 else
ab57ceaa 248 ini_count = do_remote_ini (owner);
de6a1a64
RC
249
250 if (ini_count == 0)
d9f4a2ba 251 return false;
23c9e63c 252
d2a3615c 253 if (get_root_dir ().c_str())
23c9e63c 254 {
b24c88b3 255 io_stream::mkpath_p (PATH_TO_DIR, "cygfile:///etc/setup");
04d6e06b
DD
256
257 unsigned int old_timestamp = 0;
b24c88b3
RC
258 io_stream *ots =
259 io_stream::open ("cygfile:///etc/setup/timestamp", "rt");
04d6e06b 260 if (ots)
23c9e63c 261 {
b24c88b3
RC
262 char temp[20];
263 memset (temp, '\0', 20);
264 if (ots->read (temp, 19))
265 sscanf (temp, "%u", &old_timestamp);
266 delete ots;
04d6e06b
DD
267 if (old_timestamp && setup_timestamp
268 && (old_timestamp > setup_timestamp))
269 {
ab57ceaa 270 int yn = yesno (owner, IDS_OLD_SETUPINI);
04d6e06b 271 if (yn == IDNO)
9f4a0c62 272 LogSingleton::GetInstance().exit (1);
04d6e06b 273 }
23c9e63c 274 }
04d6e06b 275 if (setup_timestamp)
23c9e63c 276 {
b24c88b3
RC
277 io_stream *nts =
278 io_stream::open ("cygfile:///etc/setup/timestamp", "wt");
04d6e06b
DD
279 if (nts)
280 {
b24c88b3
RC
281 char temp[20];
282 sprintf (temp, "%u", setup_timestamp);
283 nts->write (temp, strlen (temp));
284 delete nts;
04d6e06b 285 }
23c9e63c
DD
286 }
287 }
288
2b734ec7 289 msg (".ini setup_version is %s, our setup_version is %s", ini_setup_version.size() ?
d2a3615c 290 ini_setup_version.c_str() : "(null)",
2b734ec7
MB
291 setup_version);
292 if (ini_setup_version.size())
13d27274 293 {
2b734ec7
MB
294 if (version_compare(setup_version, ini_setup_version) < 0)
295 note (owner, IDS_OLD_SETUP_VERSION, setup_version,
d2a3615c 296 ini_setup_version.c_str());
13d27274
DD
297 }
298
d9f4a2ba 299 return true;
23c9e63c
DD
300}
301
45e01f23 302static DWORD WINAPI
ab57ceaa
RC
303do_ini_thread_reflector(void* p)
304{
072fb49a
MB
305 HANDLE *context;
306 context = (HANDLE*)p;
ab57ceaa 307
072fb49a
MB
308 try
309 {
310 bool succeeded = do_ini_thread((HINSTANCE)context[0], (HWND)context[1]);
ab57ceaa 311
072fb49a
MB
312 // Tell the progress page that we're done downloading
313 Progress.PostMessage(WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, succeeded);
314 }
315 TOPLEVEL_CATCH("ini");
ab57ceaa 316
072fb49a 317 ExitThread(0);
ab57ceaa
RC
318}
319
320static HANDLE context[2];
321
322void
323do_ini (HINSTANCE h, HWND owner)
324{
45e01f23
RC
325 context[0] = h;
326 context[1] = owner;
327
328 DWORD threadID;
329 CreateThread (NULL, 0, do_ini_thread_reflector, context, 0, &threadID);
ab57ceaa
RC
330}
331
This page took 0.086452 seconds and 5 git commands to generate.