summaryrefslogtreecommitdiff
path: root/source3/client/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/client/client.c')
-rw-r--r--source3/client/client.c271
1 files changed, 168 insertions, 103 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 267c13048e..1410fc2f33 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -309,6 +309,17 @@ static int cmd_pwd(void)
}
/****************************************************************************
+ Ensure name has correct directory separators.
+****************************************************************************/
+
+static void normalize_name(char *newdir)
+{
+ if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
+ string_replace(newdir,'/','\\');
+ }
+}
+
+/****************************************************************************
Change directory - inner section.
****************************************************************************/
@@ -329,7 +340,8 @@ static int do_cd(const char *new_dir)
TALLOC_FREE(ctx);
return 1;
}
- string_replace(newdir,'/','\\');
+
+ normalize_name(newdir);
/* Save the current directory in case the new directory is invalid */
@@ -349,17 +361,16 @@ static int do_cd(const char *new_dir)
if (!new_cd) {
goto out;
}
- if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
- new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR);
- if (!new_cd) {
- goto out;
- }
- }
- client_set_cur_dir(new_cd);
}
- if (!new_cd) {
- goto out;
+
+ /* Ensure cur_dir ends in a DIRSEP */
+ if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
+ new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR);
+ if (!new_cd) {
+ goto out;
+ }
}
+ client_set_cur_dir(new_cd);
new_cd = clean_name(ctx, new_cd);
client_set_cur_dir(new_cd);
@@ -851,26 +862,15 @@ static int cmd_dir(void)
int rc = 1;
dir_total = 0;
- if (strcmp(client_get_cur_dir(), CLI_DIRSEP_STR) != 0) {
- mask = talloc_strdup(ctx, client_get_cur_dir());
- if (!mask) {
- return 1;
- }
- if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
- mask = talloc_asprintf_append(mask, CLI_DIRSEP_STR);
- }
- } else {
- mask = talloc_strdup(ctx, CLI_DIRSEP_STR);
- }
-
+ mask = talloc_strdup(ctx, client_get_cur_dir());
if (!mask) {
return 1;
}
if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
- string_replace(buf,'/','\\');
+ normalize_name(buf);
if (*buf == CLI_DIRSEP_CHAR) {
- mask = talloc_strdup(ctx, buf + 1);
+ mask = talloc_strdup(ctx, buf);
} else {
mask = talloc_asprintf_append(mask, buf);
}
@@ -920,7 +920,7 @@ static int cmd_du(void)
}
if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
- string_replace(buf,'/','\\');
+ normalize_name(buf);
if (*buf == CLI_DIRSEP_CHAR) {
mask = talloc_strdup(ctx, buf);
} else {
@@ -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;
@@ -1112,10 +1100,7 @@ static int cmd_get(void)
char *rname = NULL;
char *fname = NULL;
- rname = talloc_asprintf(ctx,
- "%s%s",
- client_get_cur_dir(),
- CLI_DIRSEP_STR);
+ rname = talloc_strdup(ctx, client_get_cur_dir());
if (!rname) {
return 1;
}
@@ -1262,10 +1247,7 @@ static int cmd_more(void)
int fd;
int rc = 0;
- rname = talloc_asprintf(ctx,
- "%s%s",
- client_get_cur_dir(),
- CLI_DIRSEP_STR);
+ rname = talloc_strdup(ctx, client_get_cur_dir());
if (!rname) {
return 1;
}
@@ -1334,15 +1316,6 @@ static int cmd_mget(void)
if (!mget_mask) {
return 1;
}
- if ((mget_mask[0] != '\0') &&
- (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)) {
- mget_mask = talloc_asprintf_append(mget_mask,
- CLI_DIRSEP_STR);
- if (!mget_mask) {
- return 1;
- }
- }
-
if (*buf == CLI_DIRSEP_CHAR) {
mget_mask = talloc_strdup(ctx, buf);
} else {
@@ -1356,18 +1329,9 @@ static int cmd_mget(void)
}
if (!*mget_mask) {
- mget_mask = talloc_strdup(ctx, client_get_cur_dir());
- if (!mget_mask) {
- return 1;
- }
- if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR) {
- mget_mask = talloc_asprintf_append(mget_mask,
- CLI_DIRSEP_STR);
- if (!mget_mask) {
- return 1;
- }
- }
- mget_mask = talloc_asprintf_append(mget_mask, "*");
+ mget_mask = talloc_asprintf(ctx,
+ "%s*",
+ client_get_cur_dir());
if (!mget_mask) {
return 1;
}
@@ -1463,6 +1427,7 @@ static int cmd_mkdir(void)
struct cli_state *targetcli;
char *targetname = NULL;
char *p = NULL;
+ char *saveptr;
ddir2 = talloc_strdup(ctx, "");
if (!ddir2) {
@@ -1478,7 +1443,7 @@ static int cmd_mkdir(void)
return 1;
}
trim_char(ddir,'.','\0');
- p = strtok(ddir,"/\\");
+ p = strtok_r(ddir, "/\\", &saveptr);
while (p) {
ddir2 = talloc_asprintf_append(ddir2, p);
if (!ddir2) {
@@ -1491,7 +1456,7 @@ static int cmd_mkdir(void)
if (!ddir2) {
return 1;
}
- p = strtok(NULL,"/\\");
+ p = strtok_r(NULL, "/\\", &saveptr);
}
} else {
do_mkdir(mask);
@@ -1528,6 +1493,92 @@ static int cmd_altname(void)
}
/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int do_allinfo(const char *name)
+{
+ fstring altname;
+ struct timespec b_time, a_time, m_time, c_time;
+ SMB_OFF_T size;
+ uint16_t mode;
+ SMB_INO_T ino;
+ NTTIME tmp;
+ unsigned int num_streams;
+ struct stream_struct *streams;
+ unsigned int i;
+
+ if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
+ d_printf("%s getting alt name for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+ d_printf("altname: %s\n", altname);
+
+ if (!cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
+ &size, &mode, &ino)) {
+ d_printf("%s getting pathinfo for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+
+ unix_timespec_to_nt_time(&tmp, b_time);
+ d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, a_time);
+ d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, m_time);
+ d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, c_time);
+ d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ if (!cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
+ &streams)) {
+ d_printf("%s getting streams for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+
+ for (i=0; i<num_streams; i++) {
+ d_printf("stream: [%s], %lld bytes\n", streams[i].name,
+ (unsigned long long)streams[i].size);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int cmd_allinfo(void)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ char *name;
+ char *buf;
+
+ name = talloc_strdup(ctx, client_get_cur_dir());
+ if (!name) {
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
+ d_printf("allinfo <file>\n");
+ return 1;
+ }
+ name = talloc_asprintf_append(name, buf);
+ if (!name) {
+ return 1;
+ }
+
+ do_allinfo(name);
+
+ return 0;
+}
+
+/****************************************************************************
Put a single file.
****************************************************************************/
@@ -1673,10 +1724,7 @@ static int cmd_put(void)
char *rname;
char *buf;
- rname = talloc_asprintf(ctx,
- "%s%s",
- client_get_cur_dir(),
- CLI_DIRSEP_STR);
+ rname = talloc_strdup(ctx, client_get_cur_dir());
if (!rname) {
return 1;
}
@@ -1893,10 +1941,10 @@ static int cmd_mput(void)
break;
} else { /* Yes */
SAFE_FREE(rname);
- if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+ if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
break;
}
- string_replace(rname,'/','\\');
+ normalize_name(rname);
if (!cli_chkpath(cli, rname) &&
!do_mkdir(rname)) {
DEBUG (0, ("Unable to make dir, skipping..."));
@@ -1920,12 +1968,12 @@ static int cmd_mput(void)
/* Yes */
SAFE_FREE(rname);
- if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+ if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
break;
}
}
- string_replace(rname,'/','\\');
+ normalize_name(rname);
do_put(rname, lname, false);
}
@@ -3469,10 +3517,7 @@ static int cmd_reget(void)
char *fname = NULL;
char *p = NULL;
- remote_name = talloc_asprintf(ctx,
- "%s%s",
- client_get_cur_dir(),
- CLI_DIRSEP_STR);
+ remote_name = talloc_strdup(ctx, client_get_cur_dir());
if (!remote_name) {
return 1;
}
@@ -3511,10 +3556,7 @@ static int cmd_reput(void)
char *buf;
SMB_STRUCT_STAT st;
- remote_name = talloc_asprintf(ctx,
- "%s%s",
- client_get_cur_dir(),
- CLI_DIRSEP_STR);
+ remote_name = talloc_strdup(ctx, client_get_cur_dir());
if (!remote_name) {
return 1;
}
@@ -3839,6 +3881,8 @@ static struct {
char compl_args[2]; /* Completion argument info */
} commands[] = {
{"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
+ {"allinfo",cmd_allinfo,"<file> show all available info",
+ {COMPL_NONE,COMPL_NONE}},
{"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
{"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
{"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
@@ -4069,7 +4113,7 @@ static void completion_remote_filter(const char *mnt,
return;
}
if (f->mode & aDIR) {
- tmp = talloc_asprintf_append(tmp, "/");
+ tmp = talloc_asprintf_append(tmp, CLI_DIRSEP_STR);
}
if (!tmp) {
TALLOC_FREE(ctx);
@@ -4333,9 +4377,30 @@ static void readline_callback(void)
session keepalives and then drop them here.
*/
if (FD_ISSET(cli->fd,&fds)) {
- if (receive_smb_raw(cli->fd,cli->inbuf,0,0,&cli->smb_rw_error) == -1) {
- DEBUG(0, ("Read from server failed, maybe it closed the "
- "connection\n"));
+ NTSTATUS status;
+ size_t len;
+
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
+
+ status = receive_smb_raw(cli->fd, cli->inbuf, 0, 0, &len);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Read from server failed, maybe it closed "
+ "the connection\n"));
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
+ set_smb_read_error(&cli->smb_rw_error,
+ SMB_READ_EOF);
+ return;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ set_smb_read_error(&cli->smb_rw_error,
+ SMB_READ_TIMEOUT);
+ return;
+ }
+
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
return;
}
if(CVAL(cli->inbuf,0) != SMBkeepalive) {