• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <errno.h>
15 #include <fcntl.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 "test.h"
24 #include "safe_macros.h"
25 
safe_basename(const char * file,const int lineno,void (* cleanup_fn)(void),char * path)26 char *safe_basename(const char *file, const int lineno,
27 		    void (*cleanup_fn) (void), char *path)
28 {
29 	char *rval;
30 
31 	rval = basename(path);
32 	if (rval == NULL) {
33 		tst_brkm(TBROK | TERRNO, cleanup_fn,
34 			 "%s:%d: basename(%s) failed",
35 			 file, lineno, path);
36 	}
37 
38 	return rval;
39 }
40 
41 int
safe_chdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * path)42 safe_chdir(const char *file, const int lineno, void (*cleanup_fn) (void),
43 	   const char *path)
44 {
45 	int rval;
46 
47 	rval = chdir(path);
48 	if (rval == -1) {
49 		tst_brkm(TBROK | TERRNO, cleanup_fn,
50 			 "%s:%d: chdir(%s) failed",
51 			 file, lineno, path);
52 	}
53 
54 	return rval;
55 }
56 
57 int
safe_close(const char * file,const int lineno,void (* cleanup_fn)(void),int fildes)58 safe_close(const char *file, const int lineno, void (*cleanup_fn) (void),
59 	   int fildes)
60 {
61 	int rval;
62 
63 	rval = close(fildes);
64 	if (rval == -1) {
65 		tst_brkm(TBROK | TERRNO, cleanup_fn,
66 			 "%s:%d: close(%d) failed",
67 			 file, lineno, fildes);
68 	}
69 
70 	return rval;
71 }
72 
73 int
safe_creat(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)74 safe_creat(const char *file, const int lineno, void (*cleanup_fn) (void),
75 	   const char *pathname, mode_t mode)
76 {
77 	int rval;
78 
79 	rval = creat(pathname, mode);
80 	if (rval == -1) {
81 		tst_brkm(TBROK | TERRNO, cleanup_fn,
82 			 "%s:%d: creat(%s,0%o) failed",
83 			 file, lineno, pathname, mode);
84 	}
85 
86 	return rval;
87 }
88 
safe_dirname(const char * file,const int lineno,void (* cleanup_fn)(void),char * path)89 char *safe_dirname(const char *file, const int lineno,
90 		   void (*cleanup_fn) (void), char *path)
91 {
92 	char *rval;
93 
94 	rval = dirname(path);
95 	if (rval == NULL) {
96 		tst_brkm(TBROK | TERRNO, cleanup_fn,
97 			 "%s:%d: dirname(%s) failed",
98 			 file, lineno, path);
99 	}
100 
101 	return rval;
102 }
103 
safe_getcwd(const char * file,const int lineno,void (* cleanup_fn)(void),char * buf,size_t size)104 char *safe_getcwd(const char *file, const int lineno, void (*cleanup_fn) (void),
105 		  char *buf, size_t size)
106 {
107 	char *rval;
108 
109 	rval = getcwd(buf, size);
110 	if (rval == NULL) {
111 		tst_brkm(TBROK | TERRNO, cleanup_fn,
112 			 "%s:%d: getcwd(%p,%zu) failed",
113 			 file, lineno, buf, size);
114 	}
115 
116 	return rval;
117 }
118 
safe_getpwnam(const char * file,const int lineno,void (* cleanup_fn)(void),const char * name)119 struct passwd *safe_getpwnam(const char *file, const int lineno,
120 			     void (*cleanup_fn) (void), const char *name)
121 {
122 	struct passwd *rval;
123 
124 	rval = getpwnam(name);
125 	if (rval == NULL) {
126 		tst_brkm(TBROK | TERRNO, cleanup_fn,
127 			 "%s:%d: getpwnam(%s) failed",
128 			 file, lineno, name);
129 	}
130 
131 	return rval;
132 }
133 
134 int
safe_getrusage(const char * file,const int lineno,void (* cleanup_fn)(void),int who,struct rusage * usage)135 safe_getrusage(const char *file, const int lineno, void (*cleanup_fn) (void),
136 	       int who, struct rusage *usage)
137 {
138 	int rval;
139 
140 	rval = getrusage(who, usage);
141 	if (rval == -1) {
142 		tst_brkm(TBROK | TERRNO, cleanup_fn,
143 			 "%s:%d: getrusage(%d,%p) failed",
144 			 file, lineno, who, usage);
145 	}
146 
147 	return rval;
148 }
149 
safe_malloc(const char * file,const int lineno,void (* cleanup_fn)(void),size_t size)150 void *safe_malloc(const char *file, const int lineno, void (*cleanup_fn) (void),
151 		  size_t size)
152 {
153 	void *rval;
154 
155 	rval = malloc(size);
156 	if (rval == NULL) {
157 		tst_brkm(TBROK | TERRNO, cleanup_fn,
158 			 "%s:%d: malloc(%zu) failed",
159 			 file, lineno, size);
160 	}
161 
162 	return rval;
163 }
164 
safe_mkdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)165 int safe_mkdir(const char *file, const int lineno, void (*cleanup_fn) (void),
166                const char *pathname, mode_t mode)
167 {
168 	int rval;
169 
170 	rval = mkdir(pathname, mode);
171 	if (rval == -1) {
172 		tst_brkm(TBROK | TERRNO, cleanup_fn,
173 			 "%s:%d: mkdir(%s,0%o) failed",
174 			 file, lineno, pathname, mode);
175 	}
176 
177 	return (rval);
178 }
179 
safe_rmdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname)180 int safe_rmdir(const char *file, const int lineno, void (*cleanup_fn) (void),
181                const char *pathname)
182 {
183 	int rval;
184 
185 	rval = rmdir(pathname);
186 	if (rval == -1) {
187 		tst_brkm(TBROK | TERRNO, cleanup_fn,
188 			 "%s:%d: rmdir(%s) failed",
189 			 file, lineno, pathname);
190 	}
191 
192 	return (rval);
193 }
194 
safe_munmap(const char * file,const int lineno,void (* cleanup_fn)(void),void * addr,size_t length)195 int safe_munmap(const char *file, const int lineno, void (*cleanup_fn) (void),
196                 void *addr, size_t length)
197 {
198 	int rval;
199 
200 	rval = munmap(addr, length);
201 	if (rval == -1) {
202 		tst_brkm(TBROK | TERRNO, cleanup_fn,
203 			 "%s:%d: munmap(%p,%zu) failed",
204 			 file, lineno, addr, length);
205 	}
206 
207 	return rval;
208 }
209 
safe_open(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,int oflags,...)210 int safe_open(const char *file, const int lineno, void (*cleanup_fn) (void),
211               const char *pathname, int oflags, ...)
212 {
213 	va_list ap;
214 	int rval;
215 	mode_t mode;
216 
217 	va_start(ap, oflags);
218 
219 	/* Android's NDK's mode_t is smaller than an int, which results in
220 	 * SIGILL here when passing the mode_t type.
221 	 */
222 	mode = va_arg(ap, int);
223 
224 	va_end(ap);
225 
226 	rval = open(pathname, oflags, mode);
227 	if (rval == -1) {
228 		tst_brkm(TBROK | TERRNO, cleanup_fn,
229 			 "%s:%d: open(%s,%d,0%o) failed",
230 			 file, lineno, pathname, oflags, mode);
231 	}
232 
233 	return rval;
234 }
235 
safe_pipe(const char * file,const int lineno,void (* cleanup_fn)(void),int fildes[2])236 int safe_pipe(const char *file, const int lineno, void (*cleanup_fn) (void),
237               int fildes[2])
238 {
239 	int rval;
240 
241 	rval = pipe(fildes);
242 	if (rval == -1) {
243 		tst_brkm(TBROK | TERRNO, cleanup_fn,
244 			 "%s:%d: pipe({%d,%d}) failed",
245 			 file, lineno, fildes[0], fildes[1]);
246 	}
247 
248 	return rval;
249 }
250 
safe_read(const char * file,const int lineno,void (* cleanup_fn)(void),char len_strict,int fildes,void * buf,size_t nbyte)251 ssize_t safe_read(const char *file, const int lineno, void (*cleanup_fn) (void),
252                   char len_strict, int fildes, void *buf, size_t nbyte)
253 {
254 	ssize_t rval;
255 
256 	rval = read(fildes, buf, nbyte);
257 	if (rval == -1 || (len_strict && (size_t)rval != nbyte)) {
258 		tst_brkm(TBROK | TERRNO, cleanup_fn,
259 			 "%s:%d: read(%d,%p,%zu) failed, returned %zd",
260 			 file, lineno, fildes, buf, nbyte, rval);
261 	}
262 
263 	return rval;
264 }
265 
safe_setegid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t egid)266 int safe_setegid(const char *file, const int lineno, void (*cleanup_fn) (void),
267                  gid_t egid)
268 {
269 	int rval;
270 
271 	rval = setegid(egid);
272 	if (rval == -1) {
273 		tst_brkm(TBROK | TERRNO, cleanup_fn,
274 			 "%s:%d: setegid(%u) failed",
275 			 file, lineno, (unsigned) egid);
276 	}
277 
278 	return rval;
279 }
280 
safe_seteuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t euid)281 int safe_seteuid(const char *file, const int lineno, void (*cleanup_fn) (void),
282                  uid_t euid)
283 {
284 	int rval;
285 
286 	rval = seteuid(euid);
287 	if (rval == -1) {
288 		tst_brkm(TBROK | TERRNO, cleanup_fn,
289 			 "%s:%d: seteuid(%u) failed",
290 			 file, lineno, (unsigned) euid);
291 	}
292 
293 	return rval;
294 }
295 
safe_setgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t gid)296 int safe_setgid(const char *file, const int lineno, void (*cleanup_fn) (void),
297                 gid_t gid)
298 {
299 	int rval;
300 
301 	rval = setgid(gid);
302 	if (rval == -1) {
303 		tst_brkm(TBROK | TERRNO, cleanup_fn,
304 			 "%s:%d: setgid(%u) failed",
305 			 file, lineno, (unsigned) gid);
306 	}
307 
308 	return rval;
309 }
310 
safe_setuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t uid)311 int safe_setuid(const char *file, const int lineno, void (*cleanup_fn) (void),
312                 uid_t uid)
313 {
314 	int rval;
315 
316 	rval = setuid(uid);
317 	if (rval == -1) {
318 		tst_brkm(TBROK | TERRNO, cleanup_fn,
319 			 "%s:%d: setuid(%u) failed",
320 			 file, lineno, (unsigned) uid);
321 	}
322 
323 	return rval;
324 }
325 
safe_getresuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t * ruid,uid_t * euid,uid_t * suid)326 int safe_getresuid(const char *file, const int lineno, void (*cleanup_fn)(void),
327 		   uid_t *ruid, uid_t *euid, uid_t *suid)
328 {
329 	int rval;
330 
331 	rval = getresuid(ruid, euid, suid);
332 	if (rval == -1) {
333 		tst_brkm(TBROK | TERRNO, cleanup_fn,
334 			 "%s:%d: getresuid(%p, %p, %p) failed",
335 			 file, lineno, ruid, euid, suid);
336 	}
337 
338 	return rval;
339 }
340 
safe_getresgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t * rgid,gid_t * egid,gid_t * sgid)341 int safe_getresgid(const char *file, const int lineno, void (*cleanup_fn)(void),
342 		   gid_t *rgid, gid_t *egid, gid_t *sgid)
343 {
344 	int rval;
345 
346 	rval = getresgid(rgid, egid, sgid);
347 	if (rval == -1) {
348 		tst_brkm(TBROK | TERRNO, cleanup_fn,
349 			 "%s:%d: getresgid(%p, %p, %p) failed",
350 			 file, lineno, rgid, egid, sgid);
351 	}
352 
353 	return rval;
354 }
355 
safe_unlink(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname)356 int safe_unlink(const char *file, const int lineno, void (*cleanup_fn) (void),
357                 const char *pathname)
358 {
359 	int rval;
360 
361 	rval = unlink(pathname);
362 	if (rval == -1) {
363 		tst_brkm(TBROK | TERRNO, cleanup_fn,
364 			 "%s:%d: unlink(%s) failed",
365 			 file, lineno, pathname);
366 	}
367 
368 	return rval;
369 }
370 
371 
safe_link(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)372 int safe_link(const char *file, const int lineno,
373               void (cleanup_fn)(void), const char *oldpath,
374               const char *newpath)
375 {
376 	int rval;
377 
378 	rval = link(oldpath, newpath);
379 
380 	if (rval == -1) {
381 		tst_brkm(TBROK | TERRNO, cleanup_fn,
382 		         "%s:%d: link(%s,%s) failed",
383 			 file, lineno, oldpath, newpath);
384 	}
385 
386 	return rval;
387 }
388 
safe_linkat(const char * file,const int lineno,void (cleanup_fn)(void),int olddirfd,const char * oldpath,int newdirfd,const char * newpath,int flags)389 int safe_linkat(const char *file, const int lineno,
390 		void (cleanup_fn)(void), int olddirfd, const char *oldpath,
391 		int newdirfd, const char *newpath, int flags)
392 {
393 	int rval;
394 
395 	rval = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
396 
397 	if (rval == -1) {
398 		tst_brkm(TBROK | TERRNO, cleanup_fn,
399 			 "%s:%d: linkat(%d,%s,%d,%s,%d) failed",
400 			 file, lineno, olddirfd, oldpath, newdirfd,
401 			 newpath, flags);
402 	}
403 
404 	return rval;
405 }
406 
safe_readlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,char * buf,size_t bufsize)407 ssize_t safe_readlink(const char *file, const int lineno,
408 		  void (cleanup_fn)(void), const char *path,
409 		  char *buf, size_t bufsize)
410 {
411 	ssize_t rval;
412 
413 	rval = readlink(path, buf, bufsize);
414 
415 	if (rval == -1) {
416 		tst_brkm(TBROK | TERRNO, cleanup_fn,
417 			 "%s:%d: readlink(%s,%p,%zu) failed",
418 			 file, lineno, path, buf, bufsize);
419 	} else {
420 		/* readlink does not append a NUL byte to the buffer.
421 		 * Add it now. */
422 		if ((size_t) rval < bufsize)
423 			buf[rval] = '\0';
424 		else
425 			buf[bufsize-1] = '\0';
426 	}
427 
428 	return rval;
429 }
430 
safe_symlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)431 int safe_symlink(const char *file, const int lineno,
432                  void (cleanup_fn)(void), const char *oldpath,
433                  const char *newpath)
434 {
435 	int rval;
436 
437 	rval = symlink(oldpath, newpath);
438 
439 	if (rval == -1) {
440 		tst_brkm(TBROK | TERRNO, cleanup_fn,
441 		         "%s:%d: symlink(%s,%s) failed",
442 			 file, lineno, oldpath, newpath);
443 	}
444 
445 	return rval;
446 }
447 
safe_write(const char * file,const int lineno,void (cleanup_fn)(void),char len_strict,int fildes,const void * buf,size_t nbyte)448 ssize_t safe_write(const char *file, const int lineno, void (cleanup_fn) (void),
449                    char len_strict, int fildes, const void *buf, size_t nbyte)
450 {
451 	ssize_t rval;
452 
453 	rval = write(fildes, buf, nbyte);
454 	if (rval == -1 || (len_strict && (size_t)rval != nbyte)) {
455 		tst_brkm(TBROK | TERRNO, cleanup_fn,
456 			 "%s:%d: write(%d,%p,%zu) failed",
457 		         file, lineno, fildes, buf, rval);
458 	}
459 
460 	return rval;
461 }
462 
safe_strtol(const char * file,const int lineno,void (cleanup_fn)(void),char * str,long min,long max)463 long safe_strtol(const char *file, const int lineno,
464 		 void (cleanup_fn) (void), char *str, long min, long max)
465 {
466 	long rval;
467 	char *endptr;
468 
469 	errno = 0;
470 	rval = strtol(str, &endptr, 10);
471 
472 	if ((errno == ERANGE && (rval == LONG_MAX || rval == LONG_MIN))
473 	    || (errno != 0 && rval == 0)) {
474 		tst_brkm(TBROK | TERRNO, cleanup_fn,
475 			 "%s:%d: strtol(%s) failed", file, lineno, str);
476 		return rval;
477 	}
478 
479 	if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
480 		tst_brkm(TBROK, cleanup_fn,
481 			 "%s:%d: strtol(%s): Invalid value", file, lineno, str);
482 		return 0;
483 	}
484 
485 	if (rval > max || rval < min) {
486 		tst_brkm(TBROK, cleanup_fn,
487 			 "%s:%d: strtol(%s): %ld is out of range %ld - %ld",
488 			 file, lineno, str, rval, min, max);
489 		return 0;
490 	}
491 
492 	return rval;
493 }
494 
safe_strtoul(const char * file,const int lineno,void (cleanup_fn)(void),char * str,unsigned long min,unsigned long max)495 unsigned long safe_strtoul(const char *file, const int lineno,
496 			   void (cleanup_fn) (void), char *str,
497 			   unsigned long min, unsigned long max)
498 {
499 	unsigned long rval;
500 	char *endptr;
501 
502 	errno = 0;
503 	rval = strtoul(str, &endptr, 10);
504 
505 	if ((errno == ERANGE && rval == ULONG_MAX)
506 	    || (errno != 0 && rval == 0)) {
507 		tst_brkm(TBROK | TERRNO, cleanup_fn,
508 			 "%s:%d: strtoul(%s) failed", file, lineno, str);
509 		return rval;
510 	}
511 
512 	if (rval > max || rval < min) {
513 		tst_brkm(TBROK, cleanup_fn,
514 			 "%s:%d: strtoul(%s): %lu is out of range %lu - %lu",
515 			 file, lineno, str, rval, min, max);
516 		return 0;
517 	}
518 
519 	if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
520 		tst_brkm(TBROK, cleanup_fn,
521 			 "Invalid value: '%s' at %s:%d", str, file, lineno);
522 		return 0;
523 	}
524 
525 	return rval;
526 }
527 
safe_sysconf(const char * file,const int lineno,void (cleanup_fn)(void),int name)528 long safe_sysconf(const char *file, const int lineno,
529 		  void (cleanup_fn) (void), int name)
530 {
531 	long rval;
532 	errno = 0;
533 
534 	rval = sysconf(name);
535 
536 	if (rval == -1) {
537 		if (errno) {
538 			tst_brkm(TBROK | TERRNO, cleanup_fn,
539 				 "%s:%d: sysconf(%d) failed",
540 				 file, lineno, name);
541 		} else {
542 			tst_resm(TINFO, "%s:%d: sysconf(%d): "
543 				 "queried option is not available"
544 				 " or there is no definite limit",
545 				 file, lineno, name);
546 		}
547 	}
548 
549 	return rval;
550 }
551 
safe_chmod(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,mode_t mode)552 int safe_chmod(const char *file, const int lineno,
553                void (cleanup_fn)(void), const char *path, mode_t mode)
554 {
555 	int rval;
556 
557 	rval = chmod(path, mode);
558 
559 	if (rval == -1) {
560 		tst_brkm(TBROK | TERRNO, cleanup_fn,
561 			 "%s:%d: chmod(%s,0%o) failed",
562 			 file, lineno, path, mode);
563 	}
564 
565 	return rval;
566 }
567 
safe_fchmod(const char * file,const int lineno,void (cleanup_fn)(void),int fd,mode_t mode)568 int safe_fchmod(const char *file, const int lineno,
569                 void (cleanup_fn)(void), int fd, mode_t mode)
570 {
571 	int rval;
572 
573 	rval = fchmod(fd, mode);
574 
575 	if (rval == -1) {
576 		tst_brkm(TBROK | TERRNO, cleanup_fn,
577 			 "%s:%d: fchmod(%d,0%o) failed",
578 			 file, lineno, fd, mode);
579 	}
580 
581 	return rval;
582 }
583 
safe_chown(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,uid_t owner,gid_t group)584 int safe_chown(const char *file, const int lineno, void (cleanup_fn)(void),
585 			const char *path, uid_t owner, gid_t group)
586 {
587 	int rval;
588 
589 	rval = chown(path, owner, group);
590 
591 	if (rval == -1) {
592 		tst_brkm(TBROK | TERRNO, cleanup_fn,
593 			"%s:%d: chown(%s,%d,%d) failed",
594 			file, lineno, path, owner, group);
595 	}
596 
597 	return rval;
598 }
599 
safe_fchown(const char * file,const int lineno,void (cleanup_fn)(void),int fd,uid_t owner,gid_t group)600 int safe_fchown(const char *file, const int lineno, void (cleanup_fn)(void),
601                 int fd, uid_t owner, gid_t group)
602 {
603 	int rval;
604 
605 	rval = fchown(fd, owner, group);
606 
607 	if (rval == -1) {
608 		tst_brkm(TBROK | TERRNO, cleanup_fn,
609 		         "%s:%d: fchown(%d,%d,%d) failed",
610 			 file, lineno, fd, owner, group);
611 	}
612 
613 	return rval;
614 }
615 
safe_wait(const char * file,const int lineno,void (cleanup_fn)(void),int * status)616 pid_t safe_wait(const char *file, const int lineno, void (cleanup_fn)(void),
617                 int *status)
618 {
619 	pid_t rval;
620 
621 	rval = wait(status);
622 	if (rval == -1) {
623 		tst_brkm(TBROK | TERRNO, cleanup_fn,
624 			 "%s:%d: wait(%p) failed",
625 			 file, lineno, status);
626 	}
627 
628 	return rval;
629 }
630 
safe_waitpid(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int * status,int opts)631 pid_t safe_waitpid(const char *file, const int lineno, void (cleanup_fn)(void),
632                    pid_t pid, int *status, int opts)
633 {
634 	pid_t rval;
635 
636 	rval = waitpid(pid, status, opts);
637 	if (rval == -1) {
638 		tst_brkm(TBROK | TERRNO, cleanup_fn,
639 			 "%s:%d: waitpid(%d,%p,%d) failed",
640 			 file, lineno, pid, status, opts);
641 	}
642 
643 	return rval;
644 }
645 
safe_memalign(const char * file,const int lineno,void (* cleanup_fn)(void),size_t alignment,size_t size)646 void *safe_memalign(const char *file, const int lineno,
647 		    void (*cleanup_fn) (void), size_t alignment, size_t size)
648 {
649 	void *rval;
650 
651 	rval = memalign(alignment, size);
652 	if (rval == NULL)
653 		tst_brkm(TBROK | TERRNO, cleanup_fn, "memalign failed at %s:%d",
654 			 file, lineno);
655 
656 	return rval;
657 }
658 
safe_kill(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int sig)659 int safe_kill(const char *file, const int lineno, void (cleanup_fn)(void),
660 	      pid_t pid, int sig)
661 {
662 	int rval;
663 
664 	rval = kill(pid, sig);
665 
666 	if (rval == -1) {
667 		tst_brkm(TBROK | TERRNO, cleanup_fn,
668 			 "%s:%d: kill(%d,%s) failed",
669 			 file, lineno, pid, tst_strsig(sig));
670 	}
671 
672 	return rval;
673 }
674 
safe_mkfifo(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)675 int safe_mkfifo(const char *file, const int lineno,
676                 void (*cleanup_fn)(void), const char *pathname, mode_t mode)
677 {
678 	int rval;
679 
680 	rval = mkfifo(pathname, mode);
681 
682 	if (rval == -1) {
683 		tst_brkm(TBROK | TERRNO, cleanup_fn,
684 		         "%s:%d: mkfifo(%s, 0%o) failed",
685 			 file, lineno, pathname, mode);
686 	}
687 
688 	return rval;
689 }
690 
safe_rename(const char * file,const int lineno,void (* cleanup_fn)(void),const char * oldpath,const char * newpath)691 int safe_rename(const char *file, const int lineno, void (*cleanup_fn)(void),
692 		const char *oldpath, const char *newpath)
693 {
694 	int rval;
695 
696 	rval = rename(oldpath, newpath);
697 
698 	if (rval == -1) {
699 		tst_brkm(TBROK | TERRNO, cleanup_fn,
700 			 "%s:%d: rename(%s, %s) failed",
701 			 file, lineno, oldpath, newpath);
702 	}
703 
704 	return rval;
705 }
706 
707 static const char *const fuse_fs_types[] = {
708 	"exfat",
709 	"ntfs",
710 };
711 
possibly_fuse(const char * fs_type)712 static int possibly_fuse(const char *fs_type)
713 {
714 	unsigned int i;
715 
716 	if (!fs_type)
717 		return 0;
718 
719 	for (i = 0; i < ARRAY_SIZE(fuse_fs_types); i++) {
720 		if (!strcmp(fuse_fs_types[i], fs_type))
721 			return 1;
722 	}
723 
724 	return 0;
725 }
726 
safe_mount(const char * file,const int lineno,void (* cleanup_fn)(void),const char * source,const char * target,const char * filesystemtype,unsigned long mountflags,const void * data)727 int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
728 	       const char *source, const char *target,
729 	       const char *filesystemtype, unsigned long mountflags,
730 	       const void *data)
731 {
732 	int rval;
733 
734 	/*
735 	 * Don't try using the kernel's NTFS driver when mounting NTFS, since
736 	 * the kernel's NTFS driver doesn't have proper write support.
737 	 */
738 	if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
739 		rval = mount(source, target, filesystemtype, mountflags, data);
740 		if (!rval)
741 			return 0;
742 	}
743 
744 	/*
745 	 * The FUSE filesystem executes mount.fuse helper, which tries to
746 	 * execute corresponding binary name which is encoded at the start of
747 	 * the source string and separated by # from the device name.
748          *
749 	 * The mount helpers are called mount.$fs_type.
750 	 */
751 	if (possibly_fuse(filesystemtype)) {
752 		char buf[1024];
753 
754 		tst_resm(TINFO, "Trying FUSE...");
755 		snprintf(buf, sizeof(buf), "mount.%s '%s' '%s'",
756 			 filesystemtype, source, target);
757 
758 		rval = tst_system(buf);
759 		if (WIFEXITED(rval) && WEXITSTATUS(rval) == 0)
760 			return 0;
761 
762 		tst_brkm(TBROK, cleanup_fn, "mount.%s failed with %i",
763 			 filesystemtype, rval);
764 		return -1;
765 	} else {
766 		tst_brkm(TBROK | TERRNO, cleanup_fn,
767 			 "%s:%d: mount(%s, %s, %s, %lu, %p) failed",
768 			 file, lineno, source, target, filesystemtype,
769 			 mountflags, data);
770 	}
771 
772 	return -1;
773 }
774 
safe_umount(const char * file,const int lineno,void (* cleanup_fn)(void),const char * target)775 int safe_umount(const char *file, const int lineno, void (*cleanup_fn)(void),
776 		const char *target)
777 {
778 	int rval;
779 
780 	rval = tst_umount(target);
781 
782 	if (rval == -1) {
783 		tst_brkm(TBROK | TERRNO, cleanup_fn,
784 			 "%s:%d: umount(%s) failed",
785 			 file, lineno, target);
786 	}
787 
788 	return rval;
789 }
790 
safe_opendir(const char * file,const int lineno,void (cleanup_fn)(void),const char * name)791 DIR* safe_opendir(const char *file, const int lineno, void (cleanup_fn)(void),
792                   const char *name)
793 {
794 	DIR *rval;
795 
796 	rval = opendir(name);
797 
798 	if (!rval) {
799 		tst_brkm(TBROK | TERRNO, cleanup_fn,
800 		         "%s:%d: opendir(%s) failed", file, lineno, name);
801 	}
802 
803 	return rval;
804 }
805 
safe_closedir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)806 int safe_closedir(const char *file, const int lineno, void (cleanup_fn)(void),
807                   DIR *dirp)
808 {
809 	int rval;
810 
811 	rval = closedir(dirp);
812 
813 	if (rval) {
814 		tst_brkm(TBROK | TERRNO, cleanup_fn,
815 		         "%s:%d: closedir(%p) failed", file, lineno, dirp);
816 	}
817 
818 	return rval;
819 }
820 
safe_readdir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)821 struct dirent *safe_readdir(const char *file, const int lineno, void (cleanup_fn)(void),
822                             DIR *dirp)
823 {
824 	struct dirent *rval;
825 	int err = errno;
826 
827 	errno = 0;
828 	rval = readdir(dirp);
829 
830 	if (!rval && errno) {
831 		tst_brkm(TBROK | TERRNO, cleanup_fn,
832 		         "%s:%d: readdir(%p) failed", file, lineno, dirp);
833 	}
834 
835 	errno = err;
836 	return rval;
837 }
838 
safe_getpriority(const char * file,const int lineno,int which,id_t who)839 int safe_getpriority(const char *file, const int lineno, int which, id_t who)
840 {
841 	int rval, err = errno;
842 
843 	errno = 0;
844 	rval = getpriority(which, who);
845 	if (errno) {
846 		tst_brkm(TBROK | TERRNO, NULL,
847 		         "%s:%d getpriority(%i, %i) failed",
848 			 file, lineno, which, who);
849 	}
850 
851 	errno = err;
852 	return rval;
853 }
854 
safe_getxattr(const char * file,const int lineno,const char * path,const char * name,void * value,size_t size)855 ssize_t safe_getxattr(const char *file, const int lineno, const char *path,
856 		      const char *name, void *value, size_t size)
857 {
858 	ssize_t rval;
859 
860 	rval = getxattr(path, name, value, size);
861 
862 	if (rval == -1) {
863 		if (errno == ENOTSUP) {
864 			tst_brkm(TCONF, NULL,
865 				 "%s:%d: no xattr support in fs or mounted "
866 				 "without user_xattr option", file, lineno);
867 		}
868 
869 		tst_brkm(TBROK | TERRNO, NULL,
870 			 "%s:%d: getxattr(%s, %s, %p, %zu) failed",
871 			 file, lineno, path, name, value, size);
872 	}
873 
874 	return rval;
875 }
876 
safe_setxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)877 int safe_setxattr(const char *file, const int lineno, const char *path,
878 		  const char *name, const void *value, size_t size, int flags)
879 {
880 	int rval;
881 
882 	rval = setxattr(path, name, value, size, flags);
883 
884 	if (rval) {
885 		if (errno == ENOTSUP) {
886 			tst_brkm(TCONF, NULL,
887 				 "%s:%d: no xattr support in fs or mounted "
888 				 "without user_xattr option", file, lineno);
889 		}
890 
891 		tst_brkm(TBROK | TERRNO, NULL,
892 			 "%s:%d: setxattr(%s, %s, %p, %zu) failed",
893 			 file, lineno, path, name, value, size);
894 	}
895 
896 	return rval;
897 }
898 
safe_lsetxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)899 int safe_lsetxattr(const char *file, const int lineno, const char *path,
900 		   const char *name, const void *value, size_t size, int flags)
901 {
902 	int rval;
903 
904 	rval = lsetxattr(path, name, value, size, flags);
905 
906 	if (rval) {
907 		if (errno == ENOTSUP) {
908 			tst_brkm(TCONF, NULL,
909 				 "%s:%d: no xattr support in fs or mounted "
910 				 "without user_xattr option", file, lineno);
911 		}
912 
913 		tst_brkm(TBROK | TERRNO, NULL,
914 			 "%s:%d: lsetxattr(%s, %s, %p, %zu, %i) failed",
915 			 file, lineno, path, name, value, size, flags);
916 	}
917 
918 	return rval;
919 }
920 
safe_fsetxattr(const char * file,const int lineno,int fd,const char * name,const void * value,size_t size,int flags)921 int safe_fsetxattr(const char *file, const int lineno, int fd, const char *name,
922 		   const void *value, size_t size, int flags)
923 {
924 	int rval;
925 
926 	rval = fsetxattr(fd, name, value, size, flags);
927 
928 	if (rval) {
929 		if (errno == ENOTSUP) {
930 			tst_brkm(TCONF, NULL,
931 				 "%s:%d: no xattr support in fs or mounted "
932 				 "without user_xattr option", file, lineno);
933 		}
934 
935 		tst_brkm(TBROK | TERRNO, NULL,
936 			 "%s:%d: fsetxattr(%i, %s, %p, %zu, %i) failed",
937 			 file, lineno, fd, name, value, size, flags);
938 	}
939 
940 	return rval;
941 }
942 
safe_removexattr(const char * file,const int lineno,const char * path,const char * name)943 int safe_removexattr(const char *file, const int lineno, const char *path,
944 		const char *name)
945 {
946 	int rval;
947 
948 	rval = removexattr(path, name);
949 
950 	if (rval) {
951 		if (errno == ENOTSUP) {
952 			tst_brkm(TCONF, NULL,
953 				"%s:%d: no xattr support in fs or mounted "
954 				"without user_xattr option", file, lineno);
955 		}
956 
957 		tst_brkm(TBROK | TERRNO, NULL,
958 			 "%s:%d: removexattr(%s, %s) failed",
959 			 file, lineno, path, name);
960 	}
961 
962 	return rval;
963 }
964 
safe_lremovexattr(const char * file,const int lineno,const char * path,const char * name)965 int safe_lremovexattr(const char *file, const int lineno, const char *path,
966 		const char *name)
967 {
968 	int rval;
969 
970 	rval = lremovexattr(path, name);
971 
972 	if (rval) {
973 		if (errno == ENOTSUP) {
974 			tst_brkm(TCONF, NULL,
975 				"%s:%d: no xattr support in fs or mounted "
976 				"without user_xattr option", file, lineno);
977 		}
978 
979 		tst_brkm(TBROK | TERRNO, NULL,
980 			 "%s:%d: lremovexattr(%s, %s) failed",
981 			 file, lineno, path, name);
982 	}
983 
984 	return rval;
985 }
986 
safe_fremovexattr(const char * file,const int lineno,int fd,const char * name)987 int safe_fremovexattr(const char *file, const int lineno, int fd,
988 		const char *name)
989 {
990 	int rval;
991 
992 	rval = fremovexattr(fd, name);
993 
994 	if (rval) {
995 		if (errno == ENOTSUP) {
996 			tst_brkm(TCONF, NULL,
997 				"%s:%d: no xattr support in fs or mounted "
998 				"without user_xattr option", file, lineno);
999 		}
1000 
1001 		tst_brkm(TBROK | TERRNO, NULL,
1002 			 "%s:%d: fremovexattr(%i, %s) failed",
1003 			 file, lineno, fd, name);
1004 	}
1005 
1006 	return rval;
1007 }
1008 
safe_fsync(const char * file,const int lineno,int fd)1009 int safe_fsync(const char *file, const int lineno, int fd)
1010 {
1011 	int rval;
1012 
1013 	rval = fsync(fd);
1014 
1015 	if (rval) {
1016 		tst_brkm(TBROK | TERRNO, NULL,
1017 			"%s:%d: fsync(%i) failed", file, lineno, fd);
1018 	}
1019 
1020 	return rval;
1021 }
1022 
safe_setsid(const char * file,const int lineno)1023 pid_t safe_setsid(const char *file, const int lineno)
1024 {
1025 	pid_t rval;
1026 
1027 	rval = setsid();
1028 	if (rval == -1) {
1029 		tst_brkm(TBROK | TERRNO, NULL,
1030 			 "%s:%d: setsid() failed", file, lineno);
1031 	}
1032 
1033 	return rval;
1034 }
1035 
safe_mknod(const char * file,const int lineno,const char * pathname,mode_t mode,dev_t dev)1036 int safe_mknod(const char *file, const int lineno, const char *pathname,
1037 	mode_t mode, dev_t dev)
1038 {
1039 	int rval;
1040 
1041 	rval = mknod(pathname, mode, dev);
1042 	if (rval == -1) {
1043 		tst_brkm(TBROK | TERRNO, NULL,
1044 			 "%s:%d: mknod() failed", file, lineno);
1045 	}
1046 
1047 	return rval;
1048 }
1049 
safe_mlock(const char * file,const int lineno,const void * addr,size_t len)1050 int safe_mlock(const char *file, const int lineno, const void *addr,
1051 	size_t len)
1052 {
1053 	int rval;
1054 
1055 	rval = mlock(addr, len);
1056 	if (rval == -1) {
1057 		tst_brkm(TBROK | TERRNO, NULL,
1058 			 "%s:%d: mlock() failed", file, lineno);
1059 	}
1060 
1061 	return rval;
1062 }
1063 
safe_munlock(const char * file,const int lineno,const void * addr,size_t len)1064 int safe_munlock(const char *file, const int lineno, const void *addr,
1065 	size_t len)
1066 {
1067 	int rval;
1068 
1069 	rval = munlock(addr, len);
1070 	if (rval == -1) {
1071 		tst_brkm(TBROK | TERRNO, NULL,
1072 			 "%s:%d: munlock() failed", file, lineno);
1073 	}
1074 
1075 	return rval;
1076 }
1077 
safe_mincore(const char * file,const int lineno,void * start,size_t length,unsigned char * vec)1078 int safe_mincore(const char *file, const int lineno, void *start,
1079 	size_t length, unsigned char *vec)
1080 {
1081 	int rval;
1082 
1083 	rval = mincore(start, length, vec);
1084 	if (rval == -1) {
1085 		tst_brkm(TBROK | TERRNO, NULL,
1086 			 "%s:%d: mincore() failed", file, lineno);
1087 	}
1088 
1089 	return rval;
1090 }
1091