[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha7-1843-gbccc7ee

Jeremy Allison jra at samba.org
Thu May 28 04:51:42 GMT 2009


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

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


- Log -----------------------------------------------------------------
commit bccc7ee2c6456cdab08884b826ed5ddc2faf2a54
Author: Jeremy Allison <jra at samba.org>
Date:   Wed May 27 21:51:15 2009 -0700

    Add cli_posix_readlink() and a torture test for it.
    Jeremy.

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

Summary of changes:
 source3/include/proto.h   |    9 ++
 source3/libsmb/clifile.c  |  184 ++++++++++++++++++++++++++++++++++++++++++++-
 source3/torture/torture.c |   16 ++++-
 3 files changed, 207 insertions(+), 2 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index a918c29..342c143 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2341,6 +2341,15 @@ 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_readlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *fname,
+					size_t len);
+NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
+				char *retpath, size_t len);
+NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
+			char *linkpath, size_t len);
 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
 					struct event_context *ev,
 					struct cli_state *cli,
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index e48656b..187fcdf 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -106,7 +106,6 @@ static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
 			false, pconverted_size);
 }
 
-
 /****************************************************************************
  Hard/Symlink a file (UNIX extensions).
  Creates new name (sym)linked to oldname.
@@ -273,6 +272,189 @@ NTSTATUS cli_posix_symlink(struct cli_state *cli,
 }
 
 /****************************************************************************
+ Read a POSIX symlink.
+****************************************************************************/
+
+struct readlink_state {
+	uint16_t setup;
+	uint8_t *param;
+	uint8_t *data;
+	uint32_t num_data;
+};
+
+static void cli_posix_readlink_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+				subreq, struct tevent_req);
+	struct readlink_state *state = tevent_req_data(req, struct readlink_state);
+	NTSTATUS status;
+
+	status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
+			&state->data, &state->num_data);
+	TALLOC_FREE(subreq);
+	if (!NT_STATUS_IS_OK(status)) {
+		tevent_req_nterror(req, status);
+		return;
+	}
+	if (state->num_data == 0) {
+		tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
+		return;
+	}
+	if (state->data[state->num_data-1] != '\0') {
+		tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
+					struct event_context *ev,
+					struct cli_state *cli,
+					const char *fname,
+					size_t len)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct readlink_state *state = NULL;
+	uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
+
+	if (maxbytelen < len) {
+		return NULL;
+	}
+
+	req = tevent_req_create(mem_ctx, &state, struct readlink_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	/* Setup setup word. */
+	SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
+
+	/* 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,SMB_QUERY_FILE_UNIX_LINK);
+
+	state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
+				   strlen(fname)+1, NULL);
+
+	if (tevent_req_nomem(state->param, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	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. */
+				NULL,			/* data. */
+				0,			/* num data. */
+				maxbytelen);		/* max returned data. */
+
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
+	return req;
+}
+
+NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
+				char *retpath, size_t len)
+{
+	NTSTATUS status;
+	char *converted = NULL;
+	size_t converted_size = 0;
+	struct readlink_state *state = tevent_req_data(req, struct readlink_state);
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	/* The returned data is a pushed string, not raw data. */
+	if (!convert_string_talloc(state,
+				cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, 
+				CH_UNIX,
+				state->data,
+				state->num_data,
+				&converted,
+				&converted_size,
+				true)) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	len = MIN(len,converted_size);
+	if (len == 0) {
+		return NT_STATUS_DATA_ERROR;
+	}
+	memcpy(retpath, converted, len);
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
+				char *linkpath, size_t len)
+{
+	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;
+	}
+
+	/* Len is in bytes, we need it in UCS2 units. */
+	if (2*len < len) {
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto fail;
+	}
+
+	req = cli_posix_readlink_send(frame,
+				ev,
+				cli,
+				fname,
+				len);
+	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_readlink_recv(req, cli, linkpath, len);
+
+ fail:
+	TALLOC_FREE(frame);
+	if (!NT_STATUS_IS_OK(status)) {
+		cli_set_error(cli, status);
+	}
+	return status;
+}
+
+
+/****************************************************************************
  Hard link a file (UNIX extensions).
 ****************************************************************************/
 
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index bff8d07..b05ca44 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -4140,6 +4140,7 @@ static bool run_simple_posix_open_test(int dummy)
 	const char *sname = "posix:symlink";
 	const char *dname = "posix:dir";
 	char buf[10];
+	char namebuf[11];
 	uint16 major, minor;
 	uint32 caplow, caphigh;
 	uint16_t fnum1 = (uint16_t)-1;
@@ -4281,11 +4282,24 @@ static bool run_simple_posix_open_test(int dummy)
 	} else {
 		if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
 				NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
+			printf("POSIX open of %s should have failed "
+				"with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
+				"failed with %s instead.\n",
+				sname, cli_errstr(cli1));
 			goto out;
 		}
 	}
 
-	/* TODO. Add and test cli_posix_readlink() call. */
+	if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) {
+		printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1));
+		goto out;
+	}
+
+	if (strcmp(namebuf, fname) != 0) {
+		printf("POSIX readlink on %s failed to match name %s (read %s)\n",
+			sname, fname, namebuf);
+		goto out;
+	}
 
 	if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) {
 		printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1));


-- 
Samba Shared Repository


More information about the samba-cvs mailing list