2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006-2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "lib/cmdline/popt_common.h"
23 #include "system/time.h"
24 #include "system/wait.h"
25 #include "system/filesys.h"
26 #include "system/readline.h"
27 #include "../libcli/smbreadline/smbreadline.h"
28 #include "libcli/libcli.h"
29 #include "lib/events/events.h"
31 #include "torture/smbtorture.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/gensec/gensec.h"
34 #include "param/param.h"
35 #include "lib/util/samba_modules.h"
37 #if HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
41 static char *prefix_name(TALLOC_CTX
*mem_ctx
, const char *prefix
, const char *name
)
44 return talloc_strdup(mem_ctx
, name
);
46 return talloc_asprintf(mem_ctx
, "%s.%s", prefix
, name
);
49 static void print_test_list(const struct torture_suite
*suite
, const char *prefix
, const char *expr
)
51 struct torture_suite
*o
;
52 struct torture_tcase
*t
;
53 struct torture_test
*p
;
55 for (o
= suite
->children
; o
; o
= o
->next
) {
56 char *name
= prefix_name(NULL
, prefix
, o
->name
);
57 print_test_list(o
, name
, expr
);
61 for (t
= suite
->testcases
; t
; t
= t
->next
) {
62 for (p
= t
->tests
; p
; p
= p
->next
) {
63 char *name
= talloc_asprintf(NULL
, "%s.%s.%s", prefix
, t
->name
, p
->name
);
64 if (strncmp(name
, expr
, strlen(expr
)) == 0) {
72 static bool run_matching(struct torture_context
*torture
,
75 const char **restricted
,
76 struct torture_suite
*suite
,
80 struct torture_suite
*o
;
81 struct torture_tcase
*t
;
82 struct torture_test
*p
;
84 for (o
= suite
->children
; o
; o
= o
->next
) {
86 name
= prefix_name(torture
, prefix
, o
->name
);
87 if (gen_fnmatch(expr
, name
) == 0) {
89 reload_charcnv(torture
->lp_ctx
);
90 if (restricted
!= NULL
)
91 ret
&= torture_run_suite_restricted(torture
, o
, restricted
);
93 ret
&= torture_run_suite(torture
, o
);
95 ret
&= run_matching(torture
, name
, expr
, restricted
, o
, matched
);
98 for (t
= suite
->testcases
; t
; t
= t
->next
) {
99 char *name
= talloc_asprintf(torture
, "%s.%s", prefix
, t
->name
);
100 if (gen_fnmatch(expr
, name
) == 0) {
102 reload_charcnv(torture
->lp_ctx
);
103 ret
&= torture_run_tcase_restricted(torture
, t
, restricted
);
105 for (p
= t
->tests
; p
; p
= p
->next
) {
106 name
= talloc_asprintf(torture
, "%s.%s.%s", prefix
, t
->name
, p
->name
);
107 if (gen_fnmatch(expr
, name
) == 0) {
109 reload_charcnv(torture
->lp_ctx
);
110 ret
&= torture_run_test_restricted(torture
, t
, p
, restricted
);
118 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
120 /****************************************************************************
121 run a specified test or "ALL"
122 ****************************************************************************/
123 bool torture_run_named_tests(struct torture_context
*torture
, const char *name
,
124 const char **restricted
)
127 bool matched
= false;
128 struct torture_suite
*o
;
130 torture_ui_report_time(torture
);
132 if (strequal(name
, "ALL")) {
133 if (restricted
!= NULL
) {
134 printf("--load-list and ALL are incompatible\n");
137 for (o
= torture_root
->children
; o
; o
= o
->next
) {
138 ret
&= torture_run_suite(torture
, o
);
143 ret
= run_matching(torture
, NULL
, name
, restricted
, torture_root
, &matched
);
146 printf("Unknown torture operation '%s'\n", name
);
153 bool torture_parse_target(struct loadparm_context
*lp_ctx
, const char *target
)
155 char *host
= NULL
, *share
= NULL
;
156 struct dcerpc_binding
*binding_struct
;
159 /* see if its a RPC transport specifier */
160 if (!smbcli_parse_unc(target
, NULL
, &host
, &share
)) {
161 status
= dcerpc_parse_binding(talloc_autofree_context(), target
, &binding_struct
);
162 if (NT_STATUS_IS_ERR(status
)) {
163 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target
);
166 lpcfg_set_cmdline(lp_ctx
, "torture:host", binding_struct
->host
);
167 if (lpcfg_parm_string(lp_ctx
, NULL
, "torture", "share") == NULL
)
168 lpcfg_set_cmdline(lp_ctx
, "torture:share", "IPC$");
169 lpcfg_set_cmdline(lp_ctx
, "torture:binding", target
);
171 lpcfg_set_cmdline(lp_ctx
, "torture:host", host
);
172 lpcfg_set_cmdline(lp_ctx
, "torture:share", share
);
173 lpcfg_set_cmdline(lp_ctx
, "torture:binding", host
);
179 static void parse_dns(struct loadparm_context
*lp_ctx
, const char *dns
)
181 char *userdn
, *basedn
, *secret
;
184 /* retrievieng the userdn */
185 p
= strchr_m(dns
, '#');
187 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_userdn", "");
188 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", "");
189 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
192 userdn
= strndup(dns
, p
- dns
);
193 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_userdn", userdn
);
195 /* retrieve the basedn */
197 p
= strchr_m(d
, '#');
199 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", "");
200 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
203 basedn
= strndup(d
, p
- d
);
204 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_basedn", basedn
);
206 /* retrieve the secret */
209 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", "");
213 lpcfg_set_cmdline(lp_ctx
, "torture:ldap_secret", secret
);
215 printf ("%s - %s - %s\n", userdn
, basedn
, secret
);
219 /* Print the full test list, formatted into separate labelled test
222 static void print_structured_testsuite_list(void)
224 struct torture_suite
*o
;
225 struct torture_suite
*s
;
226 struct torture_tcase
*t
;
229 if (torture_root
== NULL
) {
230 printf("NO TESTS LOADED\n");
234 for (o
= torture_root
->children
; o
; o
= o
->next
) {
235 printf("\n%s (%s):\n ", o
->description
, o
->name
);
238 for (s
= o
->children
; s
; s
= s
->next
) {
239 if (i
+ strlen(o
->name
) + strlen(s
->name
) >= (MAX_COLS
- 3)) {
243 i
+=printf("%s.%s ", o
->name
, s
->name
);
246 for (t
= o
->testcases
; t
; t
= t
->next
) {
247 if (i
+ strlen(o
->name
) + strlen(t
->name
) >= (MAX_COLS
- 3)) {
251 i
+=printf("%s.%s ", o
->name
, t
->name
);
257 printf("\nThe default test is ALL.\n");
260 static void print_testsuite_list(void)
262 struct torture_suite
*o
;
263 struct torture_suite
*s
;
264 struct torture_tcase
*t
;
266 if (torture_root
== NULL
)
269 for (o
= torture_root
->children
; o
; o
= o
->next
) {
270 for (s
= o
->children
; s
; s
= s
->next
) {
271 printf("%s.%s\n", o
->name
, s
->name
);
274 for (t
= o
->testcases
; t
; t
= t
->next
) {
275 printf("%s.%s\n", o
->name
, t
->name
);
280 void torture_print_testsuites(bool structured
)
283 print_structured_testsuite_list();
285 print_testsuite_list();
289 static void usage(poptContext pc
)
291 poptPrintUsage(pc
, stdout
, 0);
294 printf("The binding format is:\n\n");
296 printf(" TRANSPORT:host[flags]\n\n");
298 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
299 printf(" or ncalrpc for local connections.\n\n");
301 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
302 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
303 printf(" string.\n\n");
305 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
306 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
307 printf(" will be auto-determined.\n\n");
309 printf(" other recognised flags are:\n\n");
311 printf(" sign : enable ntlmssp signing\n");
312 printf(" seal : enable ntlmssp sealing\n");
313 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
314 printf(" validate: enable the NDR validator\n");
315 printf(" print: enable debugging of the packets\n");
316 printf(" bigendian: use bigendian RPC\n");
317 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
319 printf(" For example, these all connect to the samr pipe:\n\n");
321 printf(" ncacn_np:myserver\n");
322 printf(" ncacn_np:myserver[samr]\n");
323 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
324 printf(" ncacn_np:myserver[/pipe/samr]\n");
325 printf(" ncacn_np:myserver[samr,sign,print]\n");
326 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
327 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
328 printf(" ncacn_np:\n");
329 printf(" ncacn_np:[/pipe/samr]\n\n");
331 printf(" ncacn_ip_tcp:myserver\n");
332 printf(" ncacn_ip_tcp:myserver[1024]\n");
333 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
335 printf(" ncalrpc:\n\n");
337 printf("The UNC format is:\n\n");
339 printf(" //server/share\n\n");
341 printf("Tests are:");
343 print_structured_testsuite_list();
347 _NORETURN_
static void max_runtime_handler(int sig
)
349 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
353 struct timeval last_suite_started
;
355 static void simple_suite_start(struct torture_context
*ctx
,
356 struct torture_suite
*suite
)
358 last_suite_started
= timeval_current();
359 printf("Running %s\n", suite
->name
);
362 static void simple_suite_finish(struct torture_context
*ctx
,
363 struct torture_suite
*suite
)
366 printf("%s took %g secs\n\n", suite
->name
,
367 timeval_elapsed(&last_suite_started
));
370 static void simple_test_result(struct torture_context
*context
,
371 enum torture_result res
, const char *reason
)
376 printf("OK: %s\n", reason
);
379 printf("TEST %s FAILED! - %s\n", context
->active_test
->name
, reason
);
382 printf("ERROR IN TEST %s! - %s\n", context
->active_test
->name
, reason
);
385 printf("SKIP: %s - %s\n", context
->active_test
->name
, reason
);
390 static void simple_comment(struct torture_context
*test
,
393 printf("%s", comment
);
396 static void simple_warning(struct torture_context
*test
,
399 fprintf(stderr
, "WARNING: %s\n", comment
);
402 static void simple_progress(struct torture_context
*test
,
403 int offset
, enum torture_progress_whence whence
)
407 const static struct torture_ui_ops std_ui_ops
= {
408 .comment
= simple_comment
,
409 .warning
= simple_warning
,
410 .suite_start
= simple_suite_start
,
411 .suite_finish
= simple_suite_finish
,
412 .test_result
= simple_test_result
,
413 .progress
= simple_progress
,
416 /****************************************************************************
418 ****************************************************************************/
419 int main(int argc
,char *argv
[])
425 struct torture_context
*torture
;
426 struct torture_results
*results
;
427 const struct torture_ui_ops
*ui_ops
;
430 static const char *target
= "other";
433 static const char *ui_ops_name
= "subunit";
434 const char *basedir
= NULL
;
436 const char *extra_module
= NULL
;
437 static int list_tests
= 0, list_testsuites
= 0;
438 int num_extra_users
= 0;
439 char **restricted
= NULL
;
440 int num_restricted
= -1;
441 const char *load_list
= NULL
;
442 enum {OPT_LOADFILE
=1000,OPT_UNCLIST
,OPT_TIMELIMIT
,OPT_DNS
, OPT_LIST
,
443 OPT_DANGEROUS
,OPT_SMB_PORTS
,OPT_ASYNC
,OPT_NUMPROGS
,
446 struct poptOption long_options
[] = {
448 {"format", 0, POPT_ARG_STRING
, &ui_ops_name
, 0, "Output format (one of: simple, subunit)", NULL
},
449 {"smb-ports", 'p', POPT_ARG_STRING
, NULL
, OPT_SMB_PORTS
, "SMB ports", NULL
},
450 {"basedir", 0, POPT_ARG_STRING
, &basedir
, 0, "base directory", "BASEDIR" },
451 {"seed", 0, POPT_ARG_INT
, &torture_seed
, 0, "Seed to use for randomizer", NULL
},
452 {"num-progs", 0, POPT_ARG_INT
, NULL
, OPT_NUMPROGS
, "num progs", NULL
},
453 {"num-ops", 0, POPT_ARG_INT
, &torture_numops
, 0, "num ops", NULL
},
454 {"entries", 0, POPT_ARG_INT
, &torture_entries
, 0, "entries", NULL
},
455 {"loadfile", 0, POPT_ARG_STRING
, NULL
, OPT_LOADFILE
, "NBench load file to use", NULL
},
456 {"list-suites", 0, POPT_ARG_NONE
, &list_testsuites
, 0, "List available testsuites and exit", NULL
},
457 {"list", 0, POPT_ARG_NONE
, &list_tests
, 0, "List available tests in specified suites and exit", NULL
},
458 {"unclist", 0, POPT_ARG_STRING
, NULL
, OPT_UNCLIST
, "unclist", NULL
},
459 {"timelimit", 't', POPT_ARG_INT
, NULL
, OPT_TIMELIMIT
, "Set time limit (in seconds)", NULL
},
460 {"failures", 'f', POPT_ARG_INT
, &torture_failures
, 0, "failures", NULL
},
461 {"parse-dns", 'D', POPT_ARG_STRING
, NULL
, OPT_DNS
, "parse-dns", NULL
},
462 {"dangerous", 'X', POPT_ARG_NONE
, NULL
, OPT_DANGEROUS
,
463 "run dangerous tests (eg. wiping out password database)", NULL
},
464 {"load-module", 0, POPT_ARG_STRING
, &extra_module
, 0, "load tests from DSO file", "SOFILE"},
465 {"shell", 0, POPT_ARG_NONE
, &shell
, true, "Run shell", NULL
},
466 {"target", 'T', POPT_ARG_STRING
, &target
, 0, "samba3|samba4|other", NULL
},
467 {"async", 'a', POPT_ARG_NONE
, NULL
, OPT_ASYNC
,
468 "run async tests", NULL
},
469 {"num-async", 0, POPT_ARG_INT
, &torture_numasync
, 0,
470 "number of simultaneous async requests", NULL
},
471 {"maximum-runtime", 0, POPT_ARG_INT
, &max_runtime
, 0,
472 "set maximum time for smbtorture to live", "seconds"},
473 {"extra-user", 0, POPT_ARG_STRING
, NULL
, OPT_EXTRA_USER
,
474 "extra user credentials", NULL
},
475 {"load-list", 0, POPT_ARG_STRING
, &load_list
, 0,
476 "load a test id list from a text file", NULL
},
478 POPT_COMMON_CONNECTION
479 POPT_COMMON_CREDENTIALS
486 /* we are never interested in SIGPIPE */
487 BlockSignals(true, SIGPIPE
);
489 pc
= poptGetContext("smbtorture", argc
, (const char **) argv
, long_options
,
490 POPT_CONTEXT_KEEP_FIRST
);
492 poptSetOtherOptionHelp(pc
, "<binding>|<unc> TEST1 TEST2 ...");
494 while((opt
= poptGetNextOpt(pc
)) != -1) {
497 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:loadfile", poptGetOptArg(pc
));
500 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:unclist", poptGetOptArg(pc
));
503 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:timelimit", poptGetOptArg(pc
));
506 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:nprocs", poptGetOptArg(pc
));
509 parse_dns(cmdline_lp_ctx
, poptGetOptArg(pc
));
512 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:dangerous", "Yes");
515 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:async", "Yes");
518 lpcfg_set_cmdline(cmdline_lp_ctx
, "smb ports", poptGetOptArg(pc
));
522 char *option
= talloc_asprintf(NULL
, "torture:extra_user%u",
524 const char *value
= poptGetOptArg(pc
);
525 lpcfg_set_cmdline(cmdline_lp_ctx
, option
, value
);
531 printf("bad command line option %d\n", opt
);
537 if (load_list
!= NULL
) {
538 restricted
= file_lines_load(load_list
, &num_restricted
, 0,
539 talloc_autofree_context());
540 if (restricted
== NULL
) {
541 printf("Unable to read load list file '%s'\n", load_list
);
546 if (strcmp(target
, "samba3") == 0) {
547 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba3", "true");
548 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
549 } else if (strcmp(target
, "samba4") == 0) {
550 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4", "true");
551 } else if (strcmp(target
, "samba4-ntvfs") == 0) {
552 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4", "true");
553 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:samba4-ntvfs", "true");
554 } else if (strcmp(target
, "winxp") == 0) {
555 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:winxp", "true");
556 } else if (strcmp(target
, "w2k3") == 0) {
557 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:w2k3", "true");
558 } else if (strcmp(target
, "w2k8") == 0) {
559 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:w2k8", "true");
560 lpcfg_set_cmdline(cmdline_lp_ctx
,
561 "torture:invalid_lock_range_support", "false");
562 } else if (strcmp(target
, "win7") == 0) {
563 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:win7", "true");
564 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:cn_max_buffer_size",
566 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
567 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:rewind_support", "false");
569 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
570 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:search_ea_support", "false");
572 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:hide_on_access_denied",
574 } else if (strcmp(target
, "onefs") == 0) {
575 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:onefs", "true");
576 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:openx_deny_dos_support",
578 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:range_not_locked_on_file_close", "false");
579 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:sacl_support", "false");
580 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:ea_support", "false");
581 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:smbexit_pdu_support",
583 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:smblock_pdu_support",
585 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:2_step_break_to_none",
587 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:deny_dos_support", "false");
588 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:deny_fcb_support", "false");
589 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:read_support", "false");
590 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:writeclose_support", "false");
591 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:resume_key_support", "false");
592 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:rewind_support", "false");
593 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:raw_search_search", "false");
594 lpcfg_set_cmdline(cmdline_lp_ctx
, "torture:search_ea_size", "false");
598 /* this will only work if nobody else uses alarm(),
599 which means it won't work for some tests, but we
600 can't use the event context method we use for smbd
601 as so many tests create their own event
602 context. This will at least catch most cases. */
603 signal(SIGALRM
, max_runtime_handler
);
607 if (extra_module
!= NULL
) {
608 init_module_fn fn
= load_module(poptGetOptArg(pc
), false, NULL
);
611 d_printf("Unable to load module from %s\n", poptGetOptArg(pc
));
614 if (NT_STATUS_IS_ERR(status
)) {
615 d_printf("Error initializing module %s: %s\n",
616 poptGetOptArg(pc
), nt_errstr(status
));
623 if (list_testsuites
) {
624 print_testsuite_list();
628 argv_new
= discard_const_p(char *, poptGetArgs(pc
));
631 for (i
=0; i
<argc
; i
++) {
632 if (argv_new
[i
] == NULL
) {
640 print_test_list(torture_root
, NULL
, "");
642 for (i
=1;i
<argc_new
;i
++) {
643 print_test_list(torture_root
, NULL
, argv_new
[i
]);
649 if (torture_seed
== 0) {
650 torture_seed
= time(NULL
);
652 printf("Using seed %d\n", torture_seed
);
653 srandom(torture_seed
);
655 if (!strcmp(ui_ops_name
, "simple")) {
656 ui_ops
= &std_ui_ops
;
657 } else if (!strcmp(ui_ops_name
, "subunit")) {
658 ui_ops
= &torture_subunit_ui_ops
;
660 printf("Unknown output format '%s'\n", ui_ops_name
);
664 results
= torture_results_init(talloc_autofree_context(), ui_ops
);
666 torture
= torture_context_init(s4_event_context_init(talloc_autofree_context()),
668 if (basedir
!= NULL
) {
669 if (basedir
[0] != '/') {
670 fprintf(stderr
, "Please specify an absolute path to --basedir\n");
673 outputdir
= talloc_asprintf(torture
, "%s/smbtortureXXXXXX", basedir
);
675 char *pwd
= talloc_size(torture
, PATH_MAX
);
676 if (!getcwd(pwd
, PATH_MAX
)) {
677 fprintf(stderr
, "Unable to determine current working directory\n");
680 outputdir
= talloc_asprintf(torture
, "%s/smbtortureXXXXXX", pwd
);
683 fprintf(stderr
, "Could not allocate per-run output dir\n");
686 torture
->outputdir
= mkdtemp(outputdir
);
687 if (!torture
->outputdir
) {
688 perror("Failed to make temp output dir");
691 torture
->lp_ctx
= cmdline_lp_ctx
;
696 /* In shell mode, just ignore any remaining test names. */
697 torture_shell(torture
);
700 /* At this point, we should just have a target string,
701 * followed by a series of test names. Unless we are in
702 * shell mode, in which case we don't need anythig more.
706 printf("You must specify a test to run, or 'ALL'\n");
708 torture
->results
->returncode
= 1;
709 } else if (!torture_parse_target(cmdline_lp_ctx
, argv_new
[1])) {
710 /* Take the target name or binding. */
712 torture
->results
->returncode
= 1;
714 for (i
=2;i
<argc_new
;i
++) {
715 if (!torture_run_named_tests(torture
, argv_new
[i
],
716 (const char **)restricted
)) {
723 /* Now delete the temp dir we created */
724 torture_deltree_outputdir(torture
);
726 if (torture
->results
->returncode
&& correct
) {