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