summaryrefslogtreecommitdiff
path: root/source3/client
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2008-02-28 15:21:33 +0100
committerVolker Lendecke <vl@samba.org>2008-03-06 13:28:23 +0100
commit62445788350b2f174537d877d721d92147f93ec7 (patch)
treee5a2b6dbc49f178a38e77e37798df43fb0e6d532 /source3/client
parent1ea0a5d0cdaf9cbc1d1a5c0720ae466f07cea816 (diff)
downloadsamba-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.c45
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;