]> cygwin.com Git - cygwin-apps/setup.git/blob - geturl.cc
Use solver to check for problems and produce a list of package transactions
[cygwin-apps/setup.git] / geturl.cc
1 /*
2
3
4 * Copyright (c) 2000, 2001, Red Hat, Inc.
5 *
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.
10 *
11 * A copy of the GNU General Public License can be found at
12 * http://www.gnu.org/
13 *
14 * Written by DJ Delorie <dj@cygnus.com>
15 *
16 */
17
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 */
21
22 #include "win32.h"
23 #include "commctrl.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28
29 #include "dialog.h"
30 #include "geturl.h"
31 #include "resource.h"
32 #include "netio.h"
33 #include "msg.h"
34 #include "io_stream.h"
35 #include "io_stream_memory.h"
36 #include "state.h"
37 #include "diskfull.h"
38 #include "mount.h"
39 #include "filemanip.h"
40
41 #include "threebar.h"
42
43 #include "Exception.h"
44
45 #include "LogSingleton.h"
46
47 using namespace std;
48
49 extern ThreeBarProgressPage Progress;
50
51 static int max_bytes = 0;
52 static int is_local_install = 0;
53
54 long long int total_download_bytes = 0;
55 long long int total_download_bytes_sofar = 0;
56
57 static DWORD start_tics;
58
59 static void
60 init_dialog (const string &url, int length)
61 {
62 if (is_local_install)
63 return;
64
65 string::size_type divide = url.find_last_of('/');
66 max_bytes = length;
67 Progress.SetText1("Downloading...");
68 Progress.SetText2((url.substr(divide + 1) + " from "
69 + url.substr(0, divide)).c_str());
70 Progress.SetText3("Connecting...");
71 Progress.SetBar1(0);
72 start_tics = GetTickCount ();
73 }
74
75
76 static void
77 progress (int bytes)
78 {
79 if (is_local_install)
80 return;
81 static char buf[100];
82 double kbps;
83 static unsigned int last_tics = 0;
84 DWORD tics = GetTickCount ();
85 if (tics == start_tics) // to prevent division by zero
86 return;
87 if (tics < last_tics + 200) // to prevent flickering updates
88 return;
89 last_tics = tics;
90
91 kbps = ((double)bytes) / (double)(tics - start_tics);
92 if (max_bytes > 0)
93 {
94 int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
95 Progress.SetBar1(bytes, max_bytes);
96 sprintf (buf, "%d %% (%dk/%dk) %03.1f kB/s",
97 perc, bytes / 1000, max_bytes / 1000, kbps);
98 if (total_download_bytes > 0)
99 Progress.SetBar2(total_download_bytes_sofar + bytes,
100 total_download_bytes);
101 }
102 else
103 sprintf (buf, "%d %2.1f kB/s", bytes, kbps);
104
105 Progress.SetText3(buf);
106 }
107
108 static void
109 getUrlToStream (const string &_url, io_stream *output)
110 {
111 is_local_install = (source == IDC_SOURCE_LOCALDIR);
112 init_dialog (_url, 0);
113 NetIO *n = NetIO::open (_url.c_str(), true);
114 if (!n || !n->ok ())
115 {
116 delete n;
117 throw new Exception (TOSTRING(__LINE__) " " __FILE__, "Error opening url", APPERR_IO_ERROR);
118 }
119
120 if (n->file_size)
121 max_bytes = n->file_size;
122
123 int total_bytes = 0;
124 progress (0);
125 while (1)
126 {
127 char buf[2048];
128 ssize_t rlen, wlen;
129 rlen = n->read (buf, 2048);
130 if (rlen > 0)
131 {
132 wlen = output->write (buf, rlen);
133 if (wlen != rlen)
134 /* FIXME: Show an error message */
135 break;
136 total_bytes += rlen;
137 progress (total_bytes);
138 }
139 else
140 break;
141 }
142 if (n)
143 delete (n);
144 /* reseeking is up to the recipient if desired */
145
146 Log (LOG_BABBLE) << "Fetched URL: " << _url << endLog;
147 }
148
149 io_stream *
150 get_url_to_membuf (const string &_url, HWND owner)
151 {
152 io_stream_memory *membuf = new io_stream_memory ();
153 try
154 {
155 getUrlToStream (_url, membuf);
156
157 if (membuf->seek (0, IO_SEEK_SET))
158 {
159 if (membuf)
160 delete membuf;
161 Log (LOG_BABBLE) << "get_url_to_membuf(): seek (0) failed for membuf!" << endLog;
162 return 0;
163 }
164 return membuf;
165 }
166 catch (Exception *e)
167 {
168 if (e->errNo() != APPERR_IO_ERROR)
169 throw e;
170 delete membuf;
171 return 0;
172 }
173 }
174
175 // predicate: url has no '\0''s in it.
176 string
177 get_url_to_string (const string &_url, HWND owner)
178 {
179 io_stream *stream = get_url_to_membuf (_url, owner);
180 if (!stream)
181 return string();
182 size_t bytes = stream->get_size ();
183 if (!bytes)
184 {
185 /* zero length, or error retrieving length */
186 delete stream;
187 Log (LOG_BABBLE) << "get_url_to_string(): couldn't retrieve buffer size, or zero length buffer" << endLog;
188 return string();
189 }
190 char temp [bytes + 1];
191 /* membufs are quite safe */
192 stream->read (temp, bytes);
193 temp [bytes] = '\0';
194 delete stream;
195 return string(temp);
196 }
197
198 int
199 get_url_to_file (const string &_url,
200 const string &_filename,
201 int expected_length,
202 HWND owner)
203 {
204 Log (LOG_BABBLE) << "get_url_to_file " << _url << " " << _filename << endLog;
205 if (total_download_bytes > 0)
206 {
207 int df = diskfull (get_root_dir ().c_str());
208 Progress.SetBar3(df);
209 }
210 init_dialog (_url, expected_length);
211
212 remove (_filename.c_str()); /* but ignore errors */
213
214 NetIO *n = NetIO::open (_url.c_str(), false);
215 if (!n || !n->ok ())
216 {
217 delete n;
218 return 1;
219 }
220
221 FILE *f = nt_fopen (_filename.c_str(), "wb");
222 if (!f)
223 {
224 const char *err = strerror (errno);
225 if (!err)
226 err = "(unknown error)";
227 fatal (owner, IDS_ERR_OPEN_WRITE, _filename.c_str(), err);
228 }
229
230 if (n->file_size)
231 max_bytes = n->file_size;
232
233 int total_bytes = 0;
234 progress (0);
235 while (1)
236 {
237 char buf[8192];
238 int count;
239 count = n->read (buf, sizeof (buf));
240 if (count <= 0)
241 break;
242 fwrite (buf, 1, count, f);
243 total_bytes += count;
244 progress (total_bytes);
245 }
246
247 total_download_bytes_sofar += total_bytes;
248
249 fclose (f);
250 if (n)
251 delete n;
252
253 if (total_download_bytes > 0)
254 {
255 int df = diskfull (get_root_dir ().c_str());
256 Progress.SetBar3(df);
257 }
258
259 return 0;
260 }
261
This page took 0.047305 seconds and 5 git commands to generate.