[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