diff options
Diffstat (limited to 'erts/emulator/drivers')
-rw-r--r-- | erts/emulator/drivers/common/efile_drv.c | 135 | ||||
-rw-r--r-- | erts/emulator/drivers/common/erl_efile.h | 34 | ||||
-rw-r--r-- | erts/emulator/drivers/common/inet_drv.c | 285 | ||||
-rw-r--r-- | erts/emulator/drivers/common/ram_file_drv.c | 82 | ||||
-rw-r--r-- | erts/emulator/drivers/common/zlib_drv.c | 19 | ||||
-rw-r--r-- | erts/emulator/drivers/unix/ttsl_drv.c | 21 | ||||
-rw-r--r-- | erts/emulator/drivers/unix/unix_efile.c | 218 | ||||
-rw-r--r-- | erts/emulator/drivers/win32/registry_drv.c | 21 | ||||
-rw-r--r-- | erts/emulator/drivers/win32/ttsl_drv.c | 35 | ||||
-rw-r--r-- | erts/emulator/drivers/win32/win_efile.c | 119 |
10 files changed, 535 insertions, 434 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 5c52b99348..36ed108b76 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -104,6 +104,7 @@ #ifndef WANT_NONBLOCKING #define WANT_NONBLOCKING #endif + #include "sys.h" #include "erl_driver.h" @@ -147,6 +148,22 @@ static ErlDrvSysInfo sys_info; #define MUTEX_UNLOCK(m) #endif + +/** + * On DARWIN sendfile can deadlock with close if called in + * different threads. So until Apple fixes so that sendfile + * is not buggy we disable usage of the async pool for + * DARWIN. The testcase t_sendfile_crashduring reproduces + * this error when using +A 10. + */ +#if !defined(DARWIN) +#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0) +#else +#define USE_THRDS_FOR_SENDFILE 0 +#endif /* !DARWIN */ + + + #if 0 /* Experimental, for forcing all file operations to use the same thread. */ static unsigned file_fixed_key = 1; @@ -224,9 +241,10 @@ typedef unsigned char uchar; static ErlDrvData file_start(ErlDrvPort port, char* command); static int file_init(void); static void file_stop(ErlDrvData); -static void file_output(ErlDrvData, char* buf, int len); -static int file_control(ErlDrvData, unsigned int command, - char* buf, int len, char **rbuf, int rlen); +static void file_output(ErlDrvData, char* buf, ErlDrvSizeT len); +static ErlDrvSSizeT file_control(ErlDrvData, unsigned int command, + char* buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen); static void file_timeout(ErlDrvData); static void file_outputv(ErlDrvData, ErlIOVec*); static void file_async_ready(ErlDrvData, ErlDrvThreadData); @@ -734,6 +752,15 @@ file_stop(ErlDrvData e) TRACE_C('p'); +#ifdef HAVE_SENDFILE + if (desc->sendfile_state == sending && !USE_THRDS_FOR_SENDFILE) { + driver_select(desc->port,(ErlDrvEvent)(long)desc->d->c.sendfile.out_fd, + ERL_DRV_WRITE|ERL_DRV_USE,0); + } else if (desc->sendfile_state == sending) { + SET_NONBLOCKING(desc->d->c.sendfile.out_fd); + } +#endif /* HAVE_SENDFILE */ + if (desc->fd != FILE_FD_INVALID) { do_close(desc->flags, desc->fd); desc->fd = FILE_FD_INVALID; @@ -799,7 +826,16 @@ static void reply_Uint_posix_error(file_descriptor *desc, Uint num, driver_output2(desc->port, response, t-response, NULL, 0); } +static void reply_string_error(file_descriptor *desc, char* str) { + char response[256]; /* Response buffer. */ + char* s; + char* t; + response[0] = FILE_RESP_ERROR; + for (s = str, t = response+1; *s; s++, t++) + *t = tolower(*s); + driver_output2(desc->port, response, t-response, NULL, 0); +} static int reply_error(file_descriptor *desc, Efile_error *errInfo) /* The error codes. */ @@ -1048,7 +1084,7 @@ static void invoke_read_line(void *data) d->c.read_line.read_offset - d->c.read_line.read_size; if (size == 0) { /* Need more place */ - size_t need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ? + ErlDrvSizeT need = (d->c.read_line.read_size >= DEFAULT_LINEBUF_SIZE) ? d->c.read_line.read_size + DEFAULT_LINEBUF_SIZE : DEFAULT_LINEBUF_SIZE; ErlDrvBinary *newbin = driver_alloc_binary(need); if (newbin == NULL) { @@ -1349,7 +1385,11 @@ static void invoke_writev(void *data) { size = d->c.writev.size; } - /* Copy the io vector to avoid locking the port que while writing */ + /* Copy the io vector to avoid locking the port que while writing, + * also, both we and efile_writev might/will change the SysIOVec + * when segmenting or due to partial write and we do not want to + * tamper with the actual queue that we get from driver_peekq + */ MUTEX_LOCK(d->c.writev.q_mtx); /* Lock before accessing the port queue */ iov0 = driver_peekq(d->c.writev.port, &iovlen); @@ -1388,7 +1428,7 @@ static void invoke_writev(void *data) { } else { d->result_ok = efile_writev(&d->errInfo, d->flags, (int) d->fd, - iov, iovcnt, size); + iov, iovcnt); } } else if (iovlen == 0) { d->result_ok = 1; @@ -1744,7 +1784,7 @@ static void invoke_sendfile(void *data) d->c.sendfile.written += nbytes; if (result == 1) { - if (sys_info.async_threads != 0) { + if (USE_THRDS_FOR_SENDFILE) { d->result_ok = 0; } else if (d->c.sendfile.nbytes == 0 && nbytes != 0) { d->result_ok = 1; @@ -2120,24 +2160,25 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) if (d->result_ok) { resbuf[0] = FILE_RESP_INFO; - put_int32(d->info.size_high, &resbuf[1 + (0 * 4)]); - put_int32(d->info.size_low, &resbuf[1 + (1 * 4)]); - put_int32(d->info.type, &resbuf[1 + (2 * 4)]); - - PUT_TIME(d->info.accessTime, resbuf + 1 + 3*4); - PUT_TIME(d->info.modifyTime, resbuf + 1 + 9*4); - PUT_TIME(d->info.cTime, resbuf + 1 + 15*4); - - put_int32(d->info.mode, &resbuf[1 + (21 * 4)]); - put_int32(d->info.links, &resbuf[1 + (22 * 4)]); - put_int32(d->info.major_device, &resbuf[1 + (23 * 4)]); - put_int32(d->info.minor_device, &resbuf[1 + (24 * 4)]); - put_int32(d->info.inode, &resbuf[1 + (25 * 4)]); - put_int32(d->info.uid, &resbuf[1 + (26 * 4)]); - put_int32(d->info.gid, &resbuf[1 + (27 * 4)]); - put_int32(d->info.access, &resbuf[1 + (28 * 4)]); - -#define RESULT_SIZE (1 + (29 * 4)) + put_int32(d->info.size_high, &resbuf[1 + ( 0 * 4)]); + put_int32(d->info.size_low, &resbuf[1 + ( 1 * 4)]); + put_int32(d->info.type, &resbuf[1 + ( 2 * 4)]); + + /* Note 64 bit indexing in resbuf here */ + put_int64(d->info.accessTime, &resbuf[1 + ( 3 * 4)]); + put_int64(d->info.modifyTime, &resbuf[1 + ( 5 * 4)]); + put_int64(d->info.cTime, &resbuf[1 + ( 7 * 4)]); + + put_int32(d->info.mode, &resbuf[1 + ( 9 * 4)]); + put_int32(d->info.links, &resbuf[1 + (10 * 4)]); + put_int32(d->info.major_device, &resbuf[1 + (11 * 4)]); + put_int32(d->info.minor_device, &resbuf[1 + (12 * 4)]); + put_int32(d->info.inode, &resbuf[1 + (13 * 4)]); + put_int32(d->info.uid, &resbuf[1 + (14 * 4)]); + put_int32(d->info.gid, &resbuf[1 + (15 * 4)]); + put_int32(d->info.access, &resbuf[1 + (16 * 4)]); + +#define RESULT_SIZE (1 + (17 * 4)) TRACE_C('R'); driver_output2(desc->port, resbuf, RESULT_SIZE, NULL, 0); #undef RESULT_SIZE @@ -2208,8 +2249,13 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) case FILE_SENDFILE: if (d->result_ok == -1) { desc->sendfile_state = not_sending; - reply_error(desc, &d->errInfo); - if (sys_info.async_threads != 0) { + if (d->errInfo.posix_errno == ECONNRESET || + d->errInfo.posix_errno == ENOTCONN || + d->errInfo.posix_errno == EPIPE) + reply_string_error(desc,"closed"); + else + reply_error(desc, &d->errInfo); + if (USE_THRDS_FOR_SENDFILE) { SET_NONBLOCKING(d->c.sendfile.out_fd); free_sendfile(data); } else { @@ -2220,7 +2266,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) } else if (d->result_ok == 0) { desc->sendfile_state = not_sending; reply_Sint64(desc, d->c.sendfile.written); - if (sys_info.async_threads != 0) { + if (USE_THRDS_FOR_SENDFILE) { SET_NONBLOCKING(d->c.sendfile.out_fd); free_sendfile(data); } else { @@ -2250,7 +2296,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) * Driver entry point -> output */ static void -file_output(ErlDrvData e, char* buf, int count) +file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { file_descriptor* desc = (file_descriptor*)e; Efile_error errInfo; /* The error codes for the last operation. */ @@ -2485,15 +2531,16 @@ file_output(ErlDrvData e, char* buf, int count) case FILE_WRITE_INFO: { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 - + FILENAME_BYTELEN(buf+21*4) + FILENAME_CHARSIZE); + + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE); - d->info.mode = get_int32(buf + 0 * 4); - d->info.uid = get_int32(buf + 1 * 4); - d->info.gid = get_int32(buf + 2 * 4); - GET_TIME(d->info.accessTime, buf + 3 * 4); - GET_TIME(d->info.modifyTime, buf + 9 * 4); - GET_TIME(d->info.cTime, buf + 15 * 4); - FILENAME_COPY(d->b, buf+21*4); + d->info.mode = get_int32(buf + 0 * 4); + d->info.uid = get_int32(buf + 1 * 4); + d->info.gid = get_int32(buf + 2 * 4); + d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4)); + d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4)); + d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); + + FILENAME_COPY(d->b, buf + 9*4); d->command = command; d->invoke = invoke_write_info; d->free = free_data; @@ -2626,9 +2673,9 @@ file_flush(ErlDrvData e) { /********************************************************************* * Driver entry point -> control */ -static int +static ErlDrvSSizeT file_control(ErlDrvData e, unsigned int command, - char* buf, int len, char **rbuf, int rlen) { + char* buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { /* * warning: variable ‘desc’ set but not used * [-Wunused-but-set-variable] @@ -2929,8 +2976,8 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { cq_enq(desc, d); } goto done; case FILE_WRITE: { - int skip = 1; - int size = ev->size - skip; + ErlDrvSizeT skip = 1; + ErlDrvSizeT size = ev->size - skip; if (lseek_flush_read(desc, &err) < 0) { reply_posix_error(desc, err); goto done; @@ -2939,7 +2986,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EBADF); goto done; } - if (size <= 0) { + if (size == 0) { reply_Uint(desc, size); goto done; } @@ -3053,7 +3100,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { EF_FREE(d); reply_Uint(desc, 0); } else { - size_t skip = 1 + 4 + 8*(2*n); + ErlDrvSizeT skip = 1 + 4 + 8*(2*n); if (skip + total != ev->size) { /* Actual amount of data does not match * total of all pos/size specs @@ -3425,7 +3472,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->c.sendfile.nbytes = nbytes; - if (sys_info.async_threads != 0) { + if (USE_THRDS_FOR_SENDFILE) { SET_BLOCKING(d->c.sendfile.out_fd); } diff --git a/erts/emulator/drivers/common/erl_efile.h b/erts/emulator/drivers/common/erl_efile.h index 349ab0e17b..69ad02633c 100644 --- a/erts/emulator/drivers/common/erl_efile.h +++ b/erts/emulator/drivers/common/erl_efile.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2010. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -67,6 +67,11 @@ #define FILENAMES_16BIT 1 #endif +// We use sendfilev if it exist on solaris +#if !defined(HAVE_SENDFILE) && defined(HAVE_SENDFILEV) +#define HAVE_SENDFILE +#endif + /* * An handle to an open directory. To be cast to the correct type * in the system-dependent directory functions. @@ -85,14 +90,15 @@ typedef struct _Efile_error { /* * This structure contains date and time. */ -typedef struct _Efile_time { - unsigned year; /* (4 digits). */ - unsigned month; /* (1..12). */ - unsigned day; /* (1..31). */ - unsigned hour; /* (0..23). */ - unsigned minute; /* (0..59). */ - unsigned second; /* (0..59). */ -} Efile_time; + +//typedef struct _Efile_time { +// unsigned year; /* (4 digits). */ +// unsigned month; /* (1..12). */ +// unsigned day; /* (1..31). */ +// unsigned hour; /* (0..23). */ +// unsigned minute; /* (0..59). */ +// unsigned second; /* (0..59). */ +//} Efile_time; /* @@ -111,9 +117,9 @@ typedef struct _Efile_info { Uint32 inode; /* Inode number. */ Uint32 uid; /* User id of owner. */ Uint32 gid; /* Group id of owner. */ - Efile_time accessTime; /* Last time the file was accessed. */ - Efile_time modifyTime; /* Last time the file was modified. */ - Efile_time cTime; /* Creation time (Windows) or last + time_t accessTime; /* Last time the file was accessed. */ + time_t modifyTime; /* Last time the file was modified. */ + time_t cTime; /* Creation time (Windows) or last * inode change (Unix). */ } Efile_info; @@ -121,7 +127,7 @@ typedef struct _Efile_info { #ifdef HAVE_SENDFILE /* - * Described the structure of header/trailers for sendfile + * Describes the structure of headers/trailers for sendfile */ struct t_sendfile_hdtl { SysIOVec *headers; @@ -156,7 +162,7 @@ int efile_write_info(Efile_error* errInfo, Efile_info* pInfo, char *name); int efile_write(Efile_error* errInfo, int flags, int fd, char* buf, size_t count); int efile_writev(Efile_error* errInfo, int flags, int fd, - SysIOVec* iov, int iovcnt, size_t size); + SysIOVec* iov, int iovcnt); int efile_read(Efile_error* errInfo, int flags, int fd, char* buf, size_t count, size_t* pBytesRead); int efile_seek(Efile_error* errInfo, int fd, diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index e0d869f328..47a99fdbe6 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -80,6 +80,13 @@ #endif #ifdef __WIN32__ +#define LLU "%I64u" +#else +#define LLU "%llu" +#endif +typedef unsigned long long llu_t; + +#ifdef __WIN32__ #define STRNCASECMP strncasecmp #define INCL_WINSOCK_API_TYPEDEFS 1 @@ -516,7 +523,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) driver_select(port, e, mode | (on?ERL_DRV_USE:0), on) #define sock_select(d, flags, onoff) do { \ - ASSERT(!onoff || !(d)->is_ignored); \ + ASSERT(!(d)->is_ignored); \ (d)->event_mask = (onoff) ? \ ((d)->event_mask | (flags)) : \ ((d)->event_mask & ~(flags)); \ @@ -539,6 +546,13 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) (((unsigned char*) (s))[1] << 8) | \ (((unsigned char*) (s))[0])) + +#ifdef VALGRIND +# include <valgrind/memcheck.h> +#else +# define VALGRIND_MAKE_MEM_DEFINED(ptr,size) +#endif + /*---------------------------------------------------------------------------- ** Interface constants. ** @@ -943,9 +957,9 @@ typedef struct { double send_avg; /* average packet size sent */ subs_list empty_out_q_subs; /* Empty out queue subscribers */ - int is_ignored; /* if a fd is ignored by from the inet_drv, - this should be set to true when the fd is used - outside of inet_drv. */ + int is_ignored; /* if a fd is ignored by the inet_drv. + This flag should be set to true when + the fd is used outside of inet_drv. */ } inet_descriptor; @@ -958,13 +972,14 @@ typedef struct { static int tcp_inet_init(void); static void tcp_inet_stop(ErlDrvData); -static void tcp_inet_command(ErlDrvData, char*, int); +static void tcp_inet_command(ErlDrvData, char*, ErlDrvSizeT); static void tcp_inet_commandv(ErlDrvData, ErlIOVec*); static void tcp_inet_flush(ErlDrvData drv_data); static void tcp_inet_drv_input(ErlDrvData, ErlDrvEvent); static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event); static ErlDrvData tcp_inet_start(ErlDrvPort, char* command); -static int tcp_inet_ctl(ErlDrvData, unsigned int, char*, int, char**, int); +static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData, unsigned int, + char*, ErlDrvSizeT, char**, ErlDrvSizeT); static void tcp_inet_timeout(ErlDrvData); static void tcp_inet_process_exit(ErlDrvData, ErlDrvMonitor *); static void inet_stop_select(ErlDrvEvent, void*); @@ -1009,15 +1024,15 @@ static struct erl_drv_entry tcp_inet_driver_entry = static int packet_inet_init(void); static void packet_inet_stop(ErlDrvData); -static void packet_inet_command(ErlDrvData, char*, int); +static void packet_inet_command(ErlDrvData, char*, ErlDrvSizeT); static void packet_inet_drv_input(ErlDrvData data, ErlDrvEvent event); static void packet_inet_drv_output(ErlDrvData data, ErlDrvEvent event); static ErlDrvData udp_inet_start(ErlDrvPort, char* command); #ifdef HAVE_SCTP static ErlDrvData sctp_inet_start(ErlDrvPort, char* command); #endif -static int packet_inet_ctl(ErlDrvData, unsigned int, char*, - int, char**, int); +static ErlDrvSSizeT packet_inet_ctl(ErlDrvData, unsigned int, char*, + ErlDrvSizeT, char**, ErlDrvSizeT); static void packet_inet_timeout(ErlDrvData); #ifdef __WIN32__ static void packet_inet_event(ErlDrvData, ErlDrvEvent); @@ -1111,7 +1126,7 @@ typedef struct { } tcp_descriptor; /* send function */ -static int tcp_send(tcp_descriptor* desc, char* ptr, int len); +static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len); static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev); static int tcp_recv(tcp_descriptor* desc, int request_len); static int tcp_deliver(tcp_descriptor* desc, int len); @@ -1178,7 +1193,7 @@ static ErlDrvTermData am_tos; static int inet_init(void); -static int ctl_reply(int, char*, int, char**, int); +static ErlDrvSSizeT ctl_reply(int, char*, ErlDrvSizeT, char**, ErlDrvSizeT); struct erl_drv_entry inet_driver_entry = { @@ -1188,7 +1203,23 @@ struct erl_drv_entry inet_driver_entry = NULL, /* output */ NULL, /* ready_input */ NULL, /* ready_output */ - "inet" + "inet", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; /* XXX: is this a driver interface function ??? */ @@ -1202,7 +1233,7 @@ void erl_exit(int n, char*, ...); #ifdef FATAL_MALLOC -static void *alloc_wrapper(size_t size){ +static void *alloc_wrapper(ErlDrvSizeT size){ void *ret = driver_alloc(size); if(ret == NULL) erl_exit(1,"Out of virtual memory in malloc (%s)", __FILE__); @@ -1210,7 +1241,7 @@ static void *alloc_wrapper(size_t size){ } #define ALLOC(X) alloc_wrapper(X) -static void *realloc_wrapper(void *current, size_t size){ +static void *realloc_wrapper(void *current, ErlDrvSizeT size){ void *ret = driver_realloc(current,size); if(ret == NULL) erl_exit(1,"Out of virtual memory in realloc (%s)", __FILE__); @@ -1439,11 +1470,11 @@ static InetDrvBufStk *get_bufstk(void) return bs; } -static ErlDrvBinary* alloc_buffer(long minsz) +static ErlDrvBinary* alloc_buffer(ErlDrvSizeT minsz) { InetDrvBufStk *bs = get_bufstk(); - DEBUGF(("alloc_buffer: %ld\r\n", minsz)); + DEBUGF(("alloc_buffer: "LLU"\r\n", (llu_t)minsz)); if (bs && bs->buf.pos > 0) { long size; @@ -1519,7 +1550,7 @@ static void release_buffer(ErlDrvBinary* buf) } } -static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, long newsz) +static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, ErlDrvSizeT newsz) { return driver_realloc_binary(buf, newsz); } @@ -1548,8 +1579,9 @@ static ErlDrvData dummy_start(ErlDrvPort port, char* command) return (ErlDrvData)port; } -static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT dummy_ctl(ErlDrvData data, unsigned int cmd, + char* buf, ErlDrvSizeT len, char** rbuf, + ErlDrvSizeT rsize) { static char error[] = "no_winsock2"; @@ -1557,7 +1589,7 @@ static int dummy_ctl(ErlDrvData data, unsigned int cmd, char* buf, int len, return ctl_reply(INET_REP_ERROR, error, sizeof(error), rbuf, rsize); } -static void dummy_command(ErlDrvData data, char* buf, int len) +static void dummy_command(ErlDrvData data, char* buf, ErlDrvSizeT len) { } @@ -1614,7 +1646,8 @@ static struct erl_drv_entry dummy_sctp_driver_entry = #endif /* general control reply function */ -static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { char* ptr; @@ -1630,7 +1663,7 @@ static int ctl_reply(int rep, char* buf, int len, char** rbuf, int rsize) } /* general control error reply function */ -static int ctl_error(int err, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_error(int err, char** rbuf, ErlDrvSizeT rsize) { char response[256]; /* Response buffer. */ char* s; @@ -1641,7 +1674,7 @@ static int ctl_error(int err, char** rbuf, int rsize) return ctl_reply(INET_REP_ERROR, response, t-response, rbuf, rsize); } -static int ctl_xerror(char* xerr, char** rbuf, int rsize) +static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) { int n = strlen(xerr); return ctl_reply(INET_REP_ERROR, xerr, n, rbuf, rsize); @@ -3658,7 +3691,8 @@ static int inet_init() ** and is set to actual length of dst on return ** return NULL on error and ptr after port address on success */ -static char* inet_set_address(int family, inet_address* dst, char* src, int* len) +static char* inet_set_address(int family, inet_address* dst, + char* src, ErlDrvSizeT* len) { short port; @@ -3694,7 +3728,7 @@ static char* inet_set_address(int family, inet_address* dst, char* src, int* len ** src = [TAG,P1,P0,X1,X2,...] when TAG = INET_AF_INET | INET_AF_INET6 */ static char *inet_set_faddress(int family, inet_address* dst, - char *src, int* len) { + char *src, ErlDrvSizeT* len) { int tag; if (*len < 1) return NULL; @@ -3809,7 +3843,13 @@ static void desc_close(inet_descriptor* desc) desc->forced_events = 0; desc->send_would_block = 0; #endif - driver_select(desc->port, (ErlDrvEvent)(long)desc->event, ERL_DRV_USE, 0); + // We should close the fd here, but the other driver might still + // be selecting on it. + if (!desc->is_ignored) + driver_select(desc->port,(ErlDrvEvent)(long)desc->event, + ERL_DRV_USE, 0); + else + inet_stop_select((ErlDrvEvent)(long)desc->event,NULL); desc->event = INVALID_EVENT; /* closed by stop_select callback */ desc->s = INVALID_SOCKET; desc->event_mask = 0; @@ -3852,8 +3892,8 @@ static int erl_inet_close(inet_descriptor* desc) } -static int inet_ctl_open(inet_descriptor* desc, int domain, int type, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type, + char** rbuf, ErlDrvSizeT rsize) { if (desc->state != INET_STATE_CLOSED) return ctl_xerror(EXBADSEQ, rbuf, rsize); @@ -3873,8 +3913,8 @@ static int inet_ctl_open(inet_descriptor* desc, int domain, int type, /* as inet_open but pass in an open socket (MUST BE OF RIGHT TYPE) */ -static int inet_ctl_fdopen(inet_descriptor* desc, int domain, int type, - SOCKET s, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type, + SOCKET s, char** rbuf, ErlDrvSizeT rsize) { inet_address name; unsigned int sz = sizeof(name); @@ -4078,14 +4118,15 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr) #if defined(__WIN32__) && defined(SIO_GET_INTERFACE_LIST) -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { char ifbuf[BUFSIZ]; char sbuf[BUFSIZ]; char* sptr; INTERFACE_INFO* ifp; DWORD len; - int n; + ErlDrvSizeT n; int err; ifp = (INTERFACE_INFO*) ifbuf; @@ -4115,8 +4156,8 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) /* input is an ip-address in string format i.e A.B.C.D ** scan the INTERFACE_LIST to get the options */ -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { char ifbuf[BUFSIZ]; int n; @@ -4217,8 +4258,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, } /* not supported */ -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } @@ -4261,12 +4303,13 @@ static void free_ifconf(struct ifconf *ifcp) { FREE(ifcp->ifc_buf); } -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { struct ifconf ifc; struct ifreq *ifrp; char *sbuf, *sp; - int i; + ErlDrvSizeT i; /* Courtesy of Per Bergqvist and W. Richard Stevens */ @@ -4278,7 +4321,7 @@ static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) *sp++ = INET_REP_OK; i = 0; for (;;) { - int n; + ErlDrvSizeT n; ifrp = (struct ifreq *) VOIDP(ifc.ifc_buf + i); n = sizeof(ifrp->ifr_name) + SIZEA(ifrp->ifr_addr); @@ -4334,8 +4377,9 @@ static int hwaddr_libdlpi_lookup(const char *ifnm, #define IFHWADDRLEN 6 #endif -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { char sbuf[BUFSIZ]; char* sptr; @@ -4529,8 +4573,9 @@ static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, } -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { struct ifreq ifreq; int namlen; @@ -4553,19 +4598,19 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, break; case INET_IFOPT_HWADDR: { - unsigned int len; + unsigned int hwalen; buf_check(buf, b_end, 2); - len = get_int16(buf); buf += 2; - buf_check(buf, b_end, len); + hwalen = get_int16(buf); buf += 2; + buf_check(buf, b_end, hwalen); #ifdef SIOCSIFHWADDR /* raw memcpy (fix include autoconf later) */ sys_memset((char*)(&ifreq.ifr_hwaddr.sa_data), '\0', sizeof(ifreq.ifr_hwaddr.sa_data)); - sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, len); + sys_memcpy((char*)(&ifreq.ifr_hwaddr.sa_data), buf, hwalen); (void) ioctl(desc->s, SIOCSIFHWADDR, (char *)&ifreq); #endif - buf += len; + buf += hwalen; break; } @@ -4651,21 +4696,24 @@ static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, #else -static int inet_ctl_getiflist(inet_descriptor* desc, char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_getiflist(inet_descriptor* desc, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } -static int inet_ctl_ifget(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } -static int inet_ctl_ifset(inet_descriptor* desc, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl_ifset(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); } @@ -4722,8 +4770,8 @@ int eq_masked_bytes(char *a, char *b, int pref_len) { return !0; } -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { int i; DWORD ret, n; @@ -4733,7 +4781,7 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p, char *buf_p; char *buf_alloc_p; - int buf_size =512; + ErlDrvSizeT buf_size = 512; # define BUF_ENSURE(Size) \ do { \ int NEED_, GOT_ = buf_p - buf_alloc_p; \ @@ -5107,12 +5155,12 @@ done: #elif defined(HAVE_GETIFADDRS) -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { struct ifaddrs *ifa_p, *ifa_free_p; - int buf_size; + ErlDrvSizeT buf_size; char *buf_p; char *buf_alloc_p; @@ -5215,8 +5263,8 @@ static int inet_ctl_getifaddrs(inet_descriptor* desc_p, #else -static int inet_ctl_getifaddrs(inet_descriptor* desc_p, - char **rbuf_pp, int rsize) +static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p, + char **rbuf_pp, ErlDrvSizeT rsize) { return ctl_error(ENOTSUP, rbuf_pp, rsize); } @@ -6017,7 +6065,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) case SCTP_OPT_PRIMARY_ADDR: case SCTP_OPT_SET_PEER_PRIMARY_ADDR: { - int alen; + ErlDrvSizeT alen; char *after; CHKLEN(curr, ASSOC_ID_LEN); @@ -6059,7 +6107,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) } case SCTP_OPT_PEER_ADDR_PARAMS: { - int alen; + ErlDrvSizeT alen; char *after; # ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS int eflags, cflags, hb_enable, hb_disable, @@ -6146,6 +6194,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) type = SCTP_DEFAULT_SEND_PARAM; arg_ptr = (char*) (&arg.sri); arg_sz = sizeof ( arg.sri); + VALGRIND_MAKE_MEM_DEFINED(arg_ptr, arg_sz); /*suppress "uninitialised bytes"*/ break; } case SCTP_OPT_EVENTS: @@ -6189,7 +6238,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) proto = IPPROTO_SCTP; type = SCTP_DELAYED_ACK_TIME; arg_ptr = (char*) (&arg.av); - arg_sz = sizeof ( arg.es); + arg_sz = sizeof ( arg.av); break; } # endif @@ -6235,8 +6284,9 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) ** ptr should point to a buffer with 9*len +1 to be safe!! */ -static int inet_fill_opts(inet_descriptor* desc, - char* buf, int len, char** dest, int destlen) +static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc, + char* buf, ErlDrvSizeT len, + char** dest, ErlDrvSizeT destlen) { int type; int proto; @@ -6246,8 +6296,8 @@ static int inet_fill_opts(inet_descriptor* desc, char* arg_ptr; unsigned int arg_sz; char *ptr = NULL; - int dest_used = 0; - int dest_allocated = destlen; + ErlDrvSizeT dest_used = 0; + ErlDrvSizeT dest_allocated = destlen; char *orig_dest = *dest; /* Ptr is a name parameter */ @@ -6262,7 +6312,7 @@ static int inet_fill_opts(inet_descriptor* desc, #define PLACE_FOR(Size,Ptr) \ do { \ - int need = dest_used + (Size); \ + ErlDrvSizeT need = dest_used + (Size); \ if (need > INET_MAX_OPT_BUFFER) { \ RETURN_ERROR(); \ } \ @@ -6283,7 +6333,7 @@ static int inet_fill_opts(inet_descriptor* desc, /* Ptr is a name parameter */ #define TRUNCATE_TO(Size,Ptr) \ do { \ - int new_need = ((Ptr) - (*dest)) + (Size); \ + ErlDrvSizeT new_need = ((Ptr) - (*dest)) + (Size); \ if (new_need > dest_used) { \ erl_exit(1,"Internal error in inet_drv, " \ "miscalculated buffer size"); \ @@ -6573,8 +6623,9 @@ static int load_paddrinfo (ErlDrvTermData * spec, int i, /* ** "sctp_fill_opts": Returns {ok, Results}, or an error: */ -static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, - char** dest, int destlen) +static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, + char* buf, ErlDrvSizeT buflen, + char** dest, ErlDrvSizeT destlen) { /* In contrast to the generic "inet_fill_opts", the output here is represented by tuples/records, which are formed in the "spec": @@ -6964,7 +7015,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, unsigned int sz = sizeof(ap); int n; char *after; - int alen; + ErlDrvSizeT alen; if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL); ap.spp_assoc_id = GET_ASSOC_ID(buf); @@ -7204,7 +7255,7 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, struct sctp_paddrinfo pai; unsigned int sz = sizeof(pai); char *after; - int alen; + ErlDrvSizeT alen; if (buflen < ASSOC_ID_LEN) RETURN_ERROR(spec, -EINVAL); pai.spinfo_assoc_id = GET_ASSOC_ID(buf); @@ -7261,7 +7312,8 @@ static int sctp_fill_opts(inet_descriptor* desc, char* buf, int buflen, /* fill statistics reply, op codes from src and result in dest ** dst area must be a least 5*len + 1 bytes */ -static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst) +static ErlDrvSSizeT inet_fill_stat(inet_descriptor* desc, + char* src, ErlDrvSizeT len, char* dst) { unsigned long val; int op; @@ -7294,7 +7346,7 @@ static int inet_fill_stat(inet_descriptor* desc, char* src, int len, char* dst) val = (unsigned long) desc->send_avg; break; case INET_STAT_SEND_PND: - val = driver_sizeq(desc->port); + val = (unsigned long) driver_sizeq(desc->port); break; case INET_STAT_RECV_OCT: put_int32(desc->recv_oct[1], dst); /* write high 32bit */ @@ -7339,7 +7391,8 @@ send_empty_out_q_msgs(inet_descriptor* desc) /* subscribe and fill subscription reply, op codes from src and ** result in dest dst area must be a least 5*len + 1 bytes */ -static int inet_subscribe(inet_descriptor* desc, char* src, int len, char* dst) +static ErlDrvSSizeT inet_subscribe(inet_descriptor* desc, + char* src, ErlDrvSizeT len, char* dst) { unsigned long val; int op; @@ -7439,14 +7492,14 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol) /* ** common TCP/UDP/SCTP control command */ -static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { switch (cmd) { case INET_REQ_GETSTAT: { char* dst; - int i; + ErlDrvSizeT i; int dstlen = 1; /* Reply code */ for (i = 0; i < len; i++) { @@ -7486,7 +7539,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, } case INET_REQ_GETOPTS: { /* get options */ - int replen; + ErlDrvSSizeT replen; DEBUGF(("inet_ctl(%ld): GETOPTS\r\n", (long)desc->port)); #ifdef HAVE_SCTP if (IS_SCTP(desc)) @@ -7725,8 +7778,8 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, return ctl_error(EINVAL, rbuf, rsize); if (*buf == 1 && !desc->is_ignored) { - desc->is_ignored = INET_IGNORE_READ; sock_select(desc, (FD_READ|FD_WRITE|FD_CLOSE|ERL_DRV_USE_NO_CALLBACK), 0); + desc->is_ignored = INET_IGNORE_READ; } else if (*buf == 0 && desc->is_ignored) { int flags = (FD_READ|FD_CLOSE|((desc->is_ignored & INET_IGNORE_WRITE)?FD_WRITE:0)); desc->is_ignored = INET_IGNORE_NONE; @@ -7797,7 +7850,7 @@ static int inet_ctl(inet_descriptor* desc, int cmd, char* buf, int len, } /* update statistics on output packets */ -static void inet_output_count(inet_descriptor* desc, int len) +static void inet_output_count(inet_descriptor* desc, ErlDrvSizeT len) { unsigned long n = desc->send_cnt + 1; unsigned long t = desc->send_oct[0] + len; @@ -7817,7 +7870,7 @@ static void inet_output_count(inet_descriptor* desc, int len) } /* update statistics on input packets */ -static void inet_input_count(inet_descriptor* desc, int len) +static void inet_input_count(inet_descriptor* desc, ErlDrvSizeT len) { unsigned long n = desc->recv_cnt + 1; unsigned long t = desc->recv_oct[0] + len; @@ -7940,7 +7993,7 @@ static void tcp_clear_input(tcp_descriptor* desc) static void tcp_clear_output(tcp_descriptor* desc) { ErlDrvPort ix = desc->inet.port; - int qsz = driver_sizeq(ix); + ErlDrvSizeT qsz = driver_sizeq(ix); driver_deq(ix, qsz); send_empty_out_q_msgs(INETP(desc)); @@ -8108,8 +8161,9 @@ static void tcp_inet_stop(ErlDrvData e) /* TCP requests from Erlang */ -static int tcp_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd, + char* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) { tcp_descriptor* desc = (tcp_descriptor*)e; @@ -8510,7 +8564,7 @@ static void tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller) ** but distribution still uses the tcp_inet_command!! */ -static void tcp_inet_command(ErlDrvData e, char *buf, int len) +static void tcp_inet_command(ErlDrvData e, char *buf, ErlDrvSizeT len) { tcp_descriptor* desc = (tcp_descriptor*)e; desc->inet.caller = driver_caller(desc->inet.port); @@ -8729,8 +8783,15 @@ static int tcp_remain(tcp_descriptor* desc, int* len) else if (tlen == 0) { /* need unknown more */ *len = 0; if (nsz == 0) { - if (nfill == n) - goto error; + if (nfill == n) { + if (desc->inet.psize != 0 && desc->inet.psize > nfill) { + if (tcp_expand_buffer(desc, desc->inet.psize) < 0) + return -1; + return desc->inet.psize; + } + else + goto error; + } DEBUGF((" => restart more=%d\r\n", nfill - n)); return nfill - n; } @@ -9332,12 +9393,12 @@ static int tcp_send_error(tcp_descriptor* desc, int err) */ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) { - int sz; + ErlDrvSizeT sz; char buf[4]; - int h_len; - int n; + ErlDrvSizeT h_len; + ssize_t n; ErlDrvPort ix = desc->inet.port; - int len = ev->size; + ErlDrvSizeT len = ev->size; switch(desc->inet.htype) { case TCP_PB_1: @@ -9385,8 +9446,8 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) else { int vsize = (ev->vsize > MAX_VSIZE) ? MAX_VSIZE : ev->vsize; - DEBUGF(("tcp_sendv(%ld): s=%d, about to send %d,%d bytes\r\n", - (long)desc->inet.port, desc->inet.s, h_len, len)); + DEBUGF(("tcp_sendv(%ld): s=%d, about to send "LLU","LLU" bytes\r\n", + (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len)); if (INETP(desc)->is_ignored) { INETP(desc)->is_ignored |= INET_IGNORE_WRITE; @@ -9412,8 +9473,10 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) return 0; } else { - DEBUGF(("tcp_sendv(%ld): s=%d, only sent %d/%d of %d/%d bytes/items\r\n", - (long)desc->inet.port, desc->inet.s, n, vsize, ev->size, ev->vsize)); + DEBUGF(("tcp_sendv(%ld): s=%d, only sent " + LLU"/%d of "LLU"/%d bytes/items\r\n", + (long)desc->inet.port, desc->inet.s, + (llu_t)n, vsize, (llu_t)ev->size, ev->vsize)); } DEBUGF(("tcp_sendv(%ld): s=%d, Send failed, queuing\r\n", @@ -9428,7 +9491,7 @@ static int tcp_sendv(tcp_descriptor* desc, ErlIOVec* ev) /* ** Send non blocking data */ -static int tcp_send(tcp_descriptor* desc, char* ptr, int len) +static int tcp_send(tcp_descriptor* desc, char* ptr, ErlDrvSizeT len) { int sz; char buf[4]; @@ -9483,8 +9546,8 @@ static int tcp_send(tcp_descriptor* desc, char* ptr, int len) iov[1].iov_base = ptr; iov[1].iov_len = len; - DEBUGF(("tcp_send(%ld): s=%d, about to send %d,%d bytes\r\n", - (long)desc->inet.port, desc->inet.s, h_len, len)); + DEBUGF(("tcp_send(%ld): s=%d, about to send "LLU","LLU" bytes\r\n", + (long)desc->inet.port, desc->inet.s, (llu_t)h_len, (llu_t)len)); if (INETP(desc)->is_ignored) { INETP(desc)->is_ignored |= INET_IGNORE_WRITE; n = 0; @@ -9596,7 +9659,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) else if (IS_CONNECTED(INETP(desc))) { for (;;) { int vsize; - int n; + ssize_t n; SysIOVec* iov; if ((iov = driver_peekq(ix, &vsize)) == NULL) { @@ -9807,10 +9870,10 @@ static int packet_error(udp_descriptor* udesc, int err) /* ** Various functions accessible via "port_control" on the Erlang side: */ -static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, - char** rbuf, int rsize) +static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, + ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { - int replen; + ErlDrvSSizeT replen; udp_descriptor * udesc = (udp_descriptor *) e; inet_descriptor* desc = INETP(udesc); int type = SOCK_DGRAM; @@ -9920,7 +9983,6 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, DEBUGF(("packet_inet_ctl(%ld): CLOSE\r\n", (long)desc->port)); erl_inet_close(desc); return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize); - return 0; case INET_REQ_CONNECT: { @@ -10066,7 +10128,7 @@ static int packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf, int len, /* List item format: Port(2), IP(4|16) -- compatible with "inet_set_address": */ inet_address tmp; - int alen = buf + len - curr; + ErlDrvSizeT alen = buf + len - curr; curr = inet_set_address(desc->sfamily, &tmp, curr, &alen); if (curr == NULL) return ctl_error(EINVAL, rbuf, rsize); @@ -10191,13 +10253,13 @@ static void packet_inet_timeout(ErlDrvData e) ** There is no destination address -- SCTYP send is performed over ** an existing association, using "sctp_sndrcvinfo" specified. */ -static void packet_inet_command(ErlDrvData e, char* buf, int len) +static void packet_inet_command(ErlDrvData e, char* buf, ErlDrvSizeT len) { udp_descriptor * udesc= (udp_descriptor*) e; inet_descriptor* desc = INETP(udesc); char* ptr = buf; char* qtr; - int sz; + ErlDrvSizeT sz; int code; inet_address other; @@ -10215,7 +10277,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len) #ifdef HAVE_SCTP if (IS_SCTP(desc)) { - int data_len; + ErlDrvSizeT data_len; struct iovec iov[1]; /* For real data */ struct msghdr mhdr; /* Message wrapper */ struct sctp_sndrcvinfo *sri; /* The actual ancilary data */ @@ -10251,6 +10313,7 @@ static void packet_inet_command(ErlDrvData e, char* buf, int len) mhdr.msg_iovlen = 1; mhdr.msg_control = cmsg.ancd; /* For ancilary data */ mhdr.msg_controllen = cmsg.hdr.cmsg_len; + VALGRIND_MAKE_MEM_DEFINED(mhdr.msg_control, mhdr.msg_controllen); /*suppress "uninitialised bytes"*/ mhdr.msg_flags = 0; /* Not used with "sendmsg" */ /* Now do the actual sending. NB: "flags" in "sendmsg" itself are NOT @@ -10962,7 +11025,7 @@ int erts_sock_connect(erts_sock_t socket, byte *ip_addr, int len, Uint16 port) { SOCKET s = (SOCKET) socket; char buf[2 + 4]; - int blen = 6; + ErlDrvSizeT blen = 6; inet_address addr; if (socket == ERTS_SOCK_INVALID_SOCKET || len != 4) diff --git a/erts/emulator/drivers/common/ram_file_drv.c b/erts/emulator/drivers/common/ram_file_drv.c index abedcc933a..a109e40333 100644 --- a/erts/emulator/drivers/common/ram_file_drv.c +++ b/erts/emulator/drivers/common/ram_file_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2010. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -98,7 +98,7 @@ typedef unsigned char uchar; static ErlDrvData rfile_start(ErlDrvPort, char*); static int rfile_init(void); static void rfile_stop(ErlDrvData); -static void rfile_command(ErlDrvData, char*, int); +static void rfile_command(ErlDrvData, char*, ErlDrvSizeT); struct erl_drv_entry ram_file_driver_entry = { @@ -108,7 +108,23 @@ struct erl_drv_entry ram_file_driver_entry = { rfile_command, NULL, NULL, - "ram_file_drv" + "ram_file_drv", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; /* A File is represented as a array of bytes, this array is @@ -121,9 +137,9 @@ typedef struct ram_file { int flags; /* flags read/write */ ErlDrvBinary* bin; /* binary to hold binary file */ char* buf; /* buffer start (in binary) */ - int size; /* buffer size (allocated) */ - int cur; /* current position in buffer */ - int end; /* end position in buffer */ + ErlDrvSSizeT size; /* buffer size (allocated) */ + ErlDrvSSizeT cur; /* current position in buffer */ + ErlDrvSSizeT end; /* end position in buffer */ } RamFile; #ifdef LOADABLE @@ -211,7 +227,7 @@ static int reply(RamFile *f, int ok, int err) return 0; } -static int numeric_reply(RamFile *f, int result) +static int numeric_reply(RamFile *f, ErlDrvSSizeT result) { char tmp[5]; @@ -231,7 +247,8 @@ static int numeric_reply(RamFile *f, int result) /* install bin as the new binary reset all pointer */ -static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len) +static void ram_file_set(RamFile *f, ErlDrvBinary *bin, + ErlDrvSSizeT bsize, ErlDrvSSizeT len) { f->size = bsize; f->buf = bin->orig_bytes; @@ -240,9 +257,9 @@ static void ram_file_set(RamFile *f, ErlDrvBinary *bin, int bsize, int len) f->bin = bin; } -static int ram_file_init(RamFile *f, char *buf, int count, int *error) +static int ram_file_init(RamFile *f, char *buf, ErlDrvSSizeT count, int *error) { - int bsize; + ErlDrvSSizeT bsize; ErlDrvBinary* bin; if (count < 0) { @@ -268,9 +285,9 @@ static int ram_file_init(RamFile *f, char *buf, int count, int *error) return count; } -static int ram_file_expand(RamFile *f, int size, int *error) +static ErlDrvSSizeT ram_file_expand(RamFile *f, ErlDrvSSizeT size, int *error) { - int bsize; + ErlDrvSSizeT bsize; ErlDrvBinary* bin; if (size < 0) { @@ -298,10 +315,10 @@ static int ram_file_expand(RamFile *f, int size, int *error) } -static int ram_file_write(RamFile *f, char *buf, int len, - int *location, int *error) +static ErlDrvSSizeT ram_file_write(RamFile *f, char *buf, ErlDrvSSizeT len, + ErlDrvSSizeT *location, int *error) { - int cur = f->cur; + ErlDrvSSizeT cur = f->cur; if (!(f->flags & RAM_FILE_MODE_WRITE)) { *error = EBADF; @@ -322,11 +339,11 @@ static int ram_file_write(RamFile *f, char *buf, int len, return len; } -static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp, - int *location, int *error) +static ErlDrvSSizeT ram_file_read(RamFile *f, ErlDrvSSizeT len, ErlDrvBinary **bp, + ErlDrvSSizeT *location, int *error) { ErlDrvBinary* bin; - int cur = f->cur; + ErlDrvSSizeT cur = f->cur; if (!(f->flags & RAM_FILE_MODE_READ)) { *error = EBADF; @@ -352,9 +369,10 @@ static int ram_file_read(RamFile *f, int len, ErlDrvBinary **bp, return len; } -static int ram_file_seek(RamFile *f, int offset, int whence, int *error) +static ErlDrvSSizeT ram_file_seek(RamFile *f, ErlDrvSSizeT offset, int whence, + int *error) { - int pos; + ErlDrvSSizeT pos; if (f->flags == 0) { *error = EBADF; @@ -389,13 +407,13 @@ static int ram_file_seek(RamFile *f, int offset, int whence, int *error) static int ram_file_uuencode(RamFile *f) { - int code_len = UULINE(UNIX_LINE); - int len = f->end; - int usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2; + ErlDrvSSizeT code_len = UULINE(UNIX_LINE); + ErlDrvSSizeT len = f->end; + ErlDrvSSizeT usize = 4*((len+2)/3) + 2*((len+code_len-1)/code_len) + 2; ErlDrvBinary* bin; uchar* inp; uchar* outp; - int count = 0; + ErlDrvSSizeT count = 0; if ((bin = driver_alloc_binary(usize)) == NULL) return error_reply(f, ENOMEM); @@ -447,8 +465,8 @@ static int ram_file_uuencode(RamFile *f) static int ram_file_uudecode(RamFile *f) { - int len = f->end; - int usize = ( (len+3) / 4 ) * 3; + ErlDrvSSizeT len = f->end; + ErlDrvSSizeT usize = ( (len+3) / 4 ) * 3; ErlDrvBinary* bin; uchar* inp; uchar* outp; @@ -510,7 +528,7 @@ static int ram_file_uudecode(RamFile *f) static int ram_file_compress(RamFile *f) { - int size = f->end; + ErlDrvSSizeT size = f->end; ErlDrvBinary* bin; if ((bin = erts_gzdeflate_buffer(f->buf, size)) == NULL) { @@ -528,7 +546,7 @@ static int ram_file_compress(RamFile *f) static int ram_file_uncompress(RamFile *f) { - int size = f->end; + ErlDrvSSizeT size = f->end; ErlDrvBinary* bin; if ((bin = erts_gzinflate_buffer(f->buf, size)) == NULL) { @@ -541,15 +559,15 @@ static int ram_file_uncompress(RamFile *f) } -static void rfile_command(ErlDrvData e, char* buf, int count) +static void rfile_command(ErlDrvData e, char* buf, ErlDrvSizeT count) { RamFile* f = (RamFile*)e; int error = 0; ErlDrvBinary* bin; char header[5]; /* result code + count */ - int offset; - int origin; /* Origin of seek. */ - int n; + ErlDrvSSizeT offset; + ErlDrvSSizeT origin; /* Origin of seek. */ + ErlDrvSSizeT n; count--; switch(*(uchar*)buf++) { diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index f50899a730..da4a17db1a 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2003-2010. All Rights Reserved. + * Copyright Ericsson AB 2003-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -64,8 +64,8 @@ static int zlib_init(void); static ErlDrvData zlib_start(ErlDrvPort port, char* buf); static void zlib_stop(ErlDrvData e); -static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static void zlib_outputv(ErlDrvData drv_data, ErlIOVec *ev); ErlDrvEntry zlib_driver_entry = { @@ -162,12 +162,12 @@ static char* zlib_reason(int code, int* err) } -static int zlib_return(int code, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_return(int code, char** rbuf, ErlDrvSizeT rlen) { int msg_code = 0; /* 0=ok, 1=error */ char* dst = *rbuf; char* src; - int len = 0; + ErlDrvSizeT len = 0; src = zlib_reason(code, &msg_code); *dst++ = msg_code; @@ -182,7 +182,8 @@ static int zlib_return(int code, char** rbuf, int rlen) return len; } -static int zlib_value2(int msg_code, int value, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_value2(int msg_code, int value, + char** rbuf, ErlDrvSizeT rlen) { char* dst = *rbuf; @@ -197,7 +198,7 @@ static int zlib_value2(int msg_code, int value, char** rbuf, int rlen) return 5; } -static int zlib_value(int value, char** rbuf, int rlen) +static ErlDrvSSizeT zlib_value(int value, char** rbuf, ErlDrvSizeT rlen) { return zlib_value2(2, value, rbuf, rlen); } @@ -409,8 +410,8 @@ static void zlib_stop(ErlDrvData e) driver_free(d); } -static int zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ZLibData* d = (ZLibData*)drv_data; int res; diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c index 45d39a559f..b29f80a8ba 100644 --- a/erts/emulator/drivers/unix/ttsl_drv.c +++ b/erts/emulator/drivers/unix/ttsl_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2010. All Rights Reserved. + * Copyright Ericsson AB 1996-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -106,7 +106,7 @@ static int lpos; /* The current "cursor position" in the line buf /* Main interface functions. */ static void ttysl_stop(ErlDrvData); -static void ttysl_from_erlang(ErlDrvData, char*, int); +static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void ttysl_from_tty(ErlDrvData, ErlDrvEvent); static void ttysl_stop_select(ErlDrvEvent, void*); static Sint16 get_sint16(char*); @@ -141,7 +141,8 @@ static void update_cols(void); static int tty_init(int,int,int,int); static int tty_set(int); static int tty_reset(int); -static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); #ifdef ERTS_NOT_USED static RETSIGTYPE suspend(int); #endif @@ -345,13 +346,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height) *height = DEF_HEIGHT; } -static int ttysl_control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char resbuff[2*sizeof(Uint32)]; - int res_size; + ErlDrvSizeT res_size; switch (command) { case CTRL_OP_GET_WINSIZE: { @@ -633,14 +634,14 @@ static int check_buf_size(byte *s, int n) } -static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count) +static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count) { if (lpos > MAXSIZE) put_chars((byte*)"\n", 1); switch (buf[0]) { case OP_PUTC: - DEBUGLOG(("OP: Putc(%d)",count-1)); + DEBUGLOG(("OP: Putc(%lu)",(unsigned long) count-1)); if (check_buf_size((byte*)buf+1, count-1) == 0) return; put_chars((byte*)buf+1, count-1); diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index e005690d78..796843a735 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2010. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -816,7 +816,6 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, char* name, int info_for_link) { struct stat statbuf; /* Information about the file */ - struct tm *timep; /* Broken-apart filetime. */ int result; #ifdef VXWORKS @@ -883,40 +882,17 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, else pInfo->type = FT_OTHER; -#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS) - { - /* Use the reentrant version of localtime() */ - static struct tm local_tm; -#define localtime(a) (localtime_r((a), &local_tm), &local_tm) -#endif - - -#define GET_TIME(dst, src) \ - timep = localtime(&statbuf.src); \ - (dst).year = timep->tm_year+1900; \ - (dst).month = timep->tm_mon+1; \ - (dst).day = timep->tm_mday; \ - (dst).hour = timep->tm_hour; \ - (dst).minute = timep->tm_min; \ - (dst).second = timep->tm_sec + pInfo->accessTime = statbuf.st_atime; + pInfo->modifyTime = statbuf.st_mtime; + pInfo->cTime = statbuf.st_ctime; - GET_TIME(pInfo->accessTime, st_atime); - GET_TIME(pInfo->modifyTime, st_mtime); - GET_TIME(pInfo->cTime, st_ctime); - -#undef GET_TIME - -#if defined(HAVE_LOCALTIME_R) || defined(VXWORKS) - } -#endif - - pInfo->mode = statbuf.st_mode; - pInfo->links = statbuf.st_nlink; + pInfo->mode = statbuf.st_mode; + pInfo->links = statbuf.st_nlink; pInfo->major_device = statbuf.st_dev; pInfo->minor_device = statbuf.st_rdev; - pInfo->inode = statbuf.st_ino; - pInfo->uid = statbuf.st_uid; - pInfo->gid = statbuf.st_gid; + pInfo->inode = statbuf.st_ino; + pInfo->uid = statbuf.st_uid; + pInfo->gid = statbuf.st_gid; return 1; } @@ -924,6 +900,8 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, int efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name) { + struct utimbuf tval; + CHECK_PATHLEN(name, errInfo); #ifdef VXWORKS @@ -976,38 +954,18 @@ efile_write_info(Efile_error *errInfo, Efile_info *pInfo, char *name) #endif /* !VXWORKS */ - if (pInfo->accessTime.year != -1 && pInfo->modifyTime.year != -1) { - struct utimbuf tval; - struct tm timebuf; - -#define MKTIME(tb, ts) \ - timebuf.tm_year = ts.year-1900; \ - timebuf.tm_mon = ts.month-1; \ - timebuf.tm_mday = ts.day; \ - timebuf.tm_hour = ts.hour; \ - timebuf.tm_min = ts.minute; \ - timebuf.tm_sec = ts.second; \ - timebuf.tm_isdst = -1; \ - if ((tb = mktime(&timebuf)) == (time_t) -1) { \ - errno = EINVAL; \ - return check_error(-1, errInfo); \ - } + tval.actime = pInfo->accessTime; + tval.modtime = pInfo->modifyTime; - MKTIME(tval.actime, pInfo->accessTime); - MKTIME(tval.modtime, pInfo->modifyTime); -#undef MKTIME - #ifdef VXWORKS - /* VxWorks' utime doesn't work when the file is a nfs mounted - * one, don't report error if utime fails. - */ - utime(name, &tval); - return 1; + /* VxWorks' utime doesn't work when the file is a nfs mounted + * one, don't report error if utime fails. + */ + utime(name, &tval); + return 1; #else - return check_error(utime(name, &tval), errInfo); + return check_error(utime(name, &tval), errInfo); #endif - } - return 1; } @@ -1046,13 +1004,11 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ * opened */ int fd, /* File descriptor to write to */ SysIOVec* iov, /* Vector of buffer structs. - * The structs are unchanged - * after the call */ - int iovcnt, /* Number of structs in vector */ - size_t size) /* Number of bytes to write */ + * The structs may be changed i.e. + * due to incomplete writes */ + int iovcnt) /* Number of structs in vector */ { int cnt = 0; /* Buffers so far written */ - int p = 0; /* Position in next buffer */ ASSERT(iovcnt >= 0); @@ -1063,66 +1019,47 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ #endif while (cnt < iovcnt) { + if ((! iov[cnt].iov_base) || (iov[cnt].iov_len <= 0)) { + /* Empty buffer - skip */ + cnt++; + } else { /* Non-empty buffer */ + ssize_t w; /* Bytes written in this call */ #ifdef HAVE_WRITEV - int w; /* Bytes written in this call */ - int b = iovcnt - cnt; /* Buffers to write */ - if (b > MAXIOV) - b = MAXIOV; - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - if (b == 1) { - /* Degenerated io vector */ - do { - w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p); - } while (w < 0 && errno == EINTR); - } else { - /* Non-empty vector first. - * Adjust pos in first buffer in case of - * previous incomplete writev */ - iov[cnt].iov_base += p; - iov[cnt].iov_len -= p; + int b = iovcnt - cnt; /* Buffers to write */ + /* Use as many buffers as MAXIOV allows */ + if (b > MAXIOV) + b = MAXIOV; + if (b > 1) { do { w = writev(fd, &iov[cnt], b); } while (w < 0 && errno == EINTR); - iov[cnt].iov_base -= p; - iov[cnt].iov_len += p; - } - if (w < 0) - return check_error(-1, errInfo); - } else { - /* Empty vector first - skip */ - cnt++; - continue; - } - ASSERT(w >= 0); - /* Move forward to next vector to write */ - for (; cnt < iovcnt; cnt++) { - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - if (w < iov[cnt].iov_len) - break; - else - w -= iov[cnt].iov_len; - } - } - ASSERT(w >= 0); - p = w > 0 ? w : 0; /* Skip p bytes next writev */ -#else /* #ifdef HAVE_WRITEV */ - if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { - /* Non-empty vector */ - int w; /* Bytes written in this call */ - while (p < iov[cnt].iov_len) { - do { - w = write(fd, iov[cnt].iov_base + p, iov[cnt].iov_len - p); - } while (w < 0 && errno == EINTR); - if (w < 0) - return check_error(-1, errInfo); - p += w; + } else + /* Degenerated io vector - use regular write */ +#endif + { + do { + w = write(fd, iov[cnt].iov_base, iov[cnt].iov_len); + } while (w < 0 && errno == EINTR); + ASSERT(w <= iov[cnt].iov_len); + } + if (w < 0) return check_error(-1, errInfo); + /* Move forward to next buffer to write */ + for (; cnt < iovcnt && w > 0; cnt++) { + if (iov[cnt].iov_base && iov[cnt].iov_len > 0) { + if (w < iov[cnt].iov_len) { + /* Adjust the buffer for next write */ + iov[cnt].iov_len -= w; + iov[cnt].iov_base += w; + w = 0; + break; + } else { + w -= iov[cnt].iov_len; + } + } } - } - cnt++; - p = 0; -#endif /* #ifdef HAVE_WRITEV */ + ASSERT(w == 0); + } /* else Non-empty buffer */ } /* while (cnt< iovcnt) */ - size = 0; /* Avoid compiler warning */ return 1; } @@ -1469,7 +1406,9 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, } #ifdef HAVE_SENDFILE -#define SENDFILE_CHUNK_SIZE ((1 << 30) -1) +// For some reason the maximum size_t cannot be used as the max size +// 3GB seems to work on all platforms +#define SENDFILE_CHUNK_SIZE ((1UL << 30) -1) /* * sendfile: The implementation of the sendfile system call varies @@ -1477,7 +1416,13 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, * we have to emulate some things in linux and play with variables on * bsd/darwin. * - * It could be possible to implement header/trailer in sendfile, though + * All of the calls will split a command which tries to send more than + * SENDFILE_CHUNK_SIZE of data at once. + * + * On platforms where *nbytes of 0 does not mean the entire file, this is + * simulated. + * + * It could be possible to implement header/trailer in sendfile. Though * you would have to emulate it in linux and on BSD/Darwin some complex * calculations have to be made when using a non blocking socket to figure * out how much of the header/file/trailer was sent in each command. @@ -1488,10 +1433,10 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl) { Uint64 written = 0; -#if defined(__linux__) || (defined(__sun) && defined(__SVR4)) +#if defined(__linux__) ssize_t retval; do { - // check if *nbytes is 0 or greater than the largest size_t + // check if *nbytes is 0 or greater than chunk size if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) retval = sendfile(out_fd, in_fd, offset, SENDFILE_CHUNK_SIZE); else @@ -1503,11 +1448,34 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, } while (retval == SENDFILE_CHUNK_SIZE); *nbytes = written; return check_error(retval == -1 ? -1 : 0, errInfo); +#elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) + ssize_t retval; + size_t len; + sendfilevec_t fdrec; + fdrec.sfv_fd = in_fd; + fdrec.sfv_flag = 0; + do { + fdrec.sfv_off = *offset; + len = 0; + // check if *nbytes is 0 or greater than chunk size + if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) + fdrec.sfv_len = SENDFILE_CHUNK_SIZE; + else + fdrec.sfv_len = *nbytes; + retval = sendfilev(out_fd, &fdrec, 1, &len); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while (len == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval == -1 ? -1 : 0, errInfo); #elif defined(DARWIN) int retval; off_t len; do { - // check if *nbytes is 0 or greater than the largest off_t + // check if *nbytes is 0 or greater than chunk size if(*nbytes > SENDFILE_CHUNK_SIZE) len = SENDFILE_CHUNK_SIZE; else diff --git a/erts/emulator/drivers/win32/registry_drv.c b/erts/emulator/drivers/win32/registry_drv.c index 05fd2ea55f..1fad34e380 100644 --- a/erts/emulator/drivers/win32/registry_drv.c +++ b/erts/emulator/drivers/win32/registry_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * Copyright Ericsson AB 1997-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -84,7 +84,7 @@ static int maperror(DWORD error); static int reg_init(void); static ErlDrvData reg_start(ErlDrvPort, char*); static void reg_stop(ErlDrvData); -static void reg_from_erlang(ErlDrvData, char*, int); +static void reg_from_erlang(ErlDrvData, char*, ErlDrvSizeT); struct erl_drv_entry registry_driver_entry = { reg_init, @@ -95,10 +95,21 @@ struct erl_drv_entry registry_driver_entry = { NULL, "registry__drv__", NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, NULL, NULL, NULL, - NULL }; static int @@ -158,7 +169,7 @@ reg_stop(ErlDrvData clientData) } static void -reg_from_erlang(ErlDrvData clientData, char* buf, int count) +reg_from_erlang(ErlDrvData clientData, char* buf, ErlDrvSizeT count) { RegPort* rp = (RegPort *) clientData; int cmd; @@ -301,7 +312,7 @@ reg_from_erlang(ErlDrvData clientData, char* buf, int count) buf = (char *) &dword; ASSERT(count == 4); } - result = RegSetValueEx(rp->hkey, name, 0, type, buf, count); + result = RegSetValueEx(rp->hkey, name, 0, type, buf, (DWORD)count); reply(rp, result); } break; diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c index e636761c67..1a74d21e99 100644 --- a/erts/emulator/drivers/win32/ttsl_drv.c +++ b/erts/emulator/drivers/win32/ttsl_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. + * Copyright Ericsson AB 1996-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -83,8 +83,9 @@ int lpos; /* The current "cursor position" in the line buf static int ttysl_init(void); static ErlDrvData ttysl_start(ErlDrvPort, char*); static void ttysl_stop(ErlDrvData); -static int ttysl_control(ErlDrvData, unsigned int, char *, int, char **, int); -static void ttysl_from_erlang(ErlDrvData, char*, int); +static ErlDrvSSizeT ttysl_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); +static void ttysl_from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void ttysl_from_tty(ErlDrvData, ErlDrvEvent); static Sint16 get_sint16(char *s); @@ -120,7 +121,19 @@ struct erl_drv_entry ttsl_driver_entry = { NULL, NULL, ttysl_control, - NULL + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; static int utf8_mode = 0; @@ -154,13 +167,13 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height) } -static int ttysl_control(ErlDrvData drv_data, +static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char resbuff[2*sizeof(Uint32)]; - int res_size; + ErlDrvSizeT res_size; switch (command) { case CTRL_OP_GET_WINSIZE: { @@ -176,7 +189,7 @@ static int ttysl_control(ErlDrvData drv_data, res_size = 1; break; case CTRL_OP_SET_UNICODE_STATE: - if (len > 0) { + if (len != 0) { int m = (int) *buf; *resbuff = (utf8_mode) ? 1 : 0; res_size = 1; @@ -438,14 +451,14 @@ static int check_buf_size(byte *s, int n) } -static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, int count) +static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count) { if (lpos > MAXSIZE) put_chars((byte*)"\n", 1); switch (buf[0]) { case OP_PUTC: - DEBUGLOG(("OP: Putc(%d)",count-1)); + DEBUGLOG(("OP: Putc(%I64u)",(unsigned long long)count-1)); if (check_buf_size((byte*)buf+1, count-1) == 0) return; put_chars((byte*)buf+1, count-1); diff --git a/erts/emulator/drivers/win32/win_efile.c b/erts/emulator/drivers/win32/win_efile.c index 0bc701c4cb..606fa1d7de 100644 --- a/erts/emulator/drivers/win32/win_efile.c +++ b/erts/emulator/drivers/win32/win_efile.c @@ -45,6 +45,26 @@ #define INVALID_FILE_ATTRIBUTES ((DWORD) 0xFFFFFFFF) #endif +#define TICKS_PER_SECOND (10000000ULL) +#define EPOCH_DIFFERENCE (11644473600LL) + +#define FILETIME_TO_EPOCH(epoch, ft) \ + do { \ + ULARGE_INTEGER ull; \ + ull.LowPart = (ft).dwLowDateTime; \ + ull.HighPart = (ft).dwHighDateTime; \ + (epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_DIFFERENCE); \ + } while(0) + +#define EPOCH_TO_FILETIME(ft, epoch) \ + do { \ + ULARGE_INTEGER ull; \ + ull.QuadPart = (((epoch) + EPOCH_DIFFERENCE) * TICKS_PER_SECOND); \ + (ft).dwLowDateTime = ull.LowPart; \ + (ft).dwHighDateTime = ull.HighPart; \ + } while(0) + + static int check_error(int result, Efile_error* errInfo); static int set_error(Efile_error* errInfo); static int is_root_unc_name(const WCHAR *path); @@ -864,14 +884,7 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, findbuf.cFileName[0] = L'\0'; pInfo->links = 1; - pInfo->modifyTime.year = 1980; - pInfo->modifyTime.month = 1; - pInfo->modifyTime.day = 1; - pInfo->modifyTime.hour = 0; - pInfo->modifyTime.minute = 0; - pInfo->modifyTime.second = 0; - - pInfo->accessTime = pInfo->modifyTime; + pInfo->cTime = pInfo->accessTime = pInfo->modifyTime = 0; } else { SYSTEMTIME SystemTime; FILETIME LocalFTime; @@ -905,34 +918,21 @@ efile_fileinfo(Efile_error* errInfo, Efile_info* pInfo, } } -#define GET_TIME(dst, src) \ -if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \ - !FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \ - return set_error(errInfo); \ -} \ -(dst).year = SystemTime.wYear; \ -(dst).month = SystemTime.wMonth; \ -(dst).day = SystemTime.wDay; \ -(dst).hour = SystemTime.wHour; \ -(dst).minute = SystemTime.wMinute; \ -(dst).second = SystemTime.wSecond; - - GET_TIME(pInfo->modifyTime, ftLastWriteTime); + FILETIME_TO_EPOCH(pInfo->modifyTime, findbuf.ftLastWriteTime); if (findbuf.ftLastAccessTime.dwLowDateTime == 0 && findbuf.ftLastAccessTime.dwHighDateTime == 0) { pInfo->accessTime = pInfo->modifyTime; } else { - GET_TIME(pInfo->accessTime, ftLastAccessTime); + FILETIME_TO_EPOCH(pInfo->accessTime, findbuf.ftLastAccessTime); } if (findbuf.ftCreationTime.dwLowDateTime == 0 && findbuf.ftCreationTime.dwHighDateTime == 0) { pInfo->cTime = pInfo->modifyTime; } else { - GET_TIME(pInfo->cTime, ftCreationTime); + FILETIME_TO_EPOCH(pInfo->cTime ,findbuf.ftCreationTime); } -#undef GET_TIME FindClose(findhandle); } @@ -968,17 +968,12 @@ efile_write_info(Efile_error* errInfo, char* name) { SYSTEMTIME timebuf; - FILETIME LocalFileTime; FILETIME ModifyFileTime; FILETIME AccessFileTime; FILETIME CreationFileTime; HANDLE fd; - FILETIME* mtime = NULL; - FILETIME* atime = NULL; - FILETIME* ctime = NULL; DWORD attr; DWORD tempAttr; - BOOL modifyTime = FALSE; WCHAR *wname = (WCHAR *) name; /* @@ -1003,57 +998,36 @@ efile_write_info(Efile_error* errInfo, * Construct all file times. */ -#define MKTIME(tb, ts, ptr) \ - timebuf.wYear = ts.year; \ - timebuf.wMonth = ts.month; \ - timebuf.wDay = ts.day; \ - timebuf.wHour = ts.hour; \ - timebuf.wMinute = ts.minute; \ - timebuf.wSecond = ts.second; \ - timebuf.wMilliseconds = 0; \ - if (ts.year != -1) { \ - modifyTime = TRUE; \ - ptr = &tb; \ - if (!SystemTimeToFileTime(&timebuf, &LocalFileTime ) || \ - !LocalFileTimeToFileTime(&LocalFileTime, &tb)) { \ - errno = EINVAL; \ - return check_error(-1, errInfo); \ - } \ - } - - MKTIME(ModifyFileTime, pInfo->modifyTime, mtime); - MKTIME(AccessFileTime, pInfo->accessTime, atime); - MKTIME(CreationFileTime, pInfo->cTime, ctime); -#undef MKTIME + EPOCH_TO_FILETIME(ModifyFileTime, pInfo->modifyTime); + EPOCH_TO_FILETIME(AccessFileTime, pInfo->accessTime); + EPOCH_TO_FILETIME(CreationFileTime, pInfo->cTime); /* * If necessary, set the file times. */ - if (modifyTime) { - /* - * If the has read only access, we must temporarily turn on - * write access (this is necessary for native filesystems, - * but not for NFS filesystems). - */ + /* + * If the has read only access, we must temporarily turn on + * write access (this is necessary for native filesystems, + * but not for NFS filesystems). + */ - if (tempAttr & FILE_ATTRIBUTE_READONLY) { - tempAttr &= ~FILE_ATTRIBUTE_READONLY; - if (!SetFileAttributesW(wname, tempAttr)) { - return set_error(errInfo); - } + if (tempAttr & FILE_ATTRIBUTE_READONLY) { + tempAttr &= ~FILE_ATTRIBUTE_READONLY; + if (!SetFileAttributesW(wname, tempAttr)) { + return set_error(errInfo); } + } - fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fd != INVALID_HANDLE_VALUE) { - BOOL result = SetFileTime(fd, ctime, atime, mtime); - if (!result) { - return set_error(errInfo); - } - CloseHandle(fd); + fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fd != INVALID_HANDLE_VALUE) { + BOOL result = SetFileTime(fd, &CreationFileTime, &AccessFileTime, &ModifyFileTime); + if (!result) { + return set_error(errInfo); } + CloseHandle(fd); } /* @@ -1141,8 +1115,7 @@ efile_writev(Efile_error* errInfo, /* Where to return error codes */ SysIOVec* iov, /* Vector of buffer structs. * The structs are unchanged * after the call */ - int iovcnt, /* Number of structs in vector */ - size_t size) /* Number of bytes to write */ + int iovcnt) /* Number of structs in vector */ { int cnt; /* Buffers so far written */ OVERLAPPED overlapped; |