From 62445788350b2f174537d877d721d92147f93ec7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Feb 2008 15:21:33 +0100 Subject: Add async cli_pull support This is the big (and potentially controversial) one. It took a phone call to explain to metze what is going on inside cli_pull_read_done, but I would really like everybody to understand this function. It is a very good and reasonably complex example of async programming. If we want more asynchronism in s3, this is what we will have to deal with :-) Make use of it in the smbclient "get" command. Volker (This used to be commit 76f9b360ee1d973630d82d401eeddce858189301) --- source3/client/client.c | 45 ++++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 29 deletions(-) (limited to 'source3/client/client.c') diff --git a/source3/client/client.c b/source3/client/client.c index f7ed33ad8a..c97f6223a7 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -964,22 +964,30 @@ static int cmd_echo(void) Get a file from rname to lname ****************************************************************************/ +static NTSTATUS writefile_sink(char *buf, size_t n, void *priv) +{ + int *pfd = (int *)priv; + if (writefile(*pfd, buf, n) == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; +} + static int do_get(const char *rname, const char *lname_in, bool reget) { TALLOC_CTX *ctx = talloc_tos(); int handle = 0, fnum; bool newhandle = false; - char *data = NULL; struct timeval tp_start; - int read_size = io_bufsize; uint16 attr; SMB_OFF_T size; off_t start = 0; - off_t nread = 0; + ssize_t nread = 0; int rc = 0; struct cli_state *targetcli = NULL; char *targetname = NULL; char *lname = NULL; + NTSTATUS status; lname = talloc_strdup(ctx, lname_in); if (!lname) { @@ -1038,36 +1046,15 @@ static int do_get(const char *rname, const char *lname_in, bool reget) DEBUG(1,("getting file %s of size %.0f as %s ", rname, (double)size, lname)); - if(!(data = (char *)SMB_MALLOC(read_size))) { - d_printf("malloc fail for size %d\n", read_size); + status = cli_pull(targetcli, fnum, start, size, 1024*1024, + writefile_sink, (void *)&handle, &nread); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "parallel_read returned %s\n", + nt_errstr(status)); cli_close(targetcli, fnum); return 1; } - while (1) { - int n = cli_read(targetcli, fnum, data, nread + start, read_size); - - if (n <= 0) - break; - - if (writefile(handle,data, n) != n) { - d_printf("Error writing local file\n"); - rc = 1; - break; - } - - nread += n; - } - - if (nread + start < size) { - DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n", - rname, (long)nread)); - - rc = 1; - } - - SAFE_FREE(data); - if (!cli_close(targetcli, fnum)) { d_printf("Error %s closing remote file\n",cli_errstr(cli)); rc = 1; -- cgit