xref: /third_party/ltp/lib/safe_macros.c (revision f08c3bdf)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) Linux Test Project, 2010-2020
4 */
5
6#define _GNU_SOURCE
7#include <sys/types.h>
8#include <sys/mman.h>
9#include <sys/resource.h>
10#include <sys/stat.h>
11#include <sys/wait.h>
12#include <sys/mount.h>
13#include <sys/xattr.h>
14#include <sys/sysinfo.h>
15#include <errno.h>
16#include <libgen.h>
17#include <limits.h>
18#include <pwd.h>
19#include <stdarg.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <malloc.h>
23#include <math.h>
24#include "lapi/fcntl.h"
25#include "test.h"
26#include "safe_macros.h"
27
28char *safe_basename(const char *file, const int lineno,
29		    void (*cleanup_fn) (void), char *path)
30{
31	char *rval;
32
33	rval = basename(path);
34
35	if (rval == NULL) {
36		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
37			"basename(%s) failed", path);
38	}
39
40	return rval;
41}
42
43int
44safe_chdir(const char *file, const int lineno, void (*cleanup_fn) (void),
45	   const char *path)
46{
47	int rval;
48
49	rval = chdir(path);
50
51	if (rval == -1) {
52		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
53			"chdir(%s) failed", path);
54	} else if (rval) {
55		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
56			"Invalid chdir(%s) return value %d", path, rval);
57	}
58
59	return rval;
60}
61
62int
63safe_close(const char *file, const int lineno, void (*cleanup_fn) (void),
64	   int fildes)
65{
66	int rval;
67
68	rval = close(fildes);
69
70	if (rval == -1) {
71		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
72			"close(%d) failed", fildes);
73	} else if (rval) {
74		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
75			"Invalid close(%d) return value %d", fildes, rval);
76	}
77
78	return rval;
79}
80
81int
82safe_creat(const char *file, const int lineno, void (*cleanup_fn) (void),
83	   const char *pathname, mode_t mode)
84{
85	int rval;
86
87	rval = creat(pathname, mode);
88
89	if (rval == -1) {
90		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
91			"creat(%s,%04o) failed", pathname, mode);
92	} else if (rval < 0) {
93		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
94			"Invalid creat(%s,%04o) return value %d", pathname,
95			mode, rval);
96	}
97
98	return rval;
99}
100
101char *safe_dirname(const char *file, const int lineno,
102		   void (*cleanup_fn) (void), char *path)
103{
104	char *rval;
105
106	rval = dirname(path);
107
108	if (rval == NULL) {
109		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
110			"dirname(%s) failed", path);
111	}
112
113	return rval;
114}
115
116char *safe_getcwd(const char *file, const int lineno, void (*cleanup_fn) (void),
117		  char *buf, size_t size)
118{
119	char *rval;
120
121	rval = getcwd(buf, size);
122
123	if (rval == NULL) {
124		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
125			"getcwd(%p,%zu) failed", buf, size);
126	}
127
128	return rval;
129}
130
131struct passwd *safe_getpwnam(const char *file, const int lineno,
132			     void (*cleanup_fn) (void), const char *name)
133{
134	struct passwd *rval;
135
136	rval = getpwnam(name);
137
138	if (rval == NULL) {
139		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
140			"getpwnam(%s) failed", name);
141	}
142
143	return rval;
144}
145
146int
147safe_getrusage(const char *file, const int lineno, void (*cleanup_fn) (void),
148	       int who, struct rusage *usage)
149{
150	int rval;
151
152	rval = getrusage(who, usage);
153
154	if (rval == -1) {
155		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
156			"getrusage(%d,%p) failed", who, usage);
157	} else if (rval) {
158		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
159			"Invalid getrusage(%d,%p) return value %d", who,
160			usage, rval);
161	}
162
163	return rval;
164}
165
166void *safe_malloc(const char *file, const int lineno, void (*cleanup_fn) (void),
167		  size_t size)
168{
169	void *rval;
170
171	rval = malloc(size);
172
173	if (rval == NULL) {
174		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
175			"malloc(%zu) failed", size);
176	}
177
178	return rval;
179}
180
181int safe_mkdir(const char *file, const int lineno, void (*cleanup_fn) (void),
182               const char *pathname, mode_t mode)
183{
184	int rval;
185
186	rval = mkdir(pathname, mode);
187
188	if (rval == -1) {
189		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
190			"mkdir(%s, %04o) failed", pathname, mode);
191	} else if (rval) {
192		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
193			"Invalid mkdir(%s, %04o) return value %d", pathname,
194			mode, rval);
195	}
196
197	return (rval);
198}
199
200int safe_rmdir(const char *file, const int lineno, void (*cleanup_fn) (void),
201               const char *pathname)
202{
203	int rval;
204
205	rval = rmdir(pathname);
206
207	if (rval == -1) {
208		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
209			"rmdir(%s) failed", pathname);
210	} else if (rval) {
211		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
212			"Invalid rmdir(%s) return value %d", pathname, rval);
213	}
214
215	return (rval);
216}
217
218int safe_munmap(const char *file, const int lineno, void (*cleanup_fn) (void),
219                void *addr, size_t length)
220{
221	int rval;
222
223	rval = munmap(addr, length);
224
225	if (rval == -1) {
226		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
227			"munmap(%p,%zu) failed", addr, length);
228	} else if (rval) {
229		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
230			"Invalid munmap(%p,%zu) return value %d", addr,
231			length, rval);
232	}
233
234	return rval;
235}
236
237int safe_open(const char *file, const int lineno, void (*cleanup_fn) (void),
238              const char *pathname, int oflags, ...)
239{
240	int rval;
241	mode_t mode = 0;
242
243	if (TST_OPEN_NEEDS_MODE(oflags)) {
244		va_list ap;
245
246		va_start(ap, oflags);
247
248		/* Android's NDK's mode_t is smaller than an int, which results in
249		 * SIGILL here when passing the mode_t type.
250		 */
251		mode = va_arg(ap, int);
252
253		va_end(ap);
254	}
255
256	rval = open(pathname, oflags, mode);
257
258	if (rval == -1) {
259		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
260			"open(%s,%d,%04o) failed", pathname, oflags, mode);
261	} else if (rval < 0) {
262		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
263			"Invalid open(%s,%d,%04o) return value %d", pathname,
264			oflags, mode, rval);
265	}
266
267	return rval;
268}
269
270int safe_pipe(const char *file, const int lineno, void (*cleanup_fn) (void),
271              int fildes[2])
272{
273	int rval;
274
275	rval = pipe(fildes);
276
277	if (rval == -1) {
278		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
279			"pipe({%d,%d}) failed", fildes[0], fildes[1]);
280	} else if (rval) {
281		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
282			"Invalid pipe({%d,%d}) return value %d", fildes[0],
283			fildes[1], rval);
284	}
285
286	return rval;
287}
288
289ssize_t safe_read(const char *file, const int lineno, void (*cleanup_fn) (void),
290                  char len_strict, int fildes, void *buf, size_t nbyte)
291{
292	ssize_t rval;
293
294	rval = read(fildes, buf, nbyte);
295
296	if (rval == -1 || (len_strict && (size_t)rval != nbyte)) {
297		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
298			"read(%d,%p,%zu) failed, returned %zd", fildes, buf,
299			nbyte, rval);
300	} else if (rval < 0) {
301		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
302			"Invalid read(%d,%p,%zu) return value %zd", fildes,
303			buf, nbyte, rval);
304	}
305
306	return rval;
307}
308
309int safe_setegid(const char *file, const int lineno, void (*cleanup_fn) (void),
310                 gid_t egid)
311{
312	int rval;
313
314	rval = setegid(egid);
315
316	if (rval == -1) {
317		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
318			"setegid(%u) failed", (unsigned int)egid);
319	} else if (rval) {
320		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
321			"Invalid setegid(%u) return value %d",
322			(unsigned int)egid, rval);
323	}
324
325	return rval;
326}
327
328int safe_seteuid(const char *file, const int lineno, void (*cleanup_fn) (void),
329                 uid_t euid)
330{
331	int rval;
332
333	rval = seteuid(euid);
334
335	if (rval == -1) {
336		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
337			"seteuid(%u) failed", (unsigned int)euid);
338	} else if (rval) {
339		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
340			"Invalid seteuid(%u) return value %d",
341			(unsigned int)euid, rval);
342	}
343
344	return rval;
345}
346
347int safe_setgid(const char *file, const int lineno, void (*cleanup_fn) (void),
348                gid_t gid)
349{
350	int rval;
351
352	rval = setgid(gid);
353
354	if (rval == -1) {
355		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
356			"setgid(%u) failed", (unsigned int)gid);
357	} else if (rval) {
358		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
359			"Invalid setgid(%u) return value %d",
360			(unsigned int)gid, rval);
361	}
362
363	return rval;
364}
365
366int safe_setuid(const char *file, const int lineno, void (*cleanup_fn) (void),
367                uid_t uid)
368{
369	int rval;
370
371	rval = setuid(uid);
372
373	if (rval == -1) {
374		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
375			"setuid(%u) failed", (unsigned int)uid);
376	} else if (rval) {
377		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
378			"Invalid setuid(%u) return value %d",
379			(unsigned int)uid, rval);
380	}
381
382	return rval;
383}
384
385int safe_getresuid(const char *file, const int lineno, void (*cleanup_fn)(void),
386		   uid_t *ruid, uid_t *euid, uid_t *suid)
387{
388	int rval;
389
390	rval = getresuid(ruid, euid, suid);
391
392	if (rval == -1) {
393		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
394			"getresuid(%p, %p, %p) failed", ruid, euid, suid);
395	} else if (rval) {
396		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
397			"Invalid getresuid(%p, %p, %p) return value %d", ruid,
398			euid, suid, rval);
399	}
400
401	return rval;
402}
403
404int safe_getresgid(const char *file, const int lineno, void (*cleanup_fn)(void),
405		   gid_t *rgid, gid_t *egid, gid_t *sgid)
406{
407	int rval;
408
409	rval = getresgid(rgid, egid, sgid);
410
411	if (rval == -1) {
412		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
413			"getresgid(%p, %p, %p) failed", rgid, egid, sgid);
414	} else if (rval) {
415		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
416			"Invalid getresgid(%p, %p, %p) return value %d", rgid,
417			egid, sgid, rval);
418	}
419
420	return rval;
421}
422
423int safe_unlink(const char *file, const int lineno, void (*cleanup_fn) (void),
424                const char *pathname)
425{
426	int rval;
427
428	rval = unlink(pathname);
429
430	if (rval == -1) {
431		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
432			"unlink(%s) failed", pathname);
433	} else if (rval) {
434		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
435			"Invalid unlink(%s) return value %d", pathname, rval);
436	}
437
438	return rval;
439}
440
441
442int safe_link(const char *file, const int lineno,
443              void (cleanup_fn)(void), const char *oldpath,
444              const char *newpath)
445{
446	int rval;
447
448	rval = link(oldpath, newpath);
449
450	if (rval == -1) {
451		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
452		        "link(%s,%s) failed", oldpath, newpath);
453	} else if (rval) {
454		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
455		        "Invalid link(%s,%s) return value %d", oldpath,
456			newpath, rval);
457	}
458
459	return rval;
460}
461
462int safe_linkat(const char *file, const int lineno,
463		void (cleanup_fn)(void), int olddirfd, const char *oldpath,
464		int newdirfd, const char *newpath, int flags)
465{
466	int rval;
467
468	rval = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
469
470	if (rval == -1) {
471		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
472			"linkat(%d,%s,%d,%s,%d) failed", olddirfd, oldpath,
473			newdirfd, newpath, flags);
474	} else if (rval) {
475		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
476			"Invalid linkat(%d,%s,%d,%s,%d) return value %d",
477			olddirfd, oldpath, newdirfd, newpath, flags, rval);
478	}
479
480	return rval;
481}
482
483ssize_t safe_readlink(const char *file, const int lineno,
484		  void (cleanup_fn)(void), const char *path,
485		  char *buf, size_t bufsize)
486{
487	ssize_t rval;
488
489	rval = readlink(path, buf, bufsize);
490
491	if (rval == -1) {
492		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
493			"readlink(%s,%p,%zu) failed", path, buf, bufsize);
494	} else if (rval < 0) {
495		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
496			"Invalid readlink(%s,%p,%zu) return value %zd", path,
497			buf, bufsize, rval);
498	} else {
499		/* readlink does not append a NUL byte to the buffer.
500		 * Add it now. */
501		if ((size_t) rval < bufsize)
502			buf[rval] = '\0';
503		else
504			buf[bufsize-1] = '\0';
505	}
506
507	return rval;
508}
509
510int safe_symlink(const char *file, const int lineno,
511                 void (cleanup_fn)(void), const char *oldpath,
512                 const char *newpath)
513{
514	int rval;
515
516	rval = symlink(oldpath, newpath);
517
518	if (rval == -1) {
519		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
520			"symlink(%s,%s) failed", oldpath, newpath);
521	} else if (rval) {
522		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
523			"Invalid symlink(%s,%s) return value %d", oldpath,
524			newpath, rval);
525	}
526
527	return rval;
528}
529
530ssize_t safe_write(const char *file, const int lineno, void (cleanup_fn) (void),
531		   enum safe_write_opts len_strict, int fildes, const void *buf,
532		   size_t nbyte)
533{
534	ssize_t rval;
535	const void *wbuf = buf;
536	size_t len = nbyte;
537	int iter = 0;
538
539	do {
540		iter++;
541		rval = write(fildes, wbuf, len);
542		if (rval == -1) {
543			if (len_strict == SAFE_WRITE_RETRY)
544				tst_resm_(file, lineno, TINFO,
545					"write() wrote %zu bytes in %d calls",
546					nbyte-len, iter);
547			tst_brkm_(file, lineno, TBROK | TERRNO,
548				cleanup_fn, "write(%d,%p,%zu) failed",
549				fildes, buf, nbyte);
550		}
551
552		if (len_strict == SAFE_WRITE_ANY)
553			return rval;
554
555		if (len_strict == SAFE_WRITE_ALL) {
556			if ((size_t)rval != nbyte)
557				tst_brkm_(file, lineno, TBROK | TERRNO,
558					cleanup_fn, "short write(%d,%p,%zu) "
559					"return value %zd",
560					fildes, buf, nbyte, rval);
561			return rval;
562		}
563
564		wbuf += rval;
565		len -= rval;
566	} while (len > 0);
567
568	return rval;
569}
570
571long safe_strtol(const char *file, const int lineno,
572		 void (cleanup_fn) (void), char *str, long min, long max)
573{
574	long rval;
575	char *endptr;
576
577	errno = 0;
578	rval = strtol(str, &endptr, 10);
579
580	if ((errno == ERANGE && (rval == LONG_MAX || rval == LONG_MIN))
581	    || (errno != 0 && rval == 0)) {
582		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
583			"strtol(%s) failed", str);
584		return rval;
585	}
586
587	if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
588		tst_brkm_(file, lineno, TBROK, cleanup_fn,
589			"strtol(%s): Invalid value", str);
590		return 0;
591	}
592
593	if (rval > max || rval < min) {
594		tst_brkm_(file, lineno, TBROK, cleanup_fn,
595			"strtol(%s): %ld is out of range %ld - %ld",
596			str, rval, min, max);
597		return 0;
598	}
599
600	return rval;
601}
602
603unsigned long safe_strtoul(const char *file, const int lineno,
604			   void (cleanup_fn) (void), char *str,
605			   unsigned long min, unsigned long max)
606{
607	unsigned long rval;
608	char *endptr;
609
610	errno = 0;
611	rval = strtoul(str, &endptr, 10);
612
613	if ((errno == ERANGE && rval == ULONG_MAX)
614	    || (errno != 0 && rval == 0)) {
615		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
616			"strtoul(%s) failed", str);
617		return rval;
618	}
619
620	if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
621		tst_brkm_(file, lineno, TBROK, cleanup_fn,
622			"Invalid value: '%s'", str);
623		return 0;
624	}
625
626	if (rval > max || rval < min) {
627		tst_brkm_(file, lineno, TBROK, cleanup_fn,
628			"strtoul(%s): %lu is out of range %lu - %lu",
629			str, rval, min, max);
630		return 0;
631	}
632
633	return rval;
634}
635
636float safe_strtof(const char *file, const int lineno,
637		  void (cleanup_fn) (void), char *str,
638		  float min, float max)
639{
640	float rval;
641	char *endptr;
642
643	errno = 0;
644	rval = strtof(str, &endptr);
645
646	if (errno) {
647		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
648			"strtof(%s) failed", str);
649		return rval;
650	}
651
652	if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
653		tst_brkm_(file, lineno, TBROK, cleanup_fn,
654			"Invalid value: '%s'", str);
655		return 0;
656	}
657
658	if (rval > max || rval < min) {
659		tst_brkm_(file, lineno, TBROK, cleanup_fn,
660			"strtof(%s): %f is out of range %f - %f",
661			str, rval, min, max);
662		return 0;
663	}
664
665	return rval;
666}
667
668long safe_sysconf(const char *file, const int lineno,
669		  void (cleanup_fn) (void), int name)
670{
671	long rval;
672
673	errno = 0;
674	rval = sysconf(name);
675
676	if (rval == -1) {
677		if (errno) {
678			tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
679				"sysconf(%d) failed", name);
680		} else {
681			tst_resm_(file, lineno, TINFO,
682				"sysconf(%d): queried option is not available or there is no definite limit",
683				name);
684		}
685	}
686
687	return rval;
688}
689
690int safe_chmod(const char *file, const int lineno,
691               void (cleanup_fn)(void), const char *path, mode_t mode)
692{
693	int rval;
694
695	rval = chmod(path, mode);
696
697	if (rval == -1) {
698		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
699			"chmod(%s,%04o) failed", path, mode);
700	} else if (rval) {
701		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
702			"Invalid chmod(%s,%04o) return value %d", path, mode,
703			rval);
704	}
705
706	return rval;
707}
708
709int safe_fchmod(const char *file, const int lineno,
710                void (cleanup_fn)(void), int fd, mode_t mode)
711{
712	int rval;
713
714	rval = fchmod(fd, mode);
715
716	if (rval == -1) {
717		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
718			"fchmod(%d,%04o) failed", fd, mode);
719	} else if (rval) {
720		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
721			"Invalid fchmod(%d,%04o) return value %d", fd, mode,
722			rval);
723	}
724
725	return rval;
726}
727
728int safe_chown(const char *file, const int lineno, void (cleanup_fn)(void),
729			const char *path, uid_t owner, gid_t group)
730{
731	int rval;
732
733	rval = chown(path, owner, group);
734
735	if (rval == -1) {
736		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
737			"chown(%s,%d,%d) failed", path, owner, group);
738	} else if (rval) {
739		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
740			"Invalid chown(%s,%d,%d) return value %d", path,
741			owner, group, rval);
742	}
743
744	return rval;
745}
746
747int safe_fchown(const char *file, const int lineno, void (cleanup_fn)(void),
748                int fd, uid_t owner, gid_t group)
749{
750	int rval;
751
752	rval = fchown(fd, owner, group);
753
754	if (rval == -1) {
755		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
756			"fchown(%d,%d,%d) failed", fd, owner, group);
757	} else if (rval) {
758		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
759			"Invalid fchown(%d,%d,%d) return value %d", fd,
760			owner, group, rval);
761	}
762
763	return rval;
764}
765
766pid_t safe_wait(const char *file, const int lineno, void (cleanup_fn)(void),
767                int *status)
768{
769	pid_t rval;
770
771	rval = wait(status);
772
773	if (rval == -1) {
774		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
775			"wait(%p) failed", status);
776	} else if (rval < 0) {
777		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
778			"Invalid wait(%p) return value %d", status, rval);
779	}
780
781	return rval;
782}
783
784pid_t safe_waitpid(const char *file, const int lineno, void (cleanup_fn)(void),
785                   pid_t pid, int *status, int opts)
786{
787	pid_t rval;
788
789	rval = waitpid(pid, status, opts);
790
791	if (rval == -1) {
792		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
793			"waitpid(%d,%p,%d) failed", pid, status, opts);
794	} else if (rval < 0) {
795		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
796			"Invalid waitpid(%d,%p,%d) return value %d", pid,
797			status, opts, rval);
798	}
799
800	return rval;
801}
802
803void *safe_memalign(const char *file, const int lineno,
804		    void (*cleanup_fn) (void), size_t alignment, size_t size)
805{
806	void *rval;
807
808	rval = memalign(alignment, size);
809
810	if (rval == NULL) {
811		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
812			"memalign() failed");
813	}
814
815	return rval;
816}
817
818int safe_kill(const char *file, const int lineno, void (cleanup_fn)(void),
819	      pid_t pid, int sig)
820{
821	int rval;
822
823	rval = kill(pid, sig);
824
825	if (rval == -1) {
826		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
827			"kill(%d,%s) failed", pid, tst_strsig(sig));
828	} else if (rval) {
829		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
830			"Invalid kill(%d,%s) return value %d", pid,
831			tst_strsig(sig), rval);
832	}
833
834	return rval;
835}
836
837int safe_mkfifo(const char *file, const int lineno,
838                void (*cleanup_fn)(void), const char *pathname, mode_t mode)
839{
840	int rval;
841
842	rval = mkfifo(pathname, mode);
843
844	if (rval == -1) {
845		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
846			"mkfifo(%s, %04o) failed", pathname, mode);
847	} else if (rval) {
848		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
849			"Invalid mkfifo(%s, %04o) return value %d", pathname,
850			mode, rval);
851	}
852
853	return rval;
854}
855
856int safe_rename(const char *file, const int lineno, void (*cleanup_fn)(void),
857		const char *oldpath, const char *newpath)
858{
859	int rval;
860
861	rval = rename(oldpath, newpath);
862
863	if (rval == -1) {
864		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
865			"rename(%s, %s) failed", oldpath, newpath);
866	} else if (rval) {
867		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
868			"Invalid rename(%s, %s) return value %d", oldpath,
869			newpath, rval);
870	}
871
872	return rval;
873}
874
875static const char *const fuse_fs_types[] = {
876	"exfat",
877	"ntfs",
878};
879
880static int possibly_fuse(const char *fs_type)
881{
882	unsigned int i;
883
884	if (!fs_type)
885		return 0;
886
887	for (i = 0; i < ARRAY_SIZE(fuse_fs_types); i++) {
888		if (!strcmp(fuse_fs_types[i], fs_type))
889			return 1;
890	}
891
892	return 0;
893}
894
895int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
896	       const char *source, const char *target,
897	       const char *filesystemtype, unsigned long mountflags,
898	       const void *data)
899{
900	int rval = -1;
901	char mpath[PATH_MAX];
902
903	if (realpath(target, mpath)) {
904		tst_resm_(file, lineno, TINFO,
905			"Mounting %s to %s fstyp=%s flags=%lx",
906			source, mpath, filesystemtype, mountflags);
907	} else {
908		tst_resm_(file, lineno, TINFO | TERRNO,
909			"Cannot resolve the absolute path of %s", target);
910	}
911	/*
912	 * Don't try using the kernel's NTFS driver when mounting NTFS, since
913	 * the kernel's NTFS driver doesn't have proper write support.
914	 */
915	if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
916		rval = mount(source, target, filesystemtype, mountflags, data);
917		if (!rval)
918			return 0;
919	}
920
921	/*
922	 * The FUSE filesystem executes mount.fuse helper, which tries to
923	 * execute corresponding binary name which is encoded at the start of
924	 * the source string and separated by # from the device name.
925         *
926	 * The mount helpers are called mount.$fs_type.
927	 */
928	if (possibly_fuse(filesystemtype)) {
929		char buf[1024];
930
931		tst_resm_(file, lineno, TINFO, "Trying FUSE...");
932		snprintf(buf, sizeof(buf), "mount.%s '%s' '%s'",
933			filesystemtype, source, target);
934
935		rval = tst_system(buf);
936		if (WIFEXITED(rval) && WEXITSTATUS(rval) == 0)
937			return 0;
938
939		tst_brkm_(file, lineno, TBROK, cleanup_fn,
940			"mount.%s failed with %i", filesystemtype, rval);
941		return -1;
942	} else if (rval == -1) {
943		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
944			"mount(%s, %s, %s, %lu, %p) failed", source, target,
945			filesystemtype, mountflags, data);
946	} else {
947		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
948			"Invalid mount(%s, %s, %s, %lu, %p) return value %d",
949			source, target, filesystemtype, mountflags, data,
950			rval);
951	}
952
953	return rval;
954}
955
956int safe_umount(const char *file, const int lineno, void (*cleanup_fn)(void),
957		const char *target)
958{
959	int rval;
960	char mpath[PATH_MAX];
961
962	if (realpath(target, mpath)) {
963		tst_resm_(file, lineno, TINFO, "Umounting %s", mpath);
964	} else {
965		tst_resm_(file, lineno, TINFO | TERRNO,
966			"Cannot resolve the absolute path of %s", target);
967	}
968
969	rval = tst_umount(target);
970
971	if (rval == -1) {
972		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
973			"umount(%s) failed", target);
974	} else if (rval) {
975		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
976			"Invalid umount(%s) return value %d", target, rval);
977	}
978
979	return rval;
980}
981
982DIR* safe_opendir(const char *file, const int lineno, void (cleanup_fn)(void),
983                  const char *name)
984{
985	DIR *rval;
986
987	rval = opendir(name);
988
989	if (!rval) {
990		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
991			"opendir(%s) failed", name);
992	}
993
994	return rval;
995}
996
997int safe_closedir(const char *file, const int lineno, void (cleanup_fn)(void),
998                  DIR *dirp)
999{
1000	int rval;
1001
1002	rval = closedir(dirp);
1003
1004	if (rval == -1) {
1005		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1006			"closedir(%p) failed", dirp);
1007	} else if (rval) {
1008		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1009			"Invalid closedir(%p) return value %d", dirp, rval);
1010	}
1011
1012	return rval;
1013}
1014
1015struct dirent *safe_readdir(const char *file, const int lineno, void (cleanup_fn)(void),
1016                            DIR *dirp)
1017{
1018	struct dirent *rval;
1019	int err = errno;
1020
1021	errno = 0;
1022	rval = readdir(dirp);
1023
1024	if (!rval && errno) {
1025		tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1026			"readdir(%p) failed", dirp);
1027	}
1028
1029	errno = err;
1030	return rval;
1031}
1032
1033int safe_getpriority(const char *file, const int lineno, int which, id_t who)
1034{
1035	int rval, err = errno;
1036
1037	errno = 0;
1038	rval = getpriority(which, who);
1039
1040	if (rval == -1 && errno) {
1041		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1042			"getpriority(%i, %i) failed", which, who);
1043	} else if (errno) {
1044		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1045			"getpriority(%i, %i) failed with return value %d",
1046			which, who, rval);
1047	}
1048
1049	errno = err;
1050	return rval;
1051}
1052
1053ssize_t safe_getxattr(const char *file, const int lineno, const char *path,
1054		      const char *name, void *value, size_t size)
1055{
1056	ssize_t rval;
1057
1058	rval = getxattr(path, name, value, size);
1059
1060	if (rval == -1) {
1061		if (errno == ENOTSUP) {
1062			tst_brkm_(file, lineno, TCONF, NULL,
1063				"no xattr support in fs or mounted without user_xattr option");
1064			return rval;
1065		}
1066
1067		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1068			"getxattr(%s, %s, %p, %zu) failed",
1069			path, name, value, size);
1070	} else if (rval < 0) {
1071		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1072			"Invalid getxattr(%s, %s, %p, %zu) return value %zd",
1073			path, name, value, size, rval);
1074	}
1075
1076	return rval;
1077}
1078
1079int safe_setxattr(const char *file, const int lineno, const char *path,
1080		  const char *name, const void *value, size_t size, int flags)
1081{
1082	int rval;
1083
1084	rval = setxattr(path, name, value, size, flags);
1085
1086	if (rval == -1) {
1087		if (errno == ENOTSUP) {
1088			tst_brkm_(file, lineno, TCONF, NULL,
1089				"no xattr support in fs, mounted without user_xattr option "
1090				"or invalid namespace/name format");
1091			return rval;
1092		}
1093
1094		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1095			"setxattr(%s, %s, %p, %zu) failed",
1096			path, name, value, size);
1097	} else if (rval) {
1098		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1099			"Invalid setxattr(%s, %s, %p, %zu) return value %d",
1100			path, name, value, size, rval);
1101	}
1102
1103	return rval;
1104}
1105
1106int safe_lsetxattr(const char *file, const int lineno, const char *path,
1107		   const char *name, const void *value, size_t size, int flags)
1108{
1109	int rval;
1110
1111	rval = lsetxattr(path, name, value, size, flags);
1112
1113	if (rval == -1) {
1114		if (errno == ENOTSUP) {
1115			tst_brkm_(file, lineno, TCONF, NULL,
1116				"no xattr support in fs, mounted without user_xattr option "
1117				"or invalid namespace/name format");
1118			return rval;
1119		}
1120
1121		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1122			"lsetxattr(%s, %s, %p, %zu, %i) failed",
1123			path, name, value, size, flags);
1124	} else if (rval) {
1125		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1126			"Invalid lsetxattr(%s, %s, %p, %zu, %i) return value %d",
1127			path, name, value, size, flags, rval);
1128	}
1129
1130	return rval;
1131}
1132
1133int safe_fsetxattr(const char *file, const int lineno, int fd, const char *name,
1134		   const void *value, size_t size, int flags)
1135{
1136	int rval;
1137
1138	rval = fsetxattr(fd, name, value, size, flags);
1139
1140	if (rval == -1) {
1141		if (errno == ENOTSUP) {
1142			tst_brkm_(file, lineno, TCONF, NULL,
1143				"no xattr support in fs, mounted without user_xattr option "
1144				"or invalid namespace/name format");
1145			return rval;
1146		}
1147
1148		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1149			"fsetxattr(%i, %s, %p, %zu, %i) failed",
1150			fd, name, value, size, flags);
1151	} else if (rval) {
1152		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1153			"Invalid fsetxattr(%i, %s, %p, %zu, %i) return value %d",
1154			fd, name, value, size, flags, rval);
1155	}
1156
1157	return rval;
1158}
1159
1160int safe_removexattr(const char *file, const int lineno, const char *path,
1161		const char *name)
1162{
1163	int rval;
1164
1165	rval = removexattr(path, name);
1166
1167	if (rval == -1) {
1168		if (errno == ENOTSUP) {
1169			tst_brkm_(file, lineno, TCONF, NULL,
1170				"no xattr support in fs or mounted without user_xattr option");
1171			return rval;
1172		}
1173
1174		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1175			"removexattr(%s, %s) failed", path, name);
1176	} else if (rval) {
1177		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1178			"Invalid removexattr(%s, %s) return value %d", path,
1179			name, rval);
1180	}
1181
1182	return rval;
1183}
1184
1185int safe_lremovexattr(const char *file, const int lineno, const char *path,
1186		const char *name)
1187{
1188	int rval;
1189
1190	rval = lremovexattr(path, name);
1191
1192	if (rval == -1) {
1193		if (errno == ENOTSUP) {
1194			tst_brkm_(file, lineno, TCONF, NULL,
1195				"no xattr support in fs or mounted without user_xattr option");
1196			return rval;
1197		}
1198
1199		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1200			"lremovexattr(%s, %s) failed", path, name);
1201	} else if (rval) {
1202		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1203			"Invalid lremovexattr(%s, %s) return value %d", path,
1204			name, rval);
1205	}
1206
1207	return rval;
1208}
1209
1210int safe_fremovexattr(const char *file, const int lineno, int fd,
1211		const char *name)
1212{
1213	int rval;
1214
1215	rval = fremovexattr(fd, name);
1216
1217	if (rval == -1) {
1218		if (errno == ENOTSUP) {
1219			tst_brkm_(file, lineno, TCONF, NULL,
1220				"no xattr support in fs or mounted without user_xattr option");
1221			return rval;
1222		}
1223
1224		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1225			"fremovexattr(%i, %s) failed", fd, name);
1226	} else if (rval) {
1227		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1228			"Invalid fremovexattr(%i, %s) return value %d", fd,
1229			name, rval);
1230	}
1231
1232	return rval;
1233}
1234
1235int safe_fsync(const char *file, const int lineno, int fd)
1236{
1237	int rval;
1238
1239	rval = fsync(fd);
1240
1241	if (rval == -1) {
1242		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1243			"fsync(%i) failed", fd);
1244	} else if (rval) {
1245		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1246			"Invalid fsync(%i) return value %d", fd, rval);
1247	}
1248
1249	return rval;
1250}
1251
1252pid_t safe_setsid(const char *file, const int lineno)
1253{
1254	pid_t rval;
1255
1256	rval = setsid();
1257
1258	if (rval == -1) {
1259		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1260			"setsid() failed");
1261	}
1262
1263	return rval;
1264}
1265
1266int safe_mknod(const char *file, const int lineno, const char *pathname,
1267	mode_t mode, dev_t dev)
1268{
1269	int rval;
1270
1271	rval = mknod(pathname, mode, dev);
1272
1273	if (rval == -1) {
1274		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1275			"mknod() failed");
1276	} else if (rval) {
1277		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1278			"Invalid mknod() return value %d", rval);
1279	}
1280
1281	return rval;
1282}
1283
1284int safe_mlock(const char *file, const int lineno, const void *addr,
1285	size_t len)
1286{
1287	int rval;
1288
1289	rval = mlock(addr, len);
1290
1291	if (rval == -1) {
1292		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1293			"mlock() failed");
1294	} else if (rval) {
1295		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1296			"Invalid mlock() return value %d", rval);
1297	}
1298
1299	return rval;
1300}
1301
1302int safe_munlock(const char *file, const int lineno, const void *addr,
1303	size_t len)
1304{
1305	int rval;
1306
1307	rval = munlock(addr, len);
1308
1309	if (rval == -1) {
1310		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1311			"munlock() failed");
1312	} else if (rval) {
1313		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1314			"Invalid munlock() return value %d", rval);
1315	}
1316
1317	return rval;
1318}
1319
1320int safe_mincore(const char *file, const int lineno, void *start,
1321	size_t length, unsigned char *vec)
1322{
1323	int rval;
1324
1325	rval = mincore(start, length, vec);
1326
1327	if (rval == -1) {
1328		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1329			"mincore() failed");
1330	} else if (rval) {
1331		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1332			"Invalid mincore() return value %d", rval);
1333	}
1334
1335	return rval;
1336}
1337
1338int safe_sysinfo(const char *file, const int lineno, struct sysinfo *info)
1339{
1340	int ret;
1341
1342	errno = 0;
1343	ret = sysinfo(info);
1344
1345	if (ret == -1) {
1346		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1347			"sysinfo() failed");
1348	} else if (ret) {
1349		tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1350			"Invalid sysinfo() return value %d", ret);
1351	}
1352
1353	return ret;
1354}
1355