From 3d3d6e7020749c63455e16ba110bc46862d3c146 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 18 Jan 2008 11:08:17 +0100 Subject: Add the "allinfo" command to smbclient Modeled after the Samba4 allinfo command (This used to be commit 3fa0cf3fe5f819f6e76df6f7cef3bb4e1c307a52) --- source3/client/client.c | 88 ++++++++++++++++++++++++++++++++ source3/include/smb.h | 10 ++++ source3/libsmb/clirap.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) (limited to 'source3') diff --git a/source3/client/client.c b/source3/client/client.c index 267c13048e..59ca2e0adc 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -1527,6 +1527,92 @@ static int cmd_altname(void) return 0; } +/**************************************************************************** + 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\n"); + return 1; + } + name = talloc_asprintf_append(name, buf); + if (!name) { + return 1; + } + + do_allinfo(name); + + return 0; +} + /**************************************************************************** Put a single file. ****************************************************************************/ @@ -3839,6 +3925,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," show all available info", + {COMPL_NONE,COMPL_NONE}}, {"altname",cmd_altname," show alt name",{COMPL_NONE,COMPL_NONE}}, {"archive",cmd_archive,"\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 (default 20)",{COMPL_NONE,COMPL_NONE}}, diff --git a/source3/include/smb.h b/source3/include/smb.h index d64b8ba80c..15e51dbdd7 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -574,6 +574,16 @@ struct trans_state { char *data; }; +/* + * Info about an alternate data stream + */ + +struct stream_struct { + SMB_OFF_T size; + SMB_OFF_T alloc_size; + char *name; +}; + /* Include VFS stuff */ #include "smb_acls.h" diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index aab77a3d54..4c5e338606 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -805,6 +805,137 @@ bool cli_qpathinfo2(struct cli_state *cli, const char *fname, return True; } +/**************************************************************************** + Get the stream info +****************************************************************************/ + +bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname, + TALLOC_CTX *mem_ctx, + unsigned int *pnum_streams, + struct stream_struct **pstreams) +{ + unsigned int data_len = 0; + unsigned int param_len = 0; + uint16 setup = TRANSACT2_QPATHINFO; + char *param; + char *rparam=NULL, *rdata=NULL; + char *p; + unsigned int num_streams; + struct stream_struct *streams; + unsigned int ofs; + size_t namelen = 2*(strlen(fname)+1); + + param = SMB_MALLOC_ARRAY(char, 6+namelen+2); + if (param == NULL) { + return false; + } + p = param; + memset(p, 0, 6); + SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION); + p += 6; + p += clistr_push(cli, p, fname, namelen, STR_TERMINATE); + + param_len = PTR_DIFF(p, param); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, len, max */ + param, param_len, 10, /* param, len, max */ + NULL, data_len, cli->max_xmit /* data, len, max */ + )) { + return false; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, ¶m_len, + &rdata, &data_len)) { + return false; + } + + if (!rdata) { + SAFE_FREE(rparam); + return false; + } + + num_streams = 0; + streams = NULL; + ofs = 0; + + while ((data_len > ofs) && (data_len - ofs >= 24)) { + uint32_t nlen, len; + ssize_t size; + void *vstr; + struct stream_struct *tmp; + uint8_t *tmp_buf; + + tmp = TALLOC_REALLOC_ARRAY(mem_ctx, streams, + struct stream_struct, + num_streams+1); + + if (tmp == NULL) { + goto fail; + } + streams = tmp; + + nlen = IVAL(rdata, ofs + 0x04); + + streams[num_streams].size = IVAL_TO_SMB_OFF_T( + rdata, ofs + 0x08); + streams[num_streams].alloc_size = IVAL_TO_SMB_OFF_T( + rdata, ofs + 0x10); + + if (nlen > data_len - (ofs + 24)) { + goto fail; + } + + /* + * We need to null-terminate src, how do I do this with + * convert_string_talloc?? + */ + + tmp_buf = TALLOC_ARRAY(streams, uint8_t, nlen+2); + if (tmp_buf == NULL) { + goto fail; + } + + memcpy(tmp_buf, rdata+ofs+24, nlen); + tmp_buf[nlen] = 0; + tmp_buf[nlen+1] = 0; + + size = convert_string_talloc(streams, CH_UTF16, CH_UNIX, + tmp_buf, nlen+2, &vstr, + false); + TALLOC_FREE(tmp_buf); + + if (size == -1) { + goto fail; + } + streams[num_streams].name = (char *)vstr; + num_streams++; + + len = IVAL(rdata, ofs); + if (len > data_len - ofs) { + goto fail; + } + if (len == 0) break; + ofs += len; + } + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + + *pnum_streams = num_streams; + *pstreams = streams; + return true; + + fail: + TALLOC_FREE(streams); + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return false; +} + /**************************************************************************** Send a qfileinfo QUERY_FILE_NAME_INFO call. ****************************************************************************/ -- cgit