summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-03-01 16:39:35 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-03-01 16:39:35 +0100
commit09ac816b36e45fd537af2f7fe7c57a11f5c744f5 (patch)
tree4d5d44c27a2395a39efc62359f6e4b6976f2ba2e /lib
parent235244f4cc707130dd130afce88bde49606bd501 (diff)
parent54bc27e9374742d37b1ed9012d1cfe8f5ace6d40 (diff)
downloadsamba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.tar.gz
samba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.tar.bz2
samba-09ac816b36e45fd537af2f7fe7c57a11f5c744f5.zip
Merge branch 'master' of git://git.samba.org/samba into teventfix
Conflicts: lib/tevent/pytevent.c
Diffstat (limited to 'lib')
-rw-r--r--lib/async_req/async_sock.c850
-rw-r--r--lib/async_req/async_sock.h55
-rw-r--r--lib/replace/getifaddrs.c9
-rw-r--r--lib/replace/libreplace_ld.m42
-rw-r--r--lib/replace/system/network.h6
-rw-r--r--lib/smbconf/smbconf.c19
-rw-r--r--lib/smbconf/smbconf.h4
-rw-r--r--lib/smbconf/smbconf_private.h3
-rw-r--r--lib/smbconf/smbconf_txt.c17
-rw-r--r--lib/tdb/common/open.c5
-rw-r--r--lib/tevent/libtevent.m42
-rw-r--r--lib/tevent/tevent.h37
-rw-r--r--lib/tevent/tevent_queue.c198
-rw-r--r--lib/tevent/tevent_req.c42
-rw-r--r--lib/torture/config.mk4
-rw-r--r--lib/util/become_daemon.c26
-rw-r--r--lib/util/system.c29
-rw-r--r--lib/util/tevent_ntstatus.c51
-rw-r--r--lib/util/tevent_ntstatus.h32
-rw-r--r--lib/util/tevent_unix.c46
-rw-r--r--lib/util/tevent_unix.h27
-rw-r--r--lib/util/util.c100
-rw-r--r--lib/util/util.h34
23 files changed, 1022 insertions, 576 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 02ae880683..1f48697f26 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -22,6 +22,7 @@
#include "lib/tevent/tevent.h"
#include "lib/async_req/async_req.h"
#include "lib/async_req/async_sock.h"
+#include "lib/util/tevent_unix.h"
#include <fcntl.h>
#ifndef TALLOC_FREE
@@ -29,72 +30,6 @@
#endif
/**
- * Discriminator for async_syscall_state
- */
-enum async_syscall_type {
- ASYNC_SYSCALL_SEND,
- ASYNC_SYSCALL_SENDALL,
- ASYNC_SYSCALL_RECV,
- ASYNC_SYSCALL_RECVALL,
- ASYNC_SYSCALL_CONNECT
-};
-
-/**
- * Holder for syscall arguments and the result
- */
-
-struct async_syscall_state {
- enum async_syscall_type syscall_type;
- struct tevent_fd *fde;
-
- union {
- struct param_send {
- int fd;
- const void *buffer;
- size_t length;
- int flags;
- } param_send;
- struct param_sendall {
- int fd;
- const void *buffer;
- size_t length;
- int flags;
- size_t sent;
- } param_sendall;
- struct param_recv {
- int fd;
- void *buffer;
- size_t length;
- int flags;
- } param_recv;
- struct param_recvall {
- int fd;
- void *buffer;
- size_t length;
- int flags;
- size_t received;
- } param_recvall;
- struct param_connect {
- /**
- * connect needs to be done on a nonblocking
- * socket. Keep the old flags around
- */
- long old_sockflags;
- int fd;
- const struct sockaddr *address;
- socklen_t address_len;
- } param_connect;
- } param;
-
- union {
- ssize_t result_ssize_t;
- size_t result_size_t;
- int result_int;
- } result;
- int sys_errno;
-};
-
-/**
* @brief Map async_req states to unix-style errnos
* @param[in] req The async req to get the state from
* @param[out] err Pointer to take the unix-style errno
@@ -143,470 +78,138 @@ int async_req_simple_recv_errno(struct async_req *req)
return 0;
}
-/**
- * @brief Create a new async syscall req
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state. The async_syscall_state will be put
- * into the async_req as private_data.
- */
-
-static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- enum async_syscall_type type,
- struct async_syscall_state **pstate)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- if (!async_req_setup(mem_ctx, &result, &state,
- struct async_syscall_state)) {
- return NULL;
- }
- state->syscall_type = type;
-
- result->private_data = state;
-
- *pstate = state;
+struct async_send_state {
+ int fd;
+ const void *buf;
+ size_t len;
+ int flags;
+ ssize_t sent;
+};
- return result;
-}
+static void async_send_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data);
-/**
- * @brief Create a new async syscall req based on a fd
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] fd The file descriptor we work on
- * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
- * @param[in] fde_cb The callback function for the file descriptor event
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state and an associated file descriptor
- * event.
- */
-
-static struct async_req *async_fde_syscall_new(
- TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- enum async_syscall_type type,
- int fd,
- uint16_t fde_flags,
- void (*fde_cb)(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv),
- struct async_syscall_state **pstate)
+struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, const void *buf, size_t len,
+ int flags)
{
- struct async_req *result;
- struct async_syscall_state *state;
+ struct tevent_req *result;
+ struct async_send_state *state;
+ struct tevent_fd *fde;
- result = async_syscall_new(mem_ctx, ev, type, &state);
+ result = tevent_req_create(mem_ctx, &state, struct async_send_state);
if (result == NULL) {
- return NULL;
+ return result;
}
+ state->fd = fd;
+ state->buf = buf;
+ state->len = len;
+ state->flags = flags;
- state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
- if (state->fde == NULL) {
+ fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, async_send_handler,
+ result);
+ if (fde == NULL) {
TALLOC_FREE(result);
return NULL;
}
- *pstate = state;
return result;
}
-/**
- * Retrieve a ssize_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_ssize_t;
-}
-
-/**
- * Retrieve a size_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_size_t;
-}
-
-/**
- * Retrieve a int typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-int async_syscall_result_int(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_int;
-}
-
-/**
- * fde event handler for the "send" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the send
- * @param[in] flags Can only be TEVENT_FD_WRITE here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_send_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
+static void async_send_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_send *p = &state->param.param_send;
-
- if (state->syscall_type != ASYNC_SYSCALL_SEND) {
- async_req_error(req, EIO);
+ struct tevent_req *req = talloc_get_type_abort(
+ private_data, struct tevent_req);
+ struct async_send_state *state = talloc_get_type_abort(
+ req->private_state, struct async_send_state);
+
+ state->sent = send(state->fd, state->buf, state->len, state->flags);
+ if (state->sent == -1) {
+ tevent_req_error(req, errno);
return;
}
-
- state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
+ tevent_req_done(req);
}
-/**
- * Async version of send(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to send to
- * @param[in] buffer The buffer to send
- * @param[in] length How many bytes to send
- * @param[in] flags flags passed to send(2)
- *
- * This function is a direct counterpart of send(2)
- */
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags)
+ssize_t async_send_recv(struct tevent_req *req, int *perrno)
{
- struct async_req *result;
- struct async_syscall_state *state;
+ struct async_send_state *state = talloc_get_type_abort(
+ req->private_state, struct async_send_state);
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_SEND,
- fd, TEVENT_FD_WRITE, async_send_callback,
- &state);
- if (result == NULL) {
- return NULL;
+ if (tevent_req_is_unix_error(req, perrno)) {
+ return -1;
}
-
- state->param.param_send.fd = fd;
- state->param.param_send.buffer = buffer;
- state->param.param_send.length = length;
- state->param.param_send.flags = flags;
-
- return result;
+ return state->sent;
}
-/**
- * fde event handler for the "sendall" syscall group
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the send
- * @param[in] flags Can only be TEVENT_FD_WRITE here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_sendall_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_sendall *p = &state->param.param_sendall;
-
- if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
- async_req_error(req, EIO);
- return;
- }
-
- state->result.result_ssize_t = send(p->fd,
- (const char *)p->buffer + p->sent,
- p->length - p->sent, p->flags);
- state->sys_errno = errno;
-
- if (state->result.result_ssize_t == -1) {
- async_req_error(req, state->sys_errno);
- return;
- }
-
- if (state->result.result_ssize_t == 0) {
- async_req_error(req, EOF);
- return;
- }
-
- p->sent += state->result.result_ssize_t;
- if (p->sent > p->length) {
- async_req_error(req, EIO);
- return;
- }
+struct async_recv_state {
+ int fd;
+ void *buf;
+ size_t len;
+ int flags;
+ ssize_t received;
+};
- if (p->sent == p->length) {
- TALLOC_FREE(state->fde);
- async_req_done(req);
- }
-}
+static void async_recv_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data);
-/**
- * @brief Send all bytes to a socket
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to send to
- * @param[in] buffer The buffer to send
- * @param[in] length How many bytes to send
- * @param[in] flags flags passed to send(2)
- *
- * async_sendall calls send(2) as long as it is necessary to send all of the
- * "length" bytes
- */
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags)
+struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, void *buf, size_t len, int flags)
{
- struct async_req *result;
- struct async_syscall_state *state;
+ struct tevent_req *result;
+ struct async_recv_state *state;
+ struct tevent_fd *fde;
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
- fd, TEVENT_FD_WRITE, async_sendall_callback,
- &state);
+ result = tevent_req_create(mem_ctx, &state, struct async_recv_state);
if (result == NULL) {
- return NULL;
- }
-
- state->param.param_sendall.fd = fd;
- state->param.param_sendall.buffer = buffer;
- state->param.param_sendall.length = length;
- state->param.param_sendall.flags = flags;
- state->param.param_sendall.sent = 0;
-
- return result;
-}
-
-ssize_t sendall_recv(struct async_req *req, int *perr)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- int err;
-
- err = async_req_simple_recv_errno(req);
-
- if (err != 0) {
- *perr = err;
- return -1;
- }
-
- return state->result.result_ssize_t;
-}
-
-/**
- * fde event handler for the "recv" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the recv
- * @param[in] flags Can only be TEVENT_FD_READ here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_recv_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_recv *p = &state->param.param_recv;
-
- if (state->syscall_type != ASYNC_SYSCALL_RECV) {
- async_req_error(req, EIO);
- return;
+ return result;
}
+ state->fd = fd;
+ state->buf = buf;
+ state->len = len;
+ state->flags = flags;
- state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
-}
-
-/**
- * Async version of recv(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] buffer The buffer to recv into
- * @param[in] length How many bytes to recv
- * @param[in] flags flags passed to recv(2)
- *
- * This function is a direct counterpart of recv(2)
- */
-
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_RECV,
- fd, TEVENT_FD_READ, async_recv_callback,
- &state);
-
- if (result == NULL) {
+ fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, async_recv_handler,
+ result);
+ if (fde == NULL) {
+ TALLOC_FREE(result);
return NULL;
}
-
- state->param.param_recv.fd = fd;
- state->param.param_recv.buffer = buffer;
- state->param.param_recv.length = length;
- state->param.param_recv.flags = flags;
-
return result;
}
-/**
- * fde event handler for the "recvall" syscall group
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the recv
- * @param[in] flags Can only be TEVENT_FD_READ here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_recvall_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
+static void async_recv_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_recvall *p = &state->param.param_recvall;
-
- if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
- async_req_error(req, EIO);
- return;
- }
-
- state->result.result_ssize_t = recv(p->fd,
- (char *)p->buffer + p->received,
- p->length - p->received, p->flags);
- state->sys_errno = errno;
-
- if (state->result.result_ssize_t == -1) {
- async_req_error(req, state->sys_errno);
+ struct tevent_req *req = talloc_get_type_abort(
+ private_data, struct tevent_req);
+ struct async_recv_state *state = talloc_get_type_abort(
+ req->private_state, struct async_recv_state);
+
+ state->received = recv(state->fd, state->buf, state->len,
+ state->flags);
+ if (state->received == -1) {
+ tevent_req_error(req, errno);
return;
}
-
- if (state->result.result_ssize_t == 0) {
- async_req_error(req, EIO);
- return;
- }
-
- p->received += state->result.result_ssize_t;
- if (p->received > p->length) {
- async_req_error(req, EIO);
- return;
- }
-
- if (p->received == p->length) {
- TALLOC_FREE(state->fde);
- async_req_done(req);
- }
-}
-
-/**
- * Receive a specified number of bytes from a socket
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] buffer The buffer to recv into
- * @param[in] length How many bytes to recv
- * @param[in] flags flags passed to recv(2)
- *
- * async_recvall will call recv(2) until "length" bytes are received
- */
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
- fd, TEVENT_FD_READ, async_recvall_callback,
- &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_recvall.fd = fd;
- state->param.param_recvall.buffer = buffer;
- state->param.param_recvall.length = length;
- state->param.param_recvall.flags = flags;
- state->param.param_recvall.received = 0;
-
- return result;
+ tevent_req_done(req);
}
-ssize_t recvall_recv(struct async_req *req, int *perr)
+ssize_t async_recv_recv(struct tevent_req *req, int *perrno)
{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- int err;
+ struct async_recv_state *state = talloc_get_type_abort(
+ req->private_state, struct async_recv_state);
- err = async_req_simple_recv_errno(req);
-
- if (err != 0) {
- *perr = err;
+ if (tevent_req_is_unix_error(req, perrno)) {
return -1;
}
-
- return state->result.result_ssize_t;
+ return state->received;
}
struct async_connect_state {
@@ -633,17 +236,18 @@ static void async_connect_connected(struct tevent_context *ev,
* connect in an async state. This will be reset when the request is finished.
*/
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int fd, const struct sockaddr *address,
- socklen_t address_len)
+struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, const struct sockaddr *address,
+ socklen_t address_len)
{
- struct async_req *result;
+ struct tevent_req *result;
struct async_connect_state *state;
struct tevent_fd *fde;
- if (!async_req_setup(mem_ctx, &result, &state,
- struct async_connect_state)) {
+ result = tevent_req_create(
+ mem_ctx, &state, struct async_connect_state);
+ if (result == NULL) {
return NULL;
}
@@ -664,8 +268,8 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
state->result = connect(fd, address, address_len);
if (state->result == 0) {
- state->sys_errno = 0;
- goto post_status;
+ tevent_req_done(result);
+ goto done;
}
/**
@@ -680,6 +284,7 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
errno == EISCONN ||
#endif
errno == EAGAIN || errno == EINTR)) {
+ state->sys_errno = errno;
goto post_errno;
}
@@ -687,21 +292,15 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
async_connect_connected, result);
if (fde == NULL) {
state->sys_errno = ENOMEM;
- goto post_status;
+ goto post_errno;
}
return result;
post_errno:
- state->sys_errno = errno;
- post_status:
+ tevent_req_error(result, state->sys_errno);
+ done:
fcntl(fd, F_SETFL, state->old_sockflags);
- if (!async_post_error(result, ev, state->sys_errno)) {
- goto fail;
- }
- return result;
- fail:
- TALLOC_FREE(result);
- return NULL;
+ return tevent_req_post(result, ev);
}
/**
@@ -716,10 +315,10 @@ static void async_connect_connected(struct tevent_context *ev,
struct tevent_fd *fde, uint16_t flags,
void *priv)
{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
+ struct tevent_req *req = talloc_get_type_abort(
+ priv, struct tevent_req);
struct async_connect_state *state = talloc_get_type_abort(
- req->private_data, struct async_connect_state);
+ req->private_state, struct async_connect_state);
TALLOC_FREE(fde);
@@ -743,27 +342,27 @@ static void async_connect_connected(struct tevent_context *ev,
DEBUG(10, ("connect returned %s\n", strerror(errno)));
fcntl(state->fd, F_SETFL, state->old_sockflags);
- async_req_error(req, state->sys_errno);
+ tevent_req_error(req, state->sys_errno);
return;
}
state->sys_errno = 0;
- async_req_done(req);
+ tevent_req_done(req);
}
-int async_connect_recv(struct async_req *req, int *perrno)
+int async_connect_recv(struct tevent_req *req, int *perrno)
{
struct async_connect_state *state = talloc_get_type_abort(
- req->private_data, struct async_connect_state);
+ req->private_state, struct async_connect_state);
int err;
fcntl(state->fd, F_SETFL, state->old_sockflags);
-
- if (async_req_is_errno(req, &err)) {
+ if (tevent_req_is_unix_error(req, &err)) {
*perrno = err;
return -1;
}
+
if (state->sys_errno == 0) {
return 0;
}
@@ -771,3 +370,226 @@ int async_connect_recv(struct async_req *req, int *perrno)
*perrno = state->sys_errno;
return -1;
}
+
+struct writev_state {
+ struct tevent_context *ev;
+ int fd;
+ struct iovec *iov;
+ int count;
+ size_t total_size;
+};
+
+static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
+ uint16_t flags, void *private_data);
+
+struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ int fd, struct iovec *iov, int count)
+{
+ struct tevent_req *result;
+ struct writev_state *state;
+ struct tevent_fd *fde;
+
+ result = tevent_req_create(mem_ctx, &state, struct writev_state);
+ if (result == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->fd = fd;
+ state->total_size = 0;
+ state->count = count;
+ state->iov = (struct iovec *)talloc_memdup(
+ state, iov, sizeof(struct iovec) * count);
+ if (state->iov == NULL) {
+ goto fail;
+ }
+
+ fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, writev_handler,
+ result);
+ if (fde == NULL) {
+ goto fail;
+ }
+ return result;
+
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
+{
+ struct tevent_req *req = talloc_get_type_abort(
+ private_data, struct tevent_req);
+ struct writev_state *state = talloc_get_type_abort(
+ req->private_state, struct writev_state);
+ size_t to_write, written;
+ int i;
+
+ to_write = 0;
+
+ for (i=0; i<state->count; i++) {
+ to_write += state->iov[i].iov_len;
+ }
+
+ written = sys_writev(state->fd, state->iov, state->count);
+ if (written == -1) {
+ tevent_req_error(req, errno);
+ return;
+ }
+ if (written == 0) {
+ tevent_req_error(req, EPIPE);
+ return;
+ }
+ state->total_size += written;
+
+ if (written == to_write) {
+ tevent_req_done(req);
+ return;
+ }
+
+ /*
+ * We've written less than we were asked to, drop stuff from
+ * state->iov.
+ */
+
+ while (written > 0) {
+ if (written < state->iov[0].iov_len) {
+ state->iov[0].iov_base =
+ (char *)state->iov[0].iov_base + written;
+ state->iov[0].iov_len -= written;
+ break;
+ }
+ written = state->iov[0].iov_len;
+ state->iov += 1;
+ state->count -= 1;
+ }
+}
+
+ssize_t writev_recv(struct tevent_req *req, int *perrno)
+{
+ struct writev_state *state = talloc_get_type_abort(
+ req->private_state, struct writev_state);
+
+ if (tevent_req_is_unix_error(req, perrno)) {
+ return -1;
+ }
+ return state->total_size;
+}
+
+struct read_packet_state {
+ int fd;
+ uint8_t *buf;
+ size_t nread;
+ ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data);
+ void *private_data;
+};
+
+static void read_packet_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data);
+
+struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, size_t initial,
+ ssize_t (*more)(uint8_t *buf,
+ size_t buflen,
+ void *private_data),
+ void *private_data)
+{
+ struct tevent_req *result;
+ struct read_packet_state *state;
+ struct tevent_fd *fde;
+
+ result = tevent_req_create(mem_ctx, &state, struct read_packet_state);
+ if (result == NULL) {
+ return NULL;
+ }
+ state->fd = fd;
+ state->nread = 0;
+ state->more = more;
+ state->private_data = private_data;
+
+ state->buf = talloc_array(state, uint8_t, initial);
+ if (state->buf == NULL) {
+ goto fail;
+ }
+
+ fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, read_packet_handler,
+ result);
+ if (fde == NULL) {
+ goto fail;
+ }
+ return result;
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void read_packet_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags, void *private_data)
+{
+ struct tevent_req *req = talloc_get_type_abort(
+ private_data, struct tevent_req);
+ struct read_packet_state *state = talloc_get_type_abort(
+ req->private_state, struct read_packet_state);
+ size_t total = talloc_get_size(state->buf);
+ ssize_t nread, more;
+ uint8_t *tmp;
+
+ nread = read(state->fd, state->buf+state->nread, total-state->nread);
+ if (nread == -1) {
+ tevent_req_error(req, errno);
+ return;
+ }
+ if (nread == 0) {
+ tevent_req_error(req, EPIPE);
+ return;
+ }
+
+ state->nread += nread;
+ if (state->nread < total) {
+ /* Come back later */
+ return;
+ }
+
+ /*
+ * We got what was initially requested. See if "more" asks for -- more.
+ */
+ if (state->more == NULL) {
+ /* Nobody to ask, this is a async read_data */
+ tevent_req_done(req);
+ return;
+ }
+
+ more = state->more(state->buf, total, state->private_data);
+ if (more == -1) {
+ /* We got an invalid packet, tell the caller */
+ tevent_req_error(req, EIO);
+ return;
+ }
+ if (more == 0) {
+ /* We're done, full packet received */
+ tevent_req_done(req);
+ return;
+ }
+
+ tmp = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, total+more);
+ if (tevent_req_nomem(tmp, req)) {
+ return;
+ }
+ state->buf = tmp;
+}
+
+ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **pbuf, int *perrno)
+{
+ struct read_packet_state *state = talloc_get_type_abort(
+ req->private_state, struct read_packet_state);
+
+ if (tevent_req_is_unix_error(req, perrno)) {
+ return -1;
+ }
+ *pbuf = talloc_move(mem_ctx, &state->buf);
+ return talloc_get_size(*pbuf);
+}
diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h
index c8739e9ed6..e001709d27 100644
--- a/lib/async_req/async_sock.h
+++ b/lib/async_req/async_sock.h
@@ -25,30 +25,35 @@
bool async_req_is_errno(struct async_req *req, int *err);
int async_req_simple_recv_errno(struct async_req *req);
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno);
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno);
-int async_syscall_result_int(struct async_req *req, int *perrno);
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags);
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags);
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int fd, const struct sockaddr *address,
- socklen_t address_len);
-int async_connect_recv(struct async_req *req, int *perrno);
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags);
-ssize_t sendall_recv(struct async_req *req, int *perr);
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags);
-ssize_t recvall_recv(struct async_req *req, int *perr);
+struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, const void *buf, size_t len,
+ int flags);
+ssize_t async_send_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, void *buf, size_t len, int flags);
+ssize_t async_recv_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, const struct sockaddr *address,
+ socklen_t address_len);
+int async_connect_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ int fd, struct iovec *iov, int count);
+ssize_t writev_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, size_t initial,
+ ssize_t (*more)(uint8_t *buf,
+ size_t buflen,
+ void *private_data),
+ void *private_data);
+ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint8_t **pbuf, int *perrno);
#endif
diff --git a/lib/replace/getifaddrs.c b/lib/replace/getifaddrs.c
index f6f0ec080c..3a91bb40d2 100644
--- a/lib/replace/getifaddrs.c
+++ b/lib/replace/getifaddrs.c
@@ -84,9 +84,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
char buff[8192];
int fd, i, n;
struct ifreq *ifr=NULL;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
struct ifaddrs *curif;
struct ifaddrs *lastif = NULL;
@@ -164,9 +161,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
char buff[8192];
int fd, i, n;
struct ifreq *ifr=NULL;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
struct ifaddrs *curif;
struct ifaddrs *lastif = NULL;
@@ -265,9 +259,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
int fd, i;
struct ifconf ifc;
struct ifreq *ifr=NULL;
- struct in_addr ipaddr;
- struct in_addr nmask;
- char *iname;
struct ifaddrs *curif;
struct ifaddrs *lastif = NULL;
diff --git a/lib/replace/libreplace_ld.m4 b/lib/replace/libreplace_ld.m4
index 81bde46219..9529c5e0a5 100644
--- a/lib/replace/libreplace_ld.m4
+++ b/lib/replace/libreplace_ld.m4
@@ -292,7 +292,7 @@ AC_DEFUN([AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR],
*linux*)
LIB_PATH_VAR=LD_LIBRARY_PATH
;;
- *netbsd*)
+ *bsd*)
LIB_PATH_VAR=LD_LIBRARY_PATH
;;
*solaris*)
diff --git a/lib/replace/system/network.h b/lib/replace/system/network.h
index 40d20db2d4..f135d175d4 100644
--- a/lib/replace/system/network.h
+++ b/lib/replace/system/network.h
@@ -327,10 +327,12 @@ struct addrinfo {
#endif
#ifdef SOCKET_WRAPPER
+#ifndef SOCKET_WRAPPER_DISABLE
#ifndef SOCKET_WRAPPER_NOT_REPLACE
#define SOCKET_WRAPPER_REPLACE
-#endif
+#endif /* SOCKET_WRAPPER_NOT_REPLACE */
#include "../socket_wrapper/socket_wrapper.h"
-#endif
+#endif /* SOCKET_WRAPPER_DISABLE */
+#endif /* SOCKET_WRAPPER */
#endif
diff --git a/lib/smbconf/smbconf.c b/lib/smbconf/smbconf.c
index bcab0b97cd..f25ccae0d4 100644
--- a/lib/smbconf/smbconf.c
+++ b/lib/smbconf/smbconf.c
@@ -203,10 +203,6 @@ WERROR smbconf_get_share(struct smbconf_ctx *ctx,
const char *servicename,
struct smbconf_service **service)
{
- if (!smbconf_share_exists(ctx, servicename)) {
- return WERR_NO_SUCH_SERVICE;
- }
-
return ctx->ops->get_share(ctx, mem_ctx, servicename, service);
}
@@ -403,3 +399,18 @@ WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx)
return werr;
}
+
+WERROR smbconf_transaction_start(struct smbconf_ctx *ctx)
+{
+ return ctx->ops->transaction_start(ctx);
+}
+
+WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx)
+{
+ return ctx->ops->transaction_commit(ctx);
+}
+
+WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx)
+{
+ return ctx->ops->transaction_cancel(ctx);
+}
diff --git a/lib/smbconf/smbconf.h b/lib/smbconf/smbconf.h
index 106fae6431..517302ac88 100644
--- a/lib/smbconf/smbconf.h
+++ b/lib/smbconf/smbconf.h
@@ -94,4 +94,8 @@ WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx,
WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service);
WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx);
+WERROR smbconf_transaction_start(struct smbconf_ctx *ctx);
+WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx);
+WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx);
+
#endif /* _LIBSMBCONF_H_ */
diff --git a/lib/smbconf/smbconf_private.h b/lib/smbconf/smbconf_private.h
index c9e44181c6..e6998ad639 100644
--- a/lib/smbconf/smbconf_private.h
+++ b/lib/smbconf/smbconf_private.h
@@ -68,6 +68,9 @@ struct smbconf_ops {
uint32_t num_includes, const char **includes);
WERROR (*delete_includes)(struct smbconf_ctx *ctx,
const char *service);
+ WERROR (*transaction_start)(struct smbconf_ctx *ctx);
+ WERROR (*transaction_commit)(struct smbconf_ctx *ctx);
+ WERROR (*transaction_cancel)(struct smbconf_ctx *ctx);
};
struct smbconf_ctx {
diff --git a/lib/smbconf/smbconf_txt.c b/lib/smbconf/smbconf_txt.c
index 1df4a9fdb7..501382cc5f 100644
--- a/lib/smbconf/smbconf_txt.c
+++ b/lib/smbconf/smbconf_txt.c
@@ -612,6 +612,20 @@ static WERROR smbconf_txt_delete_includes(struct smbconf_ctx *ctx,
return WERR_NOT_SUPPORTED;
}
+static WERROR smbconf_txt_transaction_start(struct smbconf_ctx *ctx)
+{
+ return WERR_OK;
+}
+
+static WERROR smbconf_txt_transaction_commit(struct smbconf_ctx *ctx)
+{
+ return WERR_OK;
+}
+
+static WERROR smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)
+{
+ return WERR_OK;
+}
static struct smbconf_ops smbconf_ops_txt = {
.init = smbconf_txt_init,
@@ -633,6 +647,9 @@ static struct smbconf_ops smbconf_ops_txt = {
.get_includes = smbconf_txt_get_includes,
.set_includes = smbconf_txt_set_includes,
.delete_includes = smbconf_txt_delete_includes,
+ .transaction_start = smbconf_txt_transaction_start,
+ .transaction_commit = smbconf_txt_transaction_commit,
+ .transaction_cancel = smbconf_txt_transaction_cancel,
};
diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c
index b19e4cea29..e58c8ca7ff 100644
--- a/lib/tdb/common/open.c
+++ b/lib/tdb/common/open.c
@@ -461,6 +461,10 @@ fail:
/* reopen all tdb's */
int tdb_reopen_all(int parent_longlived)
{
+#if defined(LIBREPLACE_PREAD_NOT_REPLACED) && \
+ defined(LIBREPLACE_PWRITE_NOT_REPLACED)
+ return 0;
+#else
struct tdb_context *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
@@ -483,6 +487,7 @@ int tdb_reopen_all(int parent_longlived)
if (tdb_reopen(tdb) != 0)
return -1;
}
+#endif
return 0;
}
diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4
index 29a64ae3b3..c316823a71 100644
--- a/lib/tevent/libtevent.m4
+++ b/lib/tevent/libtevent.m4
@@ -27,7 +27,7 @@ AC_SUBST(TEVENT_LIBS)
TEVENT_CFLAGS="-I$teventdir"
TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o"
-TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o"
+TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o"
TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o"
AC_CHECK_HEADERS(sys/epoll.h)
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 16fac7327f..8c119ffb8e 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include <talloc.h>
#include <sys/time.h>
+#include <stdbool.h>
struct tevent_context;
struct tevent_ops;
@@ -211,6 +212,15 @@ struct tevent_req {
void *private_state;
/**
+ * @brief A function to overwrite the default print function
+ *
+ * The implementation doing the work may want to imeplement a
+ * custom function to print the text representation of the async
+ * request.
+ */
+ char *(*private_print)(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
+ /**
* @brief Internal state of the request
*
* Callers should only access this via functions and never directly.
@@ -266,6 +276,8 @@ struct tevent_req {
} internal;
};
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req);
struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
@@ -295,6 +307,9 @@ struct tevent_req *tevent_req_post(struct tevent_req *req,
bool tevent_req_is_in_progress(struct tevent_req *req);
+bool tevent_req_poll(struct tevent_req *req,
+ struct tevent_context *ev);
+
bool tevent_req_is_error(struct tevent_req *req,
enum tevent_req_state *state,
uint64_t *error);
@@ -323,6 +338,28 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs,
struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs);
+struct tevent_queue;
+
+struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
+ const char *name,
+ const char *location);
+
+#define tevent_queue_create(_mem_ctx, _name) \
+ _tevent_queue_create((_mem_ctx), (_name), __location__)
+
+typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req,
+ void *private_data);
+bool tevent_queue_add(struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ void *private_data);
+bool tevent_queue_start(struct tevent_queue *queue,
+ struct tevent_context *ev);
+void tevent_queue_stop(struct tevent_queue *queue);
+
+size_t tevent_queue_length(struct tevent_queue *queue);
+
#ifdef TEVENT_COMPAT_DEFINES
#define event_context tevent_context
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
new file mode 100644
index 0000000000..6c8fbe4f95
--- /dev/null
+++ b/lib/tevent/tevent_queue.c
@@ -0,0 +1,198 @@
+/*
+ Unix SMB/CIFS implementation.
+ Infrastructure for async requests
+ Copyright (C) Volker Lendecke 2008
+ Copyright (C) Stefan Metzmacher 2009
+
+ ** NOTE! The following LGPL license applies to the tevent
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+struct tevent_queue_entry {
+ struct tevent_queue_entry *prev, *next;
+ struct tevent_queue *queue;
+
+ bool triggered;
+
+ struct tevent_req *req;
+
+ tevent_queue_trigger_fn_t trigger;
+ void *private_data;
+};
+
+struct tevent_queue {
+ const char *name;
+ const char *location;
+
+ bool running;
+ struct tevent_timer *timer;
+
+ size_t length;
+ struct tevent_queue_entry *list;
+};
+
+static int tevent_queue_entry_destructor(struct tevent_queue_entry *e)
+{
+ struct tevent_queue *q = e->queue;
+
+ if (!q) {
+ return 0;
+ }
+
+ DLIST_REMOVE(q->list, e);
+ q->length--;
+
+ if (e->triggered &&
+ q->running &&
+ q->list) {
+ q->list->triggered = true;
+ q->list->trigger(q->list->req,
+ q->list->private_data);
+ }
+
+ return 0;
+}
+
+static int tevent_queue_destructor(struct tevent_queue *q)
+{
+ q->running = false;
+
+ while (q->list) {
+ struct tevent_queue_entry *e = q->list;
+ talloc_free(e);
+ }
+
+ return 0;
+}
+
+struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
+ const char *name,
+ const char *location)
+{
+ struct tevent_queue *queue;
+
+ queue = talloc_zero(mem_ctx, struct tevent_queue);
+ if (!queue) {
+ return NULL;
+ }
+
+ queue->name = talloc_strdup(queue, name);
+ if (!queue->name) {
+ talloc_free(queue);
+ return NULL;
+ }
+
+ queue->location = location;
+
+ /* queue is running by default */
+ queue->running = true;
+
+ talloc_set_destructor(queue, tevent_queue_destructor);
+ return queue;
+}
+
+static void tevent_queue_timer_start(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval now,
+ void *private_data)
+{
+ struct tevent_queue *q = talloc_get_type(private_data,
+ struct tevent_queue);
+
+ talloc_free(te);
+ q->timer = NULL;
+
+ q->list->triggered = true;
+ q->list->trigger(q->list->req, q->list->private_data);
+}
+
+bool tevent_queue_add(struct tevent_queue *queue,
+ struct tevent_context *ev,
+ struct tevent_req *req,
+ tevent_queue_trigger_fn_t trigger,
+ void *private_data)
+{
+ struct tevent_queue_entry *e;
+
+ e = talloc_zero(req, struct tevent_queue_entry);
+ if (e == NULL) {
+ return false;
+ }
+
+ e->queue = queue;
+ e->req = req;
+ e->trigger = trigger;
+ e->private_data = private_data;
+
+ if (queue->running &&
+ !queue->timer &&
+ !queue->list) {
+ queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(),
+ tevent_queue_timer_start,
+ queue);
+ if (!queue->timer) {
+ talloc_free(e);
+ return false;
+ }
+ }
+
+ DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *);
+ queue->length++;
+ talloc_set_destructor(e, tevent_queue_entry_destructor);
+
+ return true;
+}
+
+bool tevent_queue_start(struct tevent_queue *queue,
+ struct tevent_context *ev)
+{
+ if (queue->running) {
+ /* already started */
+ return true;
+ }
+
+ if (!queue->timer &&
+ queue->list) {
+ queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(),
+ tevent_queue_timer_start,
+ queue);
+ if (!queue->timer) {
+ return false;
+ }
+ }
+
+ queue->running = true;
+
+ return true;
+}
+
+void tevent_queue_stop(struct tevent_queue *queue)
+{
+ queue->running = false;
+ talloc_free(queue->timer);
+ queue->timer = NULL;
+}
+
+size_t tevent_queue_length(struct tevent_queue *queue)
+{
+ return queue->length;
+}
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index 800e3855d1..e243c7de5d 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -28,14 +28,17 @@
#include "tevent_util.h"
/**
- * @brief Print an tevent_req structure in debug messages
- * @param[in] mem_ctx The memory context for the result
+ * @brief The default print function for creating debug messages
* @param[in] req The request to be printed
+ * @param[in] mem_ctx The memory context for the result
* @retval Text representation of req
*
+ * The function should not be used by users of the asynx API,
+ * but custom print function can use it and append custom text
+ * to the string.
*/
-char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
{
return talloc_asprintf(mem_ctx,
"tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] "
@@ -51,6 +54,24 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
}
/**
+ * @brief Print an tevent_req structure in debug messages
+ * @param[in] mem_ctx The memory context for the result
+ * @param[in] req The request to be printed
+ * @retval Text representation of req
+ *
+ * This function should be used by callers of the async API
+ */
+
+char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+{
+ if (!req->private_print) {
+ return tevent_req_default_print(req, mem_ctx);
+ }
+
+ return req->private_print(req, mem_ctx);
+}
+
+/**
* @brief Create an async request
* @param[in] mem_ctx The memory context for the result
* @param[in] ev The event context this async request will be driven by
@@ -235,6 +256,21 @@ bool tevent_req_is_in_progress(struct tevent_req *req)
return false;
}
+bool tevent_req_poll(struct tevent_req *req,
+ struct tevent_context *ev)
+{
+ while (tevent_req_is_in_progress(req)) {
+ int ret;
+
+ ret = tevent_loop_once(ev);
+ if (ret != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state,
uint64_t *error)
{
diff --git a/lib/torture/config.mk b/lib/torture/config.mk
index abd89260f6..b4ad9ae17f 100644
--- a/lib/torture/config.mk
+++ b/lib/torture/config.mk
@@ -3,7 +3,9 @@
PUBLIC_DEPENDENCIES = \
LIBSAMBA-HOSTCONFIG \
LIBSAMBA-UTIL \
- LIBTALLOC
+ LIBSAMBA-ERRORS \
+ LIBTALLOC \
+ LIBTEVENT
CFLAGS = -I$(libtorturesrcdir) -I$(libtorturesrcdir)/../
torture_VERSION = 0.0.1
diff --git a/lib/util/become_daemon.c b/lib/util/become_daemon.c
index 034114eade..3d06a4363d 100644
--- a/lib/util/become_daemon.c
+++ b/lib/util/become_daemon.c
@@ -28,14 +28,15 @@
/*******************************************************************
Close the low 3 fd's and open dev/null in their place.
********************************************************************/
-static void close_low_fds(bool stderr_too)
+
+_PUBLIC_ void close_low_fds(bool stderr_too)
{
#ifndef VALGRIND
int fd;
int i;
close(0);
- close(1);
+ close(1);
if (stderr_too)
close(2);
@@ -61,26 +62,26 @@ static void close_low_fds(bool stderr_too)
#endif
}
-/**
+/****************************************************************************
Become a daemon, discarding the controlling terminal.
-**/
+****************************************************************************/
-_PUBLIC_ void become_daemon(bool Fork)
+_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group)
{
- if (Fork) {
- if (fork()) {
+ if (do_fork) {
+ if (sys_fork()) {
_exit(0);
}
}
- /* detach from the terminal */
+ /* detach from the terminal */
#ifdef HAVE_SETSID
- setsid();
+ if (!no_process_group) setsid();
#elif defined(TIOCNOTTY)
- {
- int i = open("/dev/tty", O_RDWR, 0);
+ if (!no_process_group) {
+ int i = sys_open("/dev/tty", O_RDWR, 0);
if (i != -1) {
- ioctl(i, (int) TIOCNOTTY, (char *)0);
+ ioctl(i, (int) TIOCNOTTY, (char *)0);
close(i);
}
}
@@ -90,4 +91,3 @@ _PUBLIC_ void become_daemon(bool Fork)
close_low_fds(false); /* Don't close stderr, let the debug system
attach it to the logfile */
}
-
diff --git a/lib/util/system.c b/lib/util/system.c
index 9bd1800233..9bf5de1a83 100644
--- a/lib/util/system.c
+++ b/lib/util/system.c
@@ -88,3 +88,32 @@ _PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host)
return in2;
}
+/**************************************************************************
+ Wrapper for fork. Ensures we clear our pid cache.
+****************************************************************************/
+
+static pid_t mypid = (pid_t)-1;
+
+_PUBLIC_ pid_t sys_fork(void)
+{
+ pid_t forkret = fork();
+
+ if (forkret == (pid_t)0) {
+ /* Child - reset mypid so sys_getpid does a system call. */
+ mypid = (pid_t) -1;
+ }
+
+ return forkret;
+}
+
+/**************************************************************************
+ Wrapper for getpid. Ensures we only do a system call *once*.
+****************************************************************************/
+
+_PUBLIC_ pid_t sys_getpid(void)
+{
+ if (mypid == (pid_t)-1)
+ mypid = getpid();
+
+ return mypid;
+}
diff --git a/lib/util/tevent_ntstatus.c b/lib/util/tevent_ntstatus.c
new file mode 100644
index 0000000000..1a34e9c749
--- /dev/null
+++ b/lib/util/tevent_ntstatus.c
@@ -0,0 +1,51 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap unix errno around tevent_req
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "tevent_ntstatus.h"
+#include "../replace/replace.h"
+
+bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status)
+{
+ return tevent_req_error(req, NT_STATUS_V(status));
+}
+
+bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *status)
+{
+ enum tevent_req_state state;
+ uint64_t err;
+
+ if (!tevent_req_is_error(req, &state, &err)) {
+ return false;
+ }
+ switch (state) {
+ case TEVENT_REQ_TIMED_OUT:
+ *status = NT_STATUS_IO_TIMEOUT;
+ break;
+ case TEVENT_REQ_NO_MEMORY:
+ *status = NT_STATUS_NO_MEMORY;
+ break;
+ case TEVENT_REQ_USER_ERROR:
+ *status = NT_STATUS(err);
+ break;
+ default:
+ *status = NT_STATUS_INTERNAL_ERROR;
+ break;
+ }
+ return true;
+}
diff --git a/lib/util/tevent_ntstatus.h b/lib/util/tevent_ntstatus.h
new file mode 100644
index 0000000000..84c275fb13
--- /dev/null
+++ b/lib/util/tevent_ntstatus.h
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap unix errno around tevent_req
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TEVENT_NTSTATUS_H
+#define _TEVENT_NTSTATUS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "config.h"
+#include "../libcli/util/ntstatus.h"
+#include "../tevent/tevent.h"
+
+bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status);
+bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus);
+
+#endif
diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c
new file mode 100644
index 0000000000..b89d5cd4d4
--- /dev/null
+++ b/lib/util/tevent_unix.c
@@ -0,0 +1,46 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap unix errno around tevent_req
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "tevent_unix.h"
+#include "../replace/replace.h"
+
+bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno)
+{
+ enum tevent_req_state state;
+ uint64_t err;
+
+ if (!tevent_req_is_error(req, &state, &err)) {
+ return false;
+ }
+ switch (state) {
+ case TEVENT_REQ_TIMED_OUT:
+ *perrno = ETIMEDOUT;
+ break;
+ case TEVENT_REQ_NO_MEMORY:
+ *perrno = ENOMEM;
+ break;
+ case TEVENT_REQ_USER_ERROR:
+ *perrno = err;
+ break;
+ default:
+ *perrno = EINVAL;
+ break;
+ }
+ return true;
+}
diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h
new file mode 100644
index 0000000000..dc3ffaef33
--- /dev/null
+++ b/lib/util/tevent_unix.h
@@ -0,0 +1,27 @@
+/*
+ Unix SMB/CIFS implementation.
+ Wrap unix errno around tevent_req
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TEVENT_UNIX_H
+#define _TEVENT_UNIX_H
+
+#include "../tevent/tevent.h"
+
+bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno);
+
+#endif
diff --git a/lib/util/util.c b/lib/util/util.c
index 988d8f9fa0..1f31f55e8b 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -836,4 +836,104 @@ _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
return len;
}
+/**
+ * @file
+ * @brief String utilities.
+ **/
+
+static bool next_token_internal_talloc(TALLOC_CTX *ctx,
+ const char **ptr,
+ char **pp_buff,
+ const char *sep,
+ bool ltrim)
+{
+ char *s;
+ char *saved_s;
+ char *pbuf;
+ bool quoted;
+ size_t len=1;
+
+ *pp_buff = NULL;
+ if (!ptr) {
+ return(false);
+ }
+
+ s = (char *)*ptr;
+
+ /* default to simple separators */
+ if (!sep) {
+ sep = " \t\n\r";
+ }
+
+ /* find the first non sep char, if left-trimming is requested */
+ if (ltrim) {
+ while (*s && strchr_m(sep,*s)) {
+ s++;
+ }
+ }
+
+ /* nothing left? */
+ if (!*s) {
+ return false;
+ }
+
+ /* When restarting we need to go from here. */
+ saved_s = s;
+
+ /* Work out the length needed. */
+ for (quoted = false; *s &&
+ (quoted || !strchr_m(sep,*s)); s++) {
+ if (*s == '\"') {
+ quoted = !quoted;
+ } else {
+ len++;
+ }
+ }
+
+ /* We started with len = 1 so we have space for the nul. */
+ *pp_buff = talloc_array(ctx, char, len);
+ if (!*pp_buff) {
+ return false;
+ }
+
+ /* copy over the token */
+ pbuf = *pp_buff;
+ s = saved_s;
+ for (quoted = false; *s &&
+ (quoted || !strchr_m(sep,*s)); s++) {
+ if ( *s == '\"' ) {
+ quoted = !quoted;
+ } else {
+ *pbuf++ = *s;
+ }
+ }
+
+ *ptr = (*s) ? s+1 : s;
+ *pbuf = 0;
+
+ return true;
+}
+
+bool next_token_talloc(TALLOC_CTX *ctx,
+ const char **ptr,
+ char **pp_buff,
+ const char *sep)
+{
+ return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
+}
+
+/*
+ * Get the next token from a string, return false if none found. Handles
+ * double-quotes. This version does not trim leading separator characters
+ * before looking for a token.
+ */
+
+bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
+ const char **ptr,
+ char **pp_buff,
+ const char *sep)
+{
+ return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
+}
+
diff --git a/lib/util/util.h b/lib/util/util.h
index 7873f0e769..1f6e3b193b 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -134,6 +134,16 @@ apparent reason.
_PUBLIC_ struct hostent *sys_gethostbyname(const char *name);
_PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host);
+/**
+ * Wrapper for fork used to invalid pid cache.
+ **/
+_PUBLIC_ pid_t sys_fork(void);
+
+/**
+ * Wrapper for getpid. Ensures we only do a system call *once*.
+ **/
+_PUBLIC_ pid_t sys_getpid(void);
+
/* The following definitions come from lib/util/genrand.c */
/**
@@ -194,6 +204,21 @@ _PUBLIC_ void display_set_stderr(void);
/* The following definitions come from lib/util/util_str.c */
+bool next_token_talloc(TALLOC_CTX *ctx,
+ const char **ptr,
+ char **pp_buff,
+ const char *sep);
+
+/**
+ * Get the next token from a string, return false if none found. Handles
+ * double-quotes. This version does not trim leading separator characters
+ * before looking for a token.
+ */
+bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
+ const char **ptr,
+ char **pp_buff,
+ const char *sep);
+
/**
Trim the specified elements off the front and back of a string.
@@ -724,12 +749,15 @@ _PUBLIC_ int idr_remove(struct idr_context *idp, int id);
/* The following definitions come from lib/util/become_daemon.c */
-#if _SAMBA_BUILD_ == 4
+/**
+ Close the low 3 fd's and open dev/null in their place
+**/
+_PUBLIC_ void close_low_fds(bool stderr_too);
+
/**
Become a daemon, discarding the controlling terminal.
**/
-_PUBLIC_ void become_daemon(bool fork);
-#endif
+_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group);
/**
* Load a ini-style file.