summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-09-10 01:58:51 +0000
committerJeremy Allison <jra@samba.org>2002-09-10 01:58:51 +0000
commitdf920a60b5f207149cbc9dcb63d406abb0d0490c (patch)
treec2ef644a20a1675e8203949e3b6f023cf5f04c20 /source3
parent8de41d59482e7d66824c4a69563875d768f1f100 (diff)
downloadsamba-df920a60b5f207149cbc9dcb63d406abb0d0490c.tar.gz
samba-df920a60b5f207149cbc9dcb63d406abb0d0490c.tar.bz2
samba-df920a60b5f207149cbc9dcb63d406abb0d0490c.zip
Added final Steve French patch for "required" attributes with old
dir listings. Added regression test in smbtorture (in HEAD) also. Jeremy. (This used to be commit 3c9d24d7c3bad2beb641880a97f0eda5cd3e4ec7)
Diffstat (limited to 'source3')
-rw-r--r--source3/libsmb/clilist.c48
-rw-r--r--source3/smbd/dir.c21
-rw-r--r--source3/smbd/reply.c8
-rw-r--r--source3/torture/torture.c100
4 files changed, 147 insertions, 30 deletions
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 17a759f9e3..3eacc25380 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -22,13 +22,13 @@
#include "includes.h"
-
/****************************************************************************
-interpret a long filename structure - this is mostly guesses at the moment
-The length of the structure is returned
-The structure of a long filename depends on the info level. 260 is used
-by NT and 2 is used by OS/2
+ Interpret a long filename structure - this is mostly guesses at the moment.
+ The length of the structure is returned
+ The structure of a long filename depends on the info level. 260 is used
+ by NT and 2 is used by OS/2
****************************************************************************/
+
static int interpret_long_filename(struct cli_state *cli,
int level,char *p,file_info *finfo)
{
@@ -41,8 +41,7 @@ static int interpret_long_filename(struct cli_state *cli,
memcpy(finfo,&def_finfo,sizeof(*finfo));
- switch (level)
- {
+ switch (level) {
case 1: /* OS/2 understands this */
/* these dates are converted to GMT by
make_unix_date */
@@ -126,16 +125,16 @@ static int interpret_long_filename(struct cli_state *cli,
namelen, 0);
return SVAL(base, 0);
}
- }
+ }
DEBUG(1,("Unknown long filename format %d\n",level));
return(SVAL(p,0));
}
-
/****************************************************************************
- do a directory listing, calling fn on each file found
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+****************************************************************************/
+
int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
@@ -307,12 +306,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
return(total_received);
}
-
-
/****************************************************************************
-interpret a short filename structure
-The length of the structure is returned
+ Interpret a short filename structure.
+ The length of the structure is returned.
****************************************************************************/
+
static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo)
{
extern file_info def_finfo;
@@ -334,10 +332,11 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
/****************************************************************************
- do a directory listing, calling fn on each file found
- this uses the old SMBsearch interface. It is needed for testing Samba,
- but should otherwise not be used
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ this uses the old SMBsearch interface. It is needed for testing Samba,
+ but should otherwise not be used.
+****************************************************************************/
+
int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
@@ -453,16 +452,15 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
return(num_received);
}
-
/****************************************************************************
- do a directory listing, calling fn on each file found
- this auto-switches between old and new style
- ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ This auto-switches between old and new style.
+****************************************************************************/
+
int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(file_info *, const char *, void *), void *state)
{
- if (cli->protocol <= PROTOCOL_LANMAN1) {
+ if (cli->protocol <= PROTOCOL_LANMAN1)
return cli_list_old(cli, Mask, attribute, fn, state);
- }
return cli_list_new(cli, Mask, attribute, fn, state);
}
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index bdcb4b0461..396ecd98c4 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -553,9 +553,24 @@ void *dptr_fetch_lanman2(int dptr_num)
BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
{
- if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
- return False;
- return True;
+ int mask;
+
+ /* Check the "may have" search bits. */
+ if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
+ return False;
+
+ /* Check the "must have" bits, which are the may have bits shifted eight */
+ /* If must have bit is set, the file/dir can not be returned in search unless the matching
+ file attribute is set */
+ mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
+ if(mask) {
+ if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */
+ return True;
+ else
+ return False;
+ }
+
+ return True;
}
static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask)
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 01e7df282c..2b361fd43a 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -673,12 +673,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (strlen(directory) == 0)
pstrcpy(directory,"./");
memset((char *)status,'\0',21);
- SCVAL(status,0,dirtype);
+ SCVAL(status,0,(dirtype & 0x1F));
}
else
{
+ int status_dirtype;
memcpy(status,p,21);
- dirtype = CVAL(status,0) & 0x1F;
+ status_dirtype = CVAL(status,0) & 0x1F;
+ if (status_dirtype != (dirtype & 0x1F))
+ dirtype = status_dirtype;
+
conn->dirptr = dptr_fetch(status+12,&dptr_num);
if (!conn->dirptr)
goto SearchEmpty;
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 047b4c7a24..fb62b13657 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -3533,6 +3533,105 @@ static BOOL run_dirtest(int dummy)
return correct;
}
+static void del_fn(file_info *finfo, const char *mask, void *state)
+{
+ struct cli_state *pcli = (struct cli_state *)state;
+ fstring fname;
+ slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
+
+ if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
+ return;
+
+ if (finfo->mode & aDIR) {
+ if (!cli_rmdir(pcli, fname))
+ printf("del_fn: failed to rmdir %s\n,", fname );
+ } else {
+ if (!cli_unlink(pcli, fname))
+ printf("del_fn: failed to unlink %s\n,", fname );
+ }
+}
+
+static BOOL run_dirtest1(int dummy)
+{
+ int i;
+ static struct cli_state cli;
+ int fnum, num_seen;
+ BOOL correct = True;
+
+ printf("starting directory test\n");
+
+ if (!torture_open_connection(&cli)) {
+ return False;
+ }
+
+ cli_sockopt(&cli, sockops);
+
+ cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli);
+ cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli);
+ cli_rmdir(&cli, "\\LISTDIR");
+ cli_mkdir(&cli, "\\LISTDIR");
+
+ /* Create 1000 files and 1000 directories. */
+ for (i=0;i<1000;i++) {
+ fstring fname;
+ slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
+ fnum = cli_nt_create_full(&cli, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
+ if (fnum == -1) {
+ fprintf(stderr,"Failed to open %s\n", fname);
+ return False;
+ }
+ cli_close(&cli, fnum);
+ }
+ for (i=0;i<1000;i++) {
+ fstring fname;
+ slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
+ if (!cli_mkdir(&cli, fname)) {
+ fprintf(stderr,"Failed to open %s\n", fname);
+ return False;
+ }
+ }
+
+ /* Now ensure that doing an old list sees both files and directories. */
+ num_seen = cli_list_old(&cli, "\\LISTDIR\\*", aDIR, list_fn, NULL);
+ printf("num_seen = %d\n", num_seen );
+ /* We should see 100 files + 1000 directories + . and .. */
+ if (num_seen != 2002)
+ correct = False;
+
+ /* Ensure if we have the "must have" bits we only see the
+ * relevent entries.
+ */
+ num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, NULL);
+ printf("num_seen = %d\n", num_seen );
+ if (num_seen != 1002)
+ correct = False;
+
+ num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, NULL);
+ printf("num_seen = %d\n", num_seen );
+ if (num_seen != 1000)
+ correct = False;
+
+ /* Delete everything. */
+ cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli);
+ cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli);
+ cli_rmdir(&cli, "\\LISTDIR");
+
+#if 0
+ printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
+ printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
+ printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
+#endif
+
+ if (!torture_close_connection(&cli)) {
+ correct = False;
+ }
+
+ printf("finished dirtest1\n");
+
+ return correct;
+}
+
static BOOL run_error_map_extract(int dummy) {
static struct cli_state c_dos;
@@ -3761,6 +3860,7 @@ static struct {
{"OPLOCK2", run_oplock2, 0},
{"OPLOCK3", run_oplock3, 0},
{"DIR", run_dirtest, 0},
+ {"DIR1", run_dirtest1, 0},
{"DENY1", torture_denytest1, 0},
{"DENY2", torture_denytest2, 0},
{"TCON", run_tcon_test, 0},