[PATCH] libsmb: File stream listing function
Mrinal Kalakrishnan
lists at mrinal.net
Wed Jan 19 14:42:25 GMT 2005
Hi,
This patch adds a function to clifile.c to retrieve a list of streams
associated with a file. This can be used to list alternate data
streams and get their data and so on.
I don't know if this will be useful for anyone but me, but here's the
patch anyway.. :-)
--
Mrinal Kalakrishnan || http://mrinal.net/ || PGP:B1E86F5B ||
<mail at mrinal.net> || JabberID: <mrinal at myjabber.net> ||
-------------- next part --------------
diff -Nur source/include/smb.h source-patched/include/smb.h
--- source/include/smb.h 2005-01-05 02:00:38.000000000 +0530
+++ source-patched/include/smb.h 2005-01-19 19:32:31.000000000 +0530
@@ -1704,6 +1704,11 @@
DATA_BLOB value;
};
+typedef struct file_stream_info {
+ char *name;
+ off_t datasize;
+} file_stream_info;
+
/* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
/* EA to use for DOS attributes */
diff -Nur source/libsmb/clifile.c source-patched/libsmb/clifile.c
--- source/libsmb/clifile.c 2005-01-05 02:00:24.000000000 +0530
+++ source-patched/libsmb/clifile.c 2005-01-19 19:49:14.000000000 +0530
@@ -1641,3 +1641,138 @@
return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
}
+
+/*********************************************************
+ Get stream list utility fn.
+*********************************************************/
+
+static BOOL cli_get_stream_list(struct cli_state *cli,
+ uint16 setup, char *param, unsigned int param_len,
+ TALLOC_CTX *ctx,
+ size_t *pnum_streams,
+ struct file_stream_info **pstream_list)
+{
+ unsigned int data_len = 0;
+ unsigned int rparam_len, rdata_len;
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ BOOL ret = False;
+ struct file_stream_info *stream_list;
+ uint32 next_entry_offset;
+ uint32 stream_name_length;
+ off_t stream_size;
+ off_t allocation_size;
+ fstring stream_name;
+ int stream_no = 0;
+
+ *pnum_streams = 0;
+ *pstream_list = NULL;
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* Name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 10, /* param, length, max */
+ NULL, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &rparam_len,
+ &rdata, &rdata_len)) {
+ return False;
+ }
+
+ if (!rdata || rdata_len < 4) {
+ goto out;
+ }
+
+ p = rdata;
+
+ /* loop once just to count the number of streams
+ * otherwise we don't know how much memory to allocate */
+ do {
+ stream_no++;
+ next_entry_offset = (uint32)(IVAL(p,0));
+ p+=next_entry_offset;
+ }
+ while (next_entry_offset!=0);
+
+ *pnum_streams = stream_no;
+ stream_no = 0;
+
+ stream_list = (struct file_stream_info *)talloc(ctx, (*pnum_streams)*sizeof(struct file_stream_info));
+ if (!stream_list) {
+ goto out;
+ }
+
+ /* reset pointer to start of data */
+ p = rdata;
+
+ do {
+ next_entry_offset = IVAL(p,0);
+ stream_name_length = IVAL(p,4);
+ stream_size = IVAL2_TO_SMB_BIG_UINT(p,8);
+ allocation_size = IVAL2_TO_SMB_BIG_UINT(p,16);
+ stream_name[0] = '\0';
+ pull_ucs2(NULL, stream_name, p+24, sizeof(fstring), stream_name_length, STR_NOALIGN);
+ stream_list[stream_no].name = talloc_strdup(ctx, stream_name);
+ stream_list[stream_no].datasize = stream_size;
+ p+=next_entry_offset;
+ stream_no++;
+ }
+ while (next_entry_offset!=0);
+
+ *pstream_list = stream_list;
+ ret = True;
+
+ out :
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return ret;
+}
+
+/*********************************************************
+ Get stream list from a pathname.
+*********************************************************/
+
+BOOL cli_get_stream_list_path(struct cli_state *cli, const char *path,
+ TALLOC_CTX *ctx,
+ size_t *pnum_streams,
+ struct file_stream_info **pstream_list)
+{
+ uint16 setup = TRANSACT2_QPATHINFO;
+ unsigned int param_len = 0;
+ char param[sizeof(pstring)+6];
+ char *p;
+
+ p = param;
+ memset(p, 0, 6);
+ SSVAL(p, 0, SMB_QUERY_FILE_STREAM_INFO);
+ p += 6;
+ p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ return cli_get_stream_list(cli, setup, param, param_len, ctx, pnum_streams, pstream_list);
+}
+
+/*********************************************************
+ Get stream list from an fnum.
+*********************************************************/
+
+BOOL cli_get_stream_list_fnum(struct cli_state *cli, int fnum,
+ TALLOC_CTX *ctx,
+ size_t *pnum_streams,
+ struct file_stream_info **pstream_list)
+{
+ uint16 setup = TRANSACT2_QFILEINFO;
+ char param[6];
+
+ memset(param, 0, 6);
+ SSVAL(param,0,fnum);
+ SSVAL(param,2,SMB_QUERY_FILE_STREAM_INFO);
+
+ return cli_get_stream_list(cli, setup, param, 6, ctx, pnum_streams, pstream_list);
+}
More information about the samba-technical
mailing list