README: document some recent changes in the build environment
[cygwin-setup.git] / geturl.cc
blobde4e60ff9b12b1264f421051985dd5017da994d9
1 /*
4 * Copyright (c) 2000, 2001, Red Hat, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * A copy of the GNU General Public License can be found at
12 * http://www.gnu.org/
14 * Written by DJ Delorie <dj@cygnus.com>
18 /* The purpose of this file is to act as a pretty interface to
19 netio.cc. We add a progress dialog and some convenience functions
20 (like collect to string or file */
22 #if 0
23 static const char *cvsid =
24 "\n%%% $Id$\n";
25 #endif
27 #include "win32.h"
28 #include "commctrl.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
34 #include "dialog.h"
35 #include "geturl.h"
36 #include "resource.h"
37 #include "netio.h"
38 #include "msg.h"
39 #include "io_stream.h"
40 #include "io_stream_memory.h"
41 #include "state.h"
42 #include "diskfull.h"
43 #include "mount.h"
44 #include "filemanip.h"
46 #include "threebar.h"
48 #include "Exception.h"
50 #include "LogSingleton.h"
52 using namespace std;
54 extern ThreeBarProgressPage Progress;
56 static int max_bytes = 0;
57 static int is_local_install = 0;
59 long long int total_download_bytes = 0;
60 long long int total_download_bytes_sofar = 0;
62 static DWORD start_tics;
64 static void
65 init_dialog (const string &url, int length)
67 if (is_local_install)
68 return;
70 string::size_type divide = url.find_last_of('/');
71 max_bytes = length;
72 Progress.SetText1("Downloading...");
73 Progress.SetText2((url.substr(divide + 1) + " from "
74 + url.substr(0, divide)).c_str());
75 Progress.SetText3("Connecting...");
76 Progress.SetBar1(0);
77 start_tics = GetTickCount ();
81 static void
82 progress (int bytes)
84 if (is_local_install)
85 return;
86 static char buf[100];
87 double kbps;
88 static unsigned int last_tics = 0;
89 DWORD tics = GetTickCount ();
90 if (tics == start_tics) // to prevent division by zero
91 return;
92 if (tics < last_tics + 200) // to prevent flickering updates
93 return;
94 last_tics = tics;
96 kbps = ((double)bytes) / (double)(tics - start_tics);
97 if (max_bytes > 0)
99 int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
100 Progress.SetBar1(bytes, max_bytes);
101 sprintf (buf, "%d %% (%dk/%dk) %03.1f kB/s",
102 perc, bytes / 1000, max_bytes / 1000, kbps);
103 if (total_download_bytes > 0)
104 Progress.SetBar2(total_download_bytes_sofar + bytes,
105 total_download_bytes);
107 else
108 sprintf (buf, "%d %2.1f kB/s", bytes, kbps);
110 Progress.SetText3(buf);
113 static void
114 getUrlToStream (const string &_url, io_stream *output)
116 Log (LOG_BABBLE) << "getUrlToStream " << _url << endLog;
117 is_local_install = (source == IDC_SOURCE_LOCALDIR);
118 init_dialog (_url, 0);
119 NetIO *n = NetIO::open (_url.c_str());
120 if (!n || !n->ok ())
122 delete n;
123 Log (LOG_BABBLE) << "getUrlToStream failed!" << endLog;
124 throw new Exception (TOSTRING(__LINE__) " " __FILE__, "Error opening url", APPERR_IO_ERROR);
127 if (n->file_size)
128 max_bytes = n->file_size;
130 int total_bytes = 0;
131 progress (0);
132 while (1)
134 char buf[2048];
135 ssize_t rlen, wlen;
136 rlen = n->read (buf, 2048);
137 if (rlen > 0)
139 wlen = output->write (buf, rlen);
140 if (wlen != rlen)
141 /* FIXME: Show an error message */
142 break;
143 total_bytes += rlen;
144 progress (total_bytes);
146 else
147 break;
149 if (n)
150 delete (n);
151 /* reseeking is up to the recipient if desired */
154 io_stream *
155 get_url_to_membuf (const string &_url, HWND owner)
157 io_stream_memory *membuf = new io_stream_memory ();
158 try
160 Log (LOG_BABBLE) << "get_url_to_membuf " << _url << endLog;
161 getUrlToStream (_url, membuf);
163 if (membuf->seek (0, IO_SEEK_SET))
165 if (membuf)
166 delete membuf;
167 Log (LOG_BABBLE) << "get_url_to_membuf(): seek (0) failed for membuf!" << endLog;
168 return 0;
170 return membuf;
172 catch (Exception *e)
174 if (e->errNo() != APPERR_IO_ERROR)
175 throw e;
176 Log (LOG_BABBLE) << "get_url_to_membuf failed!" << endLog;
177 delete membuf;
178 return 0;
182 // predicate: url has no '\0''s in it.
183 string
184 get_url_to_string (const string &_url, HWND owner)
186 io_stream *stream = get_url_to_membuf (_url, owner);
187 if (!stream)
188 return string();
189 size_t bytes = stream->get_size ();
190 if (!bytes)
192 /* zero length, or error retrieving length */
193 delete stream;
194 Log (LOG_BABBLE) << "get_url_to_string(): couldn't retrieve buffer size, or zero length buffer" << endLog;
195 return string();
197 char temp [bytes + 1];
198 /* membufs are quite safe */
199 stream->read (temp, bytes);
200 temp [bytes] = '\0';
201 delete stream;
202 return string(temp);
206 get_url_to_file (const string &_url,
207 const string &_filename,
208 int expected_length,
209 HWND owner)
211 Log (LOG_BABBLE) << "get_url_to_file " << _url << " " << _filename << endLog;
212 if (total_download_bytes > 0)
214 int df = diskfull (get_root_dir ().c_str());
215 Progress.SetBar3(df);
217 init_dialog (_url, expected_length);
219 remove (_filename.c_str()); /* but ignore errors */
221 NetIO *n = NetIO::open (_url.c_str());
222 if (!n || !n->ok ())
224 delete n;
225 Log (LOG_BABBLE) << "get_url_to_file failed!" << endLog;
226 return 1;
229 FILE *f = nt_fopen (_filename.c_str(), "wb");
230 if (!f)
232 const char *err = strerror (errno);
233 if (!err)
234 err = "(unknown error)";
235 fatal (owner, IDS_ERR_OPEN_WRITE, _filename.c_str(), err);
238 if (n->file_size)
239 max_bytes = n->file_size;
241 int total_bytes = 0;
242 progress (0);
243 while (1)
245 char buf[8192];
246 int count;
247 count = n->read (buf, sizeof (buf));
248 if (count <= 0)
249 break;
250 fwrite (buf, 1, count, f);
251 total_bytes += count;
252 progress (total_bytes);
255 total_download_bytes_sofar += total_bytes;
257 fclose (f);
258 if (n)
259 delete n;
261 if (total_download_bytes > 0)
263 int df = diskfull (get_root_dir ().c_str());
264 Progress.SetBar3(df);
267 return 0;