2 * Copyright (c) 2000,2007 Red Hat, Inc.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
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. */
22 static const char *cvsid
=
28 #include "csu_util/rfc1738.h"
29 #include "csu_util/version_compare.h"
31 #include "setup_version.h"
33 #include "LogSingleton.h"
48 #include "IniParseFindVisitor.h"
49 #include "IniParseFeedback.h"
51 #include "io_stream.h"
52 #include "io_stream_memory.h"
56 #include "IniDBBuilderPackage.h"
58 #include "Exception.h"
60 extern ThreeBarProgressPage Progress
;
62 unsigned int setup_timestamp
= 0;
63 std::string ini_setup_version
;
65 extern int yyparse ();
66 /*extern int yydebug;*/
68 class GuiParseFeedback
: public IniParseFeedback
71 GuiParseFeedback () : lastpct (0)
73 Progress
.SetText2 ("");
74 Progress
.SetText3 ("");
75 Progress
.SetText4 ("Progress:");
77 virtual void progress(unsigned long const pos
, unsigned long const max
)
80 /* length not known or eof */
83 /* rounding down should mean this only ever fires once */
85 if (pos
* 100 / max
> lastpct
)
87 lastpct
= pos
* 100 / max
;
88 /* log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
89 << " bytes of ini file read)" << endLog; */
91 Progress
.SetBar1(pos
, max
);
93 virtual void iniName (const std::string
& name
)
95 Progress
.SetText1 (("Parsing ini file \"" + name
+ "\"").c_str());
97 virtual void babble(const std::string
& message
)const
99 log (LOG_BABBLE
) << message
<< endLog
;
101 virtual void warning (const std::string
& message
)const
103 MessageBox (0, message
.c_str(), "Warning", 0);
105 virtual void error(const std::string
& message
)const
107 MessageBox (0, message
.c_str(), "Parse Errors", 0);
109 virtual ~ GuiParseFeedback ()
111 Progress
.SetText4("Package:");
114 unsigned int lastpct
;
118 do_local_ini (HWND owner
)
120 GuiParseFeedback myFeedback
;
121 IniDBBuilderPackage
findBuilder(myFeedback
);
122 IniParseFindVisitor
myVisitor (findBuilder
, local_dir
, myFeedback
);
123 Find (local_dir
).accept(myVisitor
);
124 setup_timestamp
= myVisitor
.timeStamp();
125 ini_setup_version
= myVisitor
.version();
126 return myVisitor
.iniCount();
130 do_remote_ini (HWND owner
)
132 size_t ini_count
= 0;
133 GuiParseFeedback myFeedback
;
134 IniDBBuilderPackage
aBuilder(myFeedback
);
137 /* FIXME: Get rid of this io_stream pointer travesty. The need to
138 explicitly delete these things is ridiculous. Note that the
139 decompress io_stream "owns" the underlying compressed io_stream
140 instance, so it should not be deleted explicitly. */
142 for (SiteList::const_iterator n
= site_list
.begin();
143 n
!= site_list
.end(); ++n
)
146 /* First try to fetch the .bz2 compressed ini file. */
147 current_ini_name
= n
->url
+ "/" + SETUP_BZ2_FILENAME
;
148 if ((ini_file
= get_url_to_membuf (current_ini_name
, owner
)))
150 /* Decompress the entire file in memory right now. This has the
151 advantage that input_stream->get_size() will work during parsing
152 and we'll have an accurate status bar. Also, we can't seek
153 bz2 streams, so when it comes time to write out a local cached
154 copy of the .ini file below, we'd otherwise have to delete this
155 stream and uncompress it again from the start, which is wasteful.
156 The current uncompresed size of the .ini file as of 2007 is less
157 than 600 kB, so this is not a great deal of memory. */
158 io_stream
*bz2_stream
= compress::decompress (ini_file
);
161 /* This isn't a valid bz2 file. */
167 io_stream
*uncompressed
= new io_stream_memory ();
169 if (io_stream::copy (bz2_stream
, uncompressed
) != 0 ||
170 bz2_stream
->error () == EIO
)
172 /* There was a problem decompressing bz2. */
177 "Warning: Problem encountered while uncompressing " <<
178 current_ini_name
<< " - possibly truncated or corrupt bzip2"
179 " file. Retrying with uncompressed version." << endLog
;
184 ini_file
= uncompressed
;
185 ini_file
->seek (0, IO_SEEK_SET
);
192 /* Try to look for a plain .ini file because one of the following
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
);
203 note (owner
, IDS_SETUPINI_MISSING
, SETUP_INI_FILENAME
, n
->url
.c_str());
207 myFeedback
.iniName (current_ini_name
);
208 aBuilder
.parse_mirror
= n
->url
;
209 ini_init (ini_file
, &aBuilder
, myFeedback
);
213 if (yyparse () || yyerror_count
> 0)
214 myFeedback
.error (yyerror_messages
);
217 /* save known-good setup.ini locally */
218 const std::string fp
= "file://" + local_dir
+ "/" +
219 rfc1738_escape_part (n
->url
) +
220 "/" + SETUP_INI_FILENAME
;
221 io_stream::mkpath_p (PATH_TO_FILE
, fp
);
222 if (io_stream
*out
= io_stream::open (fp
, "wb"))
224 ini_file
->seek (0, IO_SEEK_SET
);
225 if (io_stream::copy (ini_file
, out
) != 0)
226 io_stream::remove (fp
);
231 if (aBuilder
.timestamp
> setup_timestamp
)
233 setup_timestamp
= aBuilder
.timestamp
;
234 ini_setup_version
= aBuilder
.version
;
242 do_ini_thread (HINSTANCE h
, HWND owner
)
244 size_t ini_count
= 0;
245 if (source
== IDC_SOURCE_CWD
)
246 ini_count
= do_local_ini (owner
);
248 ini_count
= do_remote_ini (owner
);
253 if (get_root_dir ().c_str())
255 io_stream::mkpath_p (PATH_TO_DIR
, "cygfile:///etc/setup");
257 unsigned int old_timestamp
= 0;
259 io_stream::open ("cygfile:///etc/setup/timestamp", "rt");
263 memset (temp
, '\0', 20);
264 if (ots
->read (temp
, 19))
265 sscanf (temp
, "%u", &old_timestamp
);
267 if (old_timestamp
&& setup_timestamp
268 && (old_timestamp
> setup_timestamp
))
270 int yn
= yesno (owner
, IDS_OLD_SETUPINI
);
272 LogSingleton::GetInstance().exit (1);
278 io_stream::open ("cygfile:///etc/setup/timestamp", "wt");
282 sprintf (temp
, "%u", setup_timestamp
);
283 nts
->write (temp
, strlen (temp
));
289 msg (".ini setup_version is %s, our setup_version is %s", ini_setup_version
.size() ?
290 ini_setup_version
.c_str() : "(null)",
292 if (ini_setup_version
.size())
294 if (version_compare(setup_version
, ini_setup_version
) < 0)
295 note (owner
, IDS_OLD_SETUP_VERSION
, setup_version
,
296 ini_setup_version
.c_str());
303 do_ini_thread_reflector(void* p
)
306 context
= (HANDLE
*)p
;
310 bool succeeded
= do_ini_thread((HINSTANCE
)context
[0], (HWND
)context
[1]);
312 // Tell the progress page that we're done downloading
313 Progress
.PostMessage(WM_APP_SETUP_INI_DOWNLOAD_COMPLETE
, 0, succeeded
);
315 TOPLEVEL_CATCH("ini");
320 static HANDLE context
[2];
323 do_ini (HINSTANCE h
, HWND owner
)
329 CreateThread (NULL
, 0, do_ini_thread_reflector
, context
, 0, &threadID
);