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 "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
28 #define BASEDIR "\\rawchkpath"
30 #define CHECK_STATUS(status, correct, dos_correct) do { \
31 if (!NT_STATUS_EQUAL(status, correct) && !NT_STATUS_EQUAL(status, dos_correct)) { \
32 printf("(%d) Incorrect status %s - should be %s\n", \
33 __LINE__, nt_errstr(status), nt_errstr(correct)); \
39 static NTSTATUS
single_search(struct smbcli_state
*cli
,
40 TALLOC_CTX
*mem_ctx
, const char *pattern
)
42 union smb_search_first io
;
45 io
.t2ffirst
.level
= RAW_SEARCH_TRANS2
;
46 io
.t2ffirst
.data_level
= RAW_SEARCH_DATA_STANDARD
;
47 io
.t2ffirst
.in
.search_attrib
= 0;
48 io
.t2ffirst
.in
.max_count
= 1;
49 io
.t2ffirst
.in
.flags
= FLAG_TRANS2_FIND_CLOSE
;
50 io
.t2ffirst
.in
.storage_type
= 0;
51 io
.t2ffirst
.in
.pattern
= pattern
;
53 status
= smb_raw_search_first(cli
->tree
, mem_ctx
,
59 static bool test_path_ex(struct smbcli_state
*cli
, struct torture_context
*tctx
,
60 const char *path
, const char *path_expected
,
61 NTSTATUS expected
, NTSTATUS dos_expected
)
64 union smb_fileinfo finfo
;
67 io
.chkpath
.in
.path
= path
;
68 status
= smb_raw_chkpath(cli
->tree
, &io
);
69 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
70 printf("FAILED %-30s chkpath %s should be %s or %s\n",
71 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
74 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
77 if (NT_STATUS_EQUAL(expected
, NT_STATUS_NOT_A_DIRECTORY
)) {
78 expected
= NT_STATUS_OK
;
82 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
83 finfo
.generic
.in
.file
.path
= path
;
84 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
85 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
86 printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
87 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
91 if (!NT_STATUS_IS_OK(status
)) {
92 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
97 (!finfo
.name_info
.out
.fname
.s
||
98 strcmp(finfo
.name_info
.out
.fname
.s
, path_expected
) != 0)) {
99 if (tctx
&& torture_setting_bool(tctx
, "samba4", false)) {
100 printf("IGNORE: %-30s => %-20s should be %s\n",
101 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
104 printf("FAILED: %-30s => %-20s should be %s\n",
105 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
108 printf("%-30s => %-20s correct\n",
109 path
, finfo
.name_info
.out
.fname
.s
);
114 static bool test_path(struct smbcli_state
*cli
, const char *path
,
115 NTSTATUS expected
, NTSTATUS dos_expected
)
117 return test_path_ex(cli
, NULL
, path
, path
, expected
, dos_expected
);
120 static bool test_chkpath(struct smbcli_state
*cli
, struct torture_context
*tctx
)
122 union smb_chkpath io
;
128 io
.chkpath
.in
.path
= BASEDIR
;
130 status
= smb_raw_chkpath(cli
->tree
, &io
);
131 CHECK_STATUS(status
, NT_STATUS_OK
, NT_STATUS_OK
);
133 ret
&= test_path(cli
, BASEDIR
"\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
135 fnum
= create_complex_file(cli
, tctx
, BASEDIR
"\\test.txt..");
137 printf("failed to open test.txt - %s\n", smbcli_errstr(cli
->tree
));
142 ret
&= test_path(cli
, BASEDIR
"\\test.txt..", NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
144 if (!torture_set_file_attribute(cli
->tree
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
)) {
145 printf("failed to set basedir hidden\n");
150 ret
&= test_path_ex(cli
, tctx
, BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
151 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
) + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
152 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\\\") + 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
, ((const char *)BASEDIR
"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
155 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\foo\\\\..\\\\") + 1, 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
, 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
"\\\\\\\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
160 ret
&= test_path_ex(cli
, tctx
, "\\\\\\\\"BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
161 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\foo\\..\\test.txt..", BASEDIR
"\\test.txt..",
162 NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
163 ret
&= test_path_ex(cli
, tctx
, "", "\\", NT_STATUS_OK
, NT_STATUS_OK
);
164 ret
&= test_path(cli
, ".", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
165 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
166 ret
&= test_path(cli
, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
167 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
168 ret
&= test_path(cli
, "." BASEDIR
, NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
169 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
170 ret
&= test_path(cli
, BASEDIR
"\\.\\test.txt..", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
171 ret
&= test_path(cli
, ".\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
172 ret
&= test_path(cli
, ".\\.\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
173 ret
&= test_path(cli
, ".\\.\\.aaaaa", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
174 ret
&= test_path(cli
, "\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
175 ret
&= test_path(cli
, "\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
176 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
178 /* Note that the two following paths are identical but
179 give different NT status returns for chkpth and findfirst. */
181 printf("testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
182 status
= single_search(cli
, tctx
, "\\.\\\\\\\\\\\\.");
183 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRinvalidname
));
185 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
187 /* We expect this open to fail with the same error code as the chkpath below. */
188 printf("testing Open on %s\n", "\\.\\\\\\\\\\\\.");
189 /* findfirst seems to fail with a different error. */
190 fnum1
= smbcli_nt_create_full(cli
->tree
, "\\.\\\\\\\\\\\\.",
191 0, SEC_RIGHTS_FILE_ALL
,
192 FILE_ATTRIBUTE_NORMAL
,
193 NTCREATEX_SHARE_ACCESS_DELETE
|
194 NTCREATEX_SHARE_ACCESS_READ
|
195 NTCREATEX_SHARE_ACCESS_WRITE
,
196 NTCREATEX_DISP_OVERWRITE_IF
,
198 status
= smbcli_nt_error(cli
->tree
);
199 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
202 ret
&= test_path(cli
, "\\.\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
203 ret
&= test_path(cli
, "..\\..\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
204 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
205 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
206 ret
&= test_path(cli
, BASEDIR
"\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
207 ret
&= test_path(cli
, BASEDIR
"\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
208 ret
&= test_path(cli
, BASEDIR
"\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
209 ret
&= test_path(cli
, BASEDIR
"\\.\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
210 ret
&= test_path(cli
, BASEDIR
"\\nt", NT_STATUS_OK
, NT_STATUS_OK
);
211 ret
&= test_path(cli
, BASEDIR
".\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
212 ret
&= test_path(cli
, BASEDIR
"xx\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
213 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
214 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
215 ret
&= test_path(cli
, ".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
216 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
217 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
218 ret
&= test_path(cli
, BASEDIR
".", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
219 ret
&= test_path(cli
, "\\", NT_STATUS_OK
,NT_STATUS_OK
);
220 ret
&= test_path(cli
, "\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
221 ret
&= test_path(cli
, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
222 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
223 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
224 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\..", "\\", NT_STATUS_OK
,NT_STATUS_OK
);
225 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
226 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
228 /* We expect this open to fail with the same error code as the chkpath below. */
229 printf("testing Open on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
230 /* findfirst seems to fail with a different error. */
231 fnum1
= smbcli_nt_create_full(cli
->tree
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\",
232 0, SEC_RIGHTS_FILE_ALL
,
233 FILE_ATTRIBUTE_NORMAL
,
234 NTCREATEX_SHARE_ACCESS_DELETE
|
235 NTCREATEX_SHARE_ACCESS_READ
|
236 NTCREATEX_SHARE_ACCESS_WRITE
,
237 NTCREATEX_DISP_OVERWRITE_IF
,
239 status
= smbcli_nt_error(cli
->tree
);
240 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
242 printf("testing findfirst on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
243 status
= single_search(cli
, tctx
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
244 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
246 /* We expect this open to fail with the same error code as the chkpath below. */
247 /* findfirst seems to fail with a different error. */
248 printf("testing Open on %s\n", BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3");
249 fnum1
= smbcli_nt_create_full(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3",
250 0, SEC_RIGHTS_FILE_ALL
,
251 FILE_ATTRIBUTE_NORMAL
,
252 NTCREATEX_SHARE_ACCESS_DELETE
|
253 NTCREATEX_SHARE_ACCESS_READ
|
254 NTCREATEX_SHARE_ACCESS_WRITE
,
255 NTCREATEX_DISP_OVERWRITE_IF
,
257 status
= smbcli_nt_error(cli
->tree
);
258 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
260 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
261 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
262 ret
&= test_path(cli
, BASEDIR
"\\nt\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
263 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
264 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
267 smbcli_close(cli
->tree
, fnum
);
271 static bool test_chkpath_names(struct smbcli_state
*cli
, struct torture_context
*tctx
)
273 union smb_chkpath io
;
274 union smb_fileinfo finfo
;
280 * we don't test characters >= 0x80 yet,
281 * as somehow our client libraries can't do that
283 for (i
=0x01; i
<= 0x7F; i
++) {
285 * it's important that we test the last character
286 * because of the error code with ':' 0x3A
287 * and servers without stream support
289 char *path
= talloc_asprintf(tctx
, "%s\\File0x%02X%c",
292 NTSTATUS expected_dos1
;
293 NTSTATUS expected_dos2
;
295 expected
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
296 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
297 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRbadfile
);
309 torture_setting_bool(tctx
, "samba3", false)) {
310 /* samba 3 handles '/' as '\\' */
313 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
314 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
315 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
319 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
320 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
321 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
326 printf("Checking File0x%02X%c%s expected[%s|%s|%s]\n",
327 i
, isprint(i
)?(char)i
:' ',
328 isprint(i
)?"":"(not printable)",
330 nt_errstr(expected_dos1
),
331 nt_errstr(expected_dos2
));
333 io
.chkpath
.in
.path
= path
;
334 status
= smb_raw_chkpath(cli
->tree
, &io
);
335 CHECK_STATUS(status
, expected
, expected_dos1
);
338 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
339 finfo
.generic
.in
.file
.path
= path
;
340 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
341 CHECK_STATUS(status
, expected
, expected_dos2
);
351 basic testing of chkpath calls
353 bool torture_raw_chkpath(struct torture_context
*torture
,
354 struct smbcli_state
*cli
)
359 if (!torture_setup_dir(cli
, BASEDIR
)) {
363 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt"))) {
364 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
368 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S"))) {
369 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
373 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98"))) {
374 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
378 fnum
= create_complex_file(cli
, torture
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe");
380 printf("failed to open \\nt\\V S\\VB98\\vb6.exe - %s\n", smbcli_errstr(cli
->tree
));
385 ret
&= test_chkpath(cli
, torture
);
386 ret
&= test_chkpath_names(cli
, torture
);
390 smb_raw_exit(cli
->session
);
391 smbcli_deltree(cli
->tree
, BASEDIR
);