X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fmswindows.c;h=179773e05fccfd99a9d566b6385540ca0ddbc9c5;hp=909c2abc07896575504e7c2c3e4665de936b0808;hb=HEAD;hpb=908d7a4bcee5adb7d4768499282cc83075d0332e
diff --git a/src/mswindows.c b/src/mswindows.c
index 909c2abc..179773e0 100644
--- a/src/mswindows.c
+++ b/src/mswindows.c
@@ -1,12 +1,13 @@
/* mswindows.c -- Windows-specific support
- Copyright (C) 1995, 1996, 1997, 1998, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+ Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
@@ -15,42 +16,30 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget. If not, see .
-In addition, as a special exception, the Free Software Foundation
-gives permission to link the code of its release of Wget with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables. You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL". If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so. If you do not wish to do
-so, delete this exception statement from your version. */
+Additional permission under GNU GPL version 3 section 7
-#include
+If you modify this program, or any covered work, by linking or
+combining it with the OpenSSL project's OpenSSL library (or a
+modified version of that library), containing parts covered by the
+terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
+grants you additional permission to convey the resulting work.
+Corresponding Source for a non-source form of such a combination
+shall include the source code for the parts of OpenSSL used as well
+as that of the covered work. */
+
+#define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
+
+#include "wget.h"
#include
#include
#include
-#include
#include
#include
-#ifdef HACK_BCC_UTIME_BUG
-# include
-# include
-# ifdef HAVE_UTIME_H
-# include
-# endif
-# ifdef HAVE_SYS_UTIME_H
-# include
-# endif
-#endif
-
-#define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
-#include "wget.h"
#include "utils.h"
#include "url.h"
@@ -71,144 +60,21 @@ void log_request_redirect_output (const char *);
void
xsleep (double seconds)
{
-#ifdef HAVE_USLEEP
+#if defined(HAVE_USLEEP) && defined(HAVE_SLEEP)
if (seconds > 1000)
{
/* Explained in utils.c. */
sleep (seconds);
seconds -= (long) seconds;
}
- usleep (seconds * 1000000L);
+ usleep (seconds * 1000000);
#else /* not HAVE_USLEEP */
SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
#endif /* not HAVE_USLEEP */
}
-#if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER < 1300)
-
-static inline int
-char_value (char c, int base)
-{
- int value;
- if (c < '0')
- return -1;
- if ('0' <= c && c <= '9')
- value = c - '0';
- else if ('a' <= c && c <= 'z')
- value = c - 'a' + 10;
- else if ('A' <= c && c <= 'Z')
- value = c - 'A' + 10;
- else
- return -1;
- if (value >= base)
- return -1;
- return value;
-}
-
-/* A fairly simple strtoll replacement for MS VC versions that don't
- supply _strtoi64. */
-
-__int64
-str_to_int64 (const char *nptr, char **endptr, int base)
-{
-#define INT64_OVERFLOW 9223372036854775807I64
-#define INT64_UNDERFLOW (-INT64_OVERFLOW - 1)
-
- __int64 result = 0;
- int negative;
-
- if (base != 0 && (base < 2 || base > 36))
- {
- errno = EINVAL;
- return 0;
- }
-
- while (*nptr == ' ' || *nptr == '\t')
- ++nptr;
- if (*nptr == '-')
- {
- negative = 1;
- ++nptr;
- }
- else if (*nptr == '+')
- {
- negative = 0;
- ++nptr;
- }
- else
- negative = 0;
-
- /* If base is 0, determine the real base based on the beginning on
- the number; octal numbers begin with "0", hexadecimal with "0x",
- and the others are considered octal. */
- if (*nptr == '0')
- {
- if ((base == 0 || base == 16)
- &&
- (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
- {
- base = 16;
- nptr += 2;
- }
- else if (base == 0)
- base = 8;
- }
- else if (base == 0)
- base = 10;
-
- if (!negative)
- {
- /* Parse positive number, checking for overflow. */
- int val;
- for (; (val = char_value (*nptr, base)) != -1; ++nptr)
- {
- __int64 newresult = base * result + val;
- if (newresult < result)
- {
- result = INT64_OVERFLOW;
- errno = ERANGE;
- break;
- }
- result = newresult;
- }
- }
- else
- {
- /* Parse negative number, checking for underflow. */
- int val;
- for (; (val = char_value (*nptr, base)) != -1; ++nptr)
- {
- __int64 newresult = base * result - val;
- if (newresult > result)
- {
- result = INT64_UNDERFLOW;
- errno = ERANGE;
- break;
- }
- result = newresult;
- }
- }
- if (endptr)
- *endptr = (char *) nptr;
- return result;
-}
-
-#else /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
-
-__int64
-str_to_int64 (const char *nptr, char **endptr, int base)
-{
-#ifdef _MSC_VER
- return _strtoi64 (nptr, endptr, base);
-#else
- return strtoll (nptr, endptr, base);
-#endif
-}
-
-#endif /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
-
void
-windows_main (int *argc, char **argv, char **exec_name)
+windows_main (char **exec_name)
{
char *p;
@@ -222,9 +88,11 @@ windows_main (int *argc, char **argv, char **exec_name)
static void
ws_cleanup (void)
{
+ xfree ((char*)exec_name);
WSACleanup ();
}
+#if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
static void
ws_hangup (const char *reason)
{
@@ -238,6 +106,7 @@ ws_hangup (const char *reason)
gesture as the parent will wait for us to terminate before resuming. */
FreeConsole ();
}
+#endif
/* Construct the name for a named section (a.k.a. `file mapping') object.
The returned string is dynamically allocated and needs to be xfree()'d. */
@@ -252,7 +121,7 @@ make_section_name (DWORD pid)
struct fake_fork_info
{
HANDLE event;
- int logfile_changed;
+ bool logfile_changed;
char lfilename[MAX_PATH + 1];
};
@@ -287,18 +156,18 @@ fake_fork_child (void)
event = info->event;
- info->logfile_changed = 0;
- if (!opt.lfilename)
+ info->logfile_changed = false;
+ if (!opt.lfilename && (!opt.quiet || opt.server_response))
{
/* See utils:fork_to_background for explanation. */
- FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, 0, &opt.lfilename);
+ FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
if (new_log_fp)
- {
- info->logfile_changed = 1;
- strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
- info->lfilename[sizeof (info->lfilename) - 1] = '\0';
- fclose (new_log_fp);
- }
+ {
+ info->logfile_changed = true;
+ strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
+ info->lfilename[sizeof (info->lfilename) - 1] = '\0';
+ fclose (new_log_fp);
+ }
}
UnmapViewOfFile (info);
@@ -422,7 +291,7 @@ fake_fork (void)
printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
if (info->logfile_changed)
- printf (_("Output will be written to `%s'.\n"), info->lfilename);
+ printf (_("Output will be written to %s.\n"), quote (info->lfilename));
UnmapViewOfFile (info);
@@ -454,7 +323,7 @@ fork_to_background (void)
rv = fake_fork_child ();
if (rv < 0)
{
- fprintf (stderr, "fake_fork_child() failed\n");
+ fprintf (stderr, _("fake_fork_child() failed\n"));
abort ();
}
else if (rv == 0)
@@ -462,7 +331,7 @@ fork_to_background (void)
/* We're the parent. */
fake_fork ();
/* If fake_fork() returns, it failed. */
- fprintf (stderr, "fake_fork() failed\n");
+ fprintf (stderr, _("fake_fork() failed\n"));
abort ();
}
/* If we get here, we're the child. */
@@ -591,14 +460,14 @@ ws_startup (void)
if (err != 0)
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
- exec_name);
+ exec_name);
exit (1);
}
if (data.wVersion < requested)
{
fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
- exec_name);
+ exec_name);
WSACleanup ();
exit (1);
}
@@ -607,34 +476,6 @@ ws_startup (void)
set_sleep_mode ();
SetConsoleCtrlHandler (ws_handler, TRUE);
}
-
-/* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
- (The Borland utime function only works on Windows NT.) */
-
-#ifdef HACK_BCC_UTIME_BUG
-int
-borland_utime (const char *path, const struct utimbuf *times)
-{
- int fd;
- int res;
- struct ftime ft;
- struct tm *ptr_tm;
-
- if ((fd = open (path, O_RDWR)) < 0)
- return -1;
-
- ptr_tm = localtime (×->modtime);
- ft.ft_tsec = ptr_tm->tm_sec >> 1;
- ft.ft_min = ptr_tm->tm_min;
- ft.ft_hour = ptr_tm->tm_hour;
- ft.ft_day = ptr_tm->tm_mday;
- ft.ft_month = ptr_tm->tm_mon + 1;
- ft.ft_year = ptr_tm->tm_year - 80;
- res = setftime (fd, &ft);
- close (fd);
- return res;
-}
-#endif
/* run_with_timeout Windows implementation. */
@@ -677,19 +518,19 @@ thread_helper (void *arg)
}
/* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
- seconds. Returns non-zero if the function was interrupted with a
- timeout, zero otherwise.
+ seconds. Returns true if the function was interrupted with a
+ timeout, false otherwise.
This works by running FUN in a separate thread and terminating the
thread if it doesn't finish in the specified time. */
-int
+bool
run_with_timeout (double seconds, void (*fun) (void *), void *arg)
{
- static HANDLE thread_hnd = NULL;
+ HANDLE thread_hnd;
struct thread_data thread_arg;
DWORD thread_id;
- int rc;
+ bool rc;
DEBUGP (("seconds %.2f, ", seconds));
@@ -697,20 +538,18 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg)
{
blocking_fallback:
fun (arg);
- return 0;
+ return false;
}
- /* Should never happen, but test for recursivety anyway. */
- assert (thread_hnd == NULL);
-
thread_arg.fun = fun;
thread_arg.arg = arg;
thread_arg.ws_error = WSAGetLastError ();
thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
- &thread_arg, 0, &thread_id);
+ &thread_arg, 0, &thread_id);
if (!thread_hnd)
{
- DEBUGP (("CreateThread() failed; %s\n", strerror (GetLastError ())));
+ DEBUGP (("CreateThread() failed; [%#lx]\n",
+ (unsigned long) GetLastError ()));
goto blocking_fallback;
}
@@ -718,133 +557,98 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg)
== WAIT_OBJECT_0)
{
/* Propagate error state (which is per-thread) to this thread,
- so the caller can inspect it. */
+ so the caller can inspect it. */
WSASetLastError (thread_arg.ws_error);
DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
- rc = 0;
+ rc = false;
}
else
{
TerminateThread (thread_hnd, 1);
- rc = 1;
+ rc = true;
}
- CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
+ CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
thread_hnd = NULL;
return rc;
}
-
-/* Wget expects network calls such as connect, recv, send, etc., to set
- errno on failure. To achieve that, Winsock calls are wrapped with code
- that, in case of error, sets errno to the value of WSAGetLastError().
- In addition, we provide a wrapper around strerror, which recognizes
- Winsock errors and prints the appropriate error message. */
-
-/* Define a macro that creates a function definition that wraps FUN into
- a function that sets errno the way the rest of the code expects. */
-
-#define WRAP(fun, decl, call) int wrapped_##fun decl { \
- int retval = fun call; \
- if (retval < 0) \
- errno = WSAGetLastError (); \
- return retval; \
-}
-WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
-WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
-WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
-WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
-WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
-WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
- (n, r, w, e, tm))
-WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
-WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
-WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
- (s, level, opt, val, len))
-WRAP (closesocket, (int s), (s))
-
-/* Return the text of the error message for Winsock error WSERR. */
-
-static const char *
-get_winsock_error (int wserr)
+
+#ifdef ENABLE_IPV6
+/* An inet_ntop implementation that uses WSAAddressToString.
+ Prototype complies with POSIX 1003.1-2004. This is only used under
+ IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
+
+const char *
+inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
{
- switch (wserr) {
- case WSAEINTR: return "Interrupted system call";
- case WSAEBADF: return "Bad file number";
- case WSAEACCES: return "Permission denied";
- case WSAEFAULT: return "Bad address";
- case WSAEINVAL: return "Invalid argument";
- case WSAEMFILE: return "Too many open files";
- case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
- case WSAEINPROGRESS: return "Operation now in progress";
- case WSAEALREADY: return "Operation already in progress";
- case WSAENOTSOCK: return "Socket operation on nonsocket";
- case WSAEDESTADDRREQ: return "Destination address required";
- case WSAEMSGSIZE: return "Message too long";
- case WSAEPROTOTYPE: return "Protocol wrong type for socket";
- case WSAENOPROTOOPT: return "Bad protocol option";
- case WSAEPROTONOSUPPORT: return "Protocol not supported";
- case WSAESOCKTNOSUPPORT: return "Socket type not supported";
- case WSAEOPNOTSUPP: return "Operation not supported";
- case WSAEPFNOSUPPORT: return "Protocol family not supported";
- case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
- case WSAEADDRINUSE: return "Address already in use";
- case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
- case WSAENETDOWN: return "Network is down";
- case WSAENETUNREACH: return "Network is unreachable";
- case WSAENETRESET: return "Network dropped connection on reset";
- case WSAECONNABORTED: return "Software caused connection abort";
- case WSAECONNRESET: return "Connection reset by peer";
- case WSAENOBUFS: return "No buffer space available";
- case WSAEISCONN: return "Socket is already connected";
- case WSAENOTCONN: return "Socket is not connected";
- case WSAESHUTDOWN: return "Cannot send after socket shutdown";
- case WSAETOOMANYREFS: return "Too many references";
- case WSAETIMEDOUT: return "Connection timed out";
- case WSAECONNREFUSED: return "Connection refused";
- case WSAELOOP: return "Too many levels of symbolic links";
- case WSAENAMETOOLONG: return "File name too long";
- case WSAEHOSTDOWN: return "Host is down";
- case WSAEHOSTUNREACH: return "No route to host";
- case WSAENOTEMPTY: return "Not empty";
- case WSAEPROCLIM: return "Too many processes";
- case WSAEUSERS: return "Too many users";
- case WSAEDQUOT: return "Bad quota";
- case WSAESTALE: return "Something is stale";
- case WSAEREMOTE: return "Remote error";
- case WSAEDISCON: return "Disconnected";
-
- /* Extended Winsock errors */
- case WSASYSNOTREADY: return "Winsock library is not ready";
- case WSANOTINITIALISED: return "Winsock library not initalised";
- case WSAVERNOTSUPPORTED: return "Winsock version not supported";
-
- case WSAHOST_NOT_FOUND: return "Host not found";
- case WSATRY_AGAIN: return "Host not found, try again";
- case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
- case WSANO_DATA: return "No data record of requested type";
-
- default:
- return NULL;
- }
+ /* struct sockaddr can't accomodate struct sockaddr_in6. */
+ union {
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
+ } sa;
+ DWORD dstlen = cnt;
+ size_t srcsize;
+
+ xzero (sa);
+ switch (af)
+ {
+ case AF_INET:
+ sa.sin.sin_family = AF_INET;
+ sa.sin.sin_addr = *(struct in_addr *) src;
+ srcsize = sizeof (sa.sin);
+ break;
+ case AF_INET6:
+ sa.sin6.sin6_family = AF_INET6;
+ sa.sin6.sin6_addr = *(struct in6_addr *) src;
+ srcsize = sizeof (sa.sin6);
+ break;
+ default:
+ abort ();
+ }
+
+ if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
+ {
+ errno = WSAGetLastError();
+ return NULL;
+ }
+ return (const char *) dst;
}
+#endif
-/* Return the error message corresponding to ERR. This is different
- from Windows libc strerror() in that it handles Winsock errors
- correctly. */
-const char *
-windows_strerror (int err)
+void
+set_windows_fd_as_blocking_socket (int fd)
{
- const char *p;
- if (err >= 0 && err < sys_nerr)
- return strerror (err);
- else if ((p = get_winsock_error (err)) != NULL)
- return p;
- else
+ /* 04/2011
+ gnulib select() converts blocking sockets to nonblocking in windows
+ discussed here:
+ http://old.nabble.com/blocking-socket-is-nonblocking-after-calling-gnulib-
+ select%28%29-in-windows-td31432857.html
+
+ wget uses blocking sockets so we must convert them back to blocking.
+ */
+ int ret = 0;
+ int wsagle = 0;
+ const int zero = 0;
+
+ do
{
- static char buf[32];
- snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
- return buf;
+ if(wsagle == WSAEINPROGRESS)
+ Sleep(1); /* use windows sleep */
+
+ WSASetLastError (0);
+ ret = ioctl (fd, FIONBIO, &zero);
+ wsagle = WSAGetLastError ();
+ }
+ while (ret && (wsagle == WSAEINPROGRESS));
+
+ if(ret)
+ {
+ fprintf (stderr,
+ _("ioctl() failed. The socket could not be set as blocking.\n") );
+ DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
+ abort ();
}
+ return;
}