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-02-28 15:27:55 +0100
commit525aac775ecef275dbd0732830a9bac0fd023135 (patch)
treef94f42e0cff50c92d927f3b1c33d3d87305be997 /source3/client
parent1d41b5bd2a58dcc6966a3a49ccb063ff05e46125 (diff)
downloadsamba-525aac775ecef275dbd0732830a9bac0fd023135.tar.gz
samba-525aac775ecef275dbd0732830a9bac0fd023135.tar.bz2
samba-525aac775ecef275dbd0732830a9bac0fd023135.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 844a163458c7585e4306a21ffdae5d08e03d6e4d)
Diffstat (limited to 'source3/client')
-rw-r--r--source3/client/client.c42
1 files changed, 15 insertions, 27 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index f7ed33ad8a..1410fc2f33 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -964,12 +964,20 @@ 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;
@@ -980,6 +988,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
struct cli_state *targetcli = NULL;
char *targetname = NULL;
char *lname = NULL;
+ NTSTATUS status;
lname = talloc_strdup(ctx, lname_in);
if (!lname) {
@@ -1038,36 +1047,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;