[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha7-1842-gf55c761

Jeremy Allison jra at samba.org
Thu May 28 00:28:55 GMT 2009


The branch, master has been updated
       via  f55c7614bd7360b484f15c2290ab88195bb78094 (commit)
      from  e381c13b023f2b512b3f6aec133db9f323bc8132 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f55c7614bd7360b484f15c2290ab88195bb78094
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 27 17:28:23 2009 -0700

    Add aync POSIX hardlink and symlink and torture test for them.
    Missing call cli_readlink() is next.
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/client/client.c   |    4 +-
 source3/include/proto.h   |   20 ++-
 source3/libsmb/clifile.c  |  451 ++++++++++++++++++++++++++++++---------------
 source3/torture/torture.c |   73 +++++++-
 4 files changed, 391 insertions(+), 157 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/client/client.c b/source3/client/client.c
index 13dee60..d7c554e 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -2725,7 +2725,7 @@ static int cmd_link(void)
 		return 1;
 	}
 
-	if (!cli_unix_hardlink(targetcli, targetname, newname)) {
+	if (!NT_STATUS_IS_OK(cli_posix_hardlink(targetcli, targetname, newname))) {
 		d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
 		return 1;
 	}
@@ -2776,7 +2776,7 @@ static int cmd_symlink(void)
 		return 1;
 	}
 
-	if (!cli_unix_symlink(targetcli, targetname, newname)) {
+	if (!NT_STATUS_IS_OK(cli_posix_symlink(targetcli, targetname, newname))) {
 		d_printf("%s symlinking files (%s -> %s)\n",
 			cli_errstr(targetcli), newname, targetname);
 		return 1;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 717a972..a918c29 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2332,12 +2332,28 @@ void cli_reset_error(struct cli_state *cli);
 
 /* The following definitions come from libsmb/clifile.c  */
 
+struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *oldname,
+					const char *newname);
+NTSTATUS cli_posix_symlink_recv(struct tevent_req *req);
+NTSTATUS cli_posix_symlink(struct cli_state *cli,
+			const char *oldname,
+			const char *newname);
+struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *oldname,
+					const char *newname);
+NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req);
+NTSTATUS cli_posix_hardlink(struct cli_state *cli,
+			const char *oldname,
+			const char *newname);
 uint32_t unix_perms_to_wire(mode_t perms);
 mode_t wire_perms_to_unix(uint32_t perms);
 bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf);
 bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf);
-bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname);
-bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname);
 bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode);
 bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid);
 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 1225aa6..e48656b 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -20,74 +20,328 @@
 
 #include "includes.h"
 
+/***********************************************************
+ Common function for pushing stings, used by smb_bytes_push_str()
+ and trans_bytes_push_str(). Only difference is the align_odd
+ parameter setting.
+***********************************************************/
+
+static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
+				const char *str, size_t str_len,
+				bool align_odd,
+				size_t *pconverted_size)
+{
+	size_t buflen;
+	char *converted;
+	size_t converted_size;
+
+	if (buf == NULL) {
+		return NULL;
+	}
+
+	buflen = talloc_get_size(buf);
+
+	if (align_odd && ucs2 && (buflen % 2 == 0)) {
+		/*
+		 * We're pushing into an SMB buffer, align odd
+		 */
+		buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1);
+		if (buf == NULL) {
+			return NULL;
+		}
+		buf[buflen] = '\0';
+		buflen += 1;
+	}
+
+	if (!convert_string_talloc(talloc_tos(), CH_UNIX,
+				   ucs2 ? CH_UTF16LE : CH_DOS,
+				   str, str_len, &converted,
+				   &converted_size, true)) {
+		return NULL;
+	}
+
+	buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
+				   buflen + converted_size);
+	if (buf == NULL) {
+		TALLOC_FREE(converted);
+		return NULL;
+	}
+
+	memcpy(buf + buflen, converted, converted_size);
+
+	TALLOC_FREE(converted);
+
+	if (pconverted_size) {
+		*pconverted_size = converted_size;
+	}
+
+	return buf;
+}
+
+/***********************************************************
+ Push a string into an SMB buffer, with odd byte alignment
+ if it's a UCS2 string.
+***********************************************************/
+
+uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
+			    const char *str, size_t str_len,
+			    size_t *pconverted_size)
+{
+	return internal_bytes_push_str(buf, ucs2, str, str_len,
+			true, pconverted_size);
+}
+
+/***********************************************************
+ Same as smb_bytes_push_str(), but without the odd byte
+ align for ucs2 (we're pushing into a param or data block).
+ static for now, although this will probably change when
+ other modules use async trans calls.
+***********************************************************/
+
+static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
+			    const char *str, size_t str_len,
+			    size_t *pconverted_size)
+{
+	return internal_bytes_push_str(buf, ucs2, str, str_len,
+			false, pconverted_size);
+}
+
+
 /****************************************************************************
  Hard/Symlink a file (UNIX extensions).
  Creates new name (sym)linked to oldname.
 ****************************************************************************/
 
