tools/nolibc: reformat list of headers to be installed
[linux-block.git] / tools / testing / selftests / nolibc / nolibc-test.c
CommitLineData
fddc8f81 1/* SPDX-License-Identifier: GPL-2.0 */
362aecb2 2
1da02f51
WT
3#define _GNU_SOURCE
4
362aecb2
WT
5/* platform-specific include files coming from the compiler */
6#include <limits.h>
7
8/* libc-specific include files
1da02f51 9 * The program may be built in 3 ways:
362aecb2 10 * $(CC) -nostdlib -include /path/to/nolibc.h => NOLIBC already defined
1da02f51
WT
11 * $(CC) -nostdlib -I/path/to/nolibc/sysroot => _NOLIBC_* guards are present
12 * $(CC) with default libc => NOLIBC* never defined
362aecb2
WT
13 */
14#ifndef NOLIBC
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
1da02f51
WT
18#ifndef _NOLIBC_STDIO_H
19/* standard libcs need more includes */
20#include <linux/reboot.h>
21#include <sys/io.h>
22#include <sys/ioctl.h>
69f2cd9f 23#include <sys/mman.h>
1da02f51
WT
24#include <sys/mount.h>
25#include <sys/reboot.h>
26#include <sys/stat.h>
27#include <sys/syscall.h>
28#include <sys/sysmacros.h>
29#include <sys/time.h>
30#include <sys/wait.h>
31#include <dirent.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <poll.h>
35#include <sched.h>
36#include <signal.h>
37#include <stdarg.h>
2df07fc5
WT
38#include <stddef.h>
39#include <stdint.h>
1da02f51
WT
40#include <unistd.h>
41#endif
362aecb2
WT
42#endif
43
44/* will be used by nolibc by getenv() */
45char **environ;
46
23da7bc9
WT
47/* definition of a series of tests */
48struct test {
fddc8f81
TW
49 const char *name; /* test name */
50 int (*func)(int min, int max); /* handler */
23da7bc9
WT
51};
52
1da02f51
WT
53#ifndef _NOLIBC_STDLIB_H
54char *itoa(int i)
55{
56 static char buf[12];
57 int ret;
58
59 ret = snprintf(buf, sizeof(buf), "%d", i);
60 return (ret >= 0 && ret < sizeof(buf)) ? buf : "#err";
61}
62#endif
63
362aecb2
WT
64#define CASE_ERR(err) \
65 case err: return #err
66
67/* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0,
68 * or the decimal value for less common ones.
69 */
70const char *errorname(int err)
71{
72 switch (err) {
73 case 0: return "SUCCESS";
74 CASE_ERR(EPERM);
75 CASE_ERR(ENOENT);
76 CASE_ERR(ESRCH);
77 CASE_ERR(EINTR);
78 CASE_ERR(EIO);
79 CASE_ERR(ENXIO);
80 CASE_ERR(E2BIG);
81 CASE_ERR(ENOEXEC);
82 CASE_ERR(EBADF);
83 CASE_ERR(ECHILD);
84 CASE_ERR(EAGAIN);
85 CASE_ERR(ENOMEM);
86 CASE_ERR(EACCES);
87 CASE_ERR(EFAULT);
88 CASE_ERR(ENOTBLK);
89 CASE_ERR(EBUSY);
90 CASE_ERR(EEXIST);
91 CASE_ERR(EXDEV);
92 CASE_ERR(ENODEV);
93 CASE_ERR(ENOTDIR);
94 CASE_ERR(EISDIR);
95 CASE_ERR(EINVAL);
96 CASE_ERR(ENFILE);
97 CASE_ERR(EMFILE);
98 CASE_ERR(ENOTTY);
99 CASE_ERR(ETXTBSY);
100 CASE_ERR(EFBIG);
101 CASE_ERR(ENOSPC);
102 CASE_ERR(ESPIPE);
103 CASE_ERR(EROFS);
104 CASE_ERR(EMLINK);
105 CASE_ERR(EPIPE);
106 CASE_ERR(EDOM);
107 CASE_ERR(ERANGE);
108 CASE_ERR(ENOSYS);
109 default:
110 return itoa(err);
111 }
112}
113
443de903
TW
114static void putcharn(char c, size_t n)
115{
116 char buf[64];
117
118 memset(buf, c, n);
119 buf[n] = '\0';
120 fputs(buf, stdout);
121}
122
362aecb2
WT
123static int pad_spc(int llen, int cnt, const char *fmt, ...)
124{
125 va_list args;
362aecb2
WT
126 int ret;
127
443de903 128 putcharn(' ', cnt - llen);
362aecb2
WT
129
130 va_start(args, fmt);
131 ret = vfprintf(stdout, fmt, args);
132 va_end(args);
443de903 133 return ret < 0 ? ret : ret + cnt - llen;
362aecb2
WT
134}
135
136/* The tests below are intended to be used by the macroes, which evaluate
137 * expression <expr>, print the status to stdout, and update the "ret"
138 * variable to count failures. The functions themselves return the number
139 * of failures, thus either 0 or 1.
140 */
141
142#define EXPECT_ZR(cond, expr) \
a0994fb9 143 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0)
362aecb2
WT
144
145static int expect_zr(int expr, int llen)
146{
147 int ret = !(expr == 0);
148
149 llen += printf(" = %d ", expr);
a0994fb9 150 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
151 return ret;
152}
153
154
155#define EXPECT_NZ(cond, expr, val) \
a0994fb9 156 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0)
362aecb2
WT
157
158static int expect_nz(int expr, int llen)
159{
160 int ret = !(expr != 0);
161
162 llen += printf(" = %d ", expr);
a0994fb9 163 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
164 return ret;
165}
166
167
168#define EXPECT_EQ(cond, expr, val) \
a0994fb9 169 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0)
362aecb2 170
a0994fb9 171static int expect_eq(uint64_t expr, int llen, uint64_t val)
362aecb2
WT
172{
173 int ret = !(expr == val);
174
a0994fb9
VD
175 llen += printf(" = %lld ", expr);
176 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
177 return ret;
178}
179
180
181#define EXPECT_NE(cond, expr, val) \
a0994fb9 182 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0)
362aecb2
WT
183
184static int expect_ne(int expr, int llen, int val)
185{
186 int ret = !(expr != val);
187
188 llen += printf(" = %d ", expr);
a0994fb9 189 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
190 return ret;
191}
192
193
194#define EXPECT_GE(cond, expr, val) \
a0994fb9 195 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0)
362aecb2
WT
196
197static int expect_ge(int expr, int llen, int val)
198{
199 int ret = !(expr >= val);
200
201 llen += printf(" = %d ", expr);
a0994fb9 202 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
203 return ret;
204}
205
206
207#define EXPECT_GT(cond, expr, val) \
a0994fb9 208 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0)
362aecb2
WT
209
210static int expect_gt(int expr, int llen, int val)
211{
212 int ret = !(expr > val);
213
214 llen += printf(" = %d ", expr);
a0994fb9 215 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
216 return ret;
217}
218
219
220#define EXPECT_LE(cond, expr, val) \
a0994fb9 221 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0)
362aecb2
WT
222
223static int expect_le(int expr, int llen, int val)
224{
225 int ret = !(expr <= val);
226
227 llen += printf(" = %d ", expr);
a0994fb9 228 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
229 return ret;
230}
231
232
233#define EXPECT_LT(cond, expr, val) \
a0994fb9 234 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0)
362aecb2
WT
235
236static int expect_lt(int expr, int llen, int val)
237{
238 int ret = !(expr < val);
239
240 llen += printf(" = %d ", expr);
a0994fb9 241 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
362aecb2
WT
242 return ret;
243}
244
245
246#define EXPECT_SYSZR(cond, expr) \
a0994fb9 247 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
362aecb2
WT
248
249static int expect_syszr(int expr, int llen)
250{
251 int ret = 0;
252
253 if (expr) {
254 ret = 1;
255 llen += printf(" = %d %s ", expr, errorname(errno));
a0994fb9 256 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2
WT
257 } else {
258 llen += printf(" = %d ", expr);
a0994fb9 259 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
260 }
261 return ret;
262}
263
264
265#define EXPECT_SYSEQ(cond, expr, val) \
a0994fb9 266 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0)
362aecb2
WT
267
268static int expect_syseq(int expr, int llen, int val)
269{
270 int ret = 0;
271
272 if (expr != val) {
273 ret = 1;
274 llen += printf(" = %d %s ", expr, errorname(errno));
a0994fb9 275 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2
WT
276 } else {
277 llen += printf(" = %d ", expr);
a0994fb9 278 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
279 }
280 return ret;
281}
282
283
284#define EXPECT_SYSNE(cond, expr, val) \
a0994fb9 285 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0)
362aecb2
WT
286
287static int expect_sysne(int expr, int llen, int val)
288{
289 int ret = 0;
290
291 if (expr == val) {
292 ret = 1;
293 llen += printf(" = %d %s ", expr, errorname(errno));
a0994fb9 294 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2
WT
295 } else {
296 llen += printf(" = %d ", expr);
a0994fb9 297 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
298 }
299 return ret;
300}
301
302
303#define EXPECT_SYSER(cond, expr, expret, experr) \
a0994fb9 304 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0)
362aecb2
WT
305
306static int expect_syserr(int expr, int expret, int experr, int llen)
307{
308 int ret = 0;
309 int _errno = errno;
310
311 llen += printf(" = %d %s ", expr, errorname(_errno));
312 if (expr != expret || _errno != experr) {
313 ret = 1;
314 llen += printf(" != (%d %s) ", expret, errorname(experr));
a0994fb9 315 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 316 } else {
a0994fb9 317 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
318 }
319 return ret;
320}
321
322
323#define EXPECT_PTRZR(cond, expr) \
a0994fb9 324 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0)
362aecb2
WT
325
326static int expect_ptrzr(const void *expr, int llen)
327{
328 int ret = 0;
329
330 llen += printf(" = <%p> ", expr);
331 if (expr) {
332 ret = 1;
a0994fb9 333 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 334 } else {
a0994fb9 335 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
336 }
337 return ret;
338}
339
340
341#define EXPECT_PTRNZ(cond, expr) \
a0994fb9 342 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0)
362aecb2
WT
343
344static int expect_ptrnz(const void *expr, int llen)
345{
346 int ret = 0;
347
348 llen += printf(" = <%p> ", expr);
349 if (!expr) {
350 ret = 1;
a0994fb9 351 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 352 } else {
a0994fb9 353 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
354 }
355 return ret;
356}
357
358
359#define EXPECT_STRZR(cond, expr) \
a0994fb9 360 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0)
362aecb2
WT
361
362static int expect_strzr(const char *expr, int llen)
363{
364 int ret = 0;
365
366 llen += printf(" = <%s> ", expr);
367 if (expr) {
368 ret = 1;
a0994fb9 369 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 370 } else {
a0994fb9 371 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
372 }
373 return ret;
374}
375
376
377#define EXPECT_STRNZ(cond, expr) \
a0994fb9 378 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0)
362aecb2
WT
379
380static int expect_strnz(const char *expr, int llen)
381{
382 int ret = 0;
383
384 llen += printf(" = <%s> ", expr);
385 if (!expr) {
386 ret = 1;
a0994fb9 387 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 388 } else {
a0994fb9 389 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
390 }
391 return ret;
392}
393
394
395#define EXPECT_STREQ(cond, expr, cmp) \
a0994fb9 396 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0)
362aecb2
WT
397
398static int expect_streq(const char *expr, int llen, const char *cmp)
399{
400 int ret = 0;
401
402 llen += printf(" = <%s> ", expr);
403 if (strcmp(expr, cmp) != 0) {
404 ret = 1;
a0994fb9 405 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 406 } else {
a0994fb9 407 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
408 }
409 return ret;
410}
411
412
413#define EXPECT_STRNE(cond, expr, cmp) \
a0994fb9 414 do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0)
362aecb2
WT
415
416static int expect_strne(const char *expr, int llen, const char *cmp)
417{
418 int ret = 0;
419
420 llen += printf(" = <%s> ", expr);
421 if (strcmp(expr, cmp) == 0) {
422 ret = 1;
a0994fb9 423 llen += pad_spc(llen, 64, "[FAIL]\n");
362aecb2 424 } else {
a0994fb9 425 llen += pad_spc(llen, 64, " [OK]\n");
362aecb2
WT
426 }
427 return ret;
428}
429
23da7bc9 430
362aecb2
WT
431/* declare tests based on line numbers. There must be exactly one test per line. */
432#define CASE_TEST(name) \
433 case __LINE__: llen += printf("%d %s", test, #name);
434
435
b4844fa0
WT
436/* used by some syscall tests below */
437int test_getdents64(const char *dir)
438{
439 char buffer[4096];
440 int fd, ret;
441 int err;
442
443 ret = fd = open(dir, O_RDONLY | O_DIRECTORY, 0);
444 if (ret < 0)
445 return ret;
446
447 ret = getdents64(fd, (void *)buffer, sizeof(buffer));
448 err = errno;
449 close(fd);
450
451 errno = err;
452 return ret;
453}
454
a290296a
AF
455static int test_getpagesize(void)
456{
457 long x = getpagesize();
458 int c;
459
460 if (x < 0)
461 return x;
462
463#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
464 /*
465 * x86 family is always 4K page.
466 */
467 c = (x == 4096);
468#elif defined(__aarch64__)
469 /*
470 * Linux aarch64 supports three values of page size: 4K, 16K, and 64K
471 * which are selected at kernel compilation time.
472 */
473 c = (x == 4096 || x == (16 * 1024) || x == (64 * 1024));
474#else
475 /*
476 * Assuming other architectures must have at least 4K page.
477 */
478 c = (x >= 4096);
479#endif
480
481 return !c;
482}
483
3ad09d72
TW
484static int test_fork(void)
485{
486 int status;
487 pid_t pid = fork();
488
489 switch (pid) {
490 case -1:
491 return 1;
492
493 case 0:
494 exit(123);
495
496 default:
497 pid = waitpid(pid, &status, 0);
498
499 return pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 123;
500 }
501}
502
b4844fa0
WT
503/* Run syscall tests between IDs <min> and <max>.
504 * Return 0 on success, non-zero on failure.
505 */
506int run_syscall(int min, int max)
507{
508 struct stat stat_buf;
3e2d337b 509 int euid0;
7172f1c6 510 int proc;
b4844fa0
WT
511 int test;
512 int tmp;
513 int ret = 0;
514 void *p1, *p2;
515
7172f1c6
WT
516 /* <proc> indicates whether or not /proc is mounted */
517 proc = stat("/proc", &stat_buf) == 0;
518
3e2d337b
WT
519 /* this will be used to skip certain tests that can't be run unprivileged */
520 euid0 = geteuid() == 0;
521
b4844fa0 522 for (test = min; test >= 0 && test <= max; test++) {
fddc8f81 523 int llen = 0; /* line length */
b4844fa0
WT
524
525 /* avoid leaving empty lines below, this will insert holes into
526 * test numbers.
527 */
528 switch (test + __LINE__ + 1) {
529 CASE_TEST(getpid); EXPECT_SYSNE(1, getpid(), -1); break;
530 CASE_TEST(getppid); EXPECT_SYSNE(1, getppid(), -1); break;
1da02f51 531#ifdef NOLIBC
b4844fa0 532 CASE_TEST(gettid); EXPECT_SYSNE(1, gettid(), -1); break;
1da02f51 533#endif
b4844fa0
WT
534 CASE_TEST(getpgid_self); EXPECT_SYSNE(1, getpgid(0), -1); break;
535 CASE_TEST(getpgid_bad); EXPECT_SYSER(1, getpgid(-1), -1, ESRCH); break;
536 CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break;
537 CASE_TEST(kill_CONT); EXPECT_SYSZR(1, kill(getpid(), 0)); break;
538 CASE_TEST(kill_BADPID); EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break;
539 CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break;
540 CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break;
541 CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); break;
542 CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir(".")); break;
543 CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break;
7172f1c6
WT
544 CASE_TEST(chmod_net); EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break;
545 CASE_TEST(chmod_self); EXPECT_SYSER(proc, chmod("/proc/self", 0555), -1, EPERM); break;
546 CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break;
3e2d337b 547 CASE_TEST(chroot_root); EXPECT_SYSZR(euid0, chroot("/")); break;
b4844fa0 548 CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break;
7172f1c6 549 CASE_TEST(chroot_exe); EXPECT_SYSER(proc, chroot("/proc/self/exe"), -1, ENOTDIR); break;
b4844fa0
WT
550 CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break;
551 CASE_TEST(close_dup); EXPECT_SYSZR(1, close(dup(0))); break;
552 CASE_TEST(dup_0); tmp = dup(0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
553 CASE_TEST(dup_m1); tmp = dup(-1); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
554 CASE_TEST(dup2_0); tmp = dup2(0, 100); EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
555 CASE_TEST(dup2_m1); tmp = dup2(-1, 100); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
556 CASE_TEST(dup3_0); tmp = dup3(0, 100, 0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
557 CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
558 CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break;
3ad09d72 559 CASE_TEST(fork); EXPECT_SYSZR(1, test_fork()); break;
b4844fa0
WT
560 CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break;
561 CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break;
562 CASE_TEST(gettimeofday_null); EXPECT_SYSZR(1, gettimeofday(NULL, NULL)); break;
1da02f51 563#ifdef NOLIBC
b4844fa0
WT
564 CASE_TEST(gettimeofday_bad1); EXPECT_SYSER(1, gettimeofday((void *)1, NULL), -1, EFAULT); break;
565 CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break;
566 CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break;
1da02f51 567#endif
a290296a 568 CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break;
b4844fa0
WT
569 CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
570 CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
571 CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break;
572 CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break;
3e2d337b 573 CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break;
7172f1c6 574 CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/net", "/blah"), -1, EXDEV); break;
b4844fa0
WT
575 CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break;
576 CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break;
577 CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break;
578 CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break;
579 CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break;
580 CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break;
581 CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break;
582 CASE_TEST(poll_fault); EXPECT_SYSER(1, poll((void *)1, 1, 0), -1, EFAULT); break;
583 CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break;
584 CASE_TEST(sched_yield); EXPECT_SYSZR(1, sched_yield()); break;
585 CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break;
586 CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break;
587 CASE_TEST(select_fault); EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break;
588 CASE_TEST(stat_blah); EXPECT_SYSER(1, stat("/proc/self/blah", &stat_buf), -1, ENOENT); break;
589 CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break;
590 CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break;
591 CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break;
592 CASE_TEST(unlink_blah); EXPECT_SYSER(1, unlink("/proc/self/blah"), -1, ENOENT); break;
593 CASE_TEST(wait_child); EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break;
594 CASE_TEST(waitpid_min); EXPECT_SYSER(1, waitpid(INT_MIN, &tmp, WNOHANG), -1, ESRCH); break;
595 CASE_TEST(waitpid_child); EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break;
596 CASE_TEST(write_badf); EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break;
597 CASE_TEST(write_zero); EXPECT_SYSZR(1, write(1, &tmp, 0)); break;
53fcfafa 598 CASE_TEST(syscall_noargs); EXPECT_SYSEQ(1, syscall(__NR_getpid), getpid()); break;
ec8e1b73 599 CASE_TEST(syscall_args); EXPECT_SYSER(1, syscall(__NR_statx, 0, NULL, 0, 0, NULL), -1, EFAULT); break;
b4844fa0
WT
600 case __LINE__:
601 return ret; /* must be last */
602 /* note: do not set any defaults so as to permit holes above */
603 }
604 }
605 return ret;
606}
607
95bc9894
WT
608int run_stdlib(int min, int max)
609{
610 int test;
611 int tmp;
612 int ret = 0;
613 void *p1, *p2;
614
615 for (test = min; test >= 0 && test <= max; test++) {
fddc8f81 616 int llen = 0; /* line length */
95bc9894
WT
617
618 /* avoid leaving empty lines below, this will insert holes into
619 * test numbers.
620 */
621 switch (test + __LINE__ + 1) {
622 CASE_TEST(getenv_TERM); EXPECT_STRNZ(1, getenv("TERM")); break;
623 CASE_TEST(getenv_blah); EXPECT_STRZR(1, getenv("blah")); break;
624 CASE_TEST(setcmp_blah_blah); EXPECT_EQ(1, strcmp("blah", "blah"), 0); break;
625 CASE_TEST(setcmp_blah_blah2); EXPECT_NE(1, strcmp("blah", "blah2"), 0); break;
626 CASE_TEST(setncmp_blah_blah); EXPECT_EQ(1, strncmp("blah", "blah", 10), 0); break;
627 CASE_TEST(setncmp_blah_blah4); EXPECT_EQ(1, strncmp("blah", "blah4", 4), 0); break;
628 CASE_TEST(setncmp_blah_blah5); EXPECT_NE(1, strncmp("blah", "blah5", 5), 0); break;
629 CASE_TEST(setncmp_blah_blah6); EXPECT_NE(1, strncmp("blah", "blah6", 6), 0); break;
630 CASE_TEST(strchr_foobar_o); EXPECT_STREQ(1, strchr("foobar", 'o'), "oobar"); break;
631 CASE_TEST(strchr_foobar_z); EXPECT_STRZR(1, strchr("foobar", 'z')); break;
632 CASE_TEST(strrchr_foobar_o); EXPECT_STREQ(1, strrchr("foobar", 'o'), "obar"); break;
633 CASE_TEST(strrchr_foobar_z); EXPECT_STRZR(1, strrchr("foobar", 'z')); break;
c80b5a0a
WT
634 CASE_TEST(memcmp_20_20); EXPECT_EQ(1, memcmp("aaa\x20", "aaa\x20", 4), 0); break;
635 CASE_TEST(memcmp_20_60); EXPECT_LT(1, memcmp("aaa\x20", "aaa\x60", 4), 0); break;
636 CASE_TEST(memcmp_60_20); EXPECT_GT(1, memcmp("aaa\x60", "aaa\x20", 4), 0); break;
637 CASE_TEST(memcmp_20_e0); EXPECT_LT(1, memcmp("aaa\x20", "aaa\xe0", 4), 0); break;
638 CASE_TEST(memcmp_e0_20); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x20", 4), 0); break;
639 CASE_TEST(memcmp_80_e0); EXPECT_LT(1, memcmp("aaa\x80", "aaa\xe0", 4), 0); break;
640 CASE_TEST(memcmp_e0_80); EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x80", 4), 0); break;
d1209597
VD
641 CASE_TEST(limit_int8_max); EXPECT_EQ(1, INT8_MAX, (int8_t) 0x7f); break;
642 CASE_TEST(limit_int8_min); EXPECT_EQ(1, INT8_MIN, (int8_t) 0x80); break;
643 CASE_TEST(limit_uint8_max); EXPECT_EQ(1, UINT8_MAX, (uint8_t) 0xff); break;
644 CASE_TEST(limit_int16_max); EXPECT_EQ(1, INT16_MAX, (int16_t) 0x7fff); break;
645 CASE_TEST(limit_int16_min); EXPECT_EQ(1, INT16_MIN, (int16_t) 0x8000); break;
646 CASE_TEST(limit_uint16_max); EXPECT_EQ(1, UINT16_MAX, (uint16_t) 0xffff); break;
647 CASE_TEST(limit_int32_max); EXPECT_EQ(1, INT32_MAX, (int32_t) 0x7fffffff); break;
648 CASE_TEST(limit_int32_min); EXPECT_EQ(1, INT32_MIN, (int32_t) 0x80000000); break;
649 CASE_TEST(limit_uint32_max); EXPECT_EQ(1, UINT32_MAX, (uint32_t) 0xffffffff); break;
650 CASE_TEST(limit_int64_max); EXPECT_EQ(1, INT64_MAX, (int64_t) 0x7fffffffffffffff); break;
651 CASE_TEST(limit_int64_min); EXPECT_EQ(1, INT64_MIN, (int64_t) 0x8000000000000000); break;
652 CASE_TEST(limit_uint64_max); EXPECT_EQ(1, UINT64_MAX, (uint64_t) 0xffffffffffffffff); break;
653 CASE_TEST(limit_int_least8_max); EXPECT_EQ(1, INT_LEAST8_MAX, (int_least8_t) 0x7f); break;
654 CASE_TEST(limit_int_least8_min); EXPECT_EQ(1, INT_LEAST8_MIN, (int_least8_t) 0x80); break;
655 CASE_TEST(limit_uint_least8_max); EXPECT_EQ(1, UINT_LEAST8_MAX, (uint_least8_t) 0xff); break;
656 CASE_TEST(limit_int_least16_max); EXPECT_EQ(1, INT_LEAST16_MAX, (int_least16_t) 0x7fff); break;
657 CASE_TEST(limit_int_least16_min); EXPECT_EQ(1, INT_LEAST16_MIN, (int_least16_t) 0x8000); break;
658 CASE_TEST(limit_uint_least16_max); EXPECT_EQ(1, UINT_LEAST16_MAX, (uint_least16_t) 0xffff); break;
659 CASE_TEST(limit_int_least32_max); EXPECT_EQ(1, INT_LEAST32_MAX, (int_least32_t) 0x7fffffff); break;
660 CASE_TEST(limit_int_least32_min); EXPECT_EQ(1, INT_LEAST32_MIN, (int_least32_t) 0x80000000); break;
661 CASE_TEST(limit_uint_least32_max); EXPECT_EQ(1, UINT_LEAST32_MAX, (uint_least32_t) 0xffffffffU); break;
662 CASE_TEST(limit_int_least64_min); EXPECT_EQ(1, INT_LEAST64_MIN, (int_least64_t) 0x8000000000000000LL); break;
663 CASE_TEST(limit_int_least64_max); EXPECT_EQ(1, INT_LEAST64_MAX, (int_least64_t) 0x7fffffffffffffffLL); break;
664 CASE_TEST(limit_uint_least64_max); EXPECT_EQ(1, UINT_LEAST64_MAX, (uint_least64_t) 0xffffffffffffffffULL); break;
665 CASE_TEST(limit_int_fast8_max); EXPECT_EQ(1, INT_FAST8_MAX, (int_fast8_t) 0x7f); break;
666 CASE_TEST(limit_int_fast8_min); EXPECT_EQ(1, INT_FAST8_MIN, (int_fast8_t) 0x80); break;
667 CASE_TEST(limit_uint_fast8_max); EXPECT_EQ(1, UINT_FAST8_MAX, (uint_fast8_t) 0xff); break;
668 CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) INTPTR_MIN); break;
669 CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) INTPTR_MAX); break;
670 CASE_TEST(limit_uint_fast16_max); EXPECT_EQ(1, UINT_FAST16_MAX, (uint_fast16_t) UINTPTR_MAX); break;
671 CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) INTPTR_MIN); break;
672 CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) INTPTR_MAX); break;
673 CASE_TEST(limit_uint_fast32_max); EXPECT_EQ(1, UINT_FAST32_MAX, (uint_fast32_t) UINTPTR_MAX); break;
674 CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INTPTR_MIN); break;
675 CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INTPTR_MAX); break;
676 CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINTPTR_MAX); break;
677#if __SIZEOF_LONG__ == 8
678 CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break;
679 CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break;
680 CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break;
681 CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break;
682 CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break;
683 CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break;
684#elif __SIZEOF_LONG__ == 4
685 CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x80000000); break;
686 CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffff); break;
687 CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break;
688 CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break;
689 CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break;
690 CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffU); break;
691#else
692# warning "__SIZEOF_LONG__ is undefined"
693#endif /* __SIZEOF_LONG__ */
95bc9894
WT
694 case __LINE__:
695 return ret; /* must be last */
696 /* note: do not set any defaults so as to permit holes above */
697 }
698 }
699 return ret;
700}
701
69f2cd9f
TW
702#define EXPECT_VFPRINTF(c, expected, fmt, ...) \
703 ret += expect_vfprintf(llen, c, expected, fmt, ##__VA_ARGS__)
704
705static int expect_vfprintf(int llen, size_t c, const char *expected, const char *fmt, ...)
706{
707 int ret, fd, w, r;
708 char buf[100];
709 FILE *memfile;
710 va_list args;
711
712 fd = memfd_create("vfprintf", 0);
713 if (fd == -1) {
714 pad_spc(llen, 64, "[FAIL]\n");
715 return 1;
716 }
717
718 memfile = fdopen(fd, "w+");
719 if (!memfile) {
720 pad_spc(llen, 64, "[FAIL]\n");
721 return 1;
722 }
723
724 va_start(args, fmt);
725 w = vfprintf(memfile, fmt, args);
726 va_end(args);
727
728 if (w != c) {
729 llen += printf(" written(%d) != %d", w, (int) c);
730 pad_spc(llen, 64, "[FAIL]\n");
731 return 1;
732 }
733
734 fflush(memfile);
735 lseek(fd, 0, SEEK_SET);
736
737 r = read(fd, buf, sizeof(buf) - 1);
738 buf[r] = '\0';
739
740 fclose(memfile);
741
742 if (r != w) {
743 llen += printf(" written(%d) != read(%d)", w, r);
744 pad_spc(llen, 64, "[FAIL]\n");
745 return 1;
746 }
747
748 llen += printf(" \"%s\" = \"%s\"", expected, buf);
749 ret = strncmp(expected, buf, c);
750
751 pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
752 return ret;
753}
754
755static int run_vfprintf(int min, int max)
756{
757 int test;
758 int tmp;
759 int ret = 0;
760 void *p1, *p2;
761
762 for (test = min; test >= 0 && test <= max; test++) {
fddc8f81 763 int llen = 0; /* line length */
69f2cd9f
TW
764
765 /* avoid leaving empty lines below, this will insert holes into
766 * test numbers.
767 */
768 switch (test + __LINE__ + 1) {
769 CASE_TEST(empty); EXPECT_VFPRINTF(0, "", ""); break;
770 CASE_TEST(simple); EXPECT_VFPRINTF(3, "foo", "foo"); break;
771 CASE_TEST(string); EXPECT_VFPRINTF(3, "foo", "%s", "foo"); break;
772 CASE_TEST(number); EXPECT_VFPRINTF(4, "1234", "%d", 1234); break;
773 CASE_TEST(negnumber); EXPECT_VFPRINTF(5, "-1234", "%d", -1234); break;
774 CASE_TEST(unsigned); EXPECT_VFPRINTF(5, "12345", "%u", 12345); break;
775 CASE_TEST(char); EXPECT_VFPRINTF(1, "c", "%c", 'c'); break;
776 CASE_TEST(hex); EXPECT_VFPRINTF(1, "f", "%x", 0xf); break;
777 CASE_TEST(pointer); EXPECT_VFPRINTF(3, "0x1", "%p", (void *) 0x1); break;
778 case __LINE__:
779 return ret; /* must be last */
780 /* note: do not set any defaults so as to permit holes above */
781 }
782 }
783 return ret;
784}
785
97357168
TW
786static int smash_stack(void)
787{
788 char buf[100];
e7654c3f 789 volatile char *ptr = buf;
aa662d12 790 size_t i;
97357168 791
aa662d12 792 for (i = 0; i < 200; i++)
e7654c3f 793 ptr[i] = 'P';
97357168
TW
794
795 return 1;
796}
797
798static int run_protection(int min, int max)
799{
800 pid_t pid;
801 int llen = 0, status;
802
803 llen += printf("0 -fstackprotector ");
804
805#if !defined(NOLIBC_STACKPROTECTOR)
806 llen += printf("not supported");
807 pad_spc(llen, 64, "[SKIPPED]\n");
808 return 0;
809#endif
810
85250921
TW
811#if defined(NOLIBC_STACKPROTECTOR)
812 if (!__stack_chk_guard) {
813 llen += printf("__stack_chk_guard not initialized");
814 pad_spc(llen, 64, "[FAIL]\n");
815 return 1;
816 }
817#endif
818
97357168
TW
819 pid = -1;
820 pid = fork();
821
822 switch (pid) {
823 case -1:
824 llen += printf("fork()");
825 pad_spc(llen, 64, "[FAIL]\n");
826 return 1;
827
828 case 0:
829 close(STDOUT_FILENO);
830 close(STDERR_FILENO);
831
832 smash_stack();
833 return 1;
834
835 default:
836 pid = waitpid(pid, &status, 0);
837
838 if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) {
839 llen += printf("waitpid()");
840 pad_spc(llen, 64, "[FAIL]\n");
841 return 1;
842 }
843 pad_spc(llen, 64, " [OK]\n");
844 return 0;
845 }
846}
847
1a5454f6
WT
848/* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
849int prepare(void)
850{
851 struct stat stat_buf;
852
853 /* It's possible that /dev doesn't even exist or was not mounted, so
854 * we'll try to create it, mount it, or create minimal entries into it.
855 * We want at least /dev/null and /dev/console.
856 */
857 if (stat("/dev/.", &stat_buf) == 0 || mkdir("/dev", 0755) == 0) {
858 if (stat("/dev/console", &stat_buf) != 0 ||
859 stat("/dev/null", &stat_buf) != 0) {
860 /* try devtmpfs first, otherwise fall back to manual creation */
861 if (mount("/dev", "/dev", "devtmpfs", 0, 0) != 0) {
862 mknod("/dev/console", 0600 | S_IFCHR, makedev(5, 1));
863 mknod("/dev/null", 0666 | S_IFCHR, makedev(1, 3));
864 }
865 }
866 }
867
868 /* If no /dev/console was found before calling init, stdio is closed so
869 * we need to reopen it from /dev/console. If it failed above, it will
870 * still fail here and we cannot emit a message anyway.
871 */
872 if (close(dup(1)) == -1) {
873 int fd = open("/dev/console", O_RDWR);
874
875 if (fd >= 0) {
876 if (fd != 0)
877 dup2(fd, 0);
878 if (fd != 1)
879 dup2(fd, 1);
880 if (fd != 2)
881 dup2(fd, 2);
882 if (fd > 2)
883 close(fd);
884 puts("\nSuccessfully reopened /dev/console.");
885 }
886 }
887
888 /* try to mount /proc if not mounted. Silently fail otherwise */
889 if (stat("/proc/.", &stat_buf) == 0 || mkdir("/proc", 0755) == 0) {
890 if (stat("/proc/self", &stat_buf) != 0)
891 mount("/proc", "/proc", "proc", 0, 0);
892 }
893
894 return 0;
895}
b4844fa0 896
23da7bc9 897/* This is the definition of known test names, with their functions */
c4560bd8 898static const struct test test_names[] = {
23da7bc9 899 /* add new tests here */
97357168
TW
900 { .name = "syscall", .func = run_syscall },
901 { .name = "stdlib", .func = run_stdlib },
69f2cd9f 902 { .name = "vfprintf", .func = run_vfprintf },
97357168 903 { .name = "protection", .func = run_protection },
23da7bc9
WT
904 { 0 }
905};
906
362aecb2
WT
907int main(int argc, char **argv, char **envp)
908{
909 int min = 0;
910 int max = __INT_MAX__;
911 int ret = 0;
23da7bc9
WT
912 int err;
913 int idx;
914 char *test;
362aecb2
WT
915
916 environ = envp;
917
1a5454f6
WT
918 /* when called as init, it's possible that no console was opened, for
919 * example if no /dev file system was provided. We'll check that fd#1
920 * was opened, and if not we'll attempt to create and open /dev/console
921 * and /dev/null that we'll use for later tests.
922 */
923 if (getpid() == 1)
924 prepare();
925
23da7bc9
WT
926 /* the definition of a series of tests comes from either argv[1] or the
927 * "NOLIBC_TEST" environment variable. It's made of a comma-delimited
928 * series of test names and optional ranges:
929 * syscall:5-15[:.*],stdlib:8-10
930 */
931 test = argv[1];
932 if (!test)
933 test = getenv("NOLIBC_TEST");
934
935 if (test) {
936 char *comma, *colon, *dash, *value;
937
938 do {
939 comma = strchr(test, ',');
940 if (comma)
941 *(comma++) = '\0';
942
943 colon = strchr(test, ':');
944 if (colon)
945 *(colon++) = '\0';
946
947 for (idx = 0; test_names[idx].name; idx++) {
948 if (strcmp(test, test_names[idx].name) == 0)
949 break;
950 }
951
952 if (test_names[idx].name) {
953 /* The test was named, it will be called at least
954 * once. We may have an optional range at <colon>
955 * here, which defaults to the full range.
956 */
957 do {
958 min = 0; max = __INT_MAX__;
959 value = colon;
960 if (value && *value) {
961 colon = strchr(value, ':');
962 if (colon)
963 *(colon++) = '\0';
964
965 dash = strchr(value, '-');
966 if (dash)
967 *(dash++) = '\0';
968
969 /* support :val: :min-max: :min-: :-max: */
970 if (*value)
971 min = atoi(value);
972 if (!dash)
973 max = min;
974 else if (*dash)
975 max = atoi(dash);
976
977 value = colon;
978 }
979
980 /* now's time to call the test */
981 printf("Running test '%s'\n", test_names[idx].name);
982 err = test_names[idx].func(min, max);
983 ret += err;
984 printf("Errors during this test: %d\n\n", err);
985 } while (colon && *colon);
986 } else
987 printf("Ignoring unknown test name '%s'\n", test);
988
989 test = comma;
990 } while (test && *test);
991 } else {
992 /* no test mentioned, run everything */
993 for (idx = 0; test_names[idx].name; idx++) {
994 printf("Running test '%s'\n", test_names[idx].name);
995 err = test_names[idx].func(min, max);
996 ret += err;
997 printf("Errors during this test: %d\n\n", err);
998 }
999 }
1000
362aecb2 1001 printf("Total number of errors: %d\n", ret);
f49896d7
WT
1002
1003 if (getpid() == 1) {
1004 /* we're running as init, there's no other process on the
1005 * system, thus likely started from a VM for a quick check.
1006 * Exiting will provoke a kernel panic that may be reported
1007 * as an error by Qemu or the hypervisor, while stopping
1008 * cleanly will often be reported as a success. This allows
1009 * to use the output of this program for bisecting kernels.
1010 */
1011 printf("Leaving init with final status: %d\n", !!ret);
1012 if (ret == 0)
1013 reboot(LINUX_REBOOT_CMD_POWER_OFF);
aa73a86c
WT
1014#if defined(__x86_64__)
1015 /* QEMU started with "-device isa-debug-exit -no-reboot" will
1016 * exit with status code 2N+1 when N is written to 0x501. We
1017 * hard-code the syscall here as it's arch-dependent.
1018 */
1da02f51 1019#if defined(_NOLIBC_SYS_H)
aa73a86c 1020 else if (my_syscall3(__NR_ioperm, 0x501, 1, 1) == 0)
1da02f51
WT
1021#else
1022 else if (ioperm(0x501, 1, 1) == 0)
1023#endif
7f291cfa 1024 __asm__ volatile ("outb %%al, %%dx" :: "d"(0x501), "a"(0));
aa73a86c
WT
1025 /* if it does nothing, fall back to the regular panic */
1026#endif
f49896d7
WT
1027 }
1028
362aecb2
WT
1029 printf("Exiting with status %d\n", !!ret);
1030 return !!ret;
1031}