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