-static bool cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, bool hard_link)
+struct link_state {
+	uint16_t setup;
+	uint8_t *param;
+	uint8_t *data;
+};
+
+static void cli_posix_link_internal_done(struct tevent_req *subreq)
 {
-	unsigned int data_len = 0;
-	unsigned int param_len = 0;
-	uint16_t setup = TRANSACT2_SETPATHINFO;
-	char *param;
-	char *data;
-	char *rparam=NULL, *rdata=NULL;
-	char *p;
-	size_t oldlen = 2*(strlen(oldname)+1);
-	size_t newlen = 2*(strlen(newname)+1);
+	struct tevent_req *req = tevent_req_callback_data(
+				subreq, struct tevent_req);
+	struct link_state *state = tevent_req_data(req, struct link_state);
+	NTSTATUS status;
+
+	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);
+}
 
-	param = SMB_MALLOC_ARRAY(char, 6+newlen+2);
+static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *oldname,
+					const char *newname,
+					bool hardlink)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct link_state *state = NULL;
 
-	if (!param) {
-		return false;
+	req = tevent_req_create(mem_ctx, &state, struct link_state);
+	if (req == NULL) {
+		return NULL;
 	}
 
-	data = SMB_MALLOC_ARRAY(char, oldlen+2);
+	/* Setup setup word. */
+	SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
 
-	if (!data) {
-		SAFE_FREE(param);
-		return false;
+	/* Setup param array. */
+	state->param = talloc_array(state, uint8_t, 6);
+	if (tevent_req_nomem(state->param, req)) {
+		return tevent_req_post(req, ev);
 	}
+	memset(state->param, '\0', 6);
+	SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
 
-	SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
-	SIVAL(param,2,0);
-	p = &param[6];
+	state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname,
+				   strlen(newname)+1, NULL);
 
-	p += clistr_push(cli, p, newname, newlen, STR_TERMINATE);
-	param_len = PTR_DIFF(p, param);
+	if (tevent_req_nomem(state->param, req)) {
+		return tevent_req_post(req, ev);
+	}
 
-	p = data;
-	p += clistr_push(cli, p, oldname, oldlen, STR_TERMINATE);
-	data_len = PTR_DIFF(p, data);
+	/* Setup data array. */
+	state->data = talloc_array(state, uint8_t, 0);
+	if (tevent_req_nomem(state->data, req)) {
+		return tevent_req_post(req, ev);
+	}
+	state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname,
+				   strlen(oldname)+1, 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 */
-			data,  data_len, cli->max_xmit /* data, length, max */
-			)) {
-		SAFE_FREE(data);
-		SAFE_FREE(param);
-		return false;
+	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. */
+				talloc_get_size(state->param),	/* num param. */
+				2,			/* max returned param. */
+				state->data,		/* data. */
+				talloc_get_size(state->data),	/* num data. */
+				0);			/* max returned data. */
+
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
 	}
