summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-06-05 16:06:05 -0700
committerJeremy Allison <jra@samba.org>2009-06-05 16:06:05 -0700
commit64a1f17aff1d17b74398fb270aac5768fd312cf6 (patch)
tree1c72b2b6a127b46b8fdc6e6d0e90b1f07e9acbaa
parent68a1ef21971b5c15db5d0a82acc89791ffceaee0 (diff)
downloadsamba-64a1f17aff1d17b74398fb270aac5768fd312cf6.tar.gz
samba-64a1f17aff1d17b74398fb270aac5768fd312cf6.tar.bz2
samba-64a1f17aff1d17b74398fb270aac5768fd312cf6.zip
Make cli_ftruncate async. Also add a simple test.
Jeremy.
-rw-r--r--source3/include/proto.h8
-rw-r--r--source3/libsmb/clifile.c188
-rw-r--r--source3/libsmb/libsmb_file.c2
-rw-r--r--source3/torture/torture.c24
4 files changed, 148 insertions, 74 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 961b3e06a4..19314e06c7 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2494,7 +2494,13 @@ struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
struct cli_state *cli, uint16_t fnum);
NTSTATUS cli_close_recv(struct tevent_req *req);
NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum);
-bool cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size);
+struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum,
+ uint64_t size);
+NTSTATUS cli_ftruncate_recv(struct tevent_req *req);
+NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size);
NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
uint32_t offset, uint32_t len,
int timeout, unsigned char locktype);
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 693d97626f..a2f089c5e9 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -1981,45 +1981,6 @@ NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
return status;
}
-#if 0
-int cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
-{
- unsigned int data_len = 1;
- unsigned int param_len = 6;
- uint16_t setup = TRANSACT2_SETFILEINFO;
- char param[6];
- unsigned char data;
- char *rparam=NULL, *rdata=NULL;
-
- memset(param, 0, param_len);
- SSVAL(param,0,fnum);
- SSVAL(param,2,SMB_SET_FILE_DISPOSITION_INFO);
-
- data = flag ? 1 : 0;
-
- if (!cli_send_trans(cli, SMBtrans2,
- NULL, /* name */
- -1, 0, /* fid, flags */
- &setup, 1, 0, /* setup, length, max */
- param, param_len, 2, /* param, length, max */
- (char *)&data, data_len, cli->max_xmit /* data, length, max */
- )) {
- return false;
- }
-
- if (!cli_receive_trans(cli, SMBtrans2,
- &rparam, &param_len,
- &rdata, &data_len)) {
- return false;
- }
-
- SAFE_FREE(rdata);
- SAFE_FREE(rparam);
-
- return true;
-}
-#endif
-
struct cli_ntcreate_state {
uint16_t vwv[24];
uint16_t fnum;
@@ -2506,50 +2467,133 @@ NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
Truncate a file to a specified size
****************************************************************************/
-bool cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
+struct ftrunc_state {
+ uint16_t setup;
+ uint8_t param[6];
+ uint8_t data[8];
+};
+
+static void cli_ftruncate_done(struct tevent_req *subreq)
{
- unsigned int param_len = 6;
- unsigned int data_len = 8;
- uint16_t setup = TRANSACT2_SETFILEINFO;
- char param[6];
- unsigned char data[8];
- char *rparam=NULL, *rdata=NULL;
- int saved_timeout = cli->timeout;
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state);
+ NTSTATUS status;
- SSVAL(param,0,fnum);
- SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
- SSVAL(param,4,0);
+ status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
- SBVAL(data, 0, size);
+struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint16_t fnum,
+ uint64_t size)
+{
+ struct tevent_req *req = NULL, *subreq = NULL;
+ struct ftrunc_state *state = NULL;
- if (!cli_send_trans(cli, SMBtrans2,
- NULL, /* name */
- -1, 0, /* fid, flags */
- &setup, 1, 0, /* setup, length, max */
- param, param_len, 2, /* param, length, max */
- (char *)&data, data_len,/* data, length, ... */
- cli->max_xmit)) { /* ... max */
- cli->timeout = saved_timeout;
- return False;
+ req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
+ if (req == NULL) {
+ return NULL;
}
- if (!cli_receive_trans(cli, SMBtrans2,
- &rparam, &param_len,
- &rdata, &data_len)) {
- cli->timeout = saved_timeout;
- SAFE_FREE(rdata);
- SAFE_FREE(rparam);
- return False;
- }
+ /* Setup setup word. */
+ SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
- cli->timeout = saved_timeout;
+ /* Setup param array. */
+ SSVAL(state->param,0,fnum);
+ SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
+ SSVAL(state->param,4,0);
- SAFE_FREE(rdata);
- SAFE_FREE(rparam);
+ /* Setup data array. */
+ SBVAL(state->data, 0, size);
- return True;
+ subreq = cli_trans_send(state, /* mem ctx. */
+ ev, /* event ctx. */
+ cli, /* cli_state. */
+ SMBtrans2, /* cmd. */
+ NULL, /* pipe name. */
+ -1, /* fid. */
+ 0, /* function. */
+ 0, /* flags. */
+ &state->setup, /* setup. */
+ 1, /* num setup uint16_t words. */
+ 0, /* max returned setup. */
+ state->param, /* param. */
+ 6, /* num param. */
+ 2, /* max returned param. */
+ state->data, /* data. */
+ 8, /* num data. */
+ 0); /* max returned data. */
+
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_ftruncate_done, req);
+ return req;
+}
+
+NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
+{
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ return NT_STATUS_OK;
}
+NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev = NULL;
+ struct tevent_req *req = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+
+ if (cli_has_async_calls(cli)) {
+ /*
+ * Can't use sync call while an async call is in flight
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = cli_ftruncate_send(frame,
+ ev,
+ cli,
+ fnum,
+ size);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+
+ status = cli_ftruncate_recv(req);
+
+ fail:
+ TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
+}
/****************************************************************************
send a lock with a specified locktype
diff --git a/source3/libsmb/libsmb_file.c b/source3/libsmb/libsmb_file.c
index abfec172e4..f6cd8ec03f 100644
--- a/source3/libsmb/libsmb_file.c
+++ b/source3/libsmb/libsmb_file.c
@@ -867,7 +867,7 @@ SMBC_ftruncate_ctx(SMBCCTX *context,
}
/*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
- if (!cli_ftruncate(targetcli, file->cli_fd, size)) {
+ if (!NT_STATUS_IS_OK(cli_ftruncate(targetcli, file->cli_fd, (uint64_t)size))) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index d185a71727..056b74adea 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -4144,6 +4144,7 @@ static bool run_simple_posix_open_test(int dummy)
uint16 major, minor;
uint32 caplow, caphigh;
uint16_t fnum1 = (uint16_t)-1;
+ SMB_STRUCT_STAT sbuf;
bool correct = false;
printf("Starting simple POSIX open test\n");
@@ -4191,6 +4192,29 @@ static bool run_simple_posix_open_test(int dummy)
goto out;
}
+ /* Test ftruncate - set file size. */
+ if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
+ printf("ftruncate failed (%s)\n", cli_errstr(cli1));
+ goto out;
+ }
+
+ /* Ensure st_size == 1000 */
+ if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
+ printf("stat failed (%s)\n", cli_errstr(cli1));
+ goto out;
+ }
+
+ if (sbuf.st_ex_size != 1000) {
+ printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
+ goto out;
+ }
+
+ /* Test ftruncate - set file size back to zero. */
+ if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 0))) {
+ printf("ftruncate failed (%s)\n", cli_errstr(cli1));
+ goto out;
+ }
+
if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
printf("close failed (%s)\n", cli_errstr(cli1));
goto out;