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