diff options
-rw-r--r-- | source3/libsmb/clilist.c | 48 | ||||
-rw-r--r-- | source3/smbd/dir.c | 21 | ||||
-rw-r--r-- | source3/smbd/reply.c | 8 | ||||
-rw-r--r-- | source3/torture/torture.c | 100 |
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}, |