2 Unix SMB/CIFS implementation.
3 chkpath individual test suite
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/locale.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "torture/raw/proto.h"
27 #define BASEDIR "\\rawchkpath"
29 #define CHECK_STATUS(status, correct, dos_correct) do { \
30 if (!NT_STATUS_EQUAL(status, correct) && !NT_STATUS_EQUAL(status, dos_correct)) { \
31 printf("(%d) Incorrect status %s - should be %s\n", \
32 __LINE__, nt_errstr(status), nt_errstr(correct)); \
38 static NTSTATUS
single_search(struct smbcli_state
*cli
,
39 TALLOC_CTX
*mem_ctx
, const char *pattern
)
41 union smb_search_first io
;
44 io
.t2ffirst
.level
= RAW_SEARCH_TRANS2
;
45 io
.t2ffirst
.data_level
= RAW_SEARCH_DATA_STANDARD
;
46 io
.t2ffirst
.in
.search_attrib
= 0;
47 io
.t2ffirst
.in
.max_count
= 1;
48 io
.t2ffirst
.in
.flags
= FLAG_TRANS2_FIND_CLOSE
;
49 io
.t2ffirst
.in
.storage_type
= 0;
50 io
.t2ffirst
.in
.pattern
= pattern
;
52 status
= smb_raw_search_first(cli
->tree
, mem_ctx
,
58 static bool test_path_ex(struct smbcli_state
*cli
, struct torture_context
*tctx
,
59 const char *path
, const char *path_expected
,
60 NTSTATUS expected
, NTSTATUS dos_expected
)
63 union smb_fileinfo finfo
;
66 io
.chkpath
.in
.path
= path
;
67 status
= smb_raw_chkpath(cli
->tree
, &io
);
68 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
69 printf("FAILED %-30s chkpath %s should be %s or %s\n",
70 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
73 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
76 if (NT_STATUS_EQUAL(expected
, NT_STATUS_NOT_A_DIRECTORY
)) {
77 expected
= NT_STATUS_OK
;
81 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
82 finfo
.generic
.in
.file
.path
= path
;
83 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
84 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
85 printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
86 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
90 if (!NT_STATUS_IS_OK(status
)) {
91 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
96 (!finfo
.name_info
.out
.fname
.s
||
97 strcmp(finfo
.name_info
.out
.fname
.s
, path_expected
) != 0)) {
98 if (tctx
&& torture_setting_bool(tctx
, "samba4", false)) {
99 printf("IGNORE: %-30s => %-20s should be %s\n",
100 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
103 printf("FAILED: %-30s => %-20s should be %s\n",
104 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
107 printf("%-30s => %-20s correct\n",
108 path
, finfo
.name_info
.out
.fname
.s
);
113 static bool test_path(struct smbcli_state
*cli
, const char *path
,
114 NTSTATUS expected
, NTSTATUS dos_expected
)
116 return test_path_ex(cli
, NULL
, path
, path
, expected
, dos_expected
);
119 static bool test_chkpath(struct smbcli_state
*cli
, struct torture_context
*tctx
)
121 union smb_chkpath io
;
126 io
.chkpath
.in
.path
= BASEDIR
;
128 status
= smb_raw_chkpath(cli
->tree
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_OK
, NT_STATUS_OK
);
131 ret
&= test_path(cli
, BASEDIR
"\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
133 fnum
= create_complex_file(cli
, tctx
, BASEDIR
"\\test.txt..");
135 printf("failed to open test.txt - %s\n", smbcli_errstr(cli
->tree
));
140 ret
&= test_path(cli
, BASEDIR
"\\test.txt..", NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
142 if (!torture_set_file_attribute(cli
->tree
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
)) {
143 printf("failed to set basedir hidden\n");
148 ret
&= test_path_ex(cli
, tctx
, BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
149 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
) + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
150 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\\\") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
151 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\foo\\..") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
152 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
153 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\foo\\\\..\\\\") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
154 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
155 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\\\..\\"BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
156 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\\\\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
157 ret
&= test_path_ex(cli
, tctx
, "\\\\\\\\"BASEDIR
"\\\\\\\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
158 ret
&= test_path_ex(cli
, tctx
, "\\\\\\\\"BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
159 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\foo\\..\\test.txt..", BASEDIR
"\\test.txt..",
160 NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
161 ret
&= test_path_ex(cli
, tctx
, "", "\\", NT_STATUS_OK
, NT_STATUS_OK
);
162 ret
&= test_path(cli
, ".", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
163 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
164 ret
&= test_path(cli
, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
165 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
166 ret
&= test_path(cli
, "." BASEDIR
, NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
167 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
168 ret
&= test_path(cli
, BASEDIR
"\\.\\test.txt..", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
169 ret
&= test_path(cli
, ".\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
170 ret
&= test_path(cli
, ".\\.\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
171 ret
&= test_path(cli
, ".\\.\\.aaaaa", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
172 ret
&= test_path(cli
, "\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
173 ret
&= test_path(cli
, "\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
174 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
176 /* Note that the two following paths are identical but
177 give different NT status returns for chkpth and findfirst. */
179 printf("Testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
180 status
= single_search(cli
, tctx
, "\\.\\\\\\\\\\\\.");
181 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRinvalidname
));
183 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
185 /* We expect this open to fail with the same error code as the chkpath below. */
186 printf("Testing Open on %s\n", "\\.\\\\\\\\\\\\.");
187 /* findfirst seems to fail with a different error. */
188 (void)smbcli_nt_create_full(cli
->tree
, "\\.\\\\\\\\\\\\.",
189 0, SEC_RIGHTS_FILE_ALL
,
190 FILE_ATTRIBUTE_NORMAL
,
191 NTCREATEX_SHARE_ACCESS_DELETE
|
192 NTCREATEX_SHARE_ACCESS_READ
|
193 NTCREATEX_SHARE_ACCESS_WRITE
,
194 NTCREATEX_DISP_OVERWRITE_IF
,
196 status
= smbcli_nt_error(cli
->tree
);
197 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
200 ret
&= test_path(cli
, "\\.\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
201 ret
&= test_path(cli
, "..\\..\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
202 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
203 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
204 ret
&= test_path(cli
, BASEDIR
"\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
205 ret
&= test_path(cli
, BASEDIR
"\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
206 ret
&= test_path(cli
, BASEDIR
"\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
207 ret
&= test_path(cli
, BASEDIR
"\\.\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
208 ret
&= test_path(cli
, BASEDIR
"\\nt", NT_STATUS_OK
, NT_STATUS_OK
);
209 ret
&= test_path(cli
, BASEDIR
".\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
210 ret
&= test_path(cli
, BASEDIR
"xx\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
211 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
212 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
213 ret
&= test_path(cli
, ".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
214 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
215 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
216 ret
&= test_path(cli
, BASEDIR
".", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
217 ret
&= test_path(cli
, "\\", NT_STATUS_OK
,NT_STATUS_OK
);
218 ret
&= test_path(cli
, "\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
219 ret
&= test_path(cli
, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
220 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
221 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
222 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\..", "\\", NT_STATUS_OK
,NT_STATUS_OK
);
223 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
224 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
226 /* We expect this open to fail with the same error code as the chkpath below. */
227 printf("Testing Open on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
228 /* findfirst seems to fail with a different error. */
229 (void)smbcli_nt_create_full(cli
->tree
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\",
230 0, SEC_RIGHTS_FILE_ALL
,
231 FILE_ATTRIBUTE_NORMAL
,
232 NTCREATEX_SHARE_ACCESS_DELETE
|
233 NTCREATEX_SHARE_ACCESS_READ
|
234 NTCREATEX_SHARE_ACCESS_WRITE
,
235 NTCREATEX_DISP_OVERWRITE_IF
,
237 status
= smbcli_nt_error(cli
->tree
);
238 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
240 printf("Testing findfirst on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
241 status
= single_search(cli
, tctx
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
242 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
244 /* We expect this open to fail with the same error code as the chkpath below. */
245 /* findfirst seems to fail with a different error. */
246 printf("Testing Open on %s\n", BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3");
247 (void)smbcli_nt_create_full(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3",
248 0, SEC_RIGHTS_FILE_ALL
,
249 FILE_ATTRIBUTE_NORMAL
,
250 NTCREATEX_SHARE_ACCESS_DELETE
|
251 NTCREATEX_SHARE_ACCESS_READ
|
252 NTCREATEX_SHARE_ACCESS_WRITE
,
253 NTCREATEX_DISP_OVERWRITE_IF
,
255 status
= smbcli_nt_error(cli
->tree
);
256 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
258 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
259 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
260 ret
&= test_path(cli
, BASEDIR
"\\nt\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
261 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
262 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
265 smbcli_close(cli
->tree
, fnum
);
269 static bool test_chkpath_names(struct smbcli_state
*cli
, struct torture_context
*tctx
)
271 union smb_chkpath io
;
272 union smb_fileinfo finfo
;
278 * we don't test characters >= 0x80 yet,
279 * as somehow our client libraries can't do that
281 for (i
=0x01; i
<= 0x7F; i
++) {
283 * it's important that we test the last character
284 * because of the error code with ':' 0x3A
285 * and servers without stream support
287 char *path
= talloc_asprintf(tctx
, "%s\\File0x%02X%c",
290 NTSTATUS expected_dos1
;
291 NTSTATUS expected_dos2
;
293 expected
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
294 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
295 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRbadfile
);
307 torture_setting_bool(tctx
, "samba3", false)) {
308 /* samba 3 handles '/' as '\\' */
311 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
312 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
313 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
317 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
318 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
319 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
324 printf("Checking File0x%02X%c%s expected[%s|%s|%s]\n",
325 i
, isprint(i
)?(char)i
:' ',
326 isprint(i
)?"":"(not printable)",
328 nt_errstr(expected_dos1
),
329 nt_errstr(expected_dos2
));
331 io
.chkpath
.in
.path
= path
;
332 status
= smb_raw_chkpath(cli
->tree
, &io
);
333 CHECK_STATUS(status
, expected
, expected_dos1
);
336 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
337 finfo
.generic
.in
.file
.path
= path
;
338 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
339 CHECK_STATUS(status
, expected
, expected_dos2
);
349 basic testing of chkpath calls
351 bool torture_raw_chkpath(struct torture_context
*torture
,
352 struct smbcli_state
*cli
)
357 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
359 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt"))) {
360 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
364 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S"))) {
365 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
369 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98"))) {
370 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
374 fnum
= create_complex_file(cli
, torture
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe");
376 printf("failed to open \\nt\\V S\\VB98\\vb6.exe - %s\n", smbcli_errstr(cli
->tree
));
381 ret
&= test_chkpath(cli
, torture
);
382 ret
&= test_chkpath_names(cli
, torture
);
386 smb_raw_exit(cli
->session
);
387 smbcli_deltree(cli
->tree
, BASEDIR
);