diff --git a/configure.ac b/configure.ac index 444e86224..64f986ca3 100644 --- a/configure.ac +++ b/configure.ac @@ -407,7 +407,7 @@ case $host_os in have_msw="yes" CXXFLAGS="$CXXFLAGS -mms-bitfields -mwin32 -mwindows" CPPFLAGS="$CPPFLAGS -DWIN32 -D_WIN32 -DWIN32_LEAN_AND_MEAN" - LIBS="$LIBS -lshell32 -lws2_32" + LIBS="$LIBS -liphlpapi -lshell32 -lws2_32" transmissionlocaledir="locale" if test -z "$host_alias"; then hostaliaswindres= diff --git a/libtransmission/bencode.c b/libtransmission/bencode.c index 35d24ef4f..1e8e9d9bf 100644 --- a/libtransmission/bencode.c +++ b/libtransmission/bencode.c @@ -18,9 +18,10 @@ #include /* realpath() */ #include -#ifdef WIN32 +#ifdef WIN32 /* tr_mkstemp() */ #include - #define fsync(fd) _commit(fd) + #define _S_IREAD 256 + #define _S_IWRITE 128 #endif #include /* stat() */ @@ -1633,6 +1634,31 @@ tr_bencToStr( const tr_benc * top, tr_fmt_mode mode, int * len ) return ret; } +/* portability wrapper for mkstemp(). */ +static int +tr_mkstemp( char * template ) +{ +#ifdef WIN32 + const int flags = O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED; + const mode_t mode = _S_IREAD | _S_IWRITE; + mktemp( template ); + return open( template, flags, mode ); +#else + return mkstemp( template ); +#endif +} + +/* portability wrapper for fsync(). */ +static void +tr_fsync( int fd ) +{ +#ifdef WIN32 + _commit( fd ); +#else + fsync( fd ); +#endif +} + int tr_bencToFile( const tr_benc * top, tr_fmt_mode mode, const char * filename ) { @@ -1642,13 +1668,13 @@ tr_bencToFile( const tr_benc * top, tr_fmt_mode mode, const char * filename ) char buf[TR_PATH_MAX]; /* follow symlinks to find the "real" file, to make sure the temporary - * we build with mkstemp() is created on the right partition */ + * we build with tr_mkstemp() is created on the right partition */ if( tr_realpath( filename, buf ) != NULL ) filename = buf; /* if the file already exists, try to move it out of the way & keep it as a backup */ tmp = tr_strdup_printf( "%s.tmp.XXXXXX", filename ); - fd = mkstemp( tmp ); + fd = tr_mkstemp( tmp ); if( fd >= 0 ) { int len; @@ -1657,7 +1683,7 @@ tr_bencToFile( const tr_benc * top, tr_fmt_mode mode, const char * filename ) if( write( fd, str, len ) == (ssize_t)len ) { - fsync( fd ); + tr_fsync( fd ); close( fd ); if( !unlink( filename ) || ( errno == ENOENT ) ) @@ -1728,3 +1754,4 @@ tr_bencLoadFile( tr_benc * setme, tr_fmt_mode mode, const char * filename ) tr_free( content ); return err; } + diff --git a/libtransmission/blocklist.c b/libtransmission/blocklist.c index cb7eaa5a5..ae2c00d01 100644 --- a/libtransmission/blocklist.c +++ b/libtransmission/blocklist.c @@ -15,6 +15,8 @@ #include #ifdef WIN32 + #include + #define WINVER WindowsXP #include #endif @@ -33,6 +35,10 @@ #include "net.h" #include "utils.h" +#ifndef O_BINARY + #define O_BINARY 0 +#endif + /*** **** PRIVATE @@ -80,18 +86,14 @@ blocklistLoad( tr_blocklist * b ) if( stat( b->filename, &st ) == -1 ) return; - fd = open( b->filename, O_RDONLY ); + fd = open( b->filename, O_RDONLY | O_BINARY ); if( fd == -1 ) { tr_err( err_fmt, b->filename, tr_strerror( errno ) ); return; } -#ifndef WIN32 b->rules = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 ); -#else - b->rules = mmap( NULL, st.st_size, 0, 0, fd, 0 ); -#endif if( !b->rules ) { tr_err( err_fmt, b->filename, tr_strerror( errno ) ); @@ -315,7 +317,7 @@ _tr_blocklistSetContent( tr_blocklist * b, return 0; } - in = fopen( filename, "r" ); + in = fopen( filename, "rb" ); if( !in ) { tr_err( err_fmt, filename, tr_strerror( errno ) ); @@ -362,7 +364,7 @@ _tr_blocklistSetContent( tr_blocklist * b, { char * base = tr_basename( b->filename ); - tr_inf( _( "Blocklist \"%1$s\" updated with %2$'d entries" ), base, outCount ); + tr_inf( _( "Blocklist \"%s\" updated with %'d entries" ), base, outCount ); tr_free( base ); } diff --git a/libtransmission/net.c b/libtransmission/net.c index d3a18d131..eccb673e2 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -32,8 +32,8 @@ #include #ifdef WIN32 - #include /* inet_addr */ - #include + #define _WIN32_WINNT 0x0501 + #include #else #include #include diff --git a/libtransmission/net.h b/libtransmission/net.h index 835ddeff8..286ae9b99 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -31,9 +31,7 @@ #ifdef WIN32 #include - #include - #include - typedef int socklen_t; + #include #else #include #include @@ -42,6 +40,7 @@ #endif #ifdef WIN32 + #define EADDRINUSE WSAEADDRINUSE #define ECONNREFUSED WSAECONNREFUSED #define ECONNRESET WSAECONNRESET #define EHOSTUNREACH WSAEHOSTUNREACH diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 77a9df79b..b10a33df6 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -1658,6 +1658,15 @@ tr_torrentClearRatioLimitHitCallback( tr_torrent * torrent ) tr_torrentSetRatioLimitHitCallback( torrent, NULL, NULL ); } +static void +tr_setenv( const char * name, const char * value, tr_bool override ) +{ +#ifdef WIN32 + putenv( tr_strdup_printf( "%s=%s", name, value ) ); /* leaks memory... */ +#else + setenv( name, value, override ); +#endif +} static void torrentCallScript( tr_torrent * tor, const char * script ) @@ -1673,16 +1682,16 @@ torrentCallScript( tr_torrent * tor, const char * script ) clearenv( ); #endif - setenv( "TR_APP_VERSION", SHORT_VERSION_STRING, 1 ); + tr_setenv( "TR_APP_VERSION", SHORT_VERSION_STRING, 1 ); tr_snprintf( buf, sizeof( buf ), "%d", tr_torrentId( tor ) ); - setenv( "TR_TORRENT_ID", buf, 1 ); - setenv( "TR_TORRENT_NAME", tr_torrentName( tor ), 1 ); - setenv( "TR_TORRENT_DIR", tor->currentDir, 1 ); - setenv( "TR_TORRENT_HASH", tor->info.hashString, 1 ); + tr_setenv( "TR_TORRENT_ID", buf, 1 ); + tr_setenv( "TR_TORRENT_NAME", tr_torrentName( tor ), 1 ); + tr_setenv( "TR_TORRENT_DIR", tor->currentDir, 1 ); + tr_setenv( "TR_TORRENT_HASH", tor->info.hashString, 1 ); tr_strlcpy( buf, ctime( &now ), sizeof( buf ) ); *strchr( buf,'\n' ) = '\0'; - setenv( "TR_TIME_LOCALTIME", buf, 1 ); + tr_setenv( "TR_TIME_LOCALTIME", buf, 1 ); tr_torinf( tor, "Calling script \"%s\"", script ); system( script ); } diff --git a/libtransmission/tr-dht.c b/libtransmission/tr-dht.c index bc8cde39e..638c2d5a7 100644 --- a/libtransmission/tr-dht.c +++ b/libtransmission/tr-dht.c @@ -25,13 +25,19 @@ THE SOFTWARE. #include /* posix */ -#include /* sockaddr_in */ #include /* sig_atomic_t */ #include -#include -#include /* socket(), bind() */ -#include #include /* close() */ +#ifdef WIN32 + #include + #define _WIN32_WINNT 0x0501 /* freeaddrinfo(),getaddrinfo(),getnameinfo() */ + #include +#else + #include + #include /* socket(), bind() */ + #include + #include /* sockaddr_in */ +#endif /* third party */ #include diff --git a/libtransmission/trevent.c b/libtransmission/trevent.c index 497929af5..1378d986f 100644 --- a/libtransmission/trevent.c +++ b/libtransmission/trevent.c @@ -26,79 +26,95 @@ #ifdef WIN32 -#include +#include "utils.h" +#include static int pgpipe( int handles[2] ) { - SOCKET s; - struct sockaddr_in serv_addr; - int len = sizeof( serv_addr ); + SOCKET s; + struct sockaddr_in serv_addr; + int len = sizeof( serv_addr ); - handles[0] = handles[1] = INVALID_SOCKET; + handles[0] = handles[1] = INVALID_SOCKET; - if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to create socket: %ui", WSAGetLastError()))); */ - return -1; - } + if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) + { + tr_dbg("pgpipe failed to create socket: %ui", WSAGetLastError()); + return -1; + } - memset( &serv_addr, 0, sizeof( serv_addr ) ); - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(0); - serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to bind: %ui", WSAGetLastError()))); */ - closesocket(s); - return -1; - } - if (listen(s, 1) == SOCKET_ERROR) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to listen: %ui", WSAGetLastError()))); */ - closesocket(s); - return -1; - } - if (getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to getsockname: %ui", WSAGetLastError()))); */ - closesocket(s); - return -1; - } - if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to create socket 2: %ui", WSAGetLastError()))); */ - closesocket(s); - return -1; - } - - if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to connect socket: %ui", WSAGetLastError()))); */ - closesocket(s); - return -1; - } - if ((handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET) - { -/* ereport(LOG, (errmsg_internal("pgpipe failed to accept socket: %ui", WSAGetLastError()))); */ - closesocket(handles[1]); - handles[1] = INVALID_SOCKET; - closesocket(s); - return -1; - } + memset( &serv_addr, 0, sizeof( serv_addr ) ); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(0); + serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) + { + tr_dbg("pgpipe failed to bind: %ui", WSAGetLastError()); closesocket(s); - return 0; + return -1; + } + if (listen(s, 1) == SOCKET_ERROR) + { + tr_ndbg("event","pgpipe failed to listen: %ui", WSAGetLastError()); + closesocket(s); + return -1; + } + if (getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR) + { + tr_dbg("pgpipe failed to getsockname: %ui", WSAGetLastError()); + closesocket(s); + return -1; + } + if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + { + tr_dbg("pgpipe failed to create socket 2: %ui", WSAGetLastError()); + closesocket(s); + return -1; + } + + if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR) + { + tr_dbg("pgpipe failed to connect socket: %ui", WSAGetLastError()); + closesocket(s); + return -1; + } + if ((handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET) + { + tr_dbg("pgpipe failed to accept socket: %ui", WSAGetLastError()); + closesocket(handles[1]); + handles[1] = INVALID_SOCKET; + closesocket(s); + return -1; + } + closesocket(s); + return 0; } static int piperead( int s, char *buf, int len ) { - int ret = recv(s, buf, len, 0); + int ret = recv(s, buf, len, 0); + int werror = 0; - if (ret < 0 && WSAGetLastError() == WSAECONNRESET) - /* EOF on the pipe! (win32 socket based implementation) */ - ret = 0; - return ret; + if (ret < 0) { + werror= WSAGetLastError(); + switch(werror) { + /* simplified error mapping (not valid for connect) */ + case WSAEWOULDBLOCK: + errno = EAGAIN; + break; + case WSAECONNRESET: + /* EOF on the pipe! (win32 socket based implementation) */ + ret = 0; + /* fall through */ + default: + errno = werror; + break; + } + } else + errno = 0; + return ret; } #define pipe(a) pgpipe(a) diff --git a/qt/qtr.ico b/qt/qtr.ico new file mode 100644 index 000000000..a11bbb337 Binary files /dev/null and b/qt/qtr.ico differ diff --git a/qt/qtr.pro b/qt/qtr.pro index 2d89611d2..67968ce62 100644 --- a/qt/qtr.pro +++ b/qt/qtr.pro @@ -9,7 +9,7 @@ INSTALLS += target CONFIG += qt qdbus thread debug link_pkgconfig QT += network -PKGCONFIG = fontconfig libcurl openssl +PKGCONFIG = fontconfig libcurl openssl dbus-1 TRANSMISSION_TOP = .. INCLUDEPATH += $${TRANSMISSION_TOP} @@ -17,7 +17,10 @@ LIBS += $${TRANSMISSION_TOP}/libtransmission/libtransmission.a LIBS += $${TRANSMISSION_TOP}/third-party/dht/libdht.a LIBS += $${TRANSMISSION_TOP}/third-party/miniupnp/libminiupnp.a LIBS += $${TRANSMISSION_TOP}/third-party/libnatpmp/libnatpmp.a -LIBS += -levent +unix: LIBS += -levent +win32:DEFINES += QT_DBUS +win32:LIBS += -levent -lws2_32 -lintl +win32:LIBS += -lidn -liconv -lwldap32 -liphlpapi TRANSLATIONS += transmission_en.ts transmission_ru.ts @@ -32,3 +35,4 @@ SOURCES += about.cc app.cc dbus-adaptor.cc details.cc file-tree.cc filters.cc \ HEADERS += $$replace(SOURCES, .cc, .h) HEADERS += speed.h types.h +win32:RC_FILE = qtr.rc diff --git a/qt/qtr.rc b/qt/qtr.rc new file mode 100644 index 000000000..a86c74bed --- /dev/null +++ b/qt/qtr.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "qtr.ico" diff --git a/qt/utils.cc b/qt/utils.cc index dfa0a0c37..73d304754 100644 --- a/qt/utils.cc +++ b/qt/utils.cc @@ -76,12 +76,12 @@ Utils :: sizeToString( double size ) else if( size < (int64_t)GIGABYTE_FACTOR ) { displayed_size = (double)size / MEGABYTE_FACTOR; - str = tr( "%L1 MiB" ).arg( displayed_size, 0, 'f', 1 ); + str = tr( "%L1 MiB" ).arg( displayed_size, 0, 'f', 2 ); } else { displayed_size = (double) size / GIGABYTE_FACTOR; - str = tr( "%L1 GiB" ).arg( displayed_size, 0, 'f', 1 ); + str = tr( "%L1 GiB" ).arg( displayed_size, 0, 'f', 3 ); } }