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) {
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 } else if (len_strict && (size_t)rval != nbyte) {
305 tst_brkm_(file, lineno, TBROK, cleanup_fn,
306 "Short read(%d,%p,%zu) returned only %zd",
307 fildes, buf, nbyte, rval);
308 }
309
310 return rval;
311 }
312
safe_setegid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t egid)313 int safe_setegid(const char *file, const int lineno, void (*cleanup_fn) (void),
314 gid_t egid)
315 {
316 int rval;
317
318 rval = setegid(egid);
319
320 if (rval == -1) {
321 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
322 "setegid(%u) failed", (unsigned int)egid);
323 } else if (rval) {
324 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
325 "Invalid setegid(%u) return value %d",
326 (unsigned int)egid, rval);
327 }
328
329 return rval;
330 }
331
safe_seteuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t euid)332 int safe_seteuid(const char *file, const int lineno, void (*cleanup_fn) (void),
333 uid_t euid)
334 {
335 int rval;
336
337 rval = seteuid(euid);
338
339 if (rval == -1) {
340 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
341 "seteuid(%u) failed", (unsigned int)euid);
342 } else if (rval) {
343 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
344 "Invalid seteuid(%u) return value %d",
345 (unsigned int)euid, rval);
346 }
347
348 return rval;
349 }
350
safe_setgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t gid)351 int safe_setgid(const char *file, const int lineno, void (*cleanup_fn) (void),
352 gid_t gid)
353 {
354 int rval;
355
356 rval = setgid(gid);
357
358 if (rval == -1) {
359 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
360 "setgid(%u) failed", (unsigned int)gid);
361 } else if (rval) {
362 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
363 "Invalid setgid(%u) return value %d",
364 (unsigned int)gid, rval);
365 }
366
367 return rval;
368 }
369
safe_setuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t uid)370 int safe_setuid(const char *file, const int lineno, void (*cleanup_fn) (void),
371 uid_t uid)
372 {
373 int rval;
374
375 rval = setuid(uid);
376
377 if (rval == -1) {
378 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
379 "setuid(%u) failed", (unsigned int)uid);
380 } else if (rval) {
381 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
382 "Invalid setuid(%u) return value %d",
383 (unsigned int)uid, rval);
384 }
385
386 return rval;
387 }
388
safe_getresuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t * ruid,uid_t * euid,uid_t * suid)389 int safe_getresuid(const char *file, const int lineno, void (*cleanup_fn)(void),
390 uid_t *ruid, uid_t *euid, uid_t *suid)
391 {
392 int rval;
393
394 rval = getresuid(ruid, euid, suid);
395
396 if (rval == -1) {
397 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
398 "getresuid(%p, %p, %p) failed", ruid, euid, suid);
399 } else if (rval) {
400 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
401 "Invalid getresuid(%p, %p, %p) return value %d", ruid,
402 euid, suid, rval);
403 }
404
405 return rval;
406 }
407
safe_getresgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t * rgid,gid_t * egid,gid_t * sgid)408 int safe_getresgid(const char *file, const int lineno, void (*cleanup_fn)(void),
409 gid_t *rgid, gid_t *egid, gid_t *sgid)
410 {
411 int rval;
412
413 rval = getresgid(rgid, egid, sgid);
414
415 if (rval == -1) {
416 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
417 "getresgid(%p, %p, %p) failed", rgid, egid, sgid);
418 } else if (rval) {
419 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
420 "Invalid getresgid(%p, %p, %p) return value %d", rgid,
421 egid, sgid, rval);
422 }
423
424 return rval;
425 }
426
safe_unlink(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname)427 int safe_unlink(const char *file, const int lineno, void (*cleanup_fn) (void),
428 const char *pathname)
429 {
430 int rval;
431
432 rval = unlink(pathname);
433
434 if (rval == -1) {
435 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
436 "unlink(%s) failed", pathname);
437 } else if (rval) {
438 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
439 "Invalid unlink(%s) return value %d", pathname, rval);
440 }
441
442 return rval;
443 }
444
445
safe_link(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)446 int safe_link(const char *file, const int lineno,
447 void (cleanup_fn)(void), const char *oldpath,
448 const char *newpath)
449 {
450 int rval;
451
452 rval = link(oldpath, newpath);
453
454 if (rval == -1) {
455 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
456 "link(%s,%s) failed", oldpath, newpath);
457 } else if (rval) {
458 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
459 "Invalid link(%s,%s) return value %d", oldpath,
460 newpath, rval);
461 }
462
463 return rval;
464 }
465
safe_linkat(const char * file,const int lineno,void (cleanup_fn)(void),int olddirfd,const char * oldpath,int newdirfd,const char * newpath,int flags)466 int safe_linkat(const char *file, const int lineno,
467 void (cleanup_fn)(void), int olddirfd, const char *oldpath,
468 int newdirfd, const char *newpath, int flags)
469 {
470 int rval;
471
472 rval = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
473
474 if (rval == -1) {
475 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
476 "linkat(%d,%s,%d,%s,%d) failed", olddirfd, oldpath,
477 newdirfd, newpath, flags);
478 } else if (rval) {
479 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
480 "Invalid linkat(%d,%s,%d,%s,%d) return value %d",
481 olddirfd, oldpath, newdirfd, newpath, flags, rval);
482 }
483
484 return rval;
485 }
486
safe_readlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,char * buf,size_t bufsize)487 ssize_t safe_readlink(const char *file, const int lineno,
488 void (cleanup_fn)(void), const char *path,
489 char *buf, size_t bufsize)
490 {
491 ssize_t rval;
492
493 rval = readlink(path, buf, bufsize);
494
495 if (rval == -1) {
496 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
497 "readlink(%s,%p,%zu) failed", path, buf, bufsize);
498 } else if (rval < 0) {
499 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
500 "Invalid readlink(%s,%p,%zu) return value %zd", path,
501 buf, bufsize, rval);
502 } else {
503 /* readlink does not append a NUL byte to the buffer.
504 * Add it now. */
505 if ((size_t) rval < bufsize)
506 buf[rval] = '\0';
507 else
508 buf[bufsize-1] = '\0';
509 }
510
511 return rval;
512 }
513
safe_symlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)514 int safe_symlink(const char *file, const int lineno,
515 void (cleanup_fn)(void), const char *oldpath,
516 const char *newpath)
517 {
518 int rval;
519
520 rval = symlink(oldpath, newpath);
521
522 if (rval == -1) {
523 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
524 "symlink(%s,%s) failed", oldpath, newpath);
525 } else if (rval) {
526 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
527 "Invalid symlink(%s,%s) return value %d", oldpath,
528 newpath, rval);
529 }
530
531 return rval;
532 }
533
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)534 ssize_t safe_write(const char *file, const int lineno, void (cleanup_fn) (void),
535 enum safe_write_opts len_strict, int fildes, const void *buf,
536 size_t nbyte)
537 {
538 ssize_t rval;
539 const void *wbuf = buf;
540 size_t len = nbyte;
541 int iter = 0;
542
543 do {
544 iter++;
545 rval = write(fildes, wbuf, len);
546 if (rval == -1) {
547 if (len_strict == SAFE_WRITE_RETRY)
548 tst_resm_(file, lineno, TINFO,
549 "write() wrote %zu bytes in %d calls",
550 nbyte-len, iter);
551 tst_brkm_(file, lineno, TBROK | TERRNO,
552 cleanup_fn, "write(%d,%p,%zu) failed",
553 fildes, buf, nbyte);
554 return rval;
555 }
556
557 if (rval < 0) {
558 tst_brkm_(file, lineno, TBROK, cleanup_fn,
559 "invalid write() return value %zi",
560 rval);
561 return rval;
562 }
563
564 if (len_strict == SAFE_WRITE_ANY)
565 return rval;
566
567 if (len_strict == SAFE_WRITE_ALL) {
568 if ((size_t)rval != nbyte)
569 tst_brkm_(file, lineno, TBROK,
570 cleanup_fn, "short write(%d,%p,%zu) "
571 "return value %zd",
572 fildes, buf, nbyte, rval);
573 return rval;
574 }
575
576 wbuf += rval;
577 len -= rval;
578 } while (len > 0);
579
580 return rval;
581 }
582
safe_strtol(const char * file,const int lineno,void (cleanup_fn)(void),char * str,long min,long max)583 long safe_strtol(const char *file, const int lineno,
584 void (cleanup_fn) (void), char *str, long min, long max)
585 {
586 long rval;
587 char *endptr;
588
589 errno = 0;
590 rval = strtol(str, &endptr, 10);
591
592 if ((errno == ERANGE && (rval == LONG_MAX || rval == LONG_MIN))
593 || (errno != 0 && rval == 0)) {
594 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
595 "strtol(%s) failed", str);
596 return rval;
597 }
598
599 if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
600 tst_brkm_(file, lineno, TBROK, cleanup_fn,
601 "strtol(%s): Invalid value", str);
602 return 0;
603 }
604
605 if (rval > max || rval < min) {
606 tst_brkm_(file, lineno, TBROK, cleanup_fn,
607 "strtol(%s): %ld is out of range %ld - %ld",
608 str, rval, min, max);
609 return 0;
610 }
611
612 return rval;
613 }
614
safe_strtoul(const char * file,const int lineno,void (cleanup_fn)(void),char * str,unsigned long min,unsigned long max)615 unsigned long safe_strtoul(const char *file, const int lineno,
616 void (cleanup_fn) (void), char *str,
617 unsigned long min, unsigned long max)
618 {
619 unsigned long rval;
620 char *endptr;
621
622 errno = 0;
623 rval = strtoul(str, &endptr, 10);
624
625 if ((errno == ERANGE && rval == ULONG_MAX)
626 || (errno != 0 && rval == 0)) {
627 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
628 "strtoul(%s) failed", str);
629 return rval;
630 }
631
632 if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
633 tst_brkm_(file, lineno, TBROK, cleanup_fn,
634 "Invalid value: '%s'", str);
635 return 0;
636 }
637
638 if (rval > max || rval < min) {
639 tst_brkm_(file, lineno, TBROK, cleanup_fn,
640 "strtoul(%s): %lu is out of range %lu - %lu",
641 str, rval, min, max);
642 return 0;
643 }
644
645 return rval;
646 }
647
safe_strtof(const char * file,const int lineno,void (cleanup_fn)(void),char * str,float min,float max)648 float safe_strtof(const char *file, const int lineno,
649 void (cleanup_fn) (void), char *str,
650 float min, float max)
651 {
652 float rval;
653 char *endptr;
654
655 errno = 0;
656 rval = strtof(str, &endptr);
657
658 if (errno) {
659 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
660 "strtof(%s) failed", str);
661 return rval;
662 }
663
664 if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
665 tst_brkm_(file, lineno, TBROK, cleanup_fn,
666 "Invalid value: '%s'", str);
667 return 0;
668 }
669
670 if (rval > max || rval < min) {
671 tst_brkm_(file, lineno, TBROK, cleanup_fn,
672 "strtof(%s): %f is out of range %f - %f",
673 str, rval, min, max);
674 return 0;
675 }
676
677 return rval;
678 }
679
safe_sysconf(const char * file,const int lineno,void (cleanup_fn)(void),int name)680 long safe_sysconf(const char *file, const int lineno,
681 void (cleanup_fn) (void), int name)
682 {
683 long rval;
684
685 errno = 0;
686 rval = sysconf(name);
687
688 if (rval == -1) {
689 if (errno) {
690 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
691 "sysconf(%d) failed", name);
692 } else {
693 tst_resm_(file, lineno, TINFO,
694 "sysconf(%d): queried option is not available or there is no definite limit",
695 name);
696 }
697 }
698
699 return rval;
700 }
701
safe_chmod(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,mode_t mode)702 int safe_chmod(const char *file, const int lineno,
703 void (cleanup_fn)(void), const char *path, mode_t mode)
704 {
705 int rval;
706
707 rval = chmod(path, mode);
708
709 if (rval == -1) {
710 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
711 "chmod(%s,%04o) failed", path, mode);
712 } else if (rval) {
713 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
714 "Invalid chmod(%s,%04o) return value %d", path, mode,
715 rval);
716 }
717
718 return rval;
719 }
720
safe_fchmod(const char * file,const int lineno,void (cleanup_fn)(void),int fd,mode_t mode)721 int safe_fchmod(const char *file, const int lineno,
722 void (cleanup_fn)(void), int fd, mode_t mode)
723 {
724 int rval;
725
726 rval = fchmod(fd, mode);
727
728 if (rval == -1) {
729 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
730 "fchmod(%d,%04o) failed", fd, mode);
731 } else if (rval) {
732 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
733 "Invalid fchmod(%d,%04o) return value %d", fd, mode,
734 rval);
735 }
736
737 return rval;
738 }
739
safe_chown(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,uid_t owner,gid_t group)740 int safe_chown(const char *file, const int lineno, void (cleanup_fn)(void),
741 const char *path, uid_t owner, gid_t group)
742 {
743 int rval;
744
745 rval = chown(path, owner, group);
746
747 if (rval == -1) {
748 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
749 "chown(%s,%d,%d) failed", path, owner, group);
750 } else if (rval) {
751 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
752 "Invalid chown(%s,%d,%d) return value %d", path,
753 owner, group, rval);
754 }
755
756 return rval;
757 }
758
safe_fchown(const char * file,const int lineno,void (cleanup_fn)(void),int fd,uid_t owner,gid_t group)759 int safe_fchown(const char *file, const int lineno, void (cleanup_fn)(void),
760 int fd, uid_t owner, gid_t group)
761 {
762 int rval;
763
764 rval = fchown(fd, owner, group);
765
766 if (rval == -1) {
767 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
768 "fchown(%d,%d,%d) failed", fd, owner, group);
769 } else if (rval) {
770 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
771 "Invalid fchown(%d,%d,%d) return value %d", fd,
772 owner, group, rval);
773 }
774
775 return rval;
776 }
777
safe_wait(const char * file,const int lineno,void (cleanup_fn)(void),int * status)778 pid_t safe_wait(const char *file, const int lineno, void (cleanup_fn)(void),
779 int *status)
780 {
781 pid_t rval;
782
783 rval = wait(status);
784
785 if (rval == -1) {
786 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
787 "wait(%p) failed", status);
788 } else if (rval < 0) {
789 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
790 "Invalid wait(%p) return value %d", status, rval);
791 }
792
793 return rval;
794 }
795
safe_waitpid(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int * status,int opts)796 pid_t safe_waitpid(const char *file, const int lineno, void (cleanup_fn)(void),
797 pid_t pid, int *status, int opts)
798 {
799 pid_t rval;
800
801 rval = waitpid(pid, status, opts);
802
803 if (rval == -1) {
804 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
805 "waitpid(%d,%p,%d) failed", pid, status, opts);
806 } else if (rval < 0) {
807 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
808 "Invalid waitpid(%d,%p,%d) return value %d", pid,
809 status, opts, rval);
810 }
811
812 return rval;
813 }
814
safe_memalign(const char * file,const int lineno,void (* cleanup_fn)(void),size_t alignment,size_t size)815 void *safe_memalign(const char *file, const int lineno,
816 void (*cleanup_fn) (void), size_t alignment, size_t size)
817 {
818 void *rval;
819
820 rval = memalign(alignment, size);
821
822 if (rval == NULL) {
823 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
824 "memalign() failed");
825 }
826
827 return rval;
828 }
829
safe_kill(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int sig)830 int safe_kill(const char *file, const int lineno, void (cleanup_fn)(void),
831 pid_t pid, int sig)
832 {
833 int rval;
834
835 rval = kill(pid, sig);
836
837 if (rval == -1) {
838 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
839 "kill(%d,%s) failed", pid, tst_strsig(sig));
840 } else if (rval) {
841 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
842 "Invalid kill(%d,%s) return value %d", pid,
843 tst_strsig(sig), rval);
844 }
845
846 return rval;
847 }
848
safe_mkfifo(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)849 int safe_mkfifo(const char *file, const int lineno,
850 void (*cleanup_fn)(void), const char *pathname, mode_t mode)
851 {
852 int rval;
853
854 rval = mkfifo(pathname, mode);
855
856 if (rval == -1) {
857 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
858 "mkfifo(%s, %04o) failed", pathname, mode);
859 } else if (rval) {
860 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
861 "Invalid mkfifo(%s, %04o) return value %d", pathname,
862 mode, rval);
863 }
864
865 return rval;
866 }
867
safe_rename(const char * file,const int lineno,void (* cleanup_fn)(void),const char * oldpath,const char * newpath)868 int safe_rename(const char *file, const int lineno, void (*cleanup_fn)(void),
869 const char *oldpath, const char *newpath)
870 {
871 int rval;
872
873 rval = rename(oldpath, newpath);
874
875 if (rval == -1) {
876 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
877 "rename(%s, %s) failed", oldpath, newpath);
878 } else if (rval) {
879 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
880 "Invalid rename(%s, %s) return value %d", oldpath,
881 newpath, rval);
882 }
883
884 return rval;
885 }
886
887 static const char *const fuse_fs_types[] = {
888 "exfat",
889 "ntfs",
890 };
891
possibly_fuse(const char * fs_type)892 static int possibly_fuse(const char *fs_type)
893 {
894 unsigned int i;
895
896 if (!fs_type)
897 return 0;
898
899 for (i = 0; i < ARRAY_SIZE(fuse_fs_types); i++) {
900 if (!strcmp(fuse_fs_types[i], fs_type))
901 return 1;
902 }
903
904 return 0;
905 }
906
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)907 int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
908 const char *source, const char *target,
909 const char *filesystemtype, unsigned long mountflags,
910 const void *data)
911 {
912 int rval = -1;
913 char mpath[PATH_MAX];
914
915 if (realpath(target, mpath)) {
916 tst_resm_(file, lineno, TINFO,
917 "Mounting %s to %s fstyp=%s flags=%lx",
918 source, mpath, filesystemtype, mountflags);
919 } else {
920 tst_resm_(file, lineno, TINFO | TERRNO,
921 "Cannot resolve the absolute path of %s", target);
922 }
923 /*
924 * Don't try using the kernel's NTFS driver when mounting NTFS, since
925 * the kernel's NTFS driver doesn't have proper write support.
926 */
927 if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
928 mode_t old_umask = umask(0);
929
930 rval = mount(source, target, filesystemtype, mountflags, data);
931 umask(old_umask);
932 if (!rval)
933 return 0;
934 }
935
936 /*
937 * The FUSE filesystem executes mount.fuse helper, which tries to
938 * execute corresponding binary name which is encoded at the start of
939 * the source string and separated by # from the device name.
940 *
941 * The mount helpers are called mount.$fs_type.
942 */
943 if (possibly_fuse(filesystemtype)) {
944 char buf[1024];
945
946 tst_resm_(file, lineno, TINFO, "Trying FUSE...");
947 snprintf(buf, sizeof(buf), "mount.%s '%s' '%s'",
948 filesystemtype, source, target);
949
950 rval = tst_system(buf);
951 if (WIFEXITED(rval) && WEXITSTATUS(rval) == 0)
952 return 0;
953
954 tst_brkm_(file, lineno, TBROK, cleanup_fn,
955 "mount.%s failed with %i", filesystemtype, rval);
956 return -1;
957 } else if (rval == -1) {
958 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
959 "mount(%s, %s, %s, %lu, %p) failed", source, target,
960 filesystemtype, mountflags, data);
961 } else {
962 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
963 "Invalid mount(%s, %s, %s, %lu, %p) return value %d",
964 source, target, filesystemtype, mountflags, data,
965 rval);
966 }
967
968 return rval;
969 }
970
safe_umount(const char * file,const int lineno,void (* cleanup_fn)(void),const char * target)971 int safe_umount(const char *file, const int lineno, void (*cleanup_fn)(void),
972 const char *target)
973 {
974 int rval;
975 char mpath[PATH_MAX];
976
977 if (realpath(target, mpath)) {
978 tst_resm_(file, lineno, TINFO, "Umounting %s", mpath);
979 } else {
980 tst_resm_(file, lineno, TINFO | TERRNO,
981 "Cannot resolve the absolute path of %s", target);
982 }
983
984 rval = tst_umount(target);
985
986 if (rval == -1) {
987 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
988 "umount(%s) failed", target);
989 } else if (rval) {
990 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
991 "Invalid umount(%s) return value %d", target, rval);
992 }
993
994 return rval;
995 }
996
safe_opendir(const char * file,const int lineno,void (cleanup_fn)(void),const char * name)997 DIR* safe_opendir(const char *file, const int lineno, void (cleanup_fn)(void),
998 const char *name)
999 {
1000 DIR *rval;
1001
1002 rval = opendir(name);
1003
1004 if (!rval) {
1005 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1006 "opendir(%s) failed", name);
1007 }
1008
1009 return rval;
1010 }
1011
safe_closedir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)1012 int safe_closedir(const char *file, const int lineno, void (cleanup_fn)(void),
1013 DIR *dirp)
1014 {
1015 int rval;
1016
1017 rval = closedir(dirp);
1018
1019 if (rval == -1) {
1020 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1021 "closedir(%p) failed", dirp);
1022 } else if (rval) {
1023 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1024 "Invalid closedir(%p) return value %d", dirp, rval);
1025 }
1026
1027 return rval;
1028 }
1029
safe_readdir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)1030 struct dirent *safe_readdir(const char *file, const int lineno, void (cleanup_fn)(void),
1031 DIR *dirp)
1032 {
1033 struct dirent *rval;
1034 int err = errno;
1035
1036 errno = 0;
1037 rval = readdir(dirp);
1038
1039 if (!rval && errno) {
1040 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
1041 "readdir(%p) failed", dirp);
1042 }
1043
1044 errno = err;
1045 return rval;
1046 }
1047
safe_getpriority(const char * file,const int lineno,int which,id_t who)1048 int safe_getpriority(const char *file, const int lineno, int which, id_t who)
1049 {
1050 int rval, err = errno;
1051
1052 errno = 0;
1053 rval = getpriority(which, who);
1054
1055 if (rval == -1 && errno) {
1056 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1057 "getpriority(%i, %i) failed", which, who);
1058 } else if (errno) {
1059 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1060 "getpriority(%i, %i) failed with return value %d",
1061 which, who, rval);
1062 }
1063
1064 errno = err;
1065 return rval;
1066 }
1067
safe_getxattr(const char * file,const int lineno,const char * path,const char * name,void * value,size_t size)1068 ssize_t safe_getxattr(const char *file, const int lineno, const char *path,
1069 const char *name, void *value, size_t size)
1070 {
1071 ssize_t rval;
1072
1073 rval = getxattr(path, name, value, size);
1074
1075 if (rval == -1) {
1076 if (errno == ENOTSUP) {
1077 tst_brkm_(file, lineno, TCONF, NULL,
1078 "no xattr support in fs or mounted without user_xattr option");
1079 return rval;
1080 }
1081
1082 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1083 "getxattr(%s, %s, %p, %zu) failed",
1084 path, name, value, size);
1085 } else if (rval < 0) {
1086 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1087 "Invalid getxattr(%s, %s, %p, %zu) return value %zd",
1088 path, name, value, size, rval);
1089 }
1090
1091 return rval;
1092 }
1093
safe_setxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)1094 int safe_setxattr(const char *file, const int lineno, const char *path,
1095 const char *name, const void *value, size_t size, int flags)
1096 {
1097 int rval;
1098
1099 rval = setxattr(path, name, value, size, flags);
1100
1101 if (rval == -1) {
1102 if (errno == ENOTSUP) {
1103 tst_brkm_(file, lineno, TCONF, NULL,
1104 "no xattr support in fs, mounted without user_xattr option "
1105 "or invalid namespace/name format");
1106 return rval;
1107 }
1108
1109 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1110 "setxattr(%s, %s, %p, %zu) failed",
1111 path, name, value, size);
1112 } else if (rval) {
1113 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1114 "Invalid setxattr(%s, %s, %p, %zu) return value %d",
1115 path, name, value, size, rval);
1116 }
1117
1118 return rval;
1119 }
1120
safe_lsetxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)1121 int safe_lsetxattr(const char *file, const int lineno, const char *path,
1122 const char *name, const void *value, size_t size, int flags)
1123 {
1124 int rval;
1125
1126 rval = lsetxattr(path, name, value, size, flags);
1127
1128 if (rval == -1) {
1129 if (errno == ENOTSUP) {
1130 tst_brkm_(file, lineno, TCONF, NULL,
1131 "no xattr support in fs, mounted without user_xattr option "
1132 "or invalid namespace/name format");
1133 return rval;
1134 }
1135
1136 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1137 "lsetxattr(%s, %s, %p, %zu, %i) failed",
1138 path, name, value, size, flags);
1139 } else if (rval) {
1140 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1141 "Invalid lsetxattr(%s, %s, %p, %zu, %i) return value %d",
1142 path, name, value, size, flags, rval);
1143 }
1144
1145 return rval;
1146 }
1147
safe_fsetxattr(const char * file,const int lineno,int fd,const char * name,const void * value,size_t size,int flags)1148 int safe_fsetxattr(const char *file, const int lineno, int fd, const char *name,
1149 const void *value, size_t size, int flags)
1150 {
1151 int rval;
1152
1153 rval = fsetxattr(fd, name, value, size, flags);
1154
1155 if (rval == -1) {
1156 if (errno == ENOTSUP) {
1157 tst_brkm_(file, lineno, TCONF, NULL,
1158 "no xattr support in fs, mounted without user_xattr option "
1159 "or invalid namespace/name format");
1160 return rval;
1161 }
1162
1163 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1164 "fsetxattr(%i, %s, %p, %zu, %i) failed",
1165 fd, name, value, size, flags);
1166 } else if (rval) {
1167 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1168 "Invalid fsetxattr(%i, %s, %p, %zu, %i) return value %d",
1169 fd, name, value, size, flags, rval);
1170 }
1171
1172 return rval;
1173 }
1174
safe_removexattr(const char * file,const int lineno,const char * path,const char * name)1175 int safe_removexattr(const char *file, const int lineno, const char *path,
1176 const char *name)
1177 {
1178 int rval;
1179
1180 rval = removexattr(path, name);
1181
1182 if (rval == -1) {
1183 if (errno == ENOTSUP) {
1184 tst_brkm_(file, lineno, TCONF, NULL,
1185 "no xattr support in fs or mounted without user_xattr option");
1186 return rval;
1187 }
1188
1189 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1190 "removexattr(%s, %s) failed", path, name);
1191 } else if (rval) {
1192 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1193 "Invalid removexattr(%s, %s) return value %d", path,
1194 name, rval);
1195 }
1196
1197 return rval;
1198 }
1199
safe_lremovexattr(const char * file,const int lineno,const char * path,const char * name)1200 int safe_lremovexattr(const char *file, const int lineno, const char *path,
1201 const char *name)
1202 {
1203 int rval;
1204
1205 rval = lremovexattr(path, name);
1206
1207 if (rval == -1) {
1208 if (errno == ENOTSUP) {
1209 tst_brkm_(file, lineno, TCONF, NULL,
1210 "no xattr support in fs or mounted without user_xattr option");
1211 return rval;
1212 }
1213
1214 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1215 "lremovexattr(%s, %s) failed", path, name);
1216 } else if (rval) {
1217 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1218 "Invalid lremovexattr(%s, %s) return value %d", path,
1219 name, rval);
1220 }
1221
1222 return rval;
1223 }
1224
safe_fremovexattr(const char * file,const int lineno,int fd,const char * name)1225 int safe_fremovexattr(const char *file, const int lineno, int fd,
1226 const char *name)
1227 {
1228 int rval;
1229
1230 rval = fremovexattr(fd, name);
1231
1232 if (rval == -1) {
1233 if (errno == ENOTSUP) {
1234 tst_brkm_(file, lineno, TCONF, NULL,
1235 "no xattr support in fs or mounted without user_xattr option");
1236 return rval;
1237 }
1238
1239 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1240 "fremovexattr(%i, %s) failed", fd, name);
1241 } else if (rval) {
1242 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1243 "Invalid fremovexattr(%i, %s) return value %d", fd,
1244 name, rval);
1245 }
1246
1247 return rval;
1248 }
1249
safe_fsync(const char * file,const int lineno,int fd)1250 int safe_fsync(const char *file, const int lineno, int fd)
1251 {
1252 int rval;
1253
1254 rval = fsync(fd);
1255
1256 if (rval == -1) {
1257 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1258 "fsync(%i) failed", fd);
1259 } else if (rval) {
1260 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1261 "Invalid fsync(%i) return value %d", fd, rval);
1262 }
1263
1264 return rval;
1265 }
1266
safe_setsid(const char * file,const int lineno)1267 pid_t safe_setsid(const char *file, const int lineno)
1268 {
1269 pid_t rval;
1270
1271 rval = setsid();
1272
1273 if (rval == -1) {
1274 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1275 "setsid() failed");
1276 }
1277
1278 return rval;
1279 }
1280
safe_mknod(const char * file,const int lineno,const char * pathname,mode_t mode,dev_t dev)1281 int safe_mknod(const char *file, const int lineno, const char *pathname,
1282 mode_t mode, dev_t dev)
1283 {
1284 int rval;
1285
1286 rval = mknod(pathname, mode, dev);
1287
1288 if (rval == -1) {
1289 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1290 "mknod() failed");
1291 } else if (rval) {
1292 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1293 "Invalid mknod() return value %d", rval);
1294 }
1295
1296 return rval;
1297 }
1298
safe_mlock(const char * file,const int lineno,const void * addr,size_t len)1299 int safe_mlock(const char *file, const int lineno, const void *addr,
1300 size_t len)
1301 {
1302 int rval;
1303
1304 rval = mlock(addr, len);
1305
1306 if (rval == -1) {
1307 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1308 "mlock() failed");
1309 } else if (rval) {
1310 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1311 "Invalid mlock() return value %d", rval);
1312 }
1313
1314 return rval;
1315 }
1316
safe_munlock(const char * file,const int lineno,const void * addr,size_t len)1317 int safe_munlock(const char *file, const int lineno, const void *addr,
1318 size_t len)
1319 {
1320 int rval;
1321
1322 rval = munlock(addr, len);
1323
1324 if (rval == -1) {
1325 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1326 "munlock() failed");
1327 } else if (rval) {
1328 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1329 "Invalid munlock() return value %d", rval);
1330 }
1331
1332 return rval;
1333 }
1334
safe_mincore(const char * file,const int lineno,void * start,size_t length,unsigned char * vec)1335 int safe_mincore(const char *file, const int lineno, void *start,
1336 size_t length, unsigned char *vec)
1337 {
1338 int rval;
1339
1340 rval = mincore(start, length, vec);
1341
1342 if (rval == -1) {
1343 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1344 "mincore() failed");
1345 } else if (rval) {
1346 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1347 "Invalid mincore() return value %d", rval);
1348 }
1349
1350 return rval;
1351 }
1352
safe_sysinfo(const char * file,const int lineno,struct sysinfo * info)1353 int safe_sysinfo(const char *file, const int lineno, struct sysinfo *info)
1354 {
1355 int ret;
1356
1357 errno = 0;
1358 ret = sysinfo(info);
1359
1360 if (ret == -1) {
1361 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1362 "sysinfo() failed");
1363 } else if (ret) {
1364 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1365 "Invalid sysinfo() return value %d", ret);
1366 }
1367
1368 return ret;
1369 }
1370