2 Unix SMB/CIFS implementation.
6 Copyright (C) Ralph Boehme 2014
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/filesys.h"
24 #include "libcli/libcli.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb/smb2_create_ctx.h"
28 #include "lib/cmdline/popt_common.h"
29 #include "param/param.h"
30 #include "libcli/resolve/resolve.h"
31 #include "MacExtensions.h"
32 #include "lib/util/tsort.h"
34 #include "torture/torture.h"
35 #include "torture/util.h"
36 #include "torture/smb2/proto.h"
37 #include "torture/vfs/proto.h"
38 #include "librpc/gen_ndr/ndr_ioctl.h"
39 #include "libcli/security/dom_sid.h"
40 #include "../librpc/gen_ndr/ndr_security.h"
41 #include "libcli/security/secace.h"
42 #include "libcli/security/security_descriptor.h"
44 #define BASEDIR "vfs_fruit_dir"
45 #define FNAME_CC_SRC "testfsctl.dat"
46 #define FNAME_CC_DST "testfsctl2.dat"
48 #define CHECK_STATUS(status, correct) do { \
49 if (!NT_STATUS_EQUAL(status, correct)) { \
50 torture_result(tctx, TORTURE_FAIL, \
51 "(%s) Incorrect status %s - should be %s\n", \
52 __location__, nt_errstr(status), nt_errstr(correct)); \
57 #define CHECK_VALUE(v, correct) do { \
58 if ((v) != (correct)) { \
59 torture_result(tctx, TORTURE_FAIL, \
60 "(%s) Incorrect value %s=%u - should be %u\n", \
61 __location__, #v, (unsigned)v, (unsigned)correct); \
66 static bool check_stream_list(struct smb2_tree *tree,
67 struct torture_context *tctx,
73 static int qsort_string(char * const *s1, char * const *s2)
75 return strcmp(*s1, *s2);
78 static int qsort_stream(const struct stream_struct * s1, const struct stream_struct *s2)
80 return strcmp(s1->stream_name.s, s2->stream_name.s);
85 * This is hokey, but what else can we do?
87 #if defined(HAVE_ATTROPEN) || defined(FREEBSD)
88 #define AFPINFO_EA_NETATALK "org.netatalk.Metadata"
89 #define AFPRESOURCE_EA_NETATALK "org.netatalk.ResourceFork"
91 #define AFPINFO_EA_NETATALK "user.org.netatalk.Metadata"
92 #define AFPRESOURCE_EA_NETATALK "user.org.netatalk.ResourceFork"
96 The metadata xattr char buf below contains the following attributes:
98 -------------------------------------------------------------------------------
99 Entry ID : 00000008 : File Dates Info
100 Offset : 00000162 : 354
101 Length : 00000010 : 16
103 -DATE------: : (GMT) : (Local)
104 create : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
105 modify : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
106 backup : 80000000 : Unknown or Initial
107 access : 1B442169 : Mon Jun 30 13:23:53 2014 : Mon Jun 30 15:23:53 2014
109 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
110 00000000 : 1B 44 21 69 1B 44 21 69 80 00 00 00 1B 44 21 69 : .D!i.D!i.....D!i
112 -------------------------------------------------------------------------------
113 Entry ID : 00000009 : Finder Info
114 Offset : 0000007A : 122
115 Length : 00000020 : 32
118 Type : 42415252 : BARR
119 Creator : 464F4F4F : FOOO
134 Location v : 0000 : 0
135 Location h : 0000 : 0
139 Rsvd|IconID: 0000 : 0
159 Rsvd|commnt: 0000 : 0
160 PutAway : 00000000 : 0
162 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
163 00000000 : 42 41 52 52 46 4F 4F 4F 40 00 00 00 00 00 00 00 : BARRFOOO@.......
164 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
166 -------------------------------------------------------------------------------
167 Entry ID : 0000000E : AFP File Info
168 Offset : 00000172 : 370
169 Length : 00000004 : 4
171 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
172 00000000 : 00 00 01 A1 : ....
175 char metadata_xattr[] = {
176 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
180 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x08, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00,
182 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
183 0x00, 0x7a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
184 0x00, 0x0e, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00,
185 0x00, 0x04, 0x80, 0x44, 0x45, 0x56, 0x00, 0x00,
186 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x80, 0x49,
187 0x4e, 0x4f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00,
188 0x00, 0x08, 0x80, 0x53, 0x59, 0x4e, 0x00, 0x00,
189 0x01, 0x86, 0x00, 0x00, 0x00, 0x08, 0x80, 0x53,
190 0x56, 0x7e, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00,
191 0x00, 0x04, 0x42, 0x41, 0x52, 0x52, 0x46, 0x4f,
192 0x4f, 0x4f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x1b, 0x44, 0x21, 0x69, 0x1b, 0x44,
221 0x21, 0x69, 0x80, 0x00, 0x00, 0x00, 0x1b, 0x44,
222 0x21, 0x69, 0x00, 0x00, 0x01, 0xa1, 0x00, 0xfd,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x20,
224 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xe3,
225 0x86, 0x53, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x01,
230 The buf below contains the following AppleDouble encoded data:
232 -------------------------------------------------------------------------------
233 MagicNumber: 00051607 : AppleDouble
234 Version : 00020000 : Version 2
235 Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
236 Num. of ent: 0002 : 2
238 -------------------------------------------------------------------------------
239 Entry ID : 00000009 : Finder Info
240 Offset : 00000032 : 50
241 Length : 00000EB0 : 3760
244 Type : 54455354 : TEST
245 Creator : 534C4F57 : SLOW
260 Location v : 0000 : 0
261 Location h : 0000 : 0
265 Rsvd|IconID: 0000 : 0
285 Rsvd|commnt: 0000 : 0
286 PutAway : 00000000 : 0
290 magic : 41545452 : ATTR
291 debug_tag : 53D4580C : 1406425100
292 total_size : 00000EE2 : 3810
293 data_start : 000000BC : 188
294 data_length: 0000005E : 94
295 reserved[0]: 00000000 : ....
296 reserved[1]: 00000000 : ....
297 reserved[2]: 00000000 : ....
301 offset : 000000BC : 188
302 length : 0000005B : 91
305 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
306 00000000 : 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 61 : com.apple.metada
307 00000010 : 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 54 : ta:_kMDItemUserT
308 00000020 : 61 67 73 00 : ags.
309 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
310 00000000 : 62 70 6C 69 73 74 30 30 A5 01 02 03 04 05 54 74 : bplist00......Tt
311 00000010 : 65 73 74 66 00 47 00 72 00 FC 00 6E 00 0A 00 32 : estf.G.r...n...2
312 00000020 : 56 4C 69 6C 61 0A 33 56 47 65 6C 62 0A 35 56 42 : VLila.3VGelb.5VB
313 00000030 : 6C 61 75 0A 34 08 0E 13 20 27 2E 00 00 00 00 00 : lau.4... '......
314 00000040 : 00 01 01 00 00 00 00 00 00 00 06 00 00 00 00 00 : ................
315 00000050 : 00 00 00 00 00 00 00 00 00 00 35 : ..........5
317 offset : 00000117 : 279
318 length : 00000003 : 3
321 -EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
322 00000000 : 66 6F 6F 3A 62 61 72 00 : foo:bar.
323 -EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
324 00000000 : 62 61 7A : baz
326 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
327 00000000 : 54 45 53 54 53 4C 4F 57 00 08 00 00 00 00 00 00 : TESTSLOW........
328 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
329 00000020 : 00 00 41 54 54 52 53 D4 58 0C 00 00 0E E2 00 00 : ..ATTRS.X.......
330 00000030 : 00 BC 00 00 00 5E 00 00 00 00 00 00 00 00 00 00 : .....^..........
331 00000040 : 00 00 00 00 00 02 00 00 00 BC 00 00 00 5B 00 00 : .............[..
332 00000050 : 24 63 6F 6D 2E 61 70 70 6C 65 2E 6D 65 74 61 64 : $com.apple.metad
333 00000060 : 61 74 61 3A 5F 6B 4D 44 49 74 65 6D 55 73 65 72 : ata:_kMDItemUser
334 00000070 : 54 61 67 73 00 00 00 00 01 17 00 00 00 03 00 00 : Tags............
335 00000080 : 08 66 6F 6F 3A 62 61 72 00 66 62 70 6C 69 73 74 : .foo:bar.fbplist
336 00000090 : 30 30 A5 01 02 03 04 05 54 74 65 73 74 66 00 47 : 00......Ttestf.G
337 000000A0 : 00 72 00 FC 00 6E 00 0A 00 32 56 4C 69 6C 61 0A : .r...n...2VLila.
338 000000B0 : 33 56 47 65 6C 62 0A 35 56 42 6C 61 75 0A 34 08 : 3VGelb.5VBlau.4.
339 000000C0 : 0E 13 20 27 2E 00 00 00 00 00 00 01 01 00 00 00 : .. '............
340 000000D0 : 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 : ................
341 000000E0 : 00 00 00 00 35 62 61 7A 00 00 00 00 00 00 00 00 : ....5baz........
342 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
344 00000EA0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
346 -------------------------------------------------------------------------------
347 Entry ID : 00000002 : Resource Fork
348 Offset : 00000EE2 : 3810
349 Length : 0000011E : 286
351 -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
352 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
353 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
354 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
355 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank ..
356 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
357 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
358 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
359 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
360 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
361 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
362 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
363 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
364 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
365 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
366 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
367 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
368 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
369 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : ..............
372 $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
374 static char osx_adouble_w_xattr[] = {
375 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
376 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
377 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
378 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
379 0x00, 0x32, 0x00, 0x00, 0x0e, 0xb0, 0x00, 0x00,
380 0x00, 0x02, 0x00, 0x00, 0x0e, 0xe2, 0x00, 0x00,
381 0x01, 0x1e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x4c,
382 0x4f, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x41, 0x54, 0x54, 0x52,
386 0x53, 0xd4, 0x58, 0x0c, 0x00, 0x00, 0x0e, 0xe2,
387 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5e,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
390 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x5b,
391 0x00, 0x00, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x61,
392 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x65, 0x74,
393 0x61, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x5f, 0x6b,
394 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x55, 0x73,
395 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x00, 0x00,
396 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00, 0x03,
397 0x00, 0x00, 0x08, 0x66, 0x6f, 0x6f, 0x3a, 0x62,
398 0x61, 0x72, 0x00, 0x66, 0x62, 0x70, 0x6c, 0x69,
399 0x73, 0x74, 0x30, 0x30, 0xa5, 0x01, 0x02, 0x03,
400 0x04, 0x05, 0x54, 0x74, 0x65, 0x73, 0x74, 0x66,
401 0x00, 0x47, 0x00, 0x72, 0x00, 0xfc, 0x00, 0x6e,
402 0x00, 0x0a, 0x00, 0x32, 0x56, 0x4c, 0x69, 0x6c,
403 0x61, 0x0a, 0x33, 0x56, 0x47, 0x65, 0x6c, 0x62,
404 0x0a, 0x35, 0x56, 0x42, 0x6c, 0x61, 0x75, 0x0a,
405 0x34, 0x08, 0x0e, 0x13, 0x20, 0x27, 0x2e, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x62,
410 0x61, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
715 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
783 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
845 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
852 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
854 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
855 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
856 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
857 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
858 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
861 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
874 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
884 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
890 * The buf below contains the following AppleDouble encoded data:
892 * -------------------------------------------------------------------------------
893 * MagicNumber: 00051607 : AppleDouble
894 * Version : 00020000 : Version 2
895 * Filler : 4D 61 63 20 4F 53 20 58 20 20 20 20 20 20 20 20 : Mac OS X
896 * Num. of ent: 0002 : 2
898 * -------------------------------------------------------------------------------
899 * Entry ID : 00000002 : Resource Fork
900 * Offset : 00000052 : 82
901 * Length : 0000011E : 286
903 * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
904 * 00000000 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
905 * 00000010 : 54 68 69 73 20 72 65 73 6F 75 72 63 65 20 66 6F : This resource fo
906 * 00000020 : 72 6B 20 69 6E 74 65 6E 74 69 6F 6E 61 6C 6C 79 : rk intentionally
907 * 00000030 : 20 6C 65 66 74 20 62 6C 61 6E 6B 20 20 20 00 00 : left blank ..
908 * 00000040 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
909 * 00000050 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
910 * 00000060 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
911 * 00000070 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
912 * 00000080 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
913 * 00000090 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
914 * 000000A0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
915 * 000000B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
916 * 000000C0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
917 * 000000D0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
918 * 000000E0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
919 * 000000F0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
920 * 00000100 : 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1E : ................
921 * 00000110 : 00 00 00 00 00 00 00 00 00 1C 00 1E FF FF : ..............
923 * Entry ID : 00000009 : Finder Info
924 * Offset : 00000032 : 50
925 * Length : 00000020 : 32
927 * -NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.
930 * Type : 57415645 : WAVE
931 * Creator : 5054756C : PTul
946 * Location v : 0000 : 0
947 * Location h : 0000 : 0
951 * Rsvd|IconID: 0000 : 0
971 * Rsvd|commnt: 0000 : 0
972 * PutAway : 00000000 : 0
974 * -RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)
975 * 00000000 : 57 41 56 45 50 54 75 6C 00 00 00 00 00 00 00 00 : WAVEPTul........
976 * 00000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 : ................
978 * It was created with:
979 * $ hexdump -ve '"\t" 7/1 "0x%02x, " 1/1 " 0x%02x," "\n"'
981 static char osx_adouble_without_xattr[] = {
982 0x00, 0x05, 0x16, 0x07, 0x00, 0x02, 0x00, 0x00,
983 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58,
984 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
985 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
986 0x00, 0x52, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00,
987 0x00, 0x09, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00,
988 0x00, 0x20, 0x57, 0x41, 0x56, 0x45, 0x50, 0x54,
989 0x75, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
993 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
994 0x00, 0x1e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x72,
995 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20,
996 0x66, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x6e, 0x74,
997 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
998 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
999 0x62, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x20, 0x20,
1000 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1001 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1019 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1026 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1e, 0xff, 0xff
1031 * talloc and intialize an AfpInfo
1033 static AfpInfo *torture_afpinfo_new(TALLOC_CTX *mem_ctx)
1037 info = talloc_zero(mem_ctx, AfpInfo);
1042 info->afpi_Signature = AFP_Signature;
1043 info->afpi_Version = AFP_Version;
1044 info->afpi_BackupTime = AFP_BackupTime;
1050 * Pack AfpInfo into a talloced buffer
1052 static char *torture_afpinfo_pack(TALLOC_CTX *mem_ctx,
1057 buf = talloc_zero_array(mem_ctx, char, AFP_INFO_SIZE);
1062 RSIVAL(buf, 0, info->afpi_Signature);
1063 RSIVAL(buf, 4, info->afpi_Version);
1064 RSIVAL(buf, 12, info->afpi_BackupTime);
1065 memcpy(buf + 16, info->afpi_FinderInfo, sizeof(info->afpi_FinderInfo));
1074 static void torture_afpinfo_unpack(AfpInfo *info, char *data)
1076 info->afpi_Signature = RIVAL(data, 0);
1077 info->afpi_Version = RIVAL(data, 4);
1078 info->afpi_BackupTime = RIVAL(data, 12);
1079 memcpy(info->afpi_FinderInfo, (const char *)data + 16,
1080 sizeof(info->afpi_FinderInfo));
1084 static bool torture_write_afpinfo(struct smb2_tree *tree,
1085 struct torture_context *tctx,
1086 TALLOC_CTX *mem_ctx,
1090 struct smb2_handle handle;
1091 struct smb2_create io;
1093 const char *full_name;
1097 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, AFPINFO_STREAM_NAME);
1098 if (full_name == NULL) {
1099 torture_comment(tctx, "talloc_asprintf error\n");
1103 io.in.desired_access = SEC_FILE_WRITE_DATA;
1104 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1105 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1106 io.in.create_options = 0;
1107 io.in.fname = full_name;
1109 status = smb2_create(tree, mem_ctx, &io);
1110 CHECK_STATUS(status, NT_STATUS_OK);
1112 handle = io.out.file.handle;
1114 infobuf = torture_afpinfo_pack(mem_ctx, info);
1115 if (infobuf == NULL) {
1119 status = smb2_util_write(tree, handle, infobuf, 0, AFP_INFO_SIZE);
1120 CHECK_STATUS(status, NT_STATUS_OK);
1122 smb2_util_close(tree, handle);
1129 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1130 * compare against buffer 'value'
1132 static bool check_stream(struct smb2_tree *tree,
1133 const char *location,
1134 struct torture_context *tctx,
1135 TALLOC_CTX *mem_ctx,
1144 struct smb2_handle handle;
1145 struct smb2_create create;
1151 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1152 if (full_name == NULL) {
1153 torture_comment(tctx, "talloc_asprintf error\n");
1156 ZERO_STRUCT(create);
1157 create.in.desired_access = SEC_FILE_READ_DATA;
1158 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1159 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1160 create.in.fname = full_name;
1162 torture_comment(tctx, "Open stream %s\n", full_name);
1164 status = smb2_create(tree, mem_ctx, &create);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 TALLOC_FREE(full_name);
1167 if (value == NULL) {
1170 torture_comment(tctx, "Unable to open stream %s\n", full_name);
1174 handle = create.out.file.handle;
1175 if (value == NULL) {
1176 TALLOC_FREE(full_name);
1177 smb2_util_close(tree, handle);
1182 r.in.file.handle = handle;
1183 r.in.length = read_count;
1184 r.in.offset = read_offset;
1186 status = smb2_read(tree, tree, &r);
1188 torture_assert_ntstatus_ok_goto(
1189 tctx, status, ret, done,
1190 talloc_asprintf(tctx, "(%s) Failed to read %lu bytes from stream '%s'\n",
1191 location, (long)strlen(value), full_name));
1193 torture_assert_goto(tctx, r.out.data.length == read_count, ret, done,
1194 talloc_asprintf(tctx, "smb2_read returned %jd bytes, expected %jd\n",
1195 (intmax_t)r.out.data.length, (intmax_t)read_count));
1197 torture_assert_goto(
1198 tctx, memcmp(r.out.data.data + comp_offset, value, comp_count) == 0,
1200 talloc_asprintf(tctx, "(%s) Bad data in stream\n", location));
1203 TALLOC_FREE(full_name);
1204 smb2_util_close(tree, handle);
1209 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1210 * compare against buffer 'value'
1212 static ssize_t read_stream(struct smb2_tree *tree,
1213 const char *location,
1214 struct torture_context *tctx,
1215 TALLOC_CTX *mem_ctx,
1221 struct smb2_handle handle;
1222 struct smb2_create create;
1225 const char *full_name;
1228 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname);
1229 if (full_name == NULL) {
1230 torture_comment(tctx, "talloc_asprintf error\n");
1233 ZERO_STRUCT(create);
1234 create.in.desired_access = SEC_FILE_READ_DATA;
1235 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1236 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1237 create.in.fname = full_name;
1239 torture_comment(tctx, "Open stream %s\n", full_name);
1241 status = smb2_create(tree, mem_ctx, &create);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 torture_comment(tctx, "Unable to open stream %s\n",
1248 handle = create.out.file.handle;
1251 r.in.file.handle = handle;
1252 r.in.length = read_count;
1253 r.in.offset = read_offset;
1255 status = smb2_read(tree, tree, &r);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
1260 smb2_util_close(tree, handle);
1266 return r.out.data.length;
1270 * Read 'count' bytes at 'offset' from stream 'fname:sname' and
1271 * compare against buffer 'value'
1273 static bool write_stream(struct smb2_tree *tree,
1274 const char *location,
1275 struct torture_context *tctx,
1276 TALLOC_CTX *mem_ctx,
1283 struct smb2_handle handle;
1284 struct smb2_create create;
1286 const char *full_name;
1288 full_name = talloc_asprintf(mem_ctx, "%s%s", fname, sname ? sname : "");
1289 if (full_name == NULL) {
1290 torture_comment(tctx, "talloc_asprintf error\n");
1293 ZERO_STRUCT(create);
1294 create.in.desired_access = SEC_FILE_WRITE_DATA;
1295 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1296 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1297 create.in.fname = full_name;
1299 status = smb2_create(tree, mem_ctx, &create);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (value == NULL) {
1304 torture_comment(tctx, "Unable to open stream %s\n",
1311 handle = create.out.file.handle;
1312 if (value == NULL) {
1316 status = smb2_util_write(tree, handle, value, offset, size);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 torture_comment(tctx, "(%s) Failed to write %lu bytes to "
1320 "stream '%s'\n", location, (long)size, full_name);
1324 smb2_util_close(tree, handle);
1328 static bool torture_setup_local_xattr(struct torture_context *tctx,
1329 const char *path_option,
1332 const char *metadata,
1340 spath = torture_setting_string(tctx, path_option, NULL);
1341 if (spath == NULL) {
1342 printf("No sharepath for option %s\n", path_option);
1346 path = talloc_asprintf(tctx, "%s/%s", spath, name);
1348 result = setxattr(path, xattr, metadata, size, 0);
1359 * Create a file or directory
1361 static bool torture_setup_file(TALLOC_CTX *mem_ctx, struct smb2_tree *tree,
1362 const char *name, bool dir)
1364 struct smb2_create io;
1367 smb2_util_unlink(tree, name);
1369 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1370 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1371 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1372 io.in.share_access =
1373 NTCREATEX_SHARE_ACCESS_DELETE|
1374 NTCREATEX_SHARE_ACCESS_READ|
1375 NTCREATEX_SHARE_ACCESS_WRITE;
1376 io.in.create_options = 0;
1379 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1380 io.in.share_access &= ~NTCREATEX_SHARE_ACCESS_DELETE;
1381 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1382 io.in.create_disposition = NTCREATEX_DISP_CREATE;
1385 status = smb2_create(tree, mem_ctx, &io);
1386 if (!NT_STATUS_IS_OK(status)) {
1390 status = smb2_util_close(tree, io.out.file.handle);
1391 if (!NT_STATUS_IS_OK(status)) {
1398 static bool enable_aapl(struct torture_context *tctx,
1399 struct smb2_tree *tree)
1401 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1404 struct smb2_create io;
1406 struct smb2_create_blob *aapl = NULL;
1407 uint32_t aapl_server_caps;
1408 uint32_t expected_scaps = (SMB2_CRTCTX_AAPL_UNIX_BASED |
1409 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1410 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
1411 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
1412 bool is_osx_server = torture_setting_bool(tctx, "osx", false);
1415 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1416 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1417 io.in.create_disposition = NTCREATEX_DISP_OPEN;
1418 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
1419 NTCREATEX_SHARE_ACCESS_READ |
1420 NTCREATEX_SHARE_ACCESS_WRITE);
1424 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
1425 * controls behaviour of Apple's SMB2 extensions for the whole
1429 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
1430 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
1431 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
1432 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
1433 SMB2_CRTCTX_AAPL_MODEL_INFO));
1434 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
1435 SMB2_CRTCTX_AAPL_UNIX_BASED |
1436 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
1438 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
1439 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_blob_add");
1441 status = smb2_create(tree, tctx, &io);
1442 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1444 status = smb2_util_close(tree, io.out.file.handle);
1445 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close");
1448 * Now check returned AAPL context
1450 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
1452 aapl = smb2_create_blob_find(&io.out.blobs,
1453 SMB2_CREATE_TAG_AAPL);
1454 torture_assert_goto(tctx, aapl != NULL, ret, done, "missing AAPL context");
1456 if (!is_osx_server) {
1457 size_t expected_aapl_ctx_size;
1459 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
1461 torture_assert_goto(
1462 tctx, aapl->data.length == expected_aapl_ctx_size,
1463 ret, done, "bad AAPL size");
1466 aapl_server_caps = BVAL(aapl->data.data, 16);
1467 torture_assert_goto(tctx, aapl_server_caps == expected_scaps,
1468 ret, done, "bad AAPL caps");
1471 talloc_free(mem_ctx);
1475 static bool test_read_netatalk_metadata(struct torture_context *tctx,
1476 struct smb2_tree *tree)
1478 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1479 const char *fname = BASEDIR "\\torture_read_metadata";
1481 struct smb2_handle testdirh;
1484 const char *localdir = NULL;
1486 torture_comment(tctx, "Checking metadata access\n");
1488 localdir = torture_setting_string(tctx, "localdir", NULL);
1489 if (localdir == NULL) {
1490 torture_skip(tctx, "Need localdir for test");
1493 smb2_util_unlink(tree, fname);
1495 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1496 CHECK_STATUS(status, NT_STATUS_OK);
1497 smb2_util_close(tree, testdirh);
1499 ret = torture_setup_file(mem_ctx, tree, fname, false);
1504 ret = torture_setup_local_xattr(tctx, "localdir",
1505 BASEDIR "/torture_read_metadata",
1506 AFPINFO_EA_NETATALK,
1507 metadata_xattr, sizeof(metadata_xattr));
1512 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1513 0, 60, 0, 4, "AFP");
1514 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1516 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1517 0, 60, 16, 8, "BARRFOOO");
1518 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1520 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1521 16, 8, 0, 3, "AFP");
1522 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1524 /* Check reading offset and read size > sizeof(AFPINFO_STREAM) */
1526 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1527 AFPINFO_STREAM, 0, 61);
1528 CHECK_VALUE(len, 60);
1530 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1531 AFPINFO_STREAM, 59, 2);
1532 CHECK_VALUE(len, 2);
1534 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1535 AFPINFO_STREAM, 60, 1);
1536 CHECK_VALUE(len, 1);
1538 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1539 AFPINFO_STREAM, 61, 1);
1540 CHECK_VALUE(len, 0);
1543 smb2_deltree(tree, BASEDIR);
1544 talloc_free(mem_ctx);
1548 static bool test_read_afpinfo(struct torture_context *tctx,
1549 struct smb2_tree *tree)
1551 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1552 const char *fname = BASEDIR "\\torture_read_metadata";
1554 struct smb2_handle testdirh;
1558 const char *type_creator = "SMB,OLE!";
1560 torture_comment(tctx, "Checking metadata access\n");
1562 smb2_util_unlink(tree, fname);
1564 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1565 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
1566 smb2_util_close(tree, testdirh);
1568 ret = torture_setup_file(mem_ctx, tree, fname, false);
1569 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
1571 info = torture_afpinfo_new(mem_ctx);
1572 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
1574 memcpy(info->afpi_FinderInfo, type_creator, 8);
1575 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1576 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
1578 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1579 0, 60, 0, 4, "AFP");
1580 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1582 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1583 0, 60, 16, 8, type_creator);
1584 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1587 * OS X ignores offset <= 60 and treats the as
1588 * offset=0. Reading from offsets > 60 returns EOF=0.
1591 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1592 16, 8, 0, 8, "AFP\0\0\0\001\0");
1593 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1595 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1596 AFPINFO_STREAM, 0, 61);
1597 torture_assert_goto(tctx, len == 60, ret, done, "read_stream failed");
1599 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1600 AFPINFO_STREAM, 59, 2);
1601 torture_assert_goto(tctx, len == 2, ret, done, "read_stream failed");
1603 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1605 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1607 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1608 AFPINFO_STREAM, 60, 1);
1609 torture_assert_goto(tctx, len == 1, ret, done, "read_stream failed");
1611 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1613 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
1615 len = read_stream(tree, __location__, tctx, mem_ctx, fname,
1616 AFPINFO_STREAM, 61, 1);
1617 torture_assert_goto(tctx, len == 0, ret, done, "read_stream failed");
1620 smb2_util_unlink(tree, fname);
1621 smb2_deltree(tree, BASEDIR);
1622 talloc_free(mem_ctx);
1626 static bool test_write_atalk_metadata(struct torture_context *tctx,
1627 struct smb2_tree *tree)
1629 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1630 const char *fname = BASEDIR "\\torture_write_metadata";
1631 const char *type_creator = "SMB,OLE!";
1633 struct smb2_handle testdirh;
1637 smb2_deltree(tree, BASEDIR);
1638 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1639 CHECK_STATUS(status, NT_STATUS_OK);
1640 smb2_util_close(tree, testdirh);
1642 ret = torture_setup_file(mem_ctx, tree, fname, false);
1647 info = torture_afpinfo_new(mem_ctx);
1652 memcpy(info->afpi_FinderInfo, type_creator, 8);
1653 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
1654 ret &= check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
1655 0, 60, 16, 8, type_creator);
1658 smb2_util_unlink(tree, fname);
1659 smb2_deltree(tree, BASEDIR);
1660 talloc_free(mem_ctx);
1664 static bool test_write_atalk_rfork_io(struct torture_context *tctx,
1665 struct smb2_tree *tree)
1667 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1668 const char *fname = BASEDIR "\\torture_write_rfork_io";
1669 const char *rfork = BASEDIR "\\torture_write_rfork_io" AFPRESOURCE_STREAM_NAME;
1670 const char *rfork_content = "1234567890";
1672 struct smb2_handle testdirh;
1676 struct smb2_handle filehandle;
1677 union smb_fileinfo finfo;
1678 union smb_setfileinfo sinfo;
1680 smb2_util_unlink(tree, fname);
1682 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1683 CHECK_STATUS(status, NT_STATUS_OK);
1684 smb2_util_close(tree, testdirh);
1686 ret = torture_setup_file(mem_ctx, tree, fname, false);
1691 torture_comment(tctx, "(%s) writing to resource fork\n",
1694 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1695 fname, AFPRESOURCE_STREAM_NAME,
1696 10, 10, rfork_content);
1698 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1699 fname, AFPRESOURCE_STREAM_NAME,
1700 0, 20, 10, 10, rfork_content);
1702 /* Check size after write */
1705 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1706 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1707 SEC_FILE_WRITE_ATTRIBUTE;
1708 io.smb2.in.fname = rfork;
1709 status = smb2_create(tree, mem_ctx, &(io.smb2));
1710 CHECK_STATUS(status, NT_STATUS_OK);
1711 filehandle = io.smb2.out.file.handle;
1713 torture_comment(tctx, "(%s) check resource fork size after write\n",
1717 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1718 finfo.generic.in.file.handle = filehandle;
1719 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1720 CHECK_STATUS(status, NT_STATUS_OK);
1721 if (finfo.all_info.out.size != 20) {
1722 torture_result(tctx, TORTURE_FAIL,
1723 "(%s) Incorrect resource fork size\n",
1726 smb2_util_close(tree, filehandle);
1729 smb2_util_close(tree, filehandle);
1731 /* Write at large offset */
1733 torture_comment(tctx, "(%s) writing to resource fork at large offset\n",
1736 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1737 fname, AFPRESOURCE_STREAM_NAME,
1738 (off_t)64*1024*1024, 10, rfork_content);
1740 ret &= check_stream(tree, __location__, tctx, mem_ctx,
1741 fname, AFPRESOURCE_STREAM_NAME,
1742 (off_t)64*1024*1024, 10, 0, 10, rfork_content);
1744 /* Truncate back to size of 1 byte */
1746 torture_comment(tctx, "(%s) truncate resource fork and check size\n",
1750 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1751 io.smb2.in.desired_access = SEC_FILE_ALL;
1752 io.smb2.in.fname = rfork;
1753 status = smb2_create(tree, mem_ctx, &(io.smb2));
1754 CHECK_STATUS(status, NT_STATUS_OK);
1755 filehandle = io.smb2.out.file.handle;
1758 sinfo.end_of_file_info.level =
1759 RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1760 sinfo.end_of_file_info.in.file.handle = filehandle;
1761 sinfo.end_of_file_info.in.size = 1;
1762 status = smb2_setinfo_file(tree, &sinfo);
1763 CHECK_STATUS(status, NT_STATUS_OK);
1765 smb2_util_close(tree, filehandle);
1767 /* Now check size */
1769 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1770 io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE |
1771 SEC_FILE_WRITE_ATTRIBUTE;
1772 io.smb2.in.fname = rfork;
1773 status = smb2_create(tree, mem_ctx, &(io.smb2));
1774 CHECK_STATUS(status, NT_STATUS_OK);
1775 filehandle = io.smb2.out.file.handle;
1778 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1779 finfo.generic.in.file.handle = filehandle;
1780 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1781 CHECK_STATUS(status, NT_STATUS_OK);
1782 if (finfo.all_info.out.size != 1) {
1783 torture_result(tctx, TORTURE_FAIL,
1784 "(%s) Incorrect resource fork size\n",
1787 smb2_util_close(tree, filehandle);
1790 smb2_util_close(tree, filehandle);
1793 smb2_util_unlink(tree, fname);
1794 smb2_deltree(tree, BASEDIR);
1795 talloc_free(mem_ctx);
1799 static bool test_rfork_truncate(struct torture_context *tctx,
1800 struct smb2_tree *tree)
1802 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1803 const char *fname = BASEDIR "\\torture_rfork_truncate";
1804 const char *rfork = BASEDIR "\\torture_rfork_truncate" AFPRESOURCE_STREAM;
1805 const char *rfork_content = "1234567890";
1807 struct smb2_handle testdirh;
1809 struct smb2_create create;
1810 struct smb2_handle fh1, fh2, fh3;
1811 union smb_setfileinfo sinfo;
1813 ret = enable_aapl(tctx, tree);
1814 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1816 smb2_util_unlink(tree, fname);
1818 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1819 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1820 smb2_util_close(tree, testdirh);
1822 ret = torture_setup_file(mem_ctx, tree, fname, false);
1827 ret &= write_stream(tree, __location__, tctx, mem_ctx,
1828 fname, AFPRESOURCE_STREAM,
1829 10, 10, rfork_content);
1831 /* Truncate back to size 0, further access MUST return ENOENT */
1833 torture_comment(tctx, "(%s) truncate resource fork to size 0\n",
1836 ZERO_STRUCT(create);
1837 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1838 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1839 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1840 create.in.fname = fname;
1841 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1842 NTCREATEX_SHARE_ACCESS_READ |
1843 NTCREATEX_SHARE_ACCESS_WRITE;
1844 status = smb2_create(tree, mem_ctx, &create);
1845 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1846 fh1 = create.out.file.handle;
1848 ZERO_STRUCT(create);
1849 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1850 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1851 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1852 create.in.fname = rfork;
1853 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1854 NTCREATEX_SHARE_ACCESS_READ |
1855 NTCREATEX_SHARE_ACCESS_WRITE;
1856 status = smb2_create(tree, mem_ctx, &create);
1857 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1858 fh2 = create.out.file.handle;
1861 sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1862 sinfo.end_of_file_info.in.file.handle = fh2;
1863 sinfo.end_of_file_info.in.size = 0;
1864 status = smb2_setinfo_file(tree, &sinfo);
1865 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file");
1868 * Now check size, we should get OBJECT_NAME_NOT_FOUND (!)
1870 ZERO_STRUCT(create);
1871 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1872 create.in.desired_access = SEC_FILE_ALL;
1873 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1874 create.in.fname = rfork;
1875 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1876 NTCREATEX_SHARE_ACCESS_READ |
1877 NTCREATEX_SHARE_ACCESS_WRITE;
1878 status = smb2_create(tree, mem_ctx, &create);
1879 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1882 * Do another open on the rfork and write to the new handle. A
1883 * naive server might unlink the AppleDouble resource fork
1884 * file when its truncated to 0 bytes above, so in case both
1885 * open handles share the same underlying fd, the unlink would
1886 * cause the below write to be lost.
1888 ZERO_STRUCT(create);
1889 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1890 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1891 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1892 create.in.fname = rfork;
1893 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1894 NTCREATEX_SHARE_ACCESS_READ |
1895 NTCREATEX_SHARE_ACCESS_WRITE;
1896 status = smb2_create(tree, mem_ctx, &create);
1897 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1898 fh3 = create.out.file.handle;
1900 status = smb2_util_write(tree, fh3, "foo", 0, 3);
1901 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write");
1903 smb2_util_close(tree, fh3);
1904 smb2_util_close(tree, fh2);
1905 smb2_util_close(tree, fh1);
1907 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM,
1909 torture_assert_goto(tctx, ret == true, ret, done, "check_stream");
1912 smb2_util_unlink(tree, fname);
1913 smb2_deltree(tree, BASEDIR);
1914 talloc_free(mem_ctx);
1918 static bool test_rfork_create(struct torture_context *tctx,
1919 struct smb2_tree *tree)
1921 TALLOC_CTX *mem_ctx = talloc_new(tctx);
1922 const char *fname = BASEDIR "\\torture_rfork_create";
1923 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
1925 struct smb2_handle testdirh;
1927 struct smb2_create create;
1928 struct smb2_handle fh1;
1929 const char *streams[] = {
1932 union smb_fileinfo finfo;
1934 ret = enable_aapl(tctx, tree);
1935 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
1937 smb2_util_unlink(tree, fname);
1939 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
1940 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
1941 smb2_util_close(tree, testdirh);
1943 ret = torture_setup_file(mem_ctx, tree, fname, false);
1948 torture_comment(tctx, "(%s) open rfork, should return ENOENT\n",
1951 ZERO_STRUCT(create);
1952 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1953 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1954 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1955 create.in.fname = rfork;
1956 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1957 NTCREATEX_SHARE_ACCESS_READ |
1958 NTCREATEX_SHARE_ACCESS_WRITE;
1959 status = smb2_create(tree, mem_ctx, &create);
1960 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
1962 torture_comment(tctx, "(%s) create resource fork\n", __location__);
1964 ZERO_STRUCT(create);
1965 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1966 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1967 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1968 create.in.fname = rfork;
1969 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
1970 NTCREATEX_SHARE_ACCESS_READ |
1971 NTCREATEX_SHARE_ACCESS_WRITE;
1972 status = smb2_create(tree, mem_ctx, &create);
1973 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
1974 fh1 = create.out.file.handle;
1976 torture_comment(tctx, "(%s) getinfo on create handle\n",
1980 finfo.generic.level = RAW_FILEINFO_ALL_INFORMATION;
1981 finfo.generic.in.file.handle = fh1;
1982 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
1983 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file");
1984 if (finfo.all_info.out.size != 0) {
1985 torture_result(tctx, TORTURE_FAIL,
1986 "(%s) Incorrect resource fork size\n",
1989 smb2_util_close(tree, fh1);
1993 torture_comment(tctx, "(%s) open rfork, should still return ENOENT\n",
1996 ZERO_STRUCT(create);
1997 create.in.create_disposition = NTCREATEX_DISP_OPEN;
1998 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
1999 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2000 create.in.fname = rfork;
2001 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2002 NTCREATEX_SHARE_ACCESS_READ |
2003 NTCREATEX_SHARE_ACCESS_WRITE;
2004 status = smb2_create(tree, mem_ctx, &create);
2005 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2007 ret = check_stream_list(tree, tctx, fname, 1, streams, false);
2008 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2010 torture_comment(tctx, "(%s) close empty created rfork, open should return ENOENT\n",
2013 ZERO_STRUCT(create);
2014 create.in.create_disposition = NTCREATEX_DISP_OPEN;
2015 create.in.desired_access = SEC_STD_READ_CONTROL | SEC_FILE_ALL;
2016 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2017 create.in.fname = rfork;
2018 create.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE |
2019 NTCREATEX_SHARE_ACCESS_READ |
2020 NTCREATEX_SHARE_ACCESS_WRITE;
2021 status = smb2_create(tree, mem_ctx, &create);
2022 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done, "smb2_create");
2025 smb2_util_unlink(tree, fname);
2026 smb2_deltree(tree, BASEDIR);
2027 talloc_free(mem_ctx);
2031 static bool test_rfork_create_ro(struct torture_context *tctx,
2032 struct smb2_tree *tree)
2034 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2035 const char *fname = BASEDIR "\\torture_rfork_create";
2036 const char *rfork = BASEDIR "\\torture_rfork_create" AFPRESOURCE_STREAM;
2038 struct smb2_handle testdirh;
2040 struct smb2_create create;
2042 smb2_util_unlink(tree, fname);
2043 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2044 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2045 "torture_smb2_testdir\n");
2046 smb2_util_close(tree, testdirh);
2048 ret = torture_setup_file(mem_ctx, tree, fname, false);
2053 torture_comment(tctx, "(%s) Try opening read-only with "
2054 "open_if create disposition, should work\n",
2057 ZERO_STRUCT(create);
2058 create.in.fname = rfork;
2059 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2060 create.in.desired_access = SEC_FILE_READ_DATA | SEC_STD_READ_CONTROL;
2061 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2062 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
2063 status = smb2_create(tree, mem_ctx, &(create));
2064 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2065 "smb2_create failed\n");
2067 smb2_util_close(tree, create.out.file.handle);
2070 smb2_util_unlink(tree, fname);
2071 smb2_deltree(tree, BASEDIR);
2072 talloc_free(mem_ctx);
2076 static bool test_adouble_conversion(struct torture_context *tctx,
2077 struct smb2_tree *tree)
2079 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2080 const char *fname = BASEDIR "\\test_adouble_conversion";
2081 const char *adname = BASEDIR "/._test_adouble_conversion";
2083 struct smb2_handle testdirh;
2085 const char *data = "This resource fork intentionally left blank";
2086 size_t datalen = strlen(data);
2087 const char *streams[] = {
2091 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
2092 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2094 bool is_osx = torture_setting_bool(tctx, "osx", false);
2097 torture_skip(tctx, "Test only works with Samba\n");
2100 smb2_deltree(tree, BASEDIR);
2102 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2103 CHECK_STATUS(status, NT_STATUS_OK);
2104 smb2_util_close(tree, testdirh);
2106 ret = torture_setup_file(tctx, tree, fname, false);
2107 torture_assert_goto(tctx, ret == true, ret, done,
2108 "torture_setup_file failed\n");
2110 ret = torture_setup_file(tctx, tree, adname, false);
2111 torture_assert_goto(tctx, ret == true, ret, done,
2112 "torture_setup_file failed\n");
2114 ret = write_stream(tree, __location__, tctx, mem_ctx,
2116 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
2117 torture_assert_goto(tctx, ret == true, ret, done,
2118 "write_stream failed\n");
2120 torture_comment(tctx, "(%s) test OS X AppleDouble conversion\n",
2123 ret = check_stream(tree, __location__, tctx, mem_ctx,
2124 fname, AFPRESOURCE_STREAM,
2125 16, datalen, 0, datalen, data);
2126 torture_assert_goto(tctx, ret == true, ret, done,
2127 "check AFPRESOURCE_STREAM failed\n");
2129 ret = check_stream(tree, __location__, tctx, mem_ctx,
2130 fname, AFPINFO_STREAM,
2131 0, 60, 16, 8, "TESTSLOW");
2132 torture_assert_goto(tctx, ret == true, ret, done,
2133 "check AFPINFO_STREAM failed\n");
2135 ret = check_stream(tree, __location__, tctx, mem_ctx, fname,
2136 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
2138 torture_assert_goto(tctx, ret == true, ret, done,
2139 "check foo:bar stream failed\n");
2141 ret = check_stream_list(tree, tctx, fname, 5, streams, false);
2142 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2145 smb2_deltree(tree, BASEDIR);
2146 talloc_free(mem_ctx);
2151 * Test conversion of AppleDouble file without embedded xattr data
2153 static bool test_adouble_conversion_wo_xattr(struct torture_context *tctx,
2154 struct smb2_tree *tree)
2156 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2157 const char *fname = BASEDIR "\\test_adouble_conversion";
2158 const char *adname = BASEDIR "/._test_adouble_conversion";
2160 struct smb2_handle testdirh;
2162 const char *streams[] = {
2167 struct smb2_create create;
2168 struct smb2_find find;
2170 union smb_search_data *d;
2171 const char *data = "This resource fork intentionally left blank";
2172 size_t datalen = strlen(data);
2173 bool is_osx = torture_setting_bool(tctx, "osx", false);
2176 torture_skip(tctx, "Test only works with Samba\n");
2179 smb2_deltree(tree, BASEDIR);
2181 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2182 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2183 "torture_smb2_testdir failed\n");
2184 smb2_util_close(tree, testdirh);
2186 ret = torture_setup_file(tctx, tree, fname, false);
2187 torture_assert_goto(tctx, ret == true, ret, done,
2188 "torture_setup_file failed\n");
2190 ret = torture_setup_file(tctx, tree, adname, false);
2191 torture_assert_goto(tctx, ret == true, ret, done,
2192 "torture_setup_file failed\n");
2194 ret = write_stream(tree, __location__, tctx, mem_ctx,
2196 sizeof(osx_adouble_without_xattr),
2197 osx_adouble_without_xattr);
2198 torture_assert_goto(tctx, ret == true, ret, done,
2199 "write_stream failed\n");
2201 ret = enable_aapl(tctx, tree);
2202 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
2205 * Issue a smb2_find(), this triggers the server-side conversion
2208 create = (struct smb2_create) {
2209 .in.desired_access = SEC_RIGHTS_DIR_READ,
2210 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
2211 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
2212 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
2213 .in.create_disposition = NTCREATEX_DISP_OPEN,
2214 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
2215 .in.fname = BASEDIR,
2218 status = smb2_create(tree, tctx, &create);
2219 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2220 "smb2_create failed\n");
2222 find = (struct smb2_find) {
2223 .in.file.handle = create.out.file.handle,
2225 .in.max_response_size = 0x1000,
2226 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
2229 status = smb2_find_level(tree, tree, &find, &count, &d);
2230 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2231 "smb2_find_level failed\n");
2233 status = smb2_util_close(tree, create.out.file.handle);
2234 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2235 "smb2_util_close failed");
2238 * Check number of streams
2241 ret = check_stream_list(tree, tctx, fname, 3, streams, false);
2242 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
2246 * Check Resourcefork data can be read.
2249 ret = check_stream(tree, __location__, tctx, mem_ctx,
2250 fname, AFPRESOURCE_STREAM,
2251 16, datalen, 0, datalen, data);
2252 torture_assert_goto(tctx, ret == true, ret, done,
2253 "check AFPRESOURCE_STREAM failed\n");
2256 * Check FinderInfo data has been migrated to stream.
2259 ret = check_stream(tree, __location__, tctx, mem_ctx,
2260 fname, AFPINFO_STREAM,
2261 0, 60, 16, 8, "WAVEPTul");
2262 torture_assert_goto(tctx, ret == true, ret, done,
2263 "check AFPINFO_STREAM failed\n");
2266 smb2_deltree(tree, BASEDIR);
2267 talloc_free(mem_ctx);
2271 static bool test_aapl(struct torture_context *tctx,
2272 struct smb2_tree *tree)
2274 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2275 const char *fname = BASEDIR "\\test_aapl";
2277 struct smb2_handle testdirh;
2279 struct smb2_create io;
2281 struct smb2_create_blob *aapl = NULL;
2283 const char *type_creator = "SMB,OLE!";
2284 char type_creator_buf[9];
2286 uint32_t aapl_reply_bitmap;
2287 uint32_t aapl_server_caps;
2288 uint32_t aapl_vol_caps;
2289 uint32_t expected_vol_caps = 0;
2293 union smb_search_data *d;
2295 bool is_osx_server = torture_setting_bool(tctx, "osx", false);
2297 smb2_deltree(tree, BASEDIR);
2299 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
2300 CHECK_STATUS(status, NT_STATUS_OK);
2301 smb2_util_close(tree, testdirh);
2304 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2305 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2306 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2307 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2308 NTCREATEX_SHARE_ACCESS_READ |
2309 NTCREATEX_SHARE_ACCESS_WRITE);
2310 io.in.fname = fname;
2313 * Issuing an SMB2/CREATE with a suitably formed AAPL context,
2314 * controls behaviour of Apple's SMB2 extensions for the whole
2318 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2319 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2320 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2321 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2322 SMB2_CRTCTX_AAPL_MODEL_INFO));
2323 SBVAL(data.data, 16, (SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2324 SMB2_CRTCTX_AAPL_UNIX_BASED |
2325 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE));
2327 torture_comment(tctx, "Testing SMB2 create context AAPL\n");
2328 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2329 CHECK_STATUS(status, NT_STATUS_OK);
2331 status = smb2_create(tree, tctx, &io);
2332 CHECK_STATUS(status, NT_STATUS_OK);
2333 status = smb2_util_close(tree, io.out.file.handle);
2334 CHECK_STATUS(status, NT_STATUS_OK);
2337 * Now check returned AAPL context
2339 torture_comment(tctx, "Comparing returned AAPL capabilities\n");
2341 aapl = smb2_create_blob_find(&io.out.blobs,
2342 SMB2_CREATE_TAG_AAPL);
2345 torture_result(tctx, TORTURE_FAIL,
2346 "(%s) unexpectedly no AAPL capabilities were returned.",
2352 if (!is_osx_server) {
2353 size_t expected_aapl_ctx_size;
2357 * uint32_t CommandCode = kAAPL_SERVER_QUERY
2358 * uint32_t Reserved = 0;
2359 * uint64_t ReplyBitmap = kAAPL_SERVER_CAPS |
2360 * kAAPL_VOLUME_CAPS |
2362 * uint64_t ServerCaps = kAAPL_SUPPORTS_READDIR_ATTR |
2363 * kAAPL_SUPPORTS_OSX_COPYFILE;
2364 * uint64_t VolumeCaps = kAAPL_SUPPORT_RESOLVE_ID |
2365 * kAAPL_CASE_SENSITIVE;
2366 * uint32_t Pad2 = 0;
2367 * uint32_t ModelStringLen = 10;
2368 * ucs2_t ModelString[5] = "MacSamba";
2370 expected_aapl_ctx_size = strlen("MacSamba") * 2 + 40;
2372 size_ok = aapl->data.length == expected_aapl_ctx_size;
2373 torture_assert_goto(tctx, size_ok, ret, done, "bad AAPL size");
2376 aapl_cmd = IVAL(aapl->data.data, 0);
2377 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2378 torture_result(tctx, TORTURE_FAIL,
2379 "(%s) unexpected cmd: %d",
2380 __location__, (int)aapl_cmd);
2385 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2386 if (aapl_reply_bitmap != (SMB2_CRTCTX_AAPL_SERVER_CAPS |
2387 SMB2_CRTCTX_AAPL_VOLUME_CAPS |
2388 SMB2_CRTCTX_AAPL_MODEL_INFO)) {
2389 torture_result(tctx, TORTURE_FAIL,
2390 "(%s) unexpected reply_bitmap: %d",
2391 __location__, (int)aapl_reply_bitmap);
2396 aapl_server_caps = BVAL(aapl->data.data, 16);
2397 if (aapl_server_caps != (SMB2_CRTCTX_AAPL_UNIX_BASED |
2398 SMB2_CRTCTX_AAPL_SUPPORTS_READ_DIR_ATTR |
2399 SMB2_CRTCTX_AAPL_SUPPORTS_NFS_ACE |
2400 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE)) {
2401 torture_result(tctx, TORTURE_FAIL,
2402 "(%s) unexpected server_caps: %d",
2403 __location__, (int)aapl_server_caps);
2408 if (is_osx_server) {
2409 expected_vol_caps = 5;
2411 aapl_vol_caps = BVAL(aapl->data.data, 24);
2412 if (aapl_vol_caps != expected_vol_caps) {
2413 /* this will fail on a case insensitive fs ... */
2414 torture_result(tctx, TORTURE_FAIL,
2415 "(%s) unexpected vol_caps: %d",
2416 __location__, (int)aapl_vol_caps);
2419 ret = convert_string_talloc(mem_ctx,
2420 CH_UTF16LE, CH_UNIX,
2421 aapl->data.data + 40, 10,
2424 torture_result(tctx, TORTURE_FAIL,
2425 "(%s) convert_string_talloc() failed",
2429 torture_comment(tctx, "Got server model: \"%s\"\n", model);
2432 * Now that Requested AAPL extensions are enabled, setup some
2433 * Mac files with metadata and resource fork
2435 ret = torture_setup_file(mem_ctx, tree, fname, false);
2437 torture_result(tctx, TORTURE_FAIL,
2438 "(%s) torture_setup_file() failed",
2443 info = torture_afpinfo_new(mem_ctx);
2445 torture_result(tctx, TORTURE_FAIL,
2446 "(%s) torture_afpinfo_new() failed",
2452 memcpy(info->afpi_FinderInfo, type_creator, 8);
2453 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
2455 torture_result(tctx, TORTURE_FAIL,
2456 "(%s) torture_write_afpinfo() failed",
2461 ret = write_stream(tree, __location__, tctx, mem_ctx,
2462 fname, AFPRESOURCE_STREAM_NAME,
2465 torture_result(tctx, TORTURE_FAIL,
2466 "(%s) write_stream() failed",
2472 * Ok, file is prepared, now call smb2/find
2476 io.in.desired_access = SEC_RIGHTS_DIR_READ;
2477 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2478 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
2479 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
2480 NTCREATEX_SHARE_ACCESS_WRITE |
2481 NTCREATEX_SHARE_ACCESS_DELETE);
2482 io.in.create_disposition = NTCREATEX_DISP_OPEN;
2483 io.in.fname = BASEDIR;
2484 status = smb2_create(tree, tctx, &io);
2485 CHECK_STATUS(status, NT_STATUS_OK);
2488 f.in.file.handle = io.out.file.handle;
2489 f.in.pattern = "test_aapl";
2490 f.in.continue_flags = SMB2_CONTINUE_FLAG_SINGLE;
2491 f.in.max_response_size = 0x1000;
2492 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2494 status = smb2_find_level(tree, tree, &f, &count, &d);
2495 CHECK_STATUS(status, NT_STATUS_OK);
2497 status = smb2_util_close(tree, io.out.file.handle);
2498 CHECK_STATUS(status, NT_STATUS_OK);
2500 if (strcmp(d[0].id_both_directory_info.name.s, "test_aapl") != 0) {
2501 torture_result(tctx, TORTURE_FAIL,
2502 "(%s) write_stream() failed",
2508 if (d[0].id_both_directory_info.short_name.private_length != 24) {
2509 torture_result(tctx, TORTURE_FAIL,
2510 "(%s) bad short_name length %" PRIu32 ", expected 24",
2511 __location__, d[0].id_both_directory_info.short_name.private_length);
2516 torture_comment(tctx, "short_name buffer:\n");
2517 dump_data(0, d[0].id_both_directory_info.short_name_buf, 24);
2520 * Extract data as specified by the AAPL extension:
2521 * - ea_size contains max_access
2522 * - short_name contains resource fork length + FinderInfo
2523 * - reserved2 contains the unix mode
2525 torture_comment(tctx, "mac_access: %" PRIx32 "\n",
2526 d[0].id_both_directory_info.ea_size);
2528 rfork_len = BVAL(d[0].id_both_directory_info.short_name_buf, 0);
2529 if (rfork_len != 3) {
2530 torture_result(tctx, TORTURE_FAIL,
2531 "(%s) expected resource fork length 3, got: %" PRIu64,
2532 __location__, rfork_len);
2537 memcpy(type_creator_buf, d[0].id_both_directory_info.short_name_buf + 8, 8);
2538 type_creator_buf[8] = 0;
2539 if (strcmp(type_creator, type_creator_buf) != 0) {
2540 torture_result(tctx, TORTURE_FAIL,
2541 "(%s) expected type/creator \"%s\" , got: %s",
2542 __location__, type_creator, type_creator_buf);
2548 smb2_util_unlink(tree, fname);
2549 smb2_deltree(tree, BASEDIR);
2550 talloc_free(mem_ctx);
2554 static uint64_t patt_hash(uint64_t off)
2559 static bool write_pattern(struct torture_context *torture,
2560 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2561 struct smb2_handle h, uint64_t off, uint64_t len,
2567 uint64_t io_sz = MIN(1024 * 64, len);
2573 torture_assert(torture, (len % 8) == 0, "invalid write len");
2575 buf = talloc_zero_size(mem_ctx, io_sz);
2576 torture_assert(torture, (buf != NULL), "no memory for file data buf");
2579 for (i = 0; i <= io_sz - 8; i += 8) {
2580 SBVAL(buf, i, patt_hash(patt_off));
2584 status = smb2_util_write(tree, h,
2586 torture_assert_ntstatus_ok(torture, status, "file write");
2597 static bool check_pattern(struct torture_context *torture,
2598 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2599 struct smb2_handle h, uint64_t off, uint64_t len,
2606 torture_assert(torture, (len % 8) == 0, "invalid read len");
2612 uint64_t io_sz = MIN(1024 * 64, len);
2615 r.in.file.handle = h;
2616 r.in.length = io_sz;
2618 status = smb2_read(tree, mem_ctx, &r);
2619 torture_assert_ntstatus_ok(torture, status, "read");
2621 torture_assert_u64_equal(torture, r.out.data.length, io_sz,
2622 "read data len mismatch");
2624 for (i = 0; i <= io_sz - 8; i += 8, patt_off += 8) {
2625 uint64_t data = BVAL(r.out.data.data, i);
2626 torture_assert_u64_equal(torture, data, patt_hash(patt_off),
2627 talloc_asprintf(torture, "read data "
2628 "pattern bad at %llu\n",
2629 (unsigned long long)off + i));
2631 talloc_free(r.out.data.data);
2639 static bool test_setup_open(struct torture_context *torture,
2640 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2642 struct smb2_handle *fh,
2643 uint32_t desired_access,
2644 uint32_t file_attributes)
2646 struct smb2_create io;
2650 io.in.desired_access = desired_access;
2651 io.in.file_attributes = file_attributes;
2652 io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
2653 io.in.share_access =
2654 NTCREATEX_SHARE_ACCESS_DELETE|
2655 NTCREATEX_SHARE_ACCESS_READ|
2656 NTCREATEX_SHARE_ACCESS_WRITE;
2657 if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) {
2658 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2660 io.in.fname = fname;
2662 status = smb2_create(tree, mem_ctx, &io);
2663 torture_assert_ntstatus_ok(torture, status, "file create");
2665 *fh = io.out.file.handle;
2670 static bool test_setup_create_fill(struct torture_context *torture,
2671 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2673 struct smb2_handle *fh,
2675 uint32_t desired_access,
2676 uint32_t file_attributes)
2680 ok = test_setup_open(torture, tree, mem_ctx,
2685 torture_assert(torture, ok, "file open");
2688 ok = write_pattern(torture, tree, mem_ctx, *fh, 0, size, 0);
2689 torture_assert(torture, ok, "write pattern");
2694 static bool test_setup_copy_chunk(struct torture_context *torture,
2695 struct smb2_tree *tree, TALLOC_CTX *mem_ctx,
2697 const char *src_name,
2698 struct smb2_handle *src_h,
2700 uint32_t src_desired_access,
2701 const char *dst_name,
2702 struct smb2_handle *dest_h,
2704 uint32_t dest_desired_access,
2705 struct srv_copychunk_copy *cc_copy,
2706 union smb_ioctl *io)
2708 struct req_resume_key_rsp res_key;
2711 enum ndr_err_code ndr_ret;
2713 ok = test_setup_create_fill(torture, tree, mem_ctx, src_name,
2714 src_h, src_size, src_desired_access,
2715 FILE_ATTRIBUTE_NORMAL);
2716 torture_assert(torture, ok, "src file create fill");
2718 ok = test_setup_create_fill(torture, tree, mem_ctx, dst_name,
2719 dest_h, dest_size, dest_desired_access,
2720 FILE_ATTRIBUTE_NORMAL);
2721 torture_assert(torture, ok, "dest file create fill");
2724 io->smb2.level = RAW_IOCTL_SMB2;
2725 io->smb2.in.file.handle = *src_h;
2726 io->smb2.in.function = FSCTL_SRV_REQUEST_RESUME_KEY;
2727 /* Allow for Key + ContextLength + Context */
2728 io->smb2.in.max_response_size = 32;
2729 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2731 status = smb2_ioctl(tree, mem_ctx, &io->smb2);
2732 torture_assert_ntstatus_ok(torture, status,
2733 "FSCTL_SRV_REQUEST_RESUME_KEY");
2735 ndr_ret = ndr_pull_struct_blob(&io->smb2.out.out, mem_ctx, &res_key,
2736 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
2738 torture_assert_ndr_success(torture, ndr_ret,
2739 "ndr_pull_req_resume_key_rsp");
2742 io->smb2.level = RAW_IOCTL_SMB2;
2743 io->smb2.in.file.handle = *dest_h;
2744 io->smb2.in.function = FSCTL_SRV_COPYCHUNK;
2745 io->smb2.in.max_response_size = sizeof(struct srv_copychunk_rsp);
2746 io->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
2748 ZERO_STRUCTPN(cc_copy);
2749 memcpy(cc_copy->source_key, res_key.resume_key, ARRAY_SIZE(cc_copy->source_key));
2750 cc_copy->chunk_count = nchunks;
2751 cc_copy->chunks = talloc_zero_array(mem_ctx, struct srv_copychunk, nchunks);
2752 torture_assert(torture, (cc_copy->chunks != NULL), "no memory for chunks");
2758 static bool check_copy_chunk_rsp(struct torture_context *torture,
2759 struct srv_copychunk_rsp *cc_rsp,
2760 uint32_t ex_chunks_written,
2761 uint32_t ex_chunk_bytes_written,
2762 uint32_t ex_total_bytes_written)
2764 torture_assert_int_equal(torture, cc_rsp->chunks_written,
2765 ex_chunks_written, "num chunks");
2766 torture_assert_int_equal(torture, cc_rsp->chunk_bytes_written,
2767 ex_chunk_bytes_written, "chunk bytes written");
2768 torture_assert_int_equal(torture, cc_rsp->total_bytes_written,
2769 ex_total_bytes_written, "chunk total bytes");
2773 static bool neg_aapl_copyfile(struct torture_context *tctx,
2774 struct smb2_tree *tree,
2777 TALLOC_CTX *mem_ctx = talloc_new(tctx);
2778 const char *fname = "aapl";
2780 struct smb2_create io;
2782 struct smb2_create_blob *aapl = NULL;
2784 uint32_t aapl_reply_bitmap;
2785 uint32_t aapl_server_caps;
2789 io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
2790 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
2791 io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
2792 io.in.share_access = (NTCREATEX_SHARE_ACCESS_DELETE |
2793 NTCREATEX_SHARE_ACCESS_READ |
2794 NTCREATEX_SHARE_ACCESS_WRITE);
2795 io.in.fname = fname;
2797 data = data_blob_talloc(mem_ctx, NULL, 3 * sizeof(uint64_t));
2798 SBVAL(data.data, 0, SMB2_CRTCTX_AAPL_SERVER_QUERY);
2799 SBVAL(data.data, 8, (SMB2_CRTCTX_AAPL_SERVER_CAPS));
2800 SBVAL(data.data, 16, flags);
2802 status = smb2_create_blob_add(tctx, &io.in.blobs, "AAPL", data);
2803 CHECK_STATUS(status, NT_STATUS_OK);
2805 status = smb2_create(tree, tctx, &io);
2806 CHECK_STATUS(status, NT_STATUS_OK);
2808 aapl = smb2_create_blob_find(&io.out.blobs,
2809 SMB2_CREATE_TAG_AAPL);
2815 if (aapl->data.length < 24) {
2820 aapl_cmd = IVAL(aapl->data.data, 0);
2821 if (aapl_cmd != SMB2_CRTCTX_AAPL_SERVER_QUERY) {
2822 torture_result(tctx, TORTURE_FAIL,
2823 "(%s) unexpected cmd: %d",
2824 __location__, (int)aapl_cmd);
2829 aapl_reply_bitmap = BVAL(aapl->data.data, 8);
2830 if (!(aapl_reply_bitmap & SMB2_CRTCTX_AAPL_SERVER_CAPS)) {
2831 torture_result(tctx, TORTURE_FAIL,
2832 "(%s) unexpected reply_bitmap: %d",
2833 __location__, (int)aapl_reply_bitmap);
2838 aapl_server_caps = BVAL(aapl->data.data, 16);
2839 if (!(aapl_server_caps & flags)) {
2840 torture_result(tctx, TORTURE_FAIL,
2841 "(%s) unexpected server_caps: %d",
2842 __location__, (int)aapl_server_caps);
2848 status = smb2_util_close(tree, io.out.file.handle);
2849 CHECK_STATUS(status, NT_STATUS_OK);
2851 smb2_util_unlink(tree, "aapl");
2852 talloc_free(mem_ctx);
2856 static bool test_copyfile(struct torture_context *torture,
2857 struct smb2_tree *tree)
2859 struct smb2_handle src_h;
2860 struct smb2_handle dest_h;
2863 TALLOC_CTX *tmp_ctx = talloc_new(tree);
2864 struct srv_copychunk_copy cc_copy;
2865 struct srv_copychunk_rsp cc_rsp;
2866 enum ndr_err_code ndr_ret;
2868 const char *sname = ":foo" "\xef\x80\xa2" "bar:$DATA";
2871 * First test a copy_chunk with a 0 chunk count without having
2872 * enabled this via AAPL. The request must not fail and the
2873 * copied length in the response must be 0. This is verified
2874 * against Windows 2008r2.
2877 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2878 0, /* 0 chunks, copyfile semantics */
2880 &src_h, 4096, /* fill 4096 byte src file */
2881 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2883 &dest_h, 0, /* 0 byte dest file */
2884 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2888 torture_fail_goto(torture, done, "setup copy chunk error");
2891 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2893 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2894 torture_assert_ndr_success(torture, ndr_ret,
2895 "ndr_push_srv_copychunk_copy");
2897 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2898 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2900 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2902 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2903 torture_assert_ndr_success(torture, ndr_ret,
2904 "ndr_pull_srv_copychunk_rsp");
2906 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2907 0, /* chunks written */
2908 0, /* chunk bytes unsuccessfully written */
2909 0); /* total bytes written */
2911 torture_fail_goto(torture, done, "bad copy chunk response data");
2915 * Now enable AAPL copyfile and test again, the file and the
2916 * stream must be copied by the server.
2918 ok = neg_aapl_copyfile(torture, tree,
2919 SMB2_CRTCTX_AAPL_SUPPORTS_OSX_COPYFILE);
2921 torture_skip_goto(torture, done, "missing AAPL copyfile");
2925 smb2_util_close(tree, src_h);
2926 smb2_util_close(tree, dest_h);
2927 smb2_util_unlink(tree, FNAME_CC_SRC);
2928 smb2_util_unlink(tree, FNAME_CC_DST);
2930 ok = torture_setup_file(tmp_ctx, tree, FNAME_CC_SRC, false);
2932 torture_fail(torture, "setup file error");
2934 ok = write_stream(tree, __location__, torture, tmp_ctx,
2935 FNAME_CC_SRC, AFPRESOURCE_STREAM,
2936 10, 10, "1234567890");
2938 torture_fail(torture, "setup stream error");
2941 ok = write_stream(tree, __location__, torture, tmp_ctx,
2942 FNAME_CC_SRC, sname,
2943 10, 10, "abcdefghij");
2944 torture_assert_goto(torture, ok == true, ok, done, "write_stream failed\n");
2946 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
2947 0, /* 0 chunks, copyfile semantics */
2949 &src_h, 4096, /* fill 4096 byte src file */
2950 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2952 &dest_h, 0, /* 0 byte dest file */
2953 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
2957 torture_fail_goto(torture, done, "setup copy chunk error");
2960 ndr_ret = ndr_push_struct_blob(&io.smb2.in.out, tmp_ctx,
2962 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
2963 torture_assert_ndr_success(torture, ndr_ret,
2964 "ndr_push_srv_copychunk_copy");
2966 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
2967 torture_assert_ntstatus_ok_goto(torture, status, ok, done, "FSCTL_SRV_COPYCHUNK");
2969 ndr_ret = ndr_pull_struct_blob(&io.smb2.out.out, tmp_ctx,
2971 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
2972 torture_assert_ndr_success(torture, ndr_ret,
2973 "ndr_pull_srv_copychunk_rsp");
2975 ok = check_copy_chunk_rsp(torture, &cc_rsp,
2976 0, /* chunks written */
2977 0, /* chunk bytes unsuccessfully written */
2978 4096); /* total bytes written */
2980 torture_fail_goto(torture, done, "bad copy chunk response data");
2983 ok = test_setup_open(torture, tree, tmp_ctx, FNAME_CC_DST, &dest_h,
2984 SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL);
2986 torture_fail_goto(torture, done,"open failed");
2988 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 4096, 0);
2990 torture_fail_goto(torture, done, "inconsistent file data");
2993 ok = check_stream(tree, __location__, torture, tmp_ctx,
2994 FNAME_CC_DST, AFPRESOURCE_STREAM,
2995 0, 20, 10, 10, "1234567890");
2997 torture_fail_goto(torture, done, "inconsistent stream data");
3000 ok = check_stream(tree, __location__, torture, tmp_ctx,
3001 FNAME_CC_DST, sname,
3002 0, 20, 10, 10, "abcdefghij");
3003 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
3006 smb2_util_close(tree, src_h);
3007 smb2_util_close(tree, dest_h);
3008 smb2_util_unlink(tree, FNAME_CC_SRC);
3009 smb2_util_unlink(tree, FNAME_CC_DST);
3010 talloc_free(tmp_ctx);
3014 static bool check_stream_list(struct smb2_tree *tree,
3015 struct torture_context *tctx,
3022 union smb_fileinfo finfo;
3025 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3027 struct stream_struct *stream_sort;
3028 struct smb2_create create;
3029 struct smb2_handle h;
3032 torture_assert_goto(tctx, tmp_ctx != NULL, ret, done, "talloc_new failed");
3034 ZERO_STRUCT(create);
3035 create.in.fname = fname;
3036 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3037 create.in.desired_access = SEC_FILE_ALL;
3038 create.in.create_options = is_dir ? NTCREATEX_OPTIONS_DIRECTORY : 0;
3039 create.in.file_attributes = is_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
3040 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3041 status = smb2_create(tree, tmp_ctx, &create);
3042 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create");
3043 h = create.out.file.handle;
3045 finfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3046 finfo.generic.in.file.handle = h;
3048 status = smb2_getinfo_file(tree, tctx, &finfo);
3049 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "get stream info");
3051 smb2_util_close(tree, h);
3053 torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams, num_exp,
3054 ret, done, "stream count");
3057 TALLOC_FREE(tmp_ctx);
3061 exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3062 torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3064 TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3066 stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3067 finfo.stream_info.out.num_streams *
3068 sizeof(*stream_sort));
3069 torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3071 TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3073 for (i=0; i<num_exp; i++) {
3074 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3075 i, exp_sort[i], stream_sort[i].stream_name.s);
3076 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s, exp_sort[i],
3077 ret, done, "stream name");
3081 TALLOC_FREE(tmp_ctx);
3085 static bool check_stream_list_handle(struct smb2_tree *tree,
3086 struct torture_context *tctx,
3087 struct smb2_handle h,
3093 union smb_fileinfo finfo;
3096 TALLOC_CTX *tmp_ctx = talloc_new(tctx);
3098 struct stream_struct *stream_sort;
3100 torture_assert_goto(tctx, tmp_ctx != NULL, ret, done,
3101 "talloc_new failed\n");
3103 finfo = (union smb_fileinfo) {
3104 .stream_info.level = RAW_FILEINFO_STREAM_INFORMATION,
3105 .stream_info.in.file.handle = h,
3108 status = smb2_getinfo_file(tree, tctx, &finfo);
3109 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3110 "get stream info\n");
3112 torture_assert_int_equal_goto(tctx, finfo.stream_info.out.num_streams,
3113 num_exp, ret, done, "stream count\n");
3116 TALLOC_FREE(tmp_ctx);
3120 exp_sort = talloc_memdup(tmp_ctx, exp, num_exp * sizeof(*exp));
3121 torture_assert_goto(tctx, exp_sort != NULL, ret, done, __location__);
3123 TYPESAFE_QSORT(exp_sort, num_exp, qsort_string);
3125 stream_sort = talloc_memdup(tmp_ctx, finfo.stream_info.out.streams,
3126 finfo.stream_info.out.num_streams *
3127 sizeof(*stream_sort));
3128 torture_assert_goto(tctx, stream_sort != NULL, ret, done, __location__);
3130 TYPESAFE_QSORT(stream_sort, finfo.stream_info.out.num_streams, qsort_stream);
3132 for (i=0; i<num_exp; i++) {
3133 torture_comment(tctx, "i[%d] exp[%s] got[%s]\n",
3134 i, exp_sort[i], stream_sort[i].stream_name.s);
3135 torture_assert_str_equal_goto(tctx, stream_sort[i].stream_name.s,
3136 exp_sort[i], ret, done,
3141 TALLOC_FREE(tmp_ctx);
3148 static bool test_stream_names(struct torture_context *tctx,
3149 struct smb2_tree *tree)
3151 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3153 struct smb2_create create;
3154 struct smb2_handle h;
3155 const char *fname = BASEDIR "\\stream_names.txt";
3158 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
3159 const char *streams[] = {
3160 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
3164 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
3166 /* clean slate ...*/
3167 smb2_util_unlink(tree, fname);
3168 smb2_deltree(tree, fname);
3169 smb2_deltree(tree, BASEDIR);
3171 status = torture_smb2_testdir(tree, BASEDIR, &h);
3172 CHECK_STATUS(status, NT_STATUS_OK);
3173 smb2_util_close(tree, h);
3175 ret = torture_setup_file(mem_ctx, tree, fname, false);
3176 torture_assert_goto(tctx, ret, ret, done, "torture_setup_file");
3178 torture_comment(tctx, "(%s) testing stream names\n", __location__);
3179 ZERO_STRUCT(create);
3180 create.in.desired_access = SEC_FILE_WRITE_DATA;
3181 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3182 create.in.share_access =
3183 NTCREATEX_SHARE_ACCESS_DELETE|
3184 NTCREATEX_SHARE_ACCESS_READ|
3185 NTCREATEX_SHARE_ACCESS_WRITE;
3186 create.in.create_disposition = NTCREATEX_DISP_CREATE;
3187 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3188 create.in.fname = sname1;
3190 status = smb2_create(tree, mem_ctx, &create);
3191 CHECK_STATUS(status, NT_STATUS_OK);
3193 status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
3194 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3195 "smb2_util_write failed\n");
3197 smb2_util_close(tree, create.out.file.handle);
3199 ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3200 CHECK_VALUE(ret, true);
3203 status = smb2_util_unlink(tree, fname);
3204 smb2_deltree(tree, BASEDIR);
3205 talloc_free(mem_ctx);
3210 /* Renaming a directory with open file, should work for OS X AAPL clients */
3211 static bool test_rename_dir_openfile(struct torture_context *torture,
3212 struct smb2_tree *tree)
3218 union smb_setfileinfo sinfo;
3219 struct smb2_handle d1, h1;
3220 const char *renamedir = BASEDIR "-new";
3221 bool server_is_osx = torture_setting_bool(torture, "osx", false);
3223 smb2_deltree(tree, BASEDIR);
3224 smb2_util_rmdir(tree, BASEDIR);
3225 smb2_deltree(tree, renamedir);
3227 ZERO_STRUCT(io.smb2);
3228 io.generic.level = RAW_OPEN_SMB2;
3229 io.smb2.in.create_flags = 0;
3230 io.smb2.in.desired_access = 0x0017019f;
3231 io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
3232 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3233 io.smb2.in.share_access = 0;
3234 io.smb2.in.alloc_size = 0;
3235 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3236 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3237 io.smb2.in.security_flags = 0;
3238 io.smb2.in.fname = BASEDIR;
3240 status = smb2_create(tree, torture, &(io.smb2));
3241 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3242 d1 = io.smb2.out.file.handle;
3244 ZERO_STRUCT(io.smb2);
3245 io.generic.level = RAW_OPEN_SMB2;
3246 io.smb2.in.create_flags = 0;
3247 io.smb2.in.desired_access = 0x0017019f;
3248 io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
3249 io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3250 io.smb2.in.share_access = 0;
3251 io.smb2.in.alloc_size = 0;
3252 io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
3253 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3254 io.smb2.in.security_flags = 0;
3255 io.smb2.in.fname = BASEDIR "\\file.txt";
3257 status = smb2_create(tree, torture, &(io.smb2));
3258 torture_assert_ntstatus_ok(torture, status, "smb2_create file");
3259 h1 = io.smb2.out.file.handle;
3261 if (!server_is_osx) {
3262 torture_comment(torture, "Renaming directory without AAPL, must fail\n");
3265 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3266 sinfo.rename_information.in.file.handle = d1;
3267 sinfo.rename_information.in.overwrite = 0;
3268 sinfo.rename_information.in.root_fid = 0;
3269 sinfo.rename_information.in.new_name = renamedir;
3270 status = smb2_setinfo_file(tree, &sinfo);
3272 torture_assert_ntstatus_equal(torture, status,
3273 NT_STATUS_ACCESS_DENIED,
3274 "smb2_setinfo_file");
3277 status = smb2_util_close(tree, d1);
3278 torture_assert_ntstatus_ok(torture, status, "smb2_util_close\n");
3281 torture_comment(torture, "Enabling AAPL\n");
3283 ret = enable_aapl(torture, tree);
3284 torture_assert(torture, ret == true, "enable_aapl failed");
3286 torture_comment(torture, "Renaming directory with AAPL\n");
3288 ZERO_STRUCT(io.smb2);
3289 io.generic.level = RAW_OPEN_SMB2;
3290 io.smb2.in.desired_access = 0x0017019f;
3291 io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
3292 io.smb2.in.share_access = 0;
3293 io.smb2.in.alloc_size = 0;
3294 io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
3295 io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
3296 io.smb2.in.security_flags = 0;
3297 io.smb2.in.fname = BASEDIR;
3299 status = smb2_create(tree, torture, &(io.smb2));
3300 torture_assert_ntstatus_ok(torture, status, "smb2_create dir");
3301 d1 = io.smb2.out.file.handle;
3304 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
3305 sinfo.rename_information.in.file.handle = d1;
3306 sinfo.rename_information.in.overwrite = 0;
3307 sinfo.rename_information.in.root_fid = 0;
3308 sinfo.rename_information.in.new_name = renamedir;
3310 status = smb2_setinfo_file(tree, &sinfo);
3311 torture_assert_ntstatus_ok(torture, status, "smb2_setinfo_file");
3313 ZERO_STRUCT(cl.smb2);
3314 cl.smb2.level = RAW_CLOSE_SMB2;
3315 cl.smb2.in.file.handle = d1;
3316 status = smb2_close(tree, &(cl.smb2));
3317 torture_assert_ntstatus_ok(torture, status, "smb2_close");
3320 cl.smb2.in.file.handle = h1;
3321 status = smb2_close(tree, &(cl.smb2));
3322 torture_assert_ntstatus_ok(torture, status, "smb2_close");
3325 torture_comment(torture, "Cleaning up\n");
3327 if (h1.data[0] || h1.data[1]) {
3328 ZERO_STRUCT(cl.smb2);
3329 cl.smb2.level = RAW_CLOSE_SMB2;
3330 cl.smb2.in.file.handle = h1;
3331 status = smb2_close(tree, &(cl.smb2));
3334 smb2_util_unlink(tree, BASEDIR "\\file.txt");
3335 smb2_util_unlink(tree, BASEDIR "-new\\file.txt");
3336 smb2_deltree(tree, renamedir);
3337 smb2_deltree(tree, BASEDIR);
3341 static bool test_afpinfo_enoent(struct torture_context *tctx,
3342 struct smb2_tree *tree)
3346 struct smb2_create create;
3347 struct smb2_handle h1;
3348 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3349 const char *fname = BASEDIR "\\file";
3350 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3352 torture_comment(tctx, "Opening file without AFP_AfpInfo\n");
3354 smb2_deltree(tree, BASEDIR);
3355 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3356 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3357 smb2_util_close(tree, h1);
3358 ret = torture_setup_file(mem_ctx, tree, fname, false);
3359 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3361 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3363 ZERO_STRUCT(create);
3364 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3365 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3366 create.in.fname = sname;
3368 status = smb2_create(tree, mem_ctx, &create);
3369 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3370 ret, done, "Got unexpected AFP_AfpInfo stream");
3373 smb2_util_unlink(tree, fname);
3374 smb2_util_rmdir(tree, BASEDIR);
3378 static bool test_create_delete_on_close(struct torture_context *tctx,
3379 struct smb2_tree *tree)
3383 struct smb2_create create;
3384 struct smb2_handle h1;
3385 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3386 const char *fname = BASEDIR "\\file";
3387 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3388 const char *type_creator = "SMB,OLE!";
3389 AfpInfo *info = NULL;
3390 const char *streams_basic[] = {
3393 const char *streams_afpinfo[] = {
3398 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3400 torture_comment(tctx, "Checking whether create with delete-on-close work with AFP_AfpInfo\n");
3402 smb2_deltree(tree, BASEDIR);
3403 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3404 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3405 smb2_util_close(tree, h1);
3406 ret = torture_setup_file(mem_ctx, tree, fname, false);
3407 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3409 torture_comment(tctx, "Opening not existing AFP_AfpInfo\n");
3411 ZERO_STRUCT(create);
3412 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3413 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3414 create.in.fname = sname;
3416 status = smb2_create(tree, mem_ctx, &create);
3417 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3418 ret, done, "Got unexpected AFP_AfpInfo stream");
3420 ZERO_STRUCT(create);
3421 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3422 create.in.desired_access = SEC_FILE_ALL;
3423 create.in.fname = sname;
3425 status = smb2_create(tree, mem_ctx, &create);
3426 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3427 ret, done, "Got unexpected AFP_AfpInfo stream");
3429 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3430 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3432 torture_comment(tctx, "Deleting AFP_AfpInfo via create with delete-on-close\n");
3434 info = torture_afpinfo_new(mem_ctx);
3435 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3437 memcpy(info->afpi_FinderInfo, type_creator, 8);
3438 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3439 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3441 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3442 0, 60, 16, 8, type_creator);
3443 torture_assert_goto(tctx, ret == true, ret, done, "Bad type/creator in AFP_AfpInfo");
3445 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3446 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3448 ZERO_STRUCT(create);
3449 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3450 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3451 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3452 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3453 create.in.fname = sname;
3454 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3456 status = smb2_create(tree, mem_ctx, &create);
3457 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3459 h1 = create.out.file.handle;
3460 smb2_util_close(tree, h1);
3462 ZERO_STRUCT(create);
3463 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3464 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
3465 create.in.fname = sname;
3466 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3467 status = smb2_create(tree, mem_ctx, &create);
3468 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3469 ret, done, "Got unexpected AFP_AfpInfo stream");
3471 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3472 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3475 smb2_util_unlink(tree, fname);
3476 smb2_util_rmdir(tree, BASEDIR);
3480 static bool test_setinfo_delete_on_close(struct torture_context *tctx,
3481 struct smb2_tree *tree)
3485 struct smb2_create create;
3486 union smb_setfileinfo sfinfo;
3487 struct smb2_handle h1;
3488 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3489 const char *fname = BASEDIR "\\file";
3490 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3491 const char *type_creator = "SMB,OLE!";
3492 AfpInfo *info = NULL;
3493 const char *streams[] = {
3497 const char *streams_basic[] = {
3501 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3503 torture_comment(tctx, "Deleting AFP_AfpInfo via setinfo with delete-on-close\n");
3505 smb2_deltree(tree, BASEDIR);
3506 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3507 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3508 smb2_util_close(tree, h1);
3509 ret = torture_setup_file(mem_ctx, tree, fname, false);
3510 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3512 info = torture_afpinfo_new(mem_ctx);
3513 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3514 memcpy(info->afpi_FinderInfo, type_creator, 8);
3515 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3516 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3518 ZERO_STRUCT(create);
3519 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3520 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3521 create.in.fname = sname;
3522 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3523 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3525 status = smb2_create(tree, mem_ctx, &create);
3526 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3528 h1 = create.out.file.handle;
3530 /* Delete stream via setinfo delete-on-close */
3531 ZERO_STRUCT(sfinfo);
3532 sfinfo.disposition_info.in.delete_on_close = 1;
3533 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3534 sfinfo.generic.in.file.handle = h1;
3535 status = smb2_setinfo_file(tree, &sfinfo);
3536 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3538 ret = check_stream_list(tree, tctx, fname, 2, streams, false);
3539 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3541 ZERO_STRUCT(create);
3542 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3543 create.in.desired_access = SEC_FILE_ALL;
3544 create.in.fname = sname;
3545 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3546 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3547 status = smb2_create(tree, mem_ctx, &create);
3548 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_DELETE_PENDING,
3549 ret, done, "Got unexpected AFP_AfpInfo stream");
3551 smb2_util_close(tree, h1);
3553 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3554 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3556 ZERO_STRUCT(create);
3557 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3558 create.in.desired_access = SEC_FILE_ALL;
3559 create.in.fname = sname;
3560 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3561 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3562 status = smb2_create(tree, mem_ctx, &create);
3563 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3564 ret, done, "Got unexpected AFP_AfpInfo stream");
3567 smb2_util_unlink(tree, fname);
3568 smb2_util_rmdir(tree, BASEDIR);
3572 static bool test_setinfo_eof(struct torture_context *tctx,
3573 struct smb2_tree *tree)
3577 struct smb2_create create;
3578 union smb_setfileinfo sfinfo;
3579 struct smb2_handle h1;
3580 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3581 const char *fname = BASEDIR "\\file";
3582 const char *sname = BASEDIR "\\file" AFPINFO_STREAM_NAME;
3583 const char *type_creator = "SMB,OLE!";
3584 AfpInfo *info = NULL;
3585 const char *streams_afpinfo[] = {
3590 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3592 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61, 1 and 0\n");
3594 smb2_deltree(tree, BASEDIR);
3595 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3596 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3597 smb2_util_close(tree, h1);
3598 ret = torture_setup_file(mem_ctx, tree, fname, false);
3599 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3601 info = torture_afpinfo_new(mem_ctx);
3602 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3603 memcpy(info->afpi_FinderInfo, type_creator, 8);
3604 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3605 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3607 ZERO_STRUCT(create);
3608 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3609 create.in.desired_access = SEC_FILE_ALL;
3610 create.in.fname = sname;
3611 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3612 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3614 status = smb2_create(tree, mem_ctx, &create);
3615 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3617 h1 = create.out.file.handle;
3619 torture_comment(tctx, "Set AFP_AfpInfo EOF to 61\n");
3621 /* Test setinfo end-of-file info */
3622 ZERO_STRUCT(sfinfo);
3623 sfinfo.generic.in.file.handle = h1;
3624 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3625 sfinfo.position_information.in.position = 61;
3626 status = smb2_setinfo_file(tree, &sfinfo);
3627 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_ALLOTTED_SPACE_EXCEEDED,
3628 ret, done, "set eof 61 failed");
3630 torture_comment(tctx, "Set AFP_AfpInfo EOF to 1\n");
3632 /* Truncation returns success, but has no effect */
3633 ZERO_STRUCT(sfinfo);
3634 sfinfo.generic.in.file.handle = h1;
3635 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3636 sfinfo.position_information.in.position = 1;
3637 status = smb2_setinfo_file(tree, &sfinfo);
3638 torture_assert_ntstatus_ok_goto(tctx, status,
3639 ret, done, "set eof 1 failed");
3640 smb2_util_close(tree, h1);
3642 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3643 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3645 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3646 0, 60, 16, 8, type_creator);
3647 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3649 ZERO_STRUCT(create);
3650 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3651 create.in.desired_access = SEC_FILE_ALL;
3652 create.in.fname = sname;
3653 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3654 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3656 status = smb2_create(tree, mem_ctx, &create);
3657 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3659 h1 = create.out.file.handle;
3662 * Delete stream via setinfo end-of-file info to 0, should
3663 * return success but stream MUST NOT deleted
3665 ZERO_STRUCT(sfinfo);
3666 sfinfo.generic.in.file.handle = h1;
3667 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
3668 sfinfo.position_information.in.position = 0;
3669 status = smb2_setinfo_file(tree, &sfinfo);
3670 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
3672 smb2_util_close(tree, h1);
3674 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3675 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3677 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
3678 0, 60, 16, 8, type_creator);
3679 torture_assert_goto(tctx, ret == true, ret, done, "FinderInfo changed");
3682 smb2_util_unlink(tree, fname);
3683 smb2_util_rmdir(tree, BASEDIR);
3687 static bool test_afpinfo_all0(struct torture_context *tctx,
3688 struct smb2_tree *tree)
3692 struct smb2_create create;
3693 struct smb2_handle h1 = {{0}};
3694 struct smb2_handle baseh = {{0}};
3695 union smb_setfileinfo setfinfo;
3696 union smb_fileinfo getfinfo;
3697 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3698 const char *fname = BASEDIR "\\file";
3699 const char *sname = BASEDIR "\\file" AFPINFO_STREAM;
3700 const char *type_creator = "SMB,OLE!";
3701 AfpInfo *info = NULL;
3702 char *infobuf = NULL;
3703 const char *streams_basic[] = {
3706 const char *streams_afpinfo[] = {
3711 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3713 torture_comment(tctx, "Write all 0 to AFP_AfpInfo and see what happens\n");
3715 smb2_deltree(tree, BASEDIR);
3716 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3717 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3718 smb2_util_close(tree, h1);
3719 ret = torture_setup_file(mem_ctx, tree, fname, false);
3720 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3722 info = torture_afpinfo_new(mem_ctx);
3723 torture_assert_goto(tctx, info != NULL, ret, done, "torture_afpinfo_new failed");
3724 memcpy(info->afpi_FinderInfo, type_creator, 8);
3725 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
3726 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
3728 ret = check_stream_list(tree, tctx, fname, 2, streams_afpinfo, false);
3729 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3731 /* Write all 0 to AFP_AfpInfo */
3732 memset(info->afpi_FinderInfo, 0, AFP_FinderSize);
3733 infobuf = torture_afpinfo_pack(mem_ctx, info);
3734 torture_assert_not_null_goto(tctx, infobuf, ret, done,
3735 "torture_afpinfo_pack failed\n");
3737 ZERO_STRUCT(create);
3738 create.in.desired_access = SEC_FILE_ALL;
3739 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3740 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3741 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
3742 create.in.fname = fname;
3744 status = smb2_create(tree, mem_ctx, &create);
3745 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3746 "smb2_create failed\n");
3747 baseh = create.out.file.handle;
3749 ZERO_STRUCT(create);
3750 create.in.desired_access = SEC_FILE_ALL;
3751 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3752 create.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
3753 create.in.fname = sname;
3755 status = smb2_create(tree, mem_ctx, &create);
3756 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3757 "smb2_create failed\n");
3758 h1 = create.out.file.handle;
3760 status = smb2_util_write(tree, h1, infobuf, 0, AFP_INFO_SIZE);
3761 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3762 "smb2_util_write failed\n");
3765 * Get stream information on open handle, must return only default
3766 * stream, the AFP_AfpInfo stream must not be returned.
3769 ZERO_STRUCT(getfinfo);
3770 getfinfo.generic.level = RAW_FILEINFO_STREAM_INFORMATION;
3771 getfinfo.generic.in.file.handle = baseh;
3773 status = smb2_getinfo_file(tree, tctx, &getfinfo);
3774 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3775 "get stream info\n");
3777 torture_assert_int_equal_goto(tctx, getfinfo.stream_info.out.num_streams,
3778 1, ret, done, "stream count");
3780 smb2_util_close(tree, baseh);
3784 * Try to set some file-basic-info (time) on the stream. This catches
3785 * naive implementation mistakes that simply deleted the backing store
3786 * from the filesystem in the zero-out step.
3789 ZERO_STRUCT(setfinfo);
3790 unix_to_nt_time(&setfinfo.basic_info.in.write_time, time(NULL));
3791 setfinfo.basic_info.in.attrib = 0x20;
3792 setfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
3793 setfinfo.generic.in.file.handle = h1;
3795 status = smb2_setinfo_file(tree, &setfinfo);
3796 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3797 "smb2_getinfo_file failed\n");
3799 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3800 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
3802 smb2_util_close(tree, h1);
3805 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3806 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3809 if (!smb2_util_handle_empty(h1)) {
3810 smb2_util_close(tree, h1);
3812 if (!smb2_util_handle_empty(baseh)) {
3813 smb2_util_close(tree, baseh);
3815 smb2_util_unlink(tree, fname);
3816 smb2_util_rmdir(tree, BASEDIR);
3820 static bool test_create_delete_on_close_resource(struct torture_context *tctx,
3821 struct smb2_tree *tree)
3825 struct smb2_create create;
3826 struct smb2_handle h1;
3827 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3828 const char *fname = BASEDIR "\\file";
3829 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3830 const char *streams_basic[] = {
3833 const char *streams_afpresource[] = {
3838 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3840 torture_comment(tctx, "Checking whether create with delete-on-close is ignored for AFP_AfpResource\n");
3842 smb2_deltree(tree, BASEDIR);
3843 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3844 torture_assert_ntstatus_ok(tctx, status, "torture_smb2_testdir");
3845 smb2_util_close(tree, h1);
3846 ret = torture_setup_file(mem_ctx, tree, fname, false);
3847 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3849 torture_comment(tctx, "Opening not existing AFP_AfpResource\n");
3851 ZERO_STRUCT(create);
3852 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3853 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE; /* stat open */
3854 create.in.fname = sname;
3856 status = smb2_create(tree, mem_ctx, &create);
3857 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3858 ret, done, "Got unexpected AFP_AfpResource stream");
3860 ZERO_STRUCT(create);
3861 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3862 create.in.desired_access = SEC_FILE_ALL;
3863 create.in.fname = sname;
3865 status = smb2_create(tree, mem_ctx, &create);
3866 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3867 ret, done, "Got unexpected AFP_AfpResource stream");
3869 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
3870 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3872 torture_comment(tctx, "Trying to delete AFP_AfpResource via create with delete-on-close\n");
3874 ret = write_stream(tree, __location__, tctx, mem_ctx,
3875 fname, AFPRESOURCE_STREAM_NAME,
3876 0, 10, "1234567890");
3877 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3879 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3880 0, 10, 0, 10, "1234567890");
3881 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3883 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3884 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3886 ZERO_STRUCT(create);
3887 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3888 create.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
3889 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3890 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3891 create.in.fname = sname;
3892 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3894 status = smb2_create(tree, mem_ctx, &create);
3895 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3897 h1 = create.out.file.handle;
3898 smb2_util_close(tree, h1);
3900 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3901 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3903 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPRESOURCE_STREAM_NAME,
3904 0, 10, 0, 10, "1234567890");
3905 torture_assert_goto(tctx, ret == true, ret, done, "Bad content from AFP_AfpResource");
3908 smb2_util_unlink(tree, fname);
3909 smb2_util_rmdir(tree, BASEDIR);
3913 static bool test_setinfo_delete_on_close_resource(struct torture_context *tctx,
3914 struct smb2_tree *tree)
3918 struct smb2_create create;
3919 union smb_setfileinfo sfinfo;
3920 struct smb2_handle h1;
3921 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3922 const char *fname = BASEDIR "\\file";
3923 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3924 const char *streams_afpresource[] = {
3929 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
3931 torture_comment(tctx, "Trying to delete AFP_AfpResource via setinfo with delete-on-close\n");
3933 smb2_deltree(tree, BASEDIR);
3934 status = torture_smb2_testdir(tree, BASEDIR, &h1);
3935 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
3936 smb2_util_close(tree, h1);
3937 ret = torture_setup_file(mem_ctx, tree, fname, false);
3938 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
3940 ret = write_stream(tree, __location__, tctx, mem_ctx,
3941 fname, AFPRESOURCE_STREAM_NAME,
3942 10, 10, "1234567890");
3943 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
3945 ZERO_STRUCT(create);
3946 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3947 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE | SEC_STD_SYNCHRONIZE | SEC_STD_DELETE;
3948 create.in.fname = sname;
3949 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3950 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3952 status = smb2_create(tree, mem_ctx, &create);
3953 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
3955 h1 = create.out.file.handle;
3957 /* Try to delete stream via setinfo delete-on-close */
3958 ZERO_STRUCT(sfinfo);
3959 sfinfo.disposition_info.in.delete_on_close = 1;
3960 sfinfo.generic.level = RAW_SFILEINFO_DISPOSITION_INFORMATION;
3961 sfinfo.generic.in.file.handle = h1;
3962 status = smb2_setinfo_file(tree, &sfinfo);
3963 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set delete-on-close failed");
3965 smb2_util_close(tree, h1);
3967 ret = check_stream_list(tree, tctx, fname, 2, streams_afpresource, false);
3968 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
3970 ZERO_STRUCT(create);
3971 create.in.create_disposition = NTCREATEX_DISP_OPEN;
3972 create.in.desired_access = SEC_FILE_ALL;
3973 create.in.fname = sname;
3974 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
3975 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
3976 status = smb2_create(tree, mem_ctx, &create);
3977 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
3978 "Got unexpected AFP_AfpResource stream");
3981 smb2_util_unlink(tree, fname);
3982 smb2_util_rmdir(tree, BASEDIR);
3986 static bool test_setinfo_eof_resource(struct torture_context *tctx,
3987 struct smb2_tree *tree)
3991 struct smb2_create create;
3992 union smb_setfileinfo sfinfo;
3993 union smb_fileinfo finfo;
3994 struct smb2_handle h1;
3995 TALLOC_CTX *mem_ctx = talloc_new(tctx);
3996 const char *fname = BASEDIR "\\file";
3997 const char *sname = BASEDIR "\\file" AFPRESOURCE_STREAM_NAME;
3998 const char *streams_basic[] = {
4002 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new");
4004 ret = enable_aapl(tctx, tree);
4005 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4007 torture_comment(tctx, "Set AFP_AfpResource EOF to 1 and 0\n");
4009 smb2_deltree(tree, BASEDIR);
4010 status = torture_smb2_testdir(tree, BASEDIR, &h1);
4011 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir");
4012 smb2_util_close(tree, h1);
4013 ret = torture_setup_file(mem_ctx, tree, fname, false);
4014 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4016 ret = write_stream(tree, __location__, tctx, mem_ctx,
4017 fname, AFPRESOURCE_STREAM_NAME,
4018 10, 10, "1234567890");
4019 torture_assert_goto(tctx, ret == true, ret, done, "Writing to AFP_AfpResource failed");
4021 ZERO_STRUCT(create);
4022 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4023 create.in.desired_access = SEC_FILE_ALL;
4024 create.in.fname = sname;
4025 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4026 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4028 status = smb2_create(tree, mem_ctx, &create);
4029 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4031 h1 = create.out.file.handle;
4033 torture_comment(tctx, "Set AFP_AfpResource EOF to 1\n");
4035 /* Test setinfo end-of-file info */
4036 ZERO_STRUCT(sfinfo);
4037 sfinfo.generic.in.file.handle = h1;
4038 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4039 sfinfo.position_information.in.position = 1;
4040 status = smb2_setinfo_file(tree, &sfinfo);
4041 torture_assert_ntstatus_ok_goto(tctx, status,
4042 ret, done, "set eof 1 failed");
4044 smb2_util_close(tree, h1);
4046 /* Check size == 1 */
4047 ZERO_STRUCT(create);
4048 create.in.fname = sname;
4049 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4050 create.in.desired_access = SEC_FILE_ALL;
4051 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4052 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4053 status = smb2_create(tree, mem_ctx, &create);
4054 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4056 h1 = create.out.file.handle;
4059 finfo.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
4060 finfo.generic.in.file.handle = h1;
4061 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
4062 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file failed");
4064 smb2_util_close(tree, h1);
4066 torture_assert_goto(tctx, finfo.all_info.out.size == 1, ret, done, "size != 1");
4068 ZERO_STRUCT(create);
4069 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4070 create.in.desired_access = SEC_FILE_ALL;
4071 create.in.fname = sname;
4072 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4073 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4075 status = smb2_create(tree, mem_ctx, &create);
4076 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4078 h1 = create.out.file.handle;
4081 * Delete stream via setinfo end-of-file info to 0, this
4082 * should delete the stream.
4084 ZERO_STRUCT(sfinfo);
4085 sfinfo.generic.in.file.handle = h1;
4086 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
4087 sfinfo.position_information.in.position = 0;
4088 status = smb2_setinfo_file(tree, &sfinfo);
4089 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "set eof 0 failed");
4091 smb2_util_close(tree, h1);
4093 ret = check_stream_list(tree, tctx, fname, 1, streams_basic, false);
4094 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4096 ZERO_STRUCT(create);
4097 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4098 create.in.desired_access = SEC_FILE_ALL;
4099 create.in.fname = sname;
4100 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4101 create.in.impersonation_level = NTCREATEX_IMPERSONATION_IMPERSONATION;
4103 status = smb2_create(tree, mem_ctx, &create);
4104 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4105 ret, done, "smb2_create failed");
4108 smb2_util_unlink(tree, fname);
4109 smb2_util_rmdir(tree, BASEDIR);
4114 * This tests that right after creating the AFP_AfpInfo stream,
4115 * reading from the stream returns an empty, default metadata blob of
4118 * NOTE: against OS X SMB server this only works if the read request
4119 * is compounded with the create that created the stream, is fails
4120 * otherwise. We don't care...
4122 static bool test_null_afpinfo(struct torture_context *tctx,
4123 struct smb2_tree *tree)
4125 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4126 const char *fname = "test_null_afpinfo";
4127 const char *sname = "test_null_afpinfo" AFPINFO_STREAM_NAME;
4130 struct smb2_request *req[3];
4131 struct smb2_handle handle;
4132 struct smb2_create create;
4133 struct smb2_read read;
4134 AfpInfo *afpinfo = NULL;
4135 char *afpinfo_buf = NULL;
4136 const char *type_creator = "SMB,OLE!";
4137 struct smb2_handle handle2;
4140 torture_comment(tctx, "Checking create of AfpInfo stream\n");
4142 smb2_util_unlink(tree, fname);
4144 ret = torture_setup_file(mem_ctx, tree, fname, false);
4145 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4147 ZERO_STRUCT(create);
4148 create.in.desired_access = SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA;
4149 create.in.share_access = FILE_SHARE_READ | FILE_SHARE_DELETE;
4150 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4151 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4152 create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
4153 create.in.fname = sname;
4155 smb2_transport_compound_start(tree->session->transport, 2);
4157 req[0] = smb2_create_send(tree, &create);
4159 handle.data[0] = UINT64_MAX;
4160 handle.data[1] = UINT64_MAX;
4162 smb2_transport_compound_set_related(tree->session->transport, true);
4165 read.in.file.handle = handle;
4166 read.in.length = AFP_INFO_SIZE;
4167 req[1] = smb2_read_send(tree, &read);
4169 status = smb2_create_recv(req[0], tree, &create);
4170 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_recv failed");
4172 handle = create.out.file.handle;
4174 status = smb2_read_recv(req[1], tree, &read);
4175 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_read_recv failed");
4177 status = torture_smb2_testfile_access(tree, sname, &handle2,
4178 SEC_FILE_READ_DATA);
4179 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4180 "torture_smb2_testfile failed\n");
4181 r = (struct smb2_read) {
4182 .in.file.handle = handle2,
4183 .in.length = AFP_INFO_SIZE,
4186 status = smb2_read(tree, tree, &r);
4187 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4188 "torture_smb2_testfile failed\n");
4189 smb2_util_close(tree, handle2);
4191 afpinfo = torture_afpinfo_new(mem_ctx);
4192 torture_assert_goto(tctx, afpinfo != NULL, ret, done, "torture_afpinfo_new failed");
4194 memcpy(afpinfo->afpi_FinderInfo, type_creator, 8);
4196 afpinfo_buf = torture_afpinfo_pack(tctx, afpinfo);
4197 torture_assert_goto(tctx, afpinfo_buf != NULL, ret, done, "torture_afpinfo_new failed");
4199 status = smb2_util_write(tree, handle, afpinfo_buf, 0, AFP_INFO_SIZE);
4200 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_write failed");
4202 smb2_util_close(tree, handle);
4204 ret = check_stream(tree, __location__, tctx, mem_ctx, fname, AFPINFO_STREAM,
4205 0, 60, 16, 8, type_creator);
4206 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed");
4209 smb2_util_unlink(tree, fname);
4210 talloc_free(mem_ctx);
4214 static bool test_delete_file_with_rfork(struct torture_context *tctx,
4215 struct smb2_tree *tree)
4217 const char *fname = "torture_write_rfork_io";
4218 const char *rfork_content = "1234567890";
4222 smb2_util_unlink(tree, fname);
4224 torture_comment(tctx, "Test deleting file with resource fork\n");
4226 ret = torture_setup_file(tctx, tree, fname, false);
4227 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed\n");
4229 ret = write_stream(tree, __location__, tctx, tctx,
4230 fname, AFPRESOURCE_STREAM_NAME,
4231 10, 10, rfork_content);
4232 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed\n");
4234 ret = check_stream(tree, __location__, tctx, tctx,
4235 fname, AFPRESOURCE_STREAM_NAME,
4236 0, 20, 10, 10, rfork_content);
4237 torture_assert_goto(tctx, ret == true, ret, done, "check_stream failed\n");
4239 status = smb2_util_unlink(tree, fname);
4240 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "check_stream failed\n");
4246 static bool test_rename_and_read_rsrc(struct torture_context *tctx,
4247 struct smb2_tree *tree)
4251 struct smb2_create create, create2;
4252 struct smb2_handle h1, h2;
4253 const char *fname = "test_rename_openfile";
4254 const char *sname = "test_rename_openfile" AFPRESOURCE_STREAM_NAME;
4255 const char *fname_renamed = "test_rename_openfile_renamed";
4256 const char *data = "1234567890";
4257 union smb_setfileinfo sinfo;
4258 bool server_is_macos = torture_setting_bool(tctx, "osx", false);
4259 NTSTATUS expected_status;
4261 ret = enable_aapl(tctx, tree);
4262 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4264 torture_comment(tctx, "Create file with resource fork\n");
4266 ret = torture_setup_file(tctx, tree, fname, false);
4267 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4269 ret = write_stream(tree, __location__, tctx, tctx,
4270 fname, AFPRESOURCE_STREAM_NAME, 0, 10, data);
4271 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4273 torture_comment(tctx, "Open resource fork\n");
4275 ZERO_STRUCT(create);
4276 create.in.desired_access = SEC_FILE_ALL;
4277 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4278 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4279 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4280 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4281 create.in.fname = sname;
4283 status = smb2_create(tree, tctx, &create);
4284 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4286 h1 = create.out.file.handle;
4288 torture_comment(tctx, "Rename base file\n");
4290 ZERO_STRUCT(create2);
4291 create2.in.desired_access = SEC_FILE_ALL;
4292 create2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4293 create2.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4294 create2.in.create_disposition = NTCREATEX_DISP_OPEN;
4295 create2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4296 create2.in.fname = fname;
4298 status = smb2_create(tree, tctx, &create2);
4299 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4301 h2 = create2.out.file.handle;
4304 sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
4305 sinfo.rename_information.in.file.handle = h2;
4306 sinfo.rename_information.in.overwrite = 0;
4307 sinfo.rename_information.in.root_fid = 0;
4308 sinfo.rename_information.in.new_name = fname_renamed;
4310 if (server_is_macos) {
4311 expected_status = NT_STATUS_SHARING_VIOLATION;
4313 expected_status = NT_STATUS_ACCESS_DENIED;
4316 status = smb2_setinfo_file(tree, &sinfo);
4317 torture_assert_ntstatus_equal_goto(
4318 tctx, status, expected_status, ret, done,
4319 "smb2_setinfo_file failed");
4321 smb2_util_close(tree, h2);
4323 status = smb2_util_write(tree, h1, "foo", 0, 3);
4324 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4327 smb2_util_close(tree, h1);
4330 smb2_util_unlink(tree, fname);
4331 smb2_util_unlink(tree, fname_renamed);
4336 static bool test_readdir_attr_illegal_ntfs(struct torture_context *tctx,
4337 struct smb2_tree *tree)
4339 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4340 const char *name = "test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4341 const char *fname = BASEDIR "\\test" "\xef\x80\xa2" "aapl"; /* "test:aapl" */
4343 struct smb2_handle testdirh;
4345 struct smb2_create io;
4347 const char *type_creator = "SMB,OLE!";
4350 union smb_search_data *d;
4354 smb2_deltree(tree, BASEDIR);
4356 status = torture_smb2_testdir(tree, BASEDIR, &testdirh);
4357 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir failed");
4358 smb2_util_close(tree, testdirh);
4360 torture_comment(tctx, "Enabling AAPL\n");
4362 ret = enable_aapl(tctx, tree);
4363 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
4366 * Now that Requested AAPL extensions are enabled, setup some
4367 * Mac files with metadata and resource fork
4370 torture_comment(tctx, "Preparing file\n");
4372 ret = torture_setup_file(mem_ctx, tree, fname, false);
4373 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file failed");
4375 info = torture_afpinfo_new(mem_ctx);
4376 torture_assert_not_null_goto(tctx, info, ret, done, "torture_afpinfo_new failed");
4378 memcpy(info->afpi_FinderInfo, type_creator, 8);
4379 ret = torture_write_afpinfo(tree, tctx, mem_ctx, fname, info);
4380 torture_assert_goto(tctx, ret == true, ret, done, "torture_write_afpinfo failed");
4382 ret = write_stream(tree, __location__, tctx, mem_ctx,
4383 fname, AFPRESOURCE_STREAM_NAME,
4385 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4388 * Ok, file is prepared, now call smb2/find
4391 torture_comment(tctx, "Issue find\n");
4394 io.in.desired_access = SEC_RIGHTS_DIR_READ;
4395 io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
4396 io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
4397 io.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
4398 NTCREATEX_SHARE_ACCESS_WRITE |
4399 NTCREATEX_SHARE_ACCESS_DELETE);
4400 io.in.create_disposition = NTCREATEX_DISP_OPEN;
4401 io.in.fname = BASEDIR;
4402 status = smb2_create(tree, tctx, &io);
4403 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create failed");
4406 f.in.file.handle = io.out.file.handle;
4408 f.in.max_response_size = 0x1000;
4409 f.in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
4411 status = smb2_find_level(tree, tree, &f, &count, &d);
4412 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_find_level failed");
4414 status = smb2_util_close(tree, io.out.file.handle);
4415 torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_util_close failed");
4417 torture_comment(tctx, "Checking find response with enriched macOS metadata\n");
4419 for (i = 0; i < count; i++) {
4420 const char *found = d[i].id_both_directory_info.name.s;
4422 if (!strcmp(found, ".") || !strcmp(found, ".."))
4424 if (strncmp(found, "._", 2) == 0) {
4430 torture_assert_str_equal_goto(tctx,
4431 d[i].id_both_directory_info.name.s, name,
4432 ret, done, "bad name");
4434 rfork_len = BVAL(d[i].id_both_directory_info.short_name_buf, 0);
4435 torture_assert_int_equal_goto(tctx, rfork_len, 3, ret, done, "bad resource fork length");
4437 torture_assert_mem_equal_goto(tctx, type_creator,
4438 d[i].id_both_directory_info.short_name_buf + 8,
4439 8, ret, done, "Bad FinderInfo");
4441 smb2_util_unlink(tree, fname);
4442 smb2_deltree(tree, BASEDIR);
4443 talloc_free(mem_ctx);
4447 static bool test_invalid_afpinfo(struct torture_context *tctx,
4448 struct smb2_tree *tree1,
4449 struct smb2_tree *tree2)
4451 const char *fname = "filtest_invalid_afpinfo";
4452 const char *sname = "filtest_invalid_afpinfo" AFPINFO_STREAM_NAME;
4453 struct smb2_create create;
4454 const char *streams_basic[] = {
4457 const char *streams_afpinfo[] = {
4464 if (tree2 == NULL) {
4465 torture_skip_goto(tctx, done, "need second share without fruit\n");
4468 torture_comment(tctx, "Testing invalid AFP_AfpInfo stream\n");
4470 ret = torture_setup_file(tctx, tree2, fname, false);
4471 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4473 ret = write_stream(tree2, __location__, tctx, tctx,
4474 fname, AFPINFO_STREAM_NAME,
4476 torture_assert_goto(tctx, ret == true, ret, done, "write_stream failed");
4478 ret = check_stream_list(tree2, tctx, fname, 2, streams_afpinfo, false);
4479 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4481 torture_comment(tctx, "Listing streams, bad AFPINFO stream must not be present\n");
4483 ret = check_stream_list(tree1, tctx, fname, 1, streams_basic, false);
4484 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
4486 torture_comment(tctx, "Try to open AFPINFO stream, must fail\n");
4488 ZERO_STRUCT(create);
4489 create.in.desired_access = SEC_FILE_ALL;
4490 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4491 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4492 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4493 create.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
4494 create.in.fname = sname;
4496 status = smb2_create(tree1, tctx, &create);
4497 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4498 ret, done, "Stream still around?");
4501 smb2_util_unlink(tree1, fname);
4505 static bool test_zero_file_id(struct torture_context *tctx,
4506 struct smb2_tree *tree)
4508 const char *fname = "filtest_file_id";
4509 struct smb2_create create = {0};
4512 uint8_t zero_file_id[8] = {0};
4514 torture_comment(tctx, "Testing zero file id\n");
4516 ret = torture_setup_file(tctx, tree, fname, false);
4517 torture_assert_goto(tctx, ret == true, ret, done, "torture_setup_file");
4519 ZERO_STRUCT(create);
4520 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4521 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4522 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4523 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4524 create.in.fname = fname;
4525 create.in.query_on_disk_id = true;
4527 status = smb2_create(tree, tctx, &create);
4528 torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
4530 "test file could not be opened");
4531 torture_assert_mem_not_equal_goto(tctx, create.out.on_disk_id,
4532 zero_file_id, 8, ret, done,
4533 "unexpected zero file id");
4535 smb2_util_close(tree, create.out.file.handle);
4537 ret = enable_aapl(tctx, tree);
4538 torture_assert(tctx, ret == true, "enable_aapl failed");
4540 ZERO_STRUCT(create);
4541 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
4542 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
4543 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
4544 create.in.create_disposition = NTCREATEX_DISP_OPEN;
4545 create.in.fname = fname;
4546 create.in.query_on_disk_id = true;
4548 status = smb2_create(tree, tctx, &create);
4549 torture_assert_ntstatus_equal_goto(
4550 tctx, status, NT_STATUS_OK, ret, done,
4551 "test file could not be opened with AAPL");
4552 torture_assert_mem_equal_goto(tctx, create.out.on_disk_id, zero_file_id,
4553 8, ret, done, "non-zero file id");
4555 smb2_util_close(tree, create.out.file.handle);
4558 smb2_util_unlink(tree, fname);
4562 static bool copy_one_stream(struct torture_context *torture,
4563 struct smb2_tree *tree,
4564 TALLOC_CTX *tmp_ctx,
4565 const char *src_sname,
4566 const char *dst_sname)
4568 struct smb2_handle src_h = {{0}};
4569 struct smb2_handle dest_h = {{0}};
4572 struct srv_copychunk_copy cc_copy;
4573 struct srv_copychunk_rsp cc_rsp;
4574 enum ndr_err_code ndr_ret;
4577 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4580 &src_h, 256, /* fill 256 byte src file */
4581 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4583 &dest_h, 0, /* 0 byte dest file */
4584 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4587 torture_assert_goto(torture, ok == true, ok, done,
4588 "setup copy chunk error\n");
4590 /* copy all src file data (via a single chunk desc) */
4591 cc_copy.chunks[0].source_off = 0;
4592 cc_copy.chunks[0].target_off = 0;
4593 cc_copy.chunks[0].length = 256;
4595 ndr_ret = ndr_push_struct_blob(
4596 &io.smb2.in.out, tmp_ctx, &cc_copy,
4597 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4599 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4600 "ndr_push_srv_copychunk_copy\n");
4602 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4603 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4604 "FSCTL_SRV_COPYCHUNK\n");
4606 ndr_ret = ndr_pull_struct_blob(
4607 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4608 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4610 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4611 "ndr_pull_srv_copychunk_rsp\n");
4613 ok = check_copy_chunk_rsp(torture, &cc_rsp,
4614 1, /* chunks written */
4615 0, /* chunk bytes unsuccessfully written */
4616 256); /* total bytes written */
4617 torture_assert_goto(torture, ok == true, ok, done,
4618 "bad copy chunk response data\n");
4620 ok = check_pattern(torture, tree, tmp_ctx, dest_h, 0, 256, 0);
4622 torture_fail(torture, "inconsistent file data\n");
4626 if (!smb2_util_handle_empty(src_h)) {
4627 smb2_util_close(tree, src_h);
4629 if (!smb2_util_handle_empty(dest_h)) {
4630 smb2_util_close(tree, dest_h);
4636 static bool copy_finderinfo_stream(struct torture_context *torture,
4637 struct smb2_tree *tree,
4638 TALLOC_CTX *tmp_ctx,
4639 const char *src_name,
4640 const char *dst_name)
4642 struct smb2_handle src_h = {{0}};
4643 struct smb2_handle dest_h = {{0}};
4646 struct srv_copychunk_copy cc_copy;
4647 struct srv_copychunk_rsp cc_rsp;
4648 enum ndr_err_code ndr_ret;
4649 const char *type_creator = "SMB,OLE!";
4650 AfpInfo *info = NULL;
4651 const char *src_name_afpinfo = NULL;
4652 const char *dst_name_afpinfo = NULL;
4655 src_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", src_name,
4657 torture_assert_not_null_goto(torture, src_name_afpinfo, ok, done,
4658 "talloc_asprintf failed\n");
4660 dst_name_afpinfo = talloc_asprintf(tmp_ctx, "%s%s", dst_name,
4662 torture_assert_not_null_goto(torture, dst_name_afpinfo, ok, done,
4663 "talloc_asprintf failed\n");
4665 info = torture_afpinfo_new(tmp_ctx);
4666 torture_assert_not_null_goto(torture, info, ok, done,
4667 "torture_afpinfo_new failed\n");
4669 memcpy(info->afpi_FinderInfo, type_creator, 8);
4670 ok = torture_write_afpinfo(tree, torture, tmp_ctx, src_name, info);
4671 torture_assert_goto(torture, ok == true, ok, done,
4672 "torture_write_afpinfo failed\n");
4674 ok = test_setup_copy_chunk(torture, tree, tmp_ctx,
4678 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4681 SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA,
4684 torture_assert_goto(torture, ok == true, ok, done,
4685 "setup copy chunk error\n");
4687 /* copy all src file data (via a single chunk desc) */
4688 cc_copy.chunks[0].source_off = 0;
4689 cc_copy.chunks[0].target_off = 0;
4690 cc_copy.chunks[0].length = 60;
4692 ndr_ret = ndr_push_struct_blob(
4693 &io.smb2.in.out, tmp_ctx, &cc_copy,
4694 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
4696 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4697 "ndr_push_srv_copychunk_copy\n");
4699 status = smb2_ioctl(tree, tmp_ctx, &io.smb2);
4700 torture_assert_ntstatus_ok_goto(torture, status, ok, done,
4701 "FSCTL_SRV_COPYCHUNK\n");
4703 ndr_ret = ndr_pull_struct_blob(
4704 &io.smb2.out.out, tmp_ctx, &cc_rsp,
4705 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
4707 torture_assert_ndr_success_goto(torture, ndr_ret, ok, done,
4708 "ndr_pull_srv_copychunk_rsp\n");
4710 smb2_util_close(tree, src_h);
4712 smb2_util_close(tree, dest_h);
4713 ZERO_STRUCT(dest_h);
4715 ok = check_copy_chunk_rsp(torture, &cc_rsp,
4716 1, /* chunks written */
4717 0, /* chunk bytes unsuccessfully written */
4718 60); /* total bytes written */
4719 torture_assert_goto(torture, ok == true, ok, done,
4720 "bad copy chunk response data\n");
4722 ok = check_stream(tree, __location__, torture, tmp_ctx,
4723 dst_name, AFPINFO_STREAM,
4724 0, 60, 16, 8, type_creator);
4725 torture_assert_goto(torture, ok == true, ok, done, "check_stream failed\n");
4728 if (!smb2_util_handle_empty(src_h)) {
4729 smb2_util_close(tree, src_h);
4731 if (!smb2_util_handle_empty(dest_h)) {
4732 smb2_util_close(tree, dest_h);
4738 static bool test_copy_chunk_streams(struct torture_context *torture,
4739 struct smb2_tree *tree)
4741 const char *src_name = "src";
4742 const char *dst_name = "dst";
4744 const char *src_sname;
4745 const char *dst_sname;
4747 { "src:foo", "dst:foo" },
4748 { "src" AFPRESOURCE_STREAM, "dst" AFPRESOURCE_STREAM }
4751 TALLOC_CTX *tmp_ctx = NULL;
4754 tmp_ctx = talloc_new(tree);
4755 torture_assert_not_null_goto(torture, tmp_ctx, ok, done,
4756 "torture_setup_file\n");
4758 smb2_util_unlink(tree, src_name);
4759 smb2_util_unlink(tree, dst_name);
4761 ok = torture_setup_file(torture, tree, src_name, false);
4762 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4763 ok = torture_setup_file(torture, tree, dst_name, false);
4764 torture_assert_goto(torture, ok == true, ok, done, "torture_setup_file\n");
4766 for (i = 0; i < ARRAY_SIZE(names); i++) {
4767 ok = copy_one_stream(torture, tree, tmp_ctx,
4769 names[i].dst_sname);
4770 torture_assert_goto(torture, ok == true, ok, done,
4771 "copy_one_stream failed\n");
4774 ok = copy_finderinfo_stream(torture, tree, tmp_ctx,
4775 src_name, dst_name);
4776 torture_assert_goto(torture, ok == true, ok, done,
4777 "copy_finderinfo_stream failed\n");
4780 smb2_util_unlink(tree, src_name);
4781 smb2_util_unlink(tree, dst_name);
4782 talloc_free(tmp_ctx);
4787 * Ensure this security descriptor has exactly one mode, uid
4791 static NTSTATUS check_nfs_sd(const struct security_descriptor *psd)
4794 bool got_one_mode = false;
4795 bool got_one_uid = false;
4796 bool got_one_gid = false;
4798 if (psd->dacl == NULL) {
4799 return NT_STATUS_INVALID_SECURITY_DESCR;
4802 for (i = 0; i < psd->dacl->num_aces; i++) {
4803 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Mode,
4804 &psd->dacl->aces[i].trustee) == 0) {
4805 if (got_one_mode == true) {
4806 /* Can't have more than one. */
4807 return NT_STATUS_INVALID_SECURITY_DESCR;
4809 got_one_mode = true;
4812 for (i = 0; i < psd->dacl->num_aces; i++) {
4813 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Users,
4814 &psd->dacl->aces[i].trustee) == 0) {
4815 if (got_one_uid == true) {
4816 /* Can't have more than one. */
4817 return NT_STATUS_INVALID_SECURITY_DESCR;
4822 for (i = 0; i < psd->dacl->num_aces; i++) {
4823 if (dom_sid_compare_domain(&global_sid_Unix_NFS_Groups,
4824 &psd->dacl->aces[i].trustee) == 0) {
4825 if (got_one_gid == true) {
4826 /* Can't have more than one. */
4827 return NT_STATUS_INVALID_SECURITY_DESCR;
4832 /* Must have at least one of each. */
4833 if (got_one_mode == false ||
4834 got_one_uid == false ||
4835 got_one_gid == false) {
4836 return NT_STATUS_INVALID_SECURITY_DESCR;
4838 return NT_STATUS_OK;
4841 static bool test_nfs_aces(struct torture_context *tctx,
4842 struct smb2_tree *tree)
4844 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4845 struct security_ace ace;
4847 const char *fname = BASEDIR "\\nfs_aces.txt";
4848 struct smb2_handle h = {{0}};
4849 union smb_fileinfo finfo2;
4850 union smb_setfileinfo set;
4851 struct security_descriptor *psd = NULL;
4854 bool is_osx = torture_setting_bool(tctx, "osx", false);
4857 torture_skip(tctx, "Test only works with Samba\n");
4860 ret = enable_aapl(tctx, tree);
4861 torture_assert(tctx, ret == true, "enable_aapl failed");
4863 /* clean slate ...*/
4864 smb2_util_unlink(tree, fname);
4865 smb2_deltree(tree, fname);
4866 smb2_deltree(tree, BASEDIR);
4868 status = torture_smb2_testdir(tree, BASEDIR, &h);
4869 CHECK_STATUS(status, NT_STATUS_OK);
4870 smb2_util_close(tree, h);
4872 /* Create a test file. */
4873 status = torture_smb2_testfile_access(tree,
4876 SEC_STD_READ_CONTROL |
4878 SEC_RIGHTS_FILE_ALL);
4879 CHECK_STATUS(status, NT_STATUS_OK);
4882 finfo2.query_secdesc.in.secinfo_flags =
4886 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4887 finfo2.generic.in.file.handle = h;
4888 status = smb2_getinfo_file(tree, tctx, &finfo2);
4889 CHECK_STATUS(status, NT_STATUS_OK);
4891 psd = finfo2.query_secdesc.out.sd;
4893 /* Ensure we have only single mode/uid/gid NFS entries. */
4894 status = check_nfs_sd(psd);
4895 if (!NT_STATUS_IS_OK(status)) {
4897 security_descriptor,
4898 discard_const_p(struct security_descriptor, psd));
4900 CHECK_STATUS(status, NT_STATUS_OK);
4902 /* Add a couple of extra NFS uids and gids. */
4903 sid_compose(&sid, &global_sid_Unix_NFS_Users, 27);
4904 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4905 status = security_descriptor_dacl_add(psd, &ace);
4906 CHECK_STATUS(status, NT_STATUS_OK);
4907 status = security_descriptor_dacl_add(psd, &ace);
4908 CHECK_STATUS(status, NT_STATUS_OK);
4910 sid_compose(&sid, &global_sid_Unix_NFS_Groups, 300);
4911 init_sec_ace(&ace, &sid, SEC_ACE_TYPE_ACCESS_DENIED, 0, 0);
4912 status = security_descriptor_dacl_add(psd, &ace);
4913 CHECK_STATUS(status, NT_STATUS_OK);
4914 status = security_descriptor_dacl_add(psd, &ace);
4915 CHECK_STATUS(status, NT_STATUS_OK);
4917 /* Now set on the file handle. */
4918 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
4919 set.set_secdesc.in.file.handle = h;
4920 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
4921 set.set_secdesc.in.sd = psd;
4922 status = smb2_setinfo_file(tree, &set);
4923 CHECK_STATUS(status, NT_STATUS_OK);
4925 /* Get the ACL again. */
4926 finfo2.query_secdesc.in.secinfo_flags =
4930 finfo2.generic.level = RAW_FILEINFO_SEC_DESC;
4931 finfo2.generic.in.file.handle = h;
4932 status = smb2_getinfo_file(tree, tctx, &finfo2);
4933 CHECK_STATUS(status, NT_STATUS_OK);
4935 psd = finfo2.query_secdesc.out.sd;
4937 /* Ensure we have only single mode/uid/gid NFS entries. */
4938 status = check_nfs_sd(psd);
4939 if (!NT_STATUS_IS_OK(status)) {
4941 security_descriptor,
4942 discard_const_p(struct security_descriptor, psd));
4944 CHECK_STATUS(status, NT_STATUS_OK);
4947 if (!smb2_util_handle_empty(h)) {
4948 smb2_util_close(tree, h);
4950 smb2_util_unlink(tree, fname);
4951 smb2_deltree(tree, fname);
4952 smb2_deltree(tree, BASEDIR);
4953 talloc_free(mem_ctx);
4957 static bool test_setinfo_stream_eof(struct torture_context *tctx,
4958 struct smb2_tree *tree)
4962 struct smb2_create create;
4963 union smb_setfileinfo sfinfo;
4964 union smb_fileinfo finfo;
4965 struct smb2_handle h1;
4966 TALLOC_CTX *mem_ctx = talloc_new(tctx);
4967 const char *fname = BASEDIR "\\file";
4968 const char *sname = BASEDIR "\\file:foo";
4970 torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
4971 "talloc_new failed\n");
4973 ret = enable_aapl(tctx, tree);
4974 torture_assert(tctx, ret == true, "enable_aapl failed");
4976 torture_comment(tctx, "Test setting EOF on a stream\n");
4978 smb2_deltree(tree, BASEDIR);
4979 status = torture_smb2_testdir(tree, BASEDIR, &h1);
4980 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4981 "torture_smb2_testdir\n");
4982 smb2_util_close(tree, h1);
4984 status = torture_smb2_testfile(tree, fname, &h1);
4985 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4986 "torture_smb2_testfile failed\n");
4987 smb2_util_close(tree, h1);
4989 status = torture_smb2_testfile_access(tree, sname, &h1,
4990 SEC_FILE_WRITE_DATA);
4991 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4992 "torture_smb2_testfile failed\n");
4994 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
4995 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
4996 "smb2_util_write failed\n");
4997 smb2_util_close(tree, h1);
5000 * Test setting EOF to 21
5003 torture_comment(tctx, "Setting stream EOF to 21\n");
5005 status = torture_smb2_testfile_access(tree, sname, &h1,
5006 SEC_FILE_WRITE_DATA);
5007 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5008 "torture_smb2_testfile failed\n");
5010 ZERO_STRUCT(sfinfo);
5011 sfinfo.generic.in.file.handle = h1;
5012 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5013 sfinfo.position_information.in.position = 21;
5014 status = smb2_setinfo_file(tree, &sfinfo);
5015 torture_assert_ntstatus_ok_goto(tctx, status,
5016 ret, done, "set EOF 21 failed\n");
5018 smb2_util_close(tree, h1);
5020 status = torture_smb2_testfile_access(tree, sname, &h1,
5021 SEC_FILE_WRITE_DATA);
5022 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5023 "torture_smb2_testfile failed\n");
5026 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5027 finfo.generic.in.file.handle = h1;
5028 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5029 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5030 "smb2_getinfo_file failed");
5032 smb2_util_close(tree, h1);
5034 torture_assert_goto(tctx, finfo.standard_info.out.size == 21,
5035 ret, done, "size != 21\n");
5038 * Test setting EOF to 0
5041 torture_comment(tctx, "Setting stream EOF to 0\n");
5043 status = torture_smb2_testfile_access(tree, sname, &h1,
5044 SEC_FILE_WRITE_DATA);
5045 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5046 "torture_smb2_testfile failed\n");
5048 ZERO_STRUCT(sfinfo);
5049 sfinfo.generic.in.file.handle = h1;
5050 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5051 sfinfo.position_information.in.position = 0;
5052 status = smb2_setinfo_file(tree, &sfinfo);
5053 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5054 "set eof 0 failed\n");
5056 ZERO_STRUCT(create);
5057 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5058 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5059 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5060 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5061 create.in.fname = sname;
5063 status = smb2_create(tree, tctx, &create);
5064 torture_assert_ntstatus_equal_goto(
5065 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5066 "Unexpected status\n");
5068 smb2_util_close(tree, h1);
5070 ZERO_STRUCT(create);
5071 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5072 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5073 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5074 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5075 create.in.fname = sname;
5077 status = smb2_create(tree, tctx, &create);
5078 torture_assert_ntstatus_equal_goto(
5079 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5080 "Unexpected status\n");
5082 status = torture_smb2_testfile_access(tree, sname, &h1,
5083 SEC_FILE_WRITE_DATA);
5084 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5085 "torture_smb2_testfile failed\n");
5088 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5089 finfo.generic.in.file.handle = h1;
5090 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5091 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5092 "smb2_getinfo_file failed\n");
5094 smb2_util_close(tree, h1);
5096 torture_assert_goto(tctx, finfo.standard_info.out.size == 0,
5097 ret, done, "size != 0\n");
5100 * Test setinfo end-of-file info to 1
5103 torture_comment(tctx, "Setting stream EOF to 1\n");
5105 status = torture_smb2_testfile_access(tree, sname, &h1,
5106 SEC_FILE_WRITE_DATA);
5107 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5108 "torture_smb2_testfile failed\n");
5110 ZERO_STRUCT(sfinfo);
5111 sfinfo.generic.in.file.handle = h1;
5112 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5113 sfinfo.position_information.in.position = 1;
5114 status = smb2_setinfo_file(tree, &sfinfo);
5115 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5116 "set EOF 1 failed\n");
5118 smb2_util_close(tree, h1);
5120 status = torture_smb2_testfile_access(tree, sname, &h1,
5121 SEC_FILE_WRITE_DATA);
5122 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5123 "torture_smb2_testfile failed\n");
5126 finfo.generic.level = RAW_FILEINFO_STANDARD_INFORMATION;
5127 finfo.generic.in.file.handle = h1;
5128 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5129 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5130 "smb2_getinfo_file failed\n");
5132 smb2_util_close(tree, h1);
5134 torture_assert_goto(tctx, finfo.standard_info.out.size == 1,
5135 ret, done, "size != 1\n");
5138 * Test setting EOF to 0 with AAPL enabled, should delete stream
5141 torture_comment(tctx, "Enabling AAPL extensions\n");
5143 ret = enable_aapl(tctx, tree);
5144 torture_assert(tctx, ret == true, "enable_aapl failed\n");
5146 torture_comment(tctx, "Setting stream EOF to 0\n");
5147 status = torture_smb2_testfile_access(tree, sname, &h1,
5148 SEC_FILE_WRITE_DATA);
5149 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5150 "torture_smb2_testfile failed\n");
5152 ZERO_STRUCT(sfinfo);
5153 sfinfo.generic.in.file.handle = h1;
5154 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5155 sfinfo.position_information.in.position = 0;
5156 status = smb2_setinfo_file(tree, &sfinfo);
5157 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5158 "set eof 0 failed\n");
5160 ZERO_STRUCT(create);
5161 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5162 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5163 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5164 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5165 create.in.fname = sname;
5167 status = smb2_create(tree, tctx, &create);
5168 torture_assert_ntstatus_equal_goto(
5169 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5170 "Unexpected status\n");
5172 smb2_util_close(tree, h1);
5174 ZERO_STRUCT(create);
5175 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5176 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5177 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5178 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5179 create.in.fname = sname;
5181 status = smb2_create(tree, tctx, &create);
5182 torture_assert_ntstatus_equal_goto(
5183 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, ret, done,
5184 "Unexpected status\n");
5187 tctx, "Setting main file EOF to 1 to force 0-truncate\n");
5189 status = torture_smb2_testfile_access(
5193 SEC_FILE_WRITE_DATA);
5194 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5195 "torture_smb2_testfile failed\n");
5197 ZERO_STRUCT(sfinfo);
5198 sfinfo.generic.in.file.handle = h1;
5199 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5200 sfinfo.position_information.in.position = 1;
5201 status = smb2_setinfo_file(tree, &sfinfo);
5202 torture_assert_ntstatus_ok_goto(
5207 "set eof 1 failed\n");
5209 sfinfo.position_information.in.position = 0;
5210 status = smb2_setinfo_file(tree, &sfinfo);
5211 torture_assert_ntstatus_ok_goto(
5216 "set eof 0 failed\n");
5218 smb2_util_close(tree, h1);
5220 ZERO_STRUCT(create);
5221 create.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
5222 create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
5223 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5224 create.in.create_disposition = NTCREATEX_DISP_OPEN;
5225 create.in.fname = fname;
5227 status = smb2_create(tree, tctx, &create);
5228 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5229 "torture_smb2_testfile failed\n");
5230 smb2_util_close(tree, h1);
5232 torture_comment(tctx, "Writing to stream after setting EOF to 0\n");
5233 status = torture_smb2_testfile_access(tree, sname, &h1,
5234 SEC_FILE_WRITE_DATA);
5235 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5236 "torture_smb2_testfile failed\n");
5238 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5239 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5240 "smb2_util_write failed\n");
5242 ZERO_STRUCT(sfinfo);
5243 sfinfo.generic.in.file.handle = h1;
5244 sfinfo.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
5245 sfinfo.position_information.in.position = 0;
5246 status = smb2_setinfo_file(tree, &sfinfo);
5247 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5248 "set eof 0 failed\n");
5250 status = smb2_util_write(tree, h1, "1234567890", 0, 10);
5251 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5252 "smb2_util_write failed\n");
5254 smb2_util_close(tree, h1);
5257 smb2_util_unlink(tree, fname);
5258 smb2_util_rmdir(tree, BASEDIR);
5262 #define MAX_STREAMS 16
5267 const char *write_data;
5269 struct tcase_results {
5271 NTSTATUS initial_status;
5272 NTSTATUS final_status;
5273 int num_streams_open_handle;
5274 const char *streams_open_handle[MAX_STREAMS];
5275 int num_streams_closed_handle;
5276 const char *streams_closed_handle[MAX_STREAMS];
5277 } create, write, overwrite, eof, doc;
5280 typedef enum {T_CREATE, T_WRITE, T_OVERWRITE, T_EOF, T_DOC} subtcase_t;
5282 static bool test_empty_stream_do_checks(
5283 struct torture_context *tctx,
5284 struct smb2_tree *tree,
5285 struct smb2_tree *tree2,
5286 struct tcase *tcase,
5287 TALLOC_CTX *mem_ctx,
5288 struct smb2_handle baseh,
5289 struct smb2_handle streamh,
5294 struct smb2_handle h1;
5295 union smb_fileinfo finfo;
5296 struct tcase_results *tcase_results = NULL;
5300 tcase_results = &tcase->create;
5303 tcase_results = &tcase->overwrite;
5306 tcase_results = &tcase->write;
5309 tcase_results = &tcase->eof;
5312 tcase_results = &tcase->doc;
5316 finfo = (union smb_fileinfo) {
5317 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5318 .generic.in.file.handle = streamh,
5322 * Test: check size, same client
5325 status = smb2_getinfo_file(tree, mem_ctx, &finfo);
5326 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5327 "torture_smb2_testfile failed\n");
5329 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5330 tcase_results->size,
5331 ret, done, "Wrong size\n");
5334 * Test: open, same client
5337 status = torture_smb2_open(tree, tcase->name,
5338 SEC_FILE_READ_ATTRIBUTE, &h1);
5339 torture_assert_ntstatus_equal_goto(tctx, status,
5340 tcase_results->initial_status,
5342 "smb2_create failed\n");
5343 if (NT_STATUS_IS_OK(status)) {
5344 status = smb2_util_close(tree, h1);
5345 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5346 "smb2_util_close failed\n");
5350 * Test: check streams, same client
5353 ret = check_stream_list_handle(tree, tctx, baseh,
5354 tcase_results->num_streams_open_handle,
5355 tcase_results->streams_open_handle,
5357 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5360 * Test: open, different client
5363 status = torture_smb2_open(tree2, tcase->name,
5364 SEC_FILE_READ_ATTRIBUTE, &h1);
5365 torture_assert_ntstatus_equal_goto(tctx, status,
5366 tcase_results->initial_status,
5368 "smb2_create failed\n");
5369 if (NT_STATUS_IS_OK(status)) {
5370 finfo = (union smb_fileinfo) {
5371 .generic.level = RAW_FILEINFO_STANDARD_INFORMATION,
5372 .generic.in.file.handle = h1,
5376 * Test: check size, different client
5379 status = smb2_getinfo_file(tree2, mem_ctx, &finfo);
5380 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5381 "smb2_getinfo_file failed\n");
5383 torture_assert_int_equal_goto(tctx, finfo.standard_info.out.size,
5384 tcase_results->size,
5385 ret, done, "Wrong size\n");
5388 * Test: check streams, different client
5391 ret = check_stream_list(tree2, tctx, BASEDIR "\\file",
5392 tcase_results->num_streams_open_handle,
5393 tcase_results->streams_open_handle,
5395 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5397 status = smb2_util_close(tree2, h1);
5398 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5399 "smb2_util_close failed\n");
5402 status = smb2_util_close(tree, streamh);
5403 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5404 "smb2_util_close failed\n");
5407 * Test: open after close, same client
5410 status = torture_smb2_open(tree, tcase->name,
5411 SEC_FILE_READ_DATA, &h1);
5412 torture_assert_ntstatus_equal_goto(tctx, status,
5413 tcase_results->final_status,
5415 "smb2_create failed\n");
5416 if (NT_STATUS_IS_OK(status)) {
5417 status = smb2_util_close(tree, h1);
5418 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5419 "smb2_util_close failed\n");
5423 * Test: open after close, different client
5426 status = torture_smb2_open(tree2, tcase->name,
5427 SEC_FILE_READ_DATA, &h1);
5428 torture_assert_ntstatus_equal_goto(tctx, status,
5429 tcase_results->final_status,
5431 "smb2_create failed\n");
5432 if (NT_STATUS_IS_OK(status)) {
5433 status = smb2_util_close(tree2, h1);
5434 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5435 "smb2_util_close failed\n");
5439 * Test: check streams after close, same client
5442 ret = check_stream_list_handle(tree, tctx, baseh,
5443 tcase_results->num_streams_closed_handle,
5444 tcase_results->streams_closed_handle,
5446 torture_assert_goto(tctx, ret == true, ret, done, "Bad streams");
5451 smb2_util_close(tree, streamh);
5452 smb2_util_close(tree, baseh);
5456 static bool test_empty_stream_do_one(
5457 struct torture_context *tctx,
5458 struct smb2_tree *tree,
5459 struct smb2_tree *tree2,
5460 struct tcase *tcase)
5464 struct smb2_handle baseh;
5465 struct smb2_handle streamh;
5466 struct smb2_create create;
5467 union smb_setfileinfo sfinfo;
5468 TALLOC_CTX *mem_ctx = talloc_new(tctx);
5470 torture_comment(tctx, "Testing stream [%s]\n", tcase->name);
5472 torture_assert_goto(tctx, mem_ctx != NULL, ret, done, "talloc_new\n");
5477 torture_comment(tctx, "Subtest: T_CREATE\n");
5479 status = smb2_util_unlink(tree, BASEDIR "\\file");
5480 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5481 "smb2_util_unlink failed\n");
5483 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5484 &baseh, SEC_FILE_ALL);
5485 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5486 "torture_smb2_testfile_access failed\n");
5488 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5490 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5491 "torture_smb2_testfile_access failed\n");
5493 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5494 mem_ctx, baseh, streamh, T_CREATE);
5495 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5497 if (!(tcase->access & SEC_FILE_WRITE_DATA)) {
5499 * All subsequent tests require write access
5506 * Subtest: create and write
5508 torture_comment(tctx, "Subtest: T_WRITE\n");
5510 status = smb2_util_unlink(tree, BASEDIR "\\file");
5511 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5512 "smb2_util_unlink failed\n");
5514 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5515 &baseh, SEC_FILE_ALL);
5516 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5517 "torture_smb2_testfile_access failed\n");
5519 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5521 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5522 "torture_smb2_testfile_access failed\n");
5524 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5526 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5527 "torture_smb2_open failed\n");
5529 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5530 mem_ctx, baseh, streamh, T_WRITE);
5531 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5534 * Subtest: overwrite
5536 torture_comment(tctx, "Subtest: T_OVERWRITE\n");
5538 status = smb2_util_unlink(tree, BASEDIR "\\file");
5539 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5540 "smb2_util_unlink failed\n");
5542 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5543 &baseh, SEC_FILE_ALL);
5544 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5545 "torture_smb2_testfile_access failed\n");
5547 create = (struct smb2_create) {
5548 .in.desired_access = SEC_FILE_ALL,
5549 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
5550 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
5551 .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF,
5552 .in.fname = tcase->name,
5555 status = smb2_create(tree, tctx, &create);
5556 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5557 "torture_smb2_testfile failed\n");
5558 streamh = create.out.file.handle;
5560 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5561 mem_ctx, baseh, streamh, T_OVERWRITE);
5562 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5565 * Subtest: setinfo EOF 0
5567 torture_comment(tctx, "Subtest: T_EOF\n");
5569 status = smb2_util_unlink(tree, BASEDIR "\\file");
5570 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5571 "smb2_util_unlink failed\n");
5573 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5574 &baseh, SEC_FILE_ALL);
5575 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5576 "torture_smb2_testfile_access failed\n");
5578 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5580 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5581 "torture_smb2_testfile_access failed\n");
5583 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5585 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5586 "torture_smb2_open failed\n");
5588 sfinfo = (union smb_setfileinfo) {
5589 .end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION,
5590 .end_of_file_info.in.file.handle = streamh,
5591 .end_of_file_info.in.size = 0,
5593 status = smb2_setinfo_file(tree, &sfinfo);
5594 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5595 "set eof 0 failed\n");
5597 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5598 mem_ctx, baseh, streamh, T_EOF);
5599 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5602 * Subtest: delete-on-close
5604 torture_comment(tctx, "Subtest: T_DOC\n");
5606 status = smb2_util_unlink(tree, BASEDIR "\\file");
5607 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5608 "smb2_util_unlink failed\n");
5610 status = torture_smb2_testfile_access(tree, BASEDIR "\\file",
5611 &baseh, SEC_FILE_ALL);
5612 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5613 "torture_smb2_testfile_access failed\n");
5615 status = torture_smb2_testfile_access(tree, tcase->name, &streamh,
5617 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5618 "torture_smb2_testfile_access failed\n");
5620 status = smb2_util_write(tree, streamh, tcase->write_data, 0,
5622 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5623 "torture_smb2_open failed\n");
5625 sfinfo = (union smb_setfileinfo) {
5626 .disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFORMATION,
5627 .disposition_info.in.file.handle = streamh,
5628 .disposition_info.in.delete_on_close = true,
5630 status = smb2_setinfo_file(tree, &sfinfo);
5631 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5632 "set eof 0 failed\n");
5634 ret = test_empty_stream_do_checks(tctx, tree, tree2, tcase,
5635 mem_ctx, baseh, streamh,
5637 torture_assert_goto(tctx, ret, ret, done, "test failed\n");
5642 smb2_util_close(tree, baseh);
5643 TALLOC_FREE(mem_ctx);
5647 static bool test_empty_stream(struct torture_context *tctx,
5648 struct smb2_tree *tree)
5650 struct smb2_tree *tree2 = NULL;
5651 struct tcase *tcase = NULL;
5652 const char *fname = BASEDIR "\\file";
5653 struct smb2_handle h1;
5656 AfpInfo ai = (AfpInfo) {
5657 .afpi_Signature = AFP_Signature,
5658 .afpi_Version = AFP_Version,
5659 .afpi_BackupTime = AFP_BackupTime,
5660 .afpi_FinderInfo = "FOO BAR ",
5662 char *ai_blob = torture_afpinfo_pack(tctx, &ai);
5663 struct tcase tcase_afpinfo_ro = (struct tcase) {
5664 .name = BASEDIR "\\file" AFPINFO_STREAM,
5665 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5667 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5668 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5669 .create.num_streams_open_handle = 1,
5670 .create.num_streams_closed_handle = 1,
5671 .create.streams_open_handle = {"::$DATA"},
5672 .create.streams_closed_handle = {"::$DATA"},
5674 struct tcase tcase_afpinfo_rw = (struct tcase) {
5675 .name = BASEDIR "\\file" AFPINFO_STREAM,
5676 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5677 .write_data = ai_blob,
5678 .write_size = AFP_INFO_SIZE,
5680 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5681 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5682 .create.num_streams_open_handle = 1,
5683 .create.num_streams_closed_handle = 1,
5684 .create.streams_open_handle = {"::$DATA"},
5685 .create.streams_closed_handle = {"::$DATA"},
5687 .write.initial_status = NT_STATUS_OK,
5688 .write.final_status = NT_STATUS_OK,
5689 .write.num_streams_open_handle = 2,
5690 .write.num_streams_closed_handle = 2,
5691 .write.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5692 .write.streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
5693 .overwrite.size = 60,
5694 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5695 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5696 .overwrite.num_streams_open_handle = 1,
5697 .overwrite.num_streams_closed_handle = 1,
5698 .overwrite.streams_open_handle = {"::$DATA"},
5699 .overwrite.streams_closed_handle = {"::$DATA"},
5701 .eof.initial_status = NT_STATUS_OK,
5702 .eof.final_status = NT_STATUS_OK,
5703 .eof.num_streams_open_handle = 2,
5704 .eof.num_streams_closed_handle = 2,
5705 .eof.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5706 .eof.streams_closed_handle = {"::$DATA", AFPINFO_STREAM},
5708 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5709 .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5710 .doc.num_streams_open_handle = 2,
5711 .doc.num_streams_closed_handle = 1,
5712 .doc.streams_open_handle = {"::$DATA", AFPINFO_STREAM},
5713 .doc.streams_closed_handle = {"::$DATA"},
5716 struct tcase tcase_afpresource_ro = (struct tcase) {
5717 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
5718 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5720 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5721 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5722 .create.num_streams_open_handle = 1,
5723 .create.num_streams_closed_handle = 1,
5724 .create.streams_open_handle = {"::$DATA"},
5725 .create.streams_closed_handle = {"::$DATA"},
5727 struct tcase tcase_afpresource_rw = (struct tcase) {
5728 .name = BASEDIR "\\file" AFPRESOURCE_STREAM,
5729 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5730 .write_data = "foo",
5733 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5734 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5735 .create.num_streams_open_handle = 1,
5736 .create.num_streams_closed_handle = 1,
5737 .create.streams_open_handle = {"::$DATA"},
5738 .create.streams_closed_handle = {"::$DATA"},
5740 .write.initial_status = NT_STATUS_OK,
5741 .write.final_status = NT_STATUS_OK,
5742 .write.num_streams_open_handle = 2,
5743 .write.num_streams_closed_handle = 2,
5744 .write.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
5745 .write.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
5746 .overwrite.size = 0,
5747 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5748 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5749 .overwrite.num_streams_open_handle = 1,
5750 .overwrite.num_streams_closed_handle = 1,
5751 .overwrite.streams_open_handle = {"::$DATA"},
5752 .overwrite.streams_closed_handle = {"::$DATA"},
5754 .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5755 .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5756 .eof.num_streams_open_handle = 1,
5757 .eof.num_streams_closed_handle = 1,
5758 .eof.streams_open_handle = {"::$DATA"},
5759 .eof.streams_closed_handle = {"::$DATA"},
5761 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5762 .doc.final_status = NT_STATUS_OK,
5763 .doc.num_streams_open_handle = 2,
5764 .doc.num_streams_closed_handle = 2,
5765 .doc.streams_open_handle = {"::$DATA", AFPRESOURCE_STREAM},
5766 .doc.streams_closed_handle = {"::$DATA", AFPRESOURCE_STREAM},
5769 struct tcase tcase_foo_ro = (struct tcase) {
5770 .name = BASEDIR "\\file:foo",
5771 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE,
5772 .write_data = "foo",
5775 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5776 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5777 .create.num_streams_open_handle = 1,
5778 .create.num_streams_closed_handle = 1,
5779 .create.streams_open_handle = {"::$DATA"},
5780 .create.streams_closed_handle = {"::$DATA"},
5783 struct tcase tcase_foo_rw = (struct tcase) {
5784 .name = BASEDIR "\\file:foo",
5785 .access = SEC_FILE_READ_DATA|SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_DATA|SEC_STD_DELETE,
5786 .write_data = "foo",
5789 .create.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5790 .create.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5791 .create.num_streams_open_handle = 1,
5792 .create.num_streams_closed_handle = 1,
5793 .create.streams_open_handle = {"::$DATA"},
5794 .create.streams_closed_handle = {"::$DATA"},
5796 .write.initial_status = NT_STATUS_OK,
5797 .write.final_status = NT_STATUS_OK,
5798 .write.num_streams_open_handle = 2,
5799 .write.num_streams_closed_handle = 2,
5800 .write.streams_open_handle = {"::$DATA", ":foo:$DATA"},
5801 .write.streams_closed_handle = {"::$DATA", ":foo:$DATA"},
5802 .overwrite.size = 0,
5803 .overwrite.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5804 .overwrite.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5805 .overwrite.num_streams_open_handle = 1,
5806 .overwrite.num_streams_closed_handle = 1,
5807 .overwrite.streams_open_handle = {"::$DATA"},
5808 .overwrite.streams_closed_handle = {"::$DATA"},
5810 .eof.initial_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5811 .eof.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5812 .eof.num_streams_open_handle = 1,
5813 .eof.num_streams_closed_handle = 1,
5814 .eof.streams_open_handle = {"::$DATA"},
5815 .eof.streams_closed_handle = {"::$DATA"},
5817 .doc.initial_status = NT_STATUS_DELETE_PENDING,
5818 .doc.final_status = NT_STATUS_OBJECT_NAME_NOT_FOUND,
5819 .doc.num_streams_open_handle = 2,
5820 .doc.num_streams_closed_handle = 1,
5821 .doc.streams_open_handle = {"::$DATA", ":foo:$DATA"},
5822 .doc.streams_closed_handle = {"::$DATA"},
5825 struct tcase tcases[] = {
5828 tcase_afpresource_ro,
5829 tcase_afpresource_rw,
5835 ret = torture_smb2_connection(tctx, &tree2);
5836 torture_assert_goto(tctx, ret == true, ret, done,
5837 "torture_smb2_connection failed\n");
5839 ret = enable_aapl(tctx, tree);
5840 torture_assert(tctx, ret == true, "enable_aapl failed\n");
5842 ret = enable_aapl(tctx, tree2);
5843 torture_assert(tctx, ret == true, "enable_aapl failed\n");
5845 smb2_deltree(tree, BASEDIR);
5847 status = torture_smb2_testdir(tree, BASEDIR, &h1);
5848 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5849 "torture_smb2_testdir\n");
5850 smb2_util_close(tree, h1);
5852 for (tcase = &tcases[0]; tcase->name != NULL; tcase++) {
5853 ret = torture_setup_file(tctx, tree, fname, false);
5854 torture_assert_goto(tctx, ret == true, ret, done,
5855 "torture_setup_file failed\n");
5857 ret = test_empty_stream_do_one(tctx, tree, tree2, tcase);
5858 torture_assert_goto(tctx, ret == true, ret, done,
5859 "subtest failed\n");
5861 status = smb2_util_unlink(tree, fname);
5862 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5863 "smb2_util_unlink failed\n");
5867 smb2_deltree(tree, BASEDIR);
5873 * Note: This test depends on "vfs objects = catia fruit streams_xattr". For
5874 * some tests torture must be run on the host it tests and takes an additional
5875 * argument with the local path to the share:
5876 * "--option=torture:localdir=<SHAREPATH>".
5878 * When running against an OS X SMB server add "--option=torture:osx=true"
5880 struct torture_suite *torture_vfs_fruit(TALLOC_CTX *ctx)
5882 struct torture_suite *suite = torture_suite_create(
5885 suite->description = talloc_strdup(suite, "vfs_fruit tests");
5887 torture_suite_add_1smb2_test(suite, "copyfile", test_copyfile);
5888 torture_suite_add_1smb2_test(suite, "read metadata", test_read_afpinfo);
5889 torture_suite_add_1smb2_test(suite, "write metadata", test_write_atalk_metadata);
5890 torture_suite_add_1smb2_test(suite, "resource fork IO", test_write_atalk_rfork_io);
5891 torture_suite_add_1smb2_test(suite, "SMB2/CREATE context AAPL", test_aapl);
5892 torture_suite_add_1smb2_test(suite, "stream names", test_stream_names);
5893 torture_suite_add_1smb2_test(suite, "truncate resource fork to 0 bytes", test_rfork_truncate);
5894 torture_suite_add_1smb2_test(suite, "opening and creating resource fork", test_rfork_create);
5895 torture_suite_add_1smb2_test(suite, "rename_dir_openfile", test_rename_dir_openfile);
5896 torture_suite_add_1smb2_test(suite, "File without AFP_AfpInfo", test_afpinfo_enoent);
5897 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpInfo", test_create_delete_on_close);
5898 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpInfo", test_setinfo_delete_on_close);
5899 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpInfo", test_setinfo_eof);
5900 torture_suite_add_1smb2_test(suite, "delete AFP_AfpInfo by writing all 0", test_afpinfo_all0);
5901 torture_suite_add_1smb2_test(suite, "create delete-on-close AFP_AfpResource", test_create_delete_on_close_resource);
5902 torture_suite_add_1smb2_test(suite, "setinfo delete-on-close AFP_AfpResource", test_setinfo_delete_on_close_resource);
5903 torture_suite_add_1smb2_test(suite, "setinfo eof AFP_AfpResource", test_setinfo_eof_resource);
5904 torture_suite_add_1smb2_test(suite, "setinfo eof stream", test_setinfo_stream_eof);
5905 torture_suite_add_1smb2_test(suite, "null afpinfo", test_null_afpinfo);
5906 torture_suite_add_1smb2_test(suite, "delete", test_delete_file_with_rfork);
5907 torture_suite_add_1smb2_test(suite, "read open rsrc after rename", test_rename_and_read_rsrc);
5908 torture_suite_add_1smb2_test(suite, "readdir_attr with names with illegal ntfs characters", test_readdir_attr_illegal_ntfs);
5909 torture_suite_add_2ns_smb2_test(suite, "invalid AFP_AfpInfo", test_invalid_afpinfo);
5910 torture_suite_add_1smb2_test(suite, "creating rsrc with read-only access", test_rfork_create_ro);
5911 torture_suite_add_1smb2_test(suite, "copy-chunk streams", test_copy_chunk_streams);
5912 torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion", test_adouble_conversion);
5913 torture_suite_add_1smb2_test(suite, "NFS ACE entries", test_nfs_aces);
5914 torture_suite_add_1smb2_test(suite, "OS X AppleDouble file conversion without embedded xattr", test_adouble_conversion_wo_xattr);
5915 torture_suite_add_1smb2_test(suite, "empty_stream", test_empty_stream);
5920 static bool test_stream_names_local(struct torture_context *tctx,
5921 struct smb2_tree *tree)
5923 TALLOC_CTX *mem_ctx = talloc_new(tctx);
5925 struct smb2_create create;
5926 struct smb2_handle h;
5927 const char *fname = BASEDIR "\\stream_names.txt";
5930 /* UTF8 private use are starts at 0xef 0x80 0x80 (0xf000) */
5931 const char *streams[] = {
5932 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
5933 ":bar" "\xef\x80\xa2" "baz:$DATA", /* "bar:baz:$DATA" */
5936 const char *localdir = NULL;
5938 localdir = torture_setting_string(tctx, "localdir", NULL);
5939 if (localdir == NULL) {
5940 torture_skip(tctx, "Need localdir for test");
5943 sname1 = talloc_asprintf(mem_ctx, "%s%s", fname, streams[0]);
5945 /* clean slate ...*/
5946 smb2_util_unlink(tree, fname);
5947 smb2_deltree(tree, fname);
5948 smb2_deltree(tree, BASEDIR);
5950 status = torture_smb2_testdir(tree, BASEDIR, &h);
5951 CHECK_STATUS(status, NT_STATUS_OK);
5952 smb2_util_close(tree, h);
5954 torture_comment(tctx, "(%s) testing stream names\n", __location__);
5955 ZERO_STRUCT(create);
5956 create.in.desired_access = SEC_FILE_WRITE_DATA;
5957 create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
5958 create.in.share_access =
5959 NTCREATEX_SHARE_ACCESS_DELETE|
5960 NTCREATEX_SHARE_ACCESS_READ|
5961 NTCREATEX_SHARE_ACCESS_WRITE;
5962 create.in.create_disposition = NTCREATEX_DISP_CREATE;
5963 create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
5964 create.in.fname = sname1;
5966 status = smb2_create(tree, mem_ctx, &create);
5967 CHECK_STATUS(status, NT_STATUS_OK);
5969 status = smb2_util_write(tree, create.out.file.handle, "foo", 0, 3);
5970 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
5971 "smb2_util_write failed\n");
5973 smb2_util_close(tree, create.out.file.handle);
5975 ret = torture_setup_local_xattr(tctx, "localdir", BASEDIR "/stream_names.txt",
5976 "user.DosStream.bar:baz:$DATA",
5977 "data", strlen("data"));
5978 CHECK_VALUE(ret, true);
5980 ret = check_stream_list(tree, tctx, fname, 3, streams, false);
5981 CHECK_VALUE(ret, true);
5984 status = smb2_util_unlink(tree, fname);
5985 smb2_deltree(tree, BASEDIR);
5986 talloc_free(mem_ctx);
5991 static bool test_fruit_locking_conflict(struct torture_context *tctx,
5992 struct smb2_tree *tree)
5994 TALLOC_CTX *mem_ctx;
5995 struct smb2_create create;
5996 struct smb2_handle h;
5997 struct smb2_lock lck;
5998 struct smb2_lock_element el;
5999 const char *fname = BASEDIR "\\locking_conflict.txt";
6003 mem_ctx = talloc_new(tctx);
6004 torture_assert_not_null(tctx, mem_ctx, "talloc_new failed");
6006 /* clean slate ...*/
6007 smb2_util_unlink(tree, fname);
6008 smb2_deltree(tree, fname);
6009 smb2_deltree(tree, BASEDIR);
6011 status = torture_smb2_testdir(tree, BASEDIR, &h);
6012 CHECK_STATUS(status, NT_STATUS_OK);
6013 smb2_util_close(tree, h);
6015 create = (struct smb2_create) {
6016 .in.desired_access = SEC_RIGHTS_FILE_READ,
6017 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6019 NTCREATEX_SHARE_ACCESS_READ|
6020 NTCREATEX_SHARE_ACCESS_WRITE,
6021 .in.create_disposition = NTCREATEX_DISP_CREATE,
6022 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6026 status = smb2_create(tree, mem_ctx, &create);
6027 CHECK_STATUS(status, NT_STATUS_OK);
6028 h = create.out.file.handle;
6030 el = (struct smb2_lock_element) {
6031 .offset = 0xfffffffffffffffc,
6033 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6035 lck = (struct smb2_lock) {
6037 .in.file.handle = h,
6041 status = smb2_lock(tree, &lck);
6042 CHECK_STATUS(status, NT_STATUS_OK);
6044 el = (struct smb2_lock_element) {
6046 .length = 0x7fffffffffffffff,
6047 .flags = SMB2_LOCK_FLAG_EXCLUSIVE,
6049 status = smb2_lock(tree, &lck);
6050 CHECK_STATUS(status, NT_STATUS_OK);
6052 create = (struct smb2_create) {
6053 .in.desired_access =
6054 SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6055 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6056 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6057 .in.create_disposition = NTCREATEX_DISP_OPEN,
6058 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6062 status = smb2_create(tree, mem_ctx, &create);
6063 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
6066 struct smb2_close cl = {
6067 .level = RAW_CLOSE_SMB2,
6068 .in.file.handle = h,
6070 smb2_close(tree, &cl);
6078 struct torture_suite *torture_vfs_fruit_netatalk(TALLOC_CTX *ctx)
6080 struct torture_suite *suite = torture_suite_create(
6081 ctx, "fruit_netatalk");
6083 suite->description = talloc_strdup(suite, "vfs_fruit tests for Netatalk interop that require fruit:metadata=netatalk");
6085 torture_suite_add_1smb2_test(suite, "read netatalk metadata", test_read_netatalk_metadata);
6086 torture_suite_add_1smb2_test(suite, "stream names with locally created xattr", test_stream_names_local);
6087 torture_suite_add_1smb2_test(
6088 suite, "locking conflict", test_fruit_locking_conflict);
6093 struct torture_suite *torture_vfs_fruit_file_id(TALLOC_CTX *ctx)
6095 struct torture_suite *suite =
6096 torture_suite_create(ctx, "fruit_file_id");
6098 suite->description =
6099 talloc_strdup(suite, "vfs_fruit tests for on-disk file ID that "
6100 "require fruit:zero_file_id=yes");
6102 torture_suite_add_1smb2_test(suite, "zero file id if AAPL negotiated",
6108 static bool test_timemachine_volsize(struct torture_context *tctx,
6109 struct smb2_tree *tree)
6111 TALLOC_CTX *mem_ctx = talloc_new(tctx);
6112 struct smb2_handle h = {{0}};
6113 union smb_fsinfo fsinfo;
6116 const char *info_plist =
6118 " <key>band-size</key>\n"
6119 " <integer>8192</integer>\n"
6122 smb2_deltree(tree, "test.sparsebundle");
6124 ok = enable_aapl(tctx, tree);
6125 torture_assert_goto(tctx, ok, ok, done, "enable_aapl failed");
6127 status = smb2_util_mkdir(tree, "test.sparsebundle");
6128 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6129 "smb2_util_mkdir\n");
6131 ok = write_stream(tree, __location__, tctx, mem_ctx,
6132 "test.sparsebundle/Info.plist", NULL,
6133 0, strlen(info_plist), info_plist);
6134 torture_assert_goto(tctx, ok, ok, done, "write_stream failed\n");
6136 status = smb2_util_mkdir(tree, "test.sparsebundle/bands");
6137 torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
6138 "smb2_util_mkdir\n");
6140 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/1", false);
6141 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6143 ok = torture_setup_file(tctx, tree, "test.sparsebundle/bands/2", false);
6144 torture_assert_goto(tctx, ok, ok, done, "torture_setup_file failed\n");
6146 status = smb2_util_roothandle(tree, &h);
6147 torture_assert_ntstatus_ok(tctx, status, "Unable to create root handle");
6149 ZERO_STRUCT(fsinfo);
6150 fsinfo.generic.level = RAW_QFS_SIZE_INFORMATION;
6151 fsinfo.generic.handle = h;
6153 status = smb2_getinfo_fs(tree, tree, &fsinfo);
6154 torture_assert_ntstatus_ok(tctx, status, "smb2_getinfo_fs failed");
6156 torture_comment(tctx, "sectors_per_unit: %" PRIu32"\n"
6157 "bytes_per_sector: %" PRIu32"\n"
6158 "total_alloc_units: %" PRIu64"\n"
6159 "avail_alloc_units: %" PRIu64"\n",
6160 fsinfo.size_info.out.sectors_per_unit,
6161 fsinfo.size_info.out.bytes_per_sector,
6162 fsinfo.size_info.out.total_alloc_units,
6163 fsinfo.size_info.out.avail_alloc_units);
6166 * Let me explain the numbers:
6168 * - the share is set to "fruit:time machine max size = 32K"
6169 * - we've faked a bandsize of 8 K in the Info.plist file
6170 * - we've created two bands files
6171 * - one allocation unit is made of two sectors with 512 B each
6172 * => we've consumed 16 allocation units, there should be 16 free
6175 torture_assert_goto(tctx, fsinfo.size_info.out.sectors_per_unit == 2,
6176 ok, done, "Bad sectors_per_unit");
6178 torture_assert_goto(tctx, fsinfo.size_info.out.bytes_per_sector == 512,
6179 ok, done, "Bad bytes_per_sector");
6181 torture_assert_goto(tctx, fsinfo.size_info.out.total_alloc_units == 32,
6182 ok, done, "Bad total_alloc_units");
6184 torture_assert_goto(tctx, fsinfo.size_info.out.avail_alloc_units == 16,
6185 ok, done, "Bad avail_alloc_units");
6188 if (!smb2_util_handle_empty(h)) {
6189 smb2_util_close(tree, h);
6191 smb2_deltree(tree, "test.sparsebundle");
6192 talloc_free(mem_ctx);
6196 struct torture_suite *torture_vfs_fruit_timemachine(TALLOC_CTX *ctx)
6198 struct torture_suite *suite = torture_suite_create(
6199 ctx, "fruit_timemachine");
6201 suite->description = talloc_strdup(
6202 suite, "vfs_fruit tests for TimeMachine");
6204 torture_suite_add_1smb2_test(suite, "Timemachine-volsize",
6205 test_timemachine_volsize);
6210 static bool test_convert_xattr_and_empty_rfork_then_delete(
6211 struct torture_context *tctx,
6212 struct smb2_tree *tree1,
6213 struct smb2_tree *tree2)
6215 TALLOC_CTX *mem_ctx = talloc_new(tctx);
6216 const char *fname = BASEDIR "\\test_adouble_conversion";
6217 const char *adname = BASEDIR "/._test_adouble_conversion";
6218 const char *rfork = BASEDIR "\\test_adouble_conversion" AFPRESOURCE_STREAM_NAME;
6220 struct smb2_handle testdirh;
6222 const char *streams[] = {
6225 ":com.apple.metadata" "\xef\x80\xa2" "_kMDItemUserTags:$DATA",
6226 ":foo" "\xef\x80\xa2" "bar:$DATA", /* "foo:bar:$DATA" */
6228 struct smb2_create create;
6229 struct smb2_find find;
6231 union smb_search_data *d;
6232 bool delete_empty_adfiles;
6233 int expected_num_files;
6235 delete_empty_adfiles = torture_setting_bool(tctx,
6236 "delete_empty_adfiles",
6239 smb2_deltree(tree1, BASEDIR);
6241 status = torture_smb2_testdir(tree1, BASEDIR, &testdirh);
6242 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6243 "torture_smb2_testdir failed\n");
6244 smb2_util_close(tree1, testdirh);
6246 ret = torture_setup_file(tctx, tree1, fname, false);
6247 torture_assert_goto(tctx, ret == true, ret, done,
6248 "torture_setup_file failed\n");
6250 ret = torture_setup_file(tctx, tree1, adname, false);
6251 torture_assert_goto(tctx, ret == true, ret, done,
6252 "torture_setup_file failed\n");
6254 ret = write_stream(tree1, __location__, tctx, mem_ctx,
6256 0, sizeof(osx_adouble_w_xattr), osx_adouble_w_xattr);
6257 torture_assert_goto(tctx, ret == true, ret, done,
6258 "write_stream failed\n");
6260 ret = enable_aapl(tctx, tree2);
6261 torture_assert_goto(tctx, ret == true, ret, done, "enable_aapl failed");
6264 * Issue a smb2_find(), this triggers the server-side conversion
6267 create = (struct smb2_create) {
6268 .in.desired_access = SEC_RIGHTS_DIR_READ,
6269 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6270 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6271 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6272 .in.create_disposition = NTCREATEX_DISP_OPEN,
6273 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6274 .in.fname = BASEDIR,
6277 status = smb2_create(tree2, tctx, &create);
6278 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6279 "smb2_create failed\n");
6281 find = (struct smb2_find) {
6282 .in.file.handle = create.out.file.handle,
6284 .in.max_response_size = 0x1000,
6285 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6288 status = smb2_find_level(tree2, tree2, &find, &count, &d);
6289 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6290 "smb2_find_level failed\n");
6292 status = smb2_util_close(tree2, create.out.file.handle);
6293 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6294 "smb2_util_close failed");
6297 * Check number of streams
6300 ret = check_stream_list(tree2, tctx, fname, 4, streams, false);
6301 torture_assert_goto(tctx, ret == true, ret, done, "check_stream_list");
6304 * Check Resource Fork is gone
6307 create = (struct smb2_create) {
6308 .in.desired_access = SEC_RIGHTS_FILE_READ|SEC_RIGHTS_FILE_WRITE,
6309 .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
6310 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6311 .in.create_disposition = NTCREATEX_DISP_OPEN,
6312 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6316 status = smb2_create(tree2, mem_ctx, &create);
6317 torture_assert_ntstatus_equal_goto(
6318 tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
6319 ret, done, "Bad smb2_create return\n");
6322 * Check xattr data has been migrated from the AppleDouble file to
6326 ret = check_stream(tree2, __location__, tctx, mem_ctx,
6327 fname, AFPINFO_STREAM,
6328 0, 60, 16, 8, "TESTSLOW");
6329 torture_assert_goto(tctx, ret == true, ret, done,
6330 "check AFPINFO_STREAM failed\n");
6332 ret = check_stream(tree2, __location__, tctx, mem_ctx,
6333 fname, ":foo" "\xef\x80\xa2" "bar", /* foo:bar */
6335 torture_assert_goto(tctx, ret == true, ret, done,
6336 "check foo stream failed\n");
6339 * Now check number of files. If delete_empty_adfiles is set, the
6340 * AppleDouble files should have been deleted.
6343 create = (struct smb2_create) {
6344 .in.desired_access = SEC_RIGHTS_DIR_READ,
6345 .in.create_options = NTCREATEX_OPTIONS_DIRECTORY,
6346 .in.file_attributes = FILE_ATTRIBUTE_DIRECTORY,
6347 .in.share_access = NTCREATEX_SHARE_ACCESS_READ,
6348 .in.create_disposition = NTCREATEX_DISP_OPEN,
6349 .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
6350 .in.fname = BASEDIR,
6353 status = smb2_create(tree2, tctx, &create);
6354 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6355 "smb2_create failed\n");
6357 find = (struct smb2_find) {
6358 .in.file.handle = create.out.file.handle,
6360 .in.max_response_size = 0x1000,
6361 .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
6364 status = smb2_find_level(tree2, tree2, &find, &count, &d);
6365 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6366 "smb2_find_level failed\n");
6368 status = smb2_util_close(tree2, create.out.file.handle);
6369 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
6370 "smb2_util_close failed");
6372 if (delete_empty_adfiles) {
6373 expected_num_files = 3;
6375 expected_num_files = 4;
6377 torture_assert_int_equal_goto(tctx, count, expected_num_files, ret, done,
6378 "Wrong number of files\n");
6381 smb2_deltree(tree1, BASEDIR);
6382 talloc_free(mem_ctx);
6386 struct torture_suite *torture_vfs_fruit_conversion(TALLOC_CTX *ctx)
6388 struct torture_suite *suite = torture_suite_create(
6389 ctx, "fruit_conversion");
6391 suite->description = talloc_strdup(
6392 suite, "vfs_fruit conversion tests");
6394 torture_suite_add_2ns_smb2_test(
6395 suite, "convert_xattr_and_empty_rfork_then_delete",
6396 test_convert_xattr_and_empty_rfork_then_delete);