diff options
author | Volker Lendecke <vl@samba.org> | 2008-02-28 15:21:33 +0100 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2008-03-06 13:28:23 +0100 |
commit | 62445788350b2f174537d877d721d92147f93ec7 (patch) | |
tree | e5a2b6dbc49f178a38e77e37798df43fb0e6d532 /source3/client | |
parent | 1ea0a5d0cdaf9cbc1d1a5c0720ae466f07cea816 (diff) | |
download | samba-62445788350b2f174537d877d721d92147f93ec7.tar.gz samba-62445788350b2f174537d877d721d92147f93ec7.tar.bz2 samba-62445788350b2f174537d877d721d92147f93ec7.zip |
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)
Diffstat (limited to 'source3/client')
-rw-r--r-- | source3/client/client.c | 45 |
1 files changed, 16 insertions, 29 deletions
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; |