+	tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
+	return req;
+}
 
-	SAFE_FREE(data);
-	SAFE_FREE(param);
+/****************************************************************************
+ Symlink a file (UNIX extensions).
+****************************************************************************/
 
-	if (!cli_receive_trans(cli, SMBtrans2,
-			&rparam, &param_len,
-			&rdata, &data_len)) {
-			return false;
+struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *oldname,
+					const char *newname)
+{
+	return cli_posix_link_internal_send(mem_ctx, ev, cli,
+			oldname, newname, false);
+}
+
+NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
+{
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
 	}
+	return NT_STATUS_OK;
+}
 
-	SAFE_FREE(data);
-	SAFE_FREE(param);
-	SAFE_FREE(rdata);
-	SAFE_FREE(rparam);
+NTSTATUS cli_posix_symlink(struct cli_state *cli,
+			const char *oldname,
+			const char *newname)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct event_context *ev = NULL;
+	struct tevent_req *req = NULL;
+	NTSTATUS status = NT_STATUS_OK;
 
-	return true;
+	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_posix_symlink_send(frame,
+				ev,
+				cli,
+				oldname,
+				newname);
+	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_posix_symlink_recv(req);
+
+ fail:
+	TALLOC_FREE(frame);
+	if (!NT_STATUS_IS_OK(status)) {
+		cli_set_error(cli, status);
+	}
+	return status;
+}
+
+/****************************************************************************
+ Hard link a file (UNIX extensions).
+****************************************************************************/
+
+struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *oldname,
+					const char *newname)
+{
+	return cli_posix_link_internal_send(mem_ctx, ev, cli,
+			oldname, newname, true);
+}
+
+NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
+{
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_posix_hardlink(struct cli_state *cli,
+			const char *oldname,
+			const char *newname)
+{
+	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_posix_hardlink_send(frame,
+				ev,
+				cli,
+				oldname,
+				newname);
+	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_posix_hardlink_recv(req);
+
+ fail:
+	TALLOC_FREE(frame);
+	if (!NT_STATUS_IS_OK(status)) {
+		cli_set_error(cli, status);
+	}
+	return status;
 }
 
 /****************************************************************************
@@ -325,25 +579,6 @@ bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbu
 
 	return true;
 }
-
-/****************************************************************************
- Symlink a file (UNIX extensions).
-****************************************************************************/
-
-bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname)
-{
-	return cli_link_internal(cli, oldname, newname, False);
-}
-
-/****************************************************************************
- Hard a file (UNIX extensions).
-****************************************************************************/
-
-bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname)
-{
-	return cli_link_internal(cli, oldname, newname, True);
-}
-
 /****************************************************************************
  Chmod or chown a file internal (UNIX extensions).
 ****************************************************************************/
@@ -1288,92 +1523,6 @@ NTSTATUS cli_ntcreate(struct cli_state *cli,
 	return status;
 }
 
-/***********************************************************
- Common function for pushing stings, used by smb_bytes_push_str()
- and trans_bytes_push_str(). Only difference is the align_odd
- parameter setting.
-***********************************************************/
-
-static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
-				const char *str, size_t str_len,
-				bool align_odd,
-				size_t *pconverted_size)
-{
-	size_t buflen;
-	char *converted;
-	size_t converted_size;
-
-	if (buf == NULL) {
-		return NULL;
-	}
-
-	buflen = talloc_get_size(buf);
-
-	if (align_odd && ucs2 && (buflen % 2 == 0)) {
-		/*
-		 * We're pushing into an SMB buffer, align odd
-		 */
-		buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1);
-		if (buf == NULL) {
-			return NULL;
-		}
-		buf[buflen] = '\0';
-		buflen += 1;
-	}
-
-	if (!convert_string_talloc(talloc_tos(), CH_UNIX,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list