diff --git a/acconfig.h b/acconfig.h index e87197fb..1e1bb19c 100644 --- a/acconfig.h +++ b/acconfig.h @@ -39,3 +39,14 @@ /* SSL */ #undef HAVE_OPENSSL + +/* If set to 64, enables 64bit off_t for some systems (eg. Linux, Solaris) */ +#undef _FILE_OFFSET_BITS + +/* What type should be used for uoff_t */ +#undef UOFF_T_INT +#undef UOFF_T_LONG +#undef UOFF_T_LONG_LONG + +/* printf()-format for uoff_t, eg. "u" or "lu" or "llu" */ +#undef PRIuUOFF_T diff --git a/configure.in b/configure.in index 45667592..e2160369 100644 --- a/configure.in +++ b/configure.in @@ -183,6 +183,12 @@ AC_ARG_WITH(perl, fi, want_perl=static) +AC_ARG_WITH(file-offset-size, +[ --with-file-offset-size=BITS Set size of file offsets. Usually 32 or 64. + (default: 64 if available)], + preferred_off_t_bits=$withval, + preferred_off_t_bits=64) + AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Enable IPv6 support], if test x$enableval = xyes; then @@ -262,6 +268,54 @@ AC_DEFINE(socklen_t, int, Define to 'int' if doesn't define.) fi AC_MSG_RESULT($irssi_cv_type_socklen_t) +dnl * off_t checks, try to make it 64bit +AC_DEFINE_UNQUOTED(_FILE_OFFSET_BITS, $preferred_off_t_bits) + +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long long) + +dnl * older autoconfs don't include sys/types.h, so do it manually +AC_MSG_CHECKING([size of off_t]) +AC_TRY_RUN([ + #include + #include + int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(off_t)); + return 0; + } +], [ + sizeof_off_t=`cat conftestval` + rm -f conftestval +], [ + AC_ERROR([Unsupported off_t size]) +]) +AC_MSG_RESULT($sizeof_off_t) + +if test $sizeof_off_t = 8; then + offt_64bit=yes +else + offt_64bit=no +fi + +if test x$sizeof_off_t = x$ac_cv_sizeof_long; then + # try to use unsigned long always first + AC_DEFINE_UNQUOTED(PRIuUOFF_T, "lu") + AC_DEFINE(UOFF_T_LONG) +elif test x$sizeof_off_t = x$ac_cv_sizeof_int; then + # next try int + AC_DEFINE_UNQUOTED(PRIuUOFF_T, "u") + AC_DEFINE(UOFF_T_INT) +elif test x$sizeof_off_t = x$ac_cv_sizeof_long_long; then + # and finally long long + AC_DEFINE_UNQUOTED(PRIuUOFF_T, "llu") + AC_DEFINE(UOFF_T_LONG_LONG) +else + AC_ERROR([Couldn't find integer type for off_t]) +fi + dnl ** dnl ** check for socks dnl ** @@ -892,11 +946,11 @@ elif test "x$want_terminfo" = "xyes"; then else text="yes, using curses" fi -echo "Building text frontend ..... : $text" -echo "Building irssi bot ......... : $want_irssibot" -echo "Building irssi proxy ....... : $want_irssiproxy" +echo "Building text frontend ........... : $text" +echo "Building irssi bot ............... : $want_irssibot" +echo "Building irssi proxy ............. : $want_irssiproxy" if test "x$have_gmodule" = "xyes"; then - echo "Building with module support : yes" + echo "Building with module support ..... : yes" else echo "Building with module support : NO!! /LOAD will not work!" echo " - You're missing gmodule (comes with glib) for some reason," @@ -904,14 +958,14 @@ else fi if test "x$want_perl" = "xstatic"; then - echo "Building with Perl support . : static (in irssi binary)" + echo "Building with Perl support ....... : static (in irssi binary)" elif test "x$want_perl" = "xmodule"; then - echo "Building with Perl support . : module" + echo "Building with Perl support ....... : module" else if test -z "$perl_check_error"; then - echo "Building with Perl support . : no" + echo "Building with Perl support ....... : no" else - echo "Building with Perl support . : NO!" + echo "Building with Perl support ....... : NO!" echo " - $perl_check_error" fi fi @@ -933,7 +987,7 @@ if test "x$want_perl" != "xno"; then if test -z "$perl_library_dir"; then perl_library_dir="(site default - `$perlpath -e 'use Config; print $Config{sitearch}'`)" fi - echo "Perl library directory ..... : $perl_library_dir" + echo "Perl library directory ........... : $perl_library_dir" if test "x$perl_prefix_note" = "xyes"; then echo " - NOTE: This was automatically set to the same directory you gave with" echo " --prefix. If you want the perl libraries to install to their 'correct'" @@ -941,12 +995,13 @@ if test "x$want_perl" != "xno"; then echo " Anyway, installing perl to this directory should work just as well." fi fi -echo "Install prefix ............. : $prefix" +echo "Install prefix ................... : $prefix" echo -echo "Building with IPv6 support . : $want_ipv6" -echo "Building with SSL support .. : ${enable_openssl}" +echo "Building with IPv6 support ....... : $want_ipv6" +echo "Building with SSL support ........ : ${enable_openssl}" +echo "Building with 64bit DCC support .. : $offt_64bit" if test "x$enable_openssl" = "xno" -a "x$ssl_error" != "x"; then echo " - $ssl_error" fi diff --git a/src/common.h b/src/common.h index 95a49b2f..66af15cf 100644 --- a/src/common.h +++ b/src/common.h @@ -52,6 +52,16 @@ # include #endif +#if defined (UOFF_T_INT) +typedef unsigned int uoff_t; +#elif defined (UOFF_T_LONG) +typedef unsigned long uoff_t; +#elif defined (UOFF_T_LONG_LONG) +typedef unsigned long long uoff_t; +#else +# error uoff_t size not set +#endif + /* input functions */ #define G_INPUT_READ (1 << 0) #define G_INPUT_WRITE (1 << 1) diff --git a/src/core/misc.c b/src/core/misc.c index 886c40f1..00f9d096 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -592,6 +592,20 @@ int dec2octal(int decimal) return octal; } +/* string -> uoff_t */ +uoff_t str_to_uofft(const char *str) +{ + uoff_t ret; + + ret = 0; + while (*str != '\0') { + ret = ret*10 + (*str - '0'); + str++; + } + + return ret; +} + /* convert all low-ascii (<32) to ^ combinations */ char *show_lowascii(const char *channel) { diff --git a/src/core/misc.h b/src/core/misc.h index b9002c1c..95946077 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -85,6 +85,9 @@ char *replace_chars(char *str, char from, char to); int octal2dec(int octal); int dec2octal(int decimal); +/* string -> uoff_t */ +uoff_t str_to_uofft(const char *str); + /* convert all low-ascii (<32) to ^ combinations */ char *show_lowascii(const char *channel); diff --git a/src/irc/dcc/dcc-autoget.c b/src/irc/dcc/dcc-autoget.c index 459f2a75..87dd00d8 100644 --- a/src/irc/dcc/dcc-autoget.c +++ b/src/irc/dcc/dcc-autoget.c @@ -58,7 +58,7 @@ static void sig_dcc_request(GET_DCC_REC *dcc, const char *nickaddr) /* check file size limit, NOTE: it's still possible to send a bogus file size and then just send what ever sized file.. */ max_size = settings_get_int("dcc_autoget_max_size"); - if (max_size > 0 && (unsigned long) max_size*1024 < dcc->size) + if (max_size > 0 && (uoff_t)max_size*1024 < dcc->size) return; /* ok. but do we want/need to resume? */ diff --git a/src/irc/dcc/dcc-file-rec.h b/src/irc/dcc/dcc-file-rec.h index a05dbc75..fe66a985 100644 --- a/src/irc/dcc/dcc-file-rec.h +++ b/src/irc/dcc/dcc-file-rec.h @@ -1,10 +1,9 @@ #include "dcc-rec.h" -unsigned long size, skipped; /* file size / skipped at start */ +uoff_t size, skipped; /* file size / skipped at start */ int fhandle; /* file handle */ int queue; /* queue number */ /* counter buffer */ char count_buf[4]; int count_pos; - diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index e8847698..9340645d 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -89,7 +89,7 @@ void dcc_get_send_received(GET_DCC_REC *dcc) { guint32 recd; - recd = (guint32) htonl(dcc->transfd); + recd = (guint32) htonl(dcc->transfd & 0xffffffff); memcpy(dcc->count_buf, &recd, 4); dcc->count_pos = @@ -133,7 +133,7 @@ static void sig_dccget_send(GET_DCC_REC *dcc) } memcpy(&recd, dcc->count_buf, 4); - if (recd != (guint32) htonl(dcc->transfd)) + if (recd != (guint32) htonl(dcc->transfd & 0xffffffff)) dcc_get_send_received(dcc); } @@ -323,7 +323,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, char **params, *fname; int paramcount, fileparams; int port, len, quoted = FALSE; - long size; + uoff_t size; /* SEND
[...] */ params = g_strsplit(data, " ", -1); @@ -341,7 +341,7 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, address = params[fileparams]; dcc_str2ip(address, &ip); port = atoi(params[fileparams+1]); - size = atol(params[fileparams+2]); + size = str_to_uofft(params[fileparams+2]); params[fileparams] = NULL; fname = g_strjoinv(" ", params); diff --git a/src/irc/dcc/dcc-rec.h b/src/irc/dcc/dcc-rec.h index 02cde37c..9fdd9582 100644 --- a/src/irc/dcc/dcc-rec.h +++ b/src/irc/dcc/dcc-rec.h @@ -18,7 +18,7 @@ int port; /* port we're connected in */ GIOChannel *handle; /* socket handle */ int tagconn, tagread, tagwrite; time_t starttime; /* transfer start time */ -unsigned long transfd; /* bytes transferred */ +uoff_t transfd; /* bytes transferred */ unsigned int destroyed:1; /* We're about to destroy this DCC recond */ diff --git a/src/irc/dcc/dcc-resume.c b/src/irc/dcc/dcc-resume.c index b273c54d..3cae3fa5 100644 --- a/src/irc/dcc/dcc-resume.c +++ b/src/irc/dcc/dcc-resume.c @@ -45,7 +45,7 @@ static FILE_DCC_REC *dcc_resume_find(int type, const char *nick, int port) } static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick, - FILE_DCC_REC **dcc, unsigned long *size) + FILE_DCC_REC **dcc, uoff_t *size) { char **params; int paramcount; @@ -57,7 +57,7 @@ static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick, if (paramcount >= 3) { port = atoi(params[paramcount-2]); - *size = strtoul(params[paramcount-1], NULL, 10); + *size = str_to_uofft(params[paramcount-1]); *dcc = dcc_resume_find(type, nick, port); } @@ -66,14 +66,14 @@ static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick, } static int dcc_resume_file_check(FILE_DCC_REC *dcc, IRC_SERVER_REC *server, - unsigned long size) + uoff_t size) { if (size >= dcc->size) { /* whole file sent */ dcc->starttime = time(NULL); dcc_reject(DCC(dcc), server); - } else if (lseek(dcc->fhandle, size, SEEK_SET) != (long)size) { - /* error, or trying to seek after end of file */ + } else if (lseek(dcc->fhandle, (off_t)size, SEEK_SET) != (off_t)size) { + /* error */ dcc_reject(DCC(dcc), server); } else { dcc->transfd = dcc->skipped = size; @@ -90,15 +90,15 @@ static void ctcp_msg_dcc_resume(IRC_SERVER_REC *server, const char *data, { FILE_DCC_REC *dcc; char *str; - unsigned long size; + uoff_t size; if (!dcc_ctcp_resume_parse(DCC_SEND_TYPE, data, nick, &dcc, &size)) { signal_emit("dcc error ctcp", 5, "RESUME", data, nick, addr, target); } else if (dcc != NULL && dcc_resume_file_check(dcc, server, size)) { str = g_strdup_printf(DCC_SEND(dcc)->file_quoted ? - "DCC ACCEPT \"%s\" %d %lu" : - "DCC ACCEPT %s %d %lu", + "DCC ACCEPT \"%s\" %d %"PRIuUOFF_T : + "DCC ACCEPT %s %d %"PRIuUOFF_T, dcc->arg, dcc->port, dcc->transfd); dcc_ctcp_message(dcc->server, dcc->nick, dcc->chat, FALSE, str); @@ -112,7 +112,7 @@ static void ctcp_msg_dcc_accept(IRC_SERVER_REC *server, const char *data, const char *target, DCC_REC *chat) { FILE_DCC_REC *dcc; - unsigned long size; + uoff_t size; if (!dcc_ctcp_resume_parse(DCC_GET_TYPE, data, nick, &dcc, &size) || (dcc != NULL && DCC_GET(dcc)->get_type != DCC_GET_RESUME)) { @@ -141,7 +141,7 @@ static void dcc_send_resume(GET_DCC_REC *dcc) dcc->get_type = DCC_GET_RESUME; pos = lseek(dcc->fhandle, 0, SEEK_END); - dcc->transfd = pos == (off_t)-1 ? 0 : (unsigned long) pos; + dcc->transfd = pos < 0 ? 0 : (uoff_t)pos; dcc->skipped = dcc->transfd; if (dcc->skipped == dcc->size) { @@ -150,8 +150,8 @@ static void dcc_send_resume(GET_DCC_REC *dcc) dcc_reject(DCC(dcc), NULL); } else { str = g_strdup_printf(dcc->file_quoted ? - "DCC RESUME \"%s\" %d %lu" : - "DCC RESUME %s %d %lu", + "DCC RESUME \"%s\" %d %"PRIuUOFF_T : + "DCC RESUME %s %d %"PRIuUOFF_T, dcc->arg, dcc->port, dcc->transfd); dcc_ctcp_message(dcc->server, dcc->nick, dcc->chat, FALSE, str); diff --git a/src/irc/dcc/dcc-send.c b/src/irc/dcc/dcc-send.c index a75984ac..46e1dd4e 100644 --- a/src/irc/dcc/dcc-send.c +++ b/src/irc/dcc/dcc-send.c @@ -254,7 +254,6 @@ static void dcc_send_read_size(SEND_DCC_REC *dcc) guint32 bytes; int ret; - /* we need to get 4 bytes.. */ ret = net_receive(dcc->handle, dcc->count_buf+dcc->count_pos, 4-dcc->count_pos); if (ret == -1) { @@ -267,14 +266,12 @@ static void dcc_send_read_size(SEND_DCC_REC *dcc) if (dcc->count_pos != 4) return; - memcpy(&bytes, dcc->count_buf, 4); - bytes = (guint32) ntohl(bytes); - - dcc->gotalldata = (unsigned long) bytes == dcc->transfd; + bytes = ntohl(*((guint32 *) dcc->count_buf)); dcc->count_pos = 0; - if (dcc->waitforend && dcc->gotalldata) { + if (dcc->waitforend && bytes == (dcc->transfd & 0xffffffff)) { /* file is sent */ + dcc->gotalldata = TRUE; dcc_close(DCC(dcc)); } } @@ -334,10 +331,10 @@ static char *dcc_send_get_file(const char *fname) static int dcc_send_one_file(int queue, const char *target, const char *fname, IRC_SERVER_REC *server, CHAT_DCC_REC *chat) { + struct stat st; char *str; char host[MAX_IP_LEN]; int hfile, port; - long fsize; SEND_DCC_REC *dcc; IPADDR own_ip; GIOChannel *handle; @@ -356,8 +353,12 @@ static int dcc_send_one_file(int queue, const char *target, const char *fname, GINT_TO_POINTER(errno)); return FALSE; } - fsize = lseek(hfile, 0, SEEK_END); - lseek(hfile, 0, SEEK_SET); + + if (fstat(hfile, &st) < 0) { + g_warning("fstat() failed: %s", strerror(errno)); + close(hfile); + return FALSE; + } /* start listening */ handle = dcc_listen(chat != NULL ? chat->handle : @@ -386,7 +387,7 @@ static int dcc_send_one_file(int queue, const char *target, const char *fname, dcc->handle = handle; dcc->port = port; - dcc->size = fsize; + dcc->size = st.st_size; dcc->fhandle = hfile; dcc->queue = queue; dcc->file_quoted = strchr(fname, ' ') != NULL; @@ -398,9 +399,9 @@ static int dcc_send_one_file(int queue, const char *target, const char *fname, dcc_ip2str(&own_ip, host); str = g_strdup_printf(dcc->file_quoted ? - "DCC SEND \"%s\" %s %d %lu" : - "DCC SEND %s %s %d %lu", - dcc->arg, host, port, fsize); + "DCC SEND \"%s\" %s %d %"PRIuUOFF_T : + "DCC SEND %s %s %d %"PRIuUOFF_T, + dcc->arg, host, port, dcc->size); dcc_ctcp_message(server, target, chat, FALSE, str); g_free(str);