Added final Steve French patch for "required" attributes with old
authorJeremy Allison <jra@samba.org>
Tue, 10 Sep 2002 01:58:51 +0000 (01:58 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 10 Sep 2002 01:58:51 +0000 (01:58 +0000)
dir listings. Added regression test in smbtorture (in HEAD) also.
Jeremy.
(This used to be commit 3c9d24d7c3bad2beb641880a97f0eda5cd3e4ec7)

source3/libsmb/clilist.c
source3/smbd/dir.c
source3/smbd/reply.c
source3/torture/torture.c

index 17a759f9e39371455fdb39ea116e64425eddbfbb..3eacc25380aba4605378b308ac4641ac3059dead 100644 (file)
 
 #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);
 }
index bdcb4b0461bd7757a712529361fe2423c46f345a..396ecd98c495e8f856edf090e96d54fa19b66a80 100644 (file)
@@ -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)
index 01e7df282cf900eaf8ddb200aae61d717e2e4e3b..2b361fd43a7678cb324aca47b62369a548c4aefa 100644 (file)
@@ -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;
index 047b4c7a240cd4553bb479fea8f5d4bab3bf0535..fb62b13657fe5d380fbef035355fa905d95338b4 100644 (file)
@@ -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},