r3746: added RAW-STREAMS and RAW-EAS tests to smbtorture
[jra/samba/.git] / source4 / torture / raw / streams.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    test alternate data streams
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "libcli/raw/libcliraw.h"
25
26 #define BASEDIR "\\teststreams"
27
28 #define CHECK_STATUS(status, correct) do { \
29         if (!NT_STATUS_EQUAL(status, correct)) { \
30                 printf("(%s) Incorrect status %s - should be %s\n", \
31                        __location__, nt_errstr(status), nt_errstr(correct)); \
32                 ret = False; \
33                 goto done; \
34         }} while (0)
35
36 #define CHECK_VALUE(v, correct) do { \
37         if ((v) != (correct)) { \
38                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
39                        __location__, #v, v, correct); \
40                 ret = False; \
41         }} while (0)
42
43 /*
44   check that a stream has the right contents
45 */
46 static BOOL check_stream(struct smbcli_state *cli, TALLOC_CTX *mem_ctx,
47                          const char *fname, const char *sname, 
48                          const char *value)
49 {
50         int fnum;
51         const char *full_name;
52         char *buf;
53         ssize_t ret;
54
55         full_name = talloc_asprintf(mem_ctx, "%s:%s", fname, sname);
56
57         fnum = smbcli_open(cli->tree, full_name, O_RDONLY, DENY_NONE);
58
59         if (value == NULL) {
60                 if (fnum != -1) {
61                         printf("should have failed stream open of %s\n", full_name);
62                         return False;
63                 }
64                 return True;
65         }
66             
67         if (fnum == -1) {
68                 printf("Failed to open stream '%s' - %s\n", 
69                        full_name, smbcli_errstr(cli->tree));
70                 return False;
71         }
72
73         buf = talloc(mem_ctx, strlen(value)+11);
74         
75         ret = smbcli_read(cli->tree, fnum, buf, 0, strlen(value)+11);
76         if (ret != strlen(value)) {
77                 printf("Failed to read %d bytes from stream '%s' - got %d\n",
78                        strlen(value), full_name, ret);
79                 return False;
80         }
81
82         if (memcmp(buf, value, strlen(value)) != 0) {
83                 printf("Bad data in stream\n");
84                 return False;
85         }
86
87         smbcli_close(cli->tree, fnum);
88         return True;
89 }
90
91 /*
92   test basic io on streams
93 */
94 static BOOL test_stream_io(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
95 {
96         NTSTATUS status;
97         union smb_open io;
98         const char *fname = BASEDIR "\\stream.txt";
99         const char *sname1, *sname2;
100         BOOL ret = True;
101         int fnum, fnum2;
102         ssize_t retsize;
103
104         sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname, "Stream One");
105
106         printf("opening non-existant directory stream\n");
107         io.generic.level = RAW_OPEN_NTCREATEX;
108         io.ntcreatex.in.root_fid = 0;
109         io.ntcreatex.in.flags = 0;
110         io.ntcreatex.in.access_mask = SEC_RIGHT_MAXIMUM_ALLOWED;
111         io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
112         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
113         io.ntcreatex.in.share_access = 
114                 NTCREATEX_SHARE_ACCESS_READ | 
115                 NTCREATEX_SHARE_ACCESS_WRITE;
116         io.ntcreatex.in.alloc_size = 0;
117         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
118         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
119         io.ntcreatex.in.security_flags = 0;
120         io.ntcreatex.in.fname = sname1;
121         status = smb_raw_open(cli->tree, mem_ctx, &io);
122         CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
123
124         printf("creating a stream on a non-existant file\n");
125         io.ntcreatex.in.create_options = 0;
126         io.ntcreatex.in.fname = sname1;
127         status = smb_raw_open(cli->tree, mem_ctx, &io);
128         CHECK_STATUS(status, NT_STATUS_OK);
129         fnum = io.ntcreatex.out.fnum;
130
131         ret &= check_stream(cli, mem_ctx, fname, "Stream One", NULL);
132
133         printf("writing to stream\n");
134         retsize = smbcli_write(cli->tree, fnum, 0, "test data", 0, 9);
135         CHECK_VALUE(retsize, 9);
136
137         smbcli_close(cli->tree, fnum);
138
139         ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test data");
140
141         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
142         status = smb_raw_open(cli->tree, mem_ctx, &io);
143         CHECK_STATUS(status, NT_STATUS_OK);
144         fnum = io.ntcreatex.out.fnum;
145
146         printf("modifying stream\n");
147         retsize = smbcli_write(cli->tree, fnum, 0, "MORE DATA ", 5, 10);
148         CHECK_VALUE(retsize, 10);
149
150         smbcli_close(cli->tree, fnum);
151
152         ret &= check_stream(cli, mem_ctx, fname, "Stream One", "test MORE DATA ");
153
154         printf("deleting stream\n");
155         status = smbcli_unlink(cli->tree, sname1);
156         CHECK_STATUS(status, NT_STATUS_OK);
157
158         printf("deleting file\n");
159         status = smbcli_unlink(cli->tree, fname);
160         CHECK_STATUS(status, NT_STATUS_OK);
161
162 done:
163         smbcli_close(cli->tree, fnum);
164         return True;
165 }
166
167 /* 
168    basic testing of streams calls
169 */
170 BOOL torture_raw_streams(void)
171 {
172         struct smbcli_state *cli;
173         BOOL ret = True;
174         TALLOC_CTX *mem_ctx;
175
176         if (!torture_open_connection(&cli)) {
177                 return False;
178         }
179
180         mem_ctx = talloc_init("torture_raw_streams");
181
182         if (!torture_setup_dir(cli, BASEDIR)) {
183                 return False;
184         }
185
186         ret &= test_stream_io(cli, mem_ctx);
187
188         smb_raw_exit(cli->session);
189         smbcli_deltree(cli->tree, BASEDIR);
190
191         torture_close_connection(cli);
192         talloc_destroy(mem_ctx);
193         return ret;
194 }