r26238: Add a loadparm context parameter to torture_context, remove more uses of...
[gd/samba-autobuild/.git] / source4 / torture / raw / eas.c
index 572a551d1762b75b06db0693244ff85e71daf81b..53449a1505b675ac5a1fbcd86c11d32b234e8df6 100644 (file)
@@ -4,10 +4,11 @@
    test DOS extended attributes
 
    Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Guenter Kukkukk 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "torture/torture.h"
 #include "libcli/raw/libcliraw.h"
-#include "librpc/gen_ndr/ndr_security.h"
+#include "libcli/libcli.h"
+#include "torture/util.h"
+#include "param/param.h"
 
 #define BASEDIR "\\testeas"
 
        if (!NT_STATUS_EQUAL(status, correct)) { \
                printf("(%s) Incorrect status %s - should be %s\n", \
                       __location__, nt_errstr(status), nt_errstr(correct)); \
-               ret = False; \
+               ret = false; \
                goto done; \
        }} while (0)
 
-static DATA_BLOB data_blob_string_const(const char *str)
-{
-       DATA_BLOB blob;
-       blob.data = discard_const(str);
-       blob.length = strlen(str);
-       return blob;
-}
+static bool maxeadebug; /* need that here, to allow no file delete in debug case */
 
-static BOOL check_ea(struct smbcli_state *cli, 
+static bool check_ea(struct smbcli_state *cli, 
                     const char *fname, const char *eaname, const char *value)
 {
        NTSTATUS status = torture_check_ea(cli, fname, eaname, value);
        return NT_STATUS_IS_OK(status);
 }
 
-static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 {
        NTSTATUS status;
        union smb_setfileinfo setfile;
        union smb_open io;
        const char *fname = BASEDIR "\\ea.txt";
-       BOOL ret = True;
+       bool ret = true;
        int fnum = -1;
 
        printf("TESTING SETFILEINFO EA_SET\n");
@@ -76,15 +73,15 @@ static BOOL test_eas(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io.ntcreatex.in.fname = fname;
        status = smb_raw_open(cli->tree, mem_ctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
+       fnum = io.ntcreatex.out.file.fnum;
        
        ret &= check_ea(cli, fname, "EAONE", NULL);
 
        printf("Adding first two EAs\n");
        setfile.generic.level = RAW_SFILEINFO_EA_SET;
-       setfile.generic.file.fnum = fnum;
+       setfile.generic.in.file.fnum = fnum;
        setfile.ea_set.in.num_eas = 2;
-       setfile.ea_set.in.eas = talloc_array_p(mem_ctx, struct ea_struct, 2);
+       setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
        setfile.ea_set.in.eas[0].flags = 0;
        setfile.ea_set.in.eas[0].name.s = "EAONE";
        setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE1");
@@ -144,15 +141,234 @@ done:
 }
 
 
+/*
+ * Helper function to retrieve the max. ea size for one ea name
+ */
+static int test_one_eamax(struct smbcli_state *cli, const int fnum, 
+                         const char *eaname, DATA_BLOB eablob, 
+                         const int eastart, const int eadebug) 
+{
+       NTSTATUS status;
+       struct ea_struct eastruct;
+       union smb_setfileinfo setfile;
+       int i, high, low, maxeasize;
+
+       setfile.generic.level = RAW_SFILEINFO_EA_SET;
+       setfile.generic.in.file.fnum = fnum;
+       setfile.ea_set.in.num_eas = 1;
+       setfile.ea_set.in.eas = &eastruct;
+       setfile.ea_set.in.eas->flags = 0;
+       setfile.ea_set.in.eas->name.s = eaname;
+       setfile.ea_set.in.eas->value = eablob;
+
+       maxeasize = eablob.length;
+       i = eastart;
+       low = 0;
+       high = maxeasize;
+
+       do {
+               if (eadebug) {
+                       printf ("Testing EA size: %d\n", i);
+               }
+               setfile.ea_set.in.eas->value.length = i;
+
+               status = smb_raw_setfileinfo(cli->tree, &setfile);
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
+                       if (eadebug) {
+                               printf ("[%s] EA size %d succeeded! "
+                                       "(high=%d low=%d)\n", 
+                                       eaname, i, high, low);
+                       }
+                       low = i;
+                       if (low == maxeasize) {
+                               printf ("Max. EA size for \"%s\"=%d "
+                                       "[but could be possibly larger]\n", 
+                                       eaname, low);
+                               break;
+                       }
+                       if (high - low == 1 && high != maxeasize) {
+                               printf ("Max. EA size for \"%s\"=%d\n", 
+                                       eaname, low);
+                               break;
+                       }
+                       i += (high - low + 1) / 2;
+               } else {
+                       if (eadebug) {
+                               printf ("[%s] EA size %d failed!    "
+                                       "(high=%d low=%d) [%s]\n", 
+                                       eaname, i, high, low, 
+                                       nt_errstr(status));
+                       }
+                       high = i;
+                       if (high - low <= 1) {
+                               printf ("Max. EA size for \"%s\"=%d\n", 
+                                       eaname, low);
+                               break;
+                       }
+                       i -= (high - low + 1) / 2;
+               }
+       } while (true);
+
+       return low;
+}
+
+/*
+ * Test for maximum ea size - more than one ea name is checked.
+ *
+ * Additional parameters can be passed, to allow further testing:
+ *
+ *             default
+ * maxeasize    65536   limit the max. size for a single EA name
+ * maxeanames     101   limit of the number of tested names
+ * maxeastart       1   this EA size is used to test for the 1st EA (atm)
+ * maxeadebug       0   if set true, further debug output is done - in addition
+ *                      the testfile is not deleted for further inspection!
+ *
+ * Set some/all of these options on the cmdline with:
+ * --option torture:maxeasize=1024 --option torture:maxeadebug=1 ...
+ *
+ */
+static bool test_max_eas(struct smbcli_state *cli, struct torture_context *tctx)
+{
+       NTSTATUS status;
+       union smb_open io;
+       const char *fname = BASEDIR "\\ea_max.txt";
+       int fnum = -1;
+       bool ret = true;
+       bool err = false;
+
+       int       i, j, k, last, total;
+       DATA_BLOB eablob;
+       char      *eaname = NULL;
+       int       maxeasize;
+       int       maxeanames;
+       int       maxeastart;
+
+       printf("TESTING SETFILEINFO MAX. EA_SET\n");
+
+       maxeasize  = torture_setting_int(tctx, "maxeasize", 65536);
+       maxeanames = torture_setting_int(tctx, "maxeanames", 101);
+       maxeastart = torture_setting_int(tctx, "maxeastart", 1);
+       maxeadebug = torture_setting_int(tctx, "maxeadebug", 0);
+
+       /* Do some sanity check on possibly passed parms */
+       if (maxeasize <= 0) {
+               printf("Invalid parameter 'maxeasize=%d'",maxeasize);
+               err = true;
+       }
+       if (maxeanames <= 0) {
+               printf("Invalid parameter 'maxeanames=%d'",maxeanames);
+               err = true;
+       }
+       if (maxeastart <= 0) {
+               printf("Invalid parameter 'maxeastart=%d'",maxeastart);
+               err = true;
+       }
+       if (maxeadebug < 0) {
+               printf("Invalid parameter 'maxeadebug=%d'",maxeadebug);
+               err = true;
+       }
+       if (err) {
+         printf("\n\n");
+         goto done;
+       }
+       if (maxeastart > maxeasize) {
+               maxeastart = maxeasize;
+               printf ("'maxeastart' outside range - corrected to %d\n", 
+                       maxeastart);
+       }
+       printf("MAXEA parms: maxeasize=%d maxeanames=%d maxeastart=%d"
+              " maxeadebug=%d\n", maxeasize, maxeanames, maxeastart, 
+              maxeadebug);
+
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = 
+               NTCREATEX_SHARE_ACCESS_READ | 
+               NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname;
+       status = smb_raw_open(cli->tree, tctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+       
+       eablob = data_blob_talloc(tctx, NULL, maxeasize);
+       if (eablob.data == NULL) {
+               goto done;
+       }
+       /* 
+        * Fill in some EA data - the offset could be easily checked 
+        * during a hexdump.
+        */
+       for (i = 0, k = 0; i < eablob.length / 4; i++, k+=4) {
+               eablob.data[k]   = k & 0xff;
+               eablob.data[k+1] = (k >>  8) & 0xff;
+               eablob.data[k+2] = (k >> 16) & 0xff;
+               eablob.data[k+3] = (k >> 24) & 0xff;
+       }
+
+       i = eablob.length % 4;
+       if (i-- > 0) { 
+               eablob.data[k] = k & 0xff;
+               if (i-- > 0) { 
+                       eablob.data[k+1] = (k >>  8) & 0xff;
+                       if (i-- > 0) { 
+                               eablob.data[k+2] = (k >> 16) & 0xff;
+                       }
+               }
+       }
+       /*
+        * Filesystems might allow max. EAs data for different EA names.
+        * So more than one EA name should be checked.
+        */
+       total = 0;
+       last  = maxeastart;
+
+       for (i = 0; i < maxeanames; i++) {
+               if (eaname != NULL) {
+                       talloc_free(eaname);
+               }
+               eaname = talloc_asprintf(tctx, "MAX%d", i);
+               if(eaname == NULL) {
+                       goto done;
+               }
+               j = test_one_eamax(cli, fnum, eaname, eablob, last, maxeadebug);
+               if (j <= 0) {
+                       break;
+               }
+               total += j;
+               last = j;
+       }
+
+       printf("Total EA size:%d\n", total);
+       if (i == maxeanames) {
+               printf ("NOTE: More EAs could be available!\n");
+       } 
+       if (total == 0) {
+               ret = false;
+       }
+done:
+       smbcli_close(cli->tree, fnum);
+       return ret;
+}
+
 /*
   test using NTTRANS CREATE to create a file with an initial EA set
 */
-static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 {
        NTSTATUS status;
        union smb_open io;
        const char *fname = BASEDIR "\\ea2.txt";
-       BOOL ret = True;
+       bool ret = true;
        int fnum = -1;
        struct ea_struct eas[3];
        struct smb_ea_list ea_list;
@@ -194,7 +410,7 @@ static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        status = smb_raw_open(cli->tree, mem_ctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
+       fnum = io.ntcreatex.out.file.fnum;
        
        ret &= check_ea(cli, fname, "EAONE", NULL);
        ret &= check_ea(cli, fname, "1st EA", "Value One");
@@ -214,7 +430,7 @@ static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        status = smb_raw_open(cli->tree, mem_ctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
-       fnum = io.ntcreatex.out.fnum;
+       fnum = io.ntcreatex.out.file.fnum;
        
        ret &= check_ea(cli, fname, "1st EA", "Value One");
        ret &= check_ea(cli, fname, "2nd EA", "Second Value");
@@ -229,29 +445,46 @@ done:
 /* 
    basic testing of EA calls
 */
-BOOL torture_raw_eas(void)
+bool torture_raw_eas(struct torture_context *torture, struct smbcli_state *cli)
 {
-       struct smbcli_state *cli;
-       BOOL ret = True;
-       TALLOC_CTX *mem_ctx;
+       bool ret = true;
 
-       if (!torture_open_connection(&cli)) {
-               return False;
+       if (!torture_setup_dir(cli, BASEDIR)) {
+               return false;
        }
 
-       mem_ctx = talloc_init("torture_raw_eas");
+       ret &= test_eas(cli, torture);
+       ret &= test_nttrans_create(cli, torture);
+
+       smb_raw_exit(cli->session);
+
+       return ret;
+}
+
+/* 
+   test max EA size
+*/
+bool torture_max_eas(struct torture_context *torture)
+{
+       struct smbcli_state *cli;
+       bool ret = true;
+
+       if (!torture_open_connection(&cli, 0)) {
+               return false;
+       }
 
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
-       ret &= test_eas(cli, mem_ctx);
-       ret &= test_nttrans_create(cli, mem_ctx);
+       ret &= test_max_eas(cli, torture);
 
        smb_raw_exit(cli->session);
-       smbcli_deltree(cli->tree, BASEDIR);
+       if (!maxeadebug) {
+               /* in no ea debug case, all files are gone now */
+               smbcli_deltree(cli->tree, BASEDIR);
+       }
 
        torture_close_connection(cli);
-       talloc_destroy(mem_ctx);
        return ret;
 }