1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2002
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /* 11/01/2002	Port to LTP	robbiew@us.ibm.com */
21 /* 06/30/2001	Port to Linux	nsharoff@us.ibm.com */
22 
23 			   /*inode02.c */
24 /*======================================================================
25 	=================== TESTPLAN SEGMENT ===================
26 CALLS:	mkdir, stat, open
27 
28 	Run with TERM mode.
29 
30 >KEYS:  < file system and I/O management, system resource constraints.
31 >WHAT:  < Can the system handle a heavy load on the file system I/O
32 	< functions?
33 >HOW:   < Create several identical process that call inode02.c.  This
34 	< will simulate the multi-user environment, and hopefully uncover
35 	< conflicts that might occur in "real life" use.
36 >BUGS:  <
37 ======================================================================*/
38 
39 #define PATH_STRING_LENGTH  1024
40 #define NAME_LENGTH  8
41 #define MAX_PATH_STRING_LENGTH  (PATH_STRING_LENGTH - NAME_LENGTH - 40)
42 #define DIRECTORY_MODE  00777
43 #define FILE_MODE       00777
44 
45 #define MKDIR_STRING_LENGTH  (MAX_PATH_STRING_LENGTH + 7)
46 
47 /* #define DEBUG	 you can watch the generation with this flag */
48 
49 #define TRUE  1
50 #define FALSE 0
51 #define READ  0
52 #define WRITE 1
53 
54 #include <stdio.h>
55 #include <errno.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <signal.h>
59 #include <fcntl.h>
60 #include <errno.h>
61 #include <wait.h>
62 
63 #ifdef LINUX
64 #include <stdlib.h>
65 #include <unistd.h>
66 #include <string.h>
67 #endif
68 
69 #define MAXCHILD	25
70 int allchild[MAXCHILD + 1];
71 
72 char name[NAME_LENGTH + 1];
73 char path_string[PATH_STRING_LENGTH + 1];
74 char read_string[PATH_STRING_LENGTH + 1];
75 char write_string[PATH_STRING_LENGTH + 1];
76 char remove_string[PATH_STRING_LENGTH + 10];
77 int parent_pid;
78 int nchild;
79 
80 FILE *list_stream = NULL;
81 int list_id;
82 int file_id;
83 
84 int increment_name(), get_next_name(), mode(), escrivez(), massmurder();
85 int max_depth, max_breadth, file_length;
86 int bd_arg(char *);
87 
88 #ifdef LINUX
89 void (*sigset(int, void (*)(int))) (int);
90 #endif
91 
92 /** LTP Port **/
93 #include "test.h"
94 
95 void setup(void);
96 void fail_exit(void);
97 void anyfail(void);
98 void ok_exit(void);
99 void forkfail(void);
100 void terror(char *);
101 int instress(void);
102 
103 #define FAILED 0
104 #define PASSED 1
105 
106 int local_flag = PASSED;
107 FILE *temp;
108 
109 char *TCID = "inode02";		/* Test program identifier.    */
110 int TST_TOTAL = 1;		/* Total number of test cases. */
111 /**************/
112 
main(argc,argv)113 int main(argc, argv)
114 int argc;
115 char *argv[];
116 {
117 	int pid, tree(), p, status;
118 	int count, child;
119 	register int i;
120 	int term();
121 
122 	setup();
123 
124 	parent_pid = getpid();
125 
126 	if (sigset(SIGTERM, (void (*)())term) == SIG_ERR) {
127 		tst_resm(TBROK, "\tSIGTERM sigset set failed, errno=%d\n",
128 			 errno);
129 		exit(1);
130 	}
131 
132 	/************************************************/
133 	/*                                              */
134 	/*  Input the parameters for the directory---   */
135 	/*  file trees which are to be generated        */
136 	/*                                              */
137 	/************************************************/
138 
139 	if (argc < 2) {
140 		max_depth = 6;
141 		max_breadth = 5;
142 		file_length = 8;
143 		nchild = 5;
144 	} else if (argc < 5) {
145 		tst_resm(TCONF, "Bad argument count.\n");
146 		printf
147 		    ("\tinode02 max_depth max_breadth file_length #children\n\tdefault: inode02 6 5 8 5\n");
148 		exit(1);
149 	} else {
150 		i = 1;
151 		if (sscanf(argv[i++], "%d", &max_depth) != 1)
152 			bd_arg(argv[i - 1]);
153 		if (sscanf(argv[i++], "%d", &max_breadth) != 1)
154 			bd_arg(argv[i - 1]);
155 		if (sscanf(argv[i++], "%d", &file_length) != 1)
156 			bd_arg(argv[i - 1]);
157 		if (sscanf(argv[i++], "%d", &nchild) != 1)
158 			bd_arg(argv[i - 1]);
159 		if (nchild > MAXCHILD) {
160 			fprintf(temp, "too many children - max is %d\n",
161 				MAXCHILD);
162 			exit(1);
163 		}
164 	}
165 
166 	/************************************************/
167 	/*                                              */
168 	/*  Generate and check nchild trees             */
169 	/*                                              */
170 	/************************************************/
171 
172 	for (p = 0; p < nchild; p++) {
173 		pid = fork();
174 		if (pid == 0) {
175 			tree();
176 		} else {
177 			if (pid < 1) {
178 				terror
179 				    ("Fork failed (may be OK if under stress)");
180 				massmurder();
181 				if (instress()) {
182 					ok_exit();
183 				}
184 				forkfail();
185 			}
186 		}
187 	}
188 
189 	count = 0;
190 	while ((child = wait(&status)) > 0) {
191 #ifdef DEBUG
192 		tst_resm(TINFO, "Test %d exited status = %d\n", child, status);
193 #endif
194 		if (status) {
195 			fprintf(temp, "Test %d failed - expected 0 exit.\n",
196 				child);
197 			local_flag = FAILED;
198 		}
199 		count++;
200 	}
201 
202 	if (count != nchild) {
203 		tst_resm(TFAIL, "Wrong number of children waited on!\n");
204 		tst_resm(TFAIL, "Saw %d, expected %d\n", count, nchild);
205 		local_flag = FAILED;
206 	}
207 
208 	/************************************************/
209 	/*                                              */
210 	/*  And report the results..........            */
211 	/*                                              */
212 	/************************************************/
213 
214 	anyfail();
215 	/** NOT REACHED **/
216 	tst_exit();
217 }
218 
bd_arg(str)219 int bd_arg(str)
220 char *str;
221 {
222 	fprintf(temp,
223 		"Bad argument - %s - could not parse as number.\n\tinode02 [max_depth] [max_breadth] [file_length] [#children]\n\tdefault: inode02 6 5 8 5\n",
224 		str);
225 	exit(1);
226 }
227 
tree()228 int tree()
229 
230 /************************************************/
231 /*						*/
232 /*  		      TREE			*/
233 /*						*/
234 /*   generate a tree of directories and files   */
235 /*   and save the path names in the path_list	*/
236 /*   file 					*/
237 /*						*/
238 /*   then, read the path names and attempt to   */
239 /*   access the corresponding directories and	*/
240 /*   files					*/
241 /*						*/
242 /************************************************/
243 {
244 	int gen_ret_val, ch_ret_val, exit_val, level;
245 	int ret_val;
246 	int generate(), check();
247 	char path_list_string[PATH_STRING_LENGTH + 10];
248 	int len;
249 	int status;
250 	int snp_ret;
251 
252 	/********************************/
253 	/*                              */
254 	/*  make the root directory for */
255 	/*  the tree                    */
256 	/*                              */
257 	/********************************/
258 
259 	sprintf(path_string, "inode02.%d", getpid());
260 
261 	ret_val = mkdir(path_string, DIRECTORY_MODE);
262 
263 	if (ret_val == -1) {
264 		tst_resm(TBROK,
265 			 "Reason: Impossible to create directory %s, errno=%d\n",
266 			 path_string, errno);
267 		exit(-5);
268 	}
269 
270 	strcpy(remove_string, "rm -rf ");
271 	strcat(remove_string, path_string);
272 
273 #ifdef DEBUG
274 	tst_resm(TINFO, "\n%s\n", path_string);
275 #endif
276 
277 	/****************************************/
278 	/*                                      */
279 	/*  create the "path_list" file, in     */
280 	/*  which the list of generated paths   */
281 	/*  will be stored so that they later   */
282 	/*  may be checked                      */
283 	/*                                      */
284 	/****************************************/
285 
286 	snp_ret = snprintf(path_list_string, sizeof(path_list_string),
287 		"%s/path_list",	path_string);
288 	if (snp_ret < 0 || snp_ret >= sizeof(path_list_string)) {
289 		tst_resm(TBROK, "snprintf(path_list_string,..) returned %d",
290 			snp_ret);
291 		exit(-1);
292 	}
293 	list_id = creat(path_list_string, FILE_MODE);
294 	if (list_id == -1) {
295 		fprintf(temp,
296 			"\nThe path_list file '%s' cannot be created, errno=%d\n",
297 			path_list_string, errno);
298 		exit(-7);
299 	}
300 
301 	/****************************************/
302 	/*                                      */
303 	/*   and store its name in path_list    */
304 	/*                                      */
305 	/****************************************/
306 
307 	strcpy(write_string, path_string);
308 	len = strlen(write_string);
309 	write_string[len++] = 'D';
310 	write_string[len] = '\0';
311 	escrivez(write_string);
312 
313 	/****************************************/
314 	/*                                      */
315 	/*   generate the directory-file tree   */
316 	/*                                      */
317 	/****************************************/
318 
319 	level = 0;
320 
321 #ifdef DEBUG
322 	tst_resm(TINFO, "\n\t%s\n\n", "GENERATING:");
323 #endif
324 
325 	gen_ret_val = generate(path_string, level);
326 	close(list_id);
327 	list_id = open(path_list_string, READ);
328 	if (list_id == -1) {
329 		fprintf(temp,
330 			"\nThe path_list file cannot be opened for reading, errno=%d\n",
331 			errno);
332 		exit(-8);
333 	}
334 	list_stream = fdopen(list_id, "r");
335 
336 	/****************************************/
337 	/*                                      */
338 	/*   check the directory-file tree      */
339 	/*      for correctness                 */
340 	/*                                      */
341 	/****************************************/
342 
343 #ifdef DEBUG
344 	tst_resm(TINFO, "\n\t%s\n\n", "CHECKING:");
345 #endif
346 
347 	ch_ret_val = check();
348 
349 	if (gen_ret_val > ch_ret_val)
350 		exit_val = ch_ret_val;
351 	else
352 		exit_val = gen_ret_val;
353 
354 	status = fclose(list_stream);
355 	if (status != 0) {
356 		fprintf(temp,
357 			"Failed to close list_stream: ret=%d errno=%d (%s)\n",
358 			status, errno, strerror(errno));
359 		exit(-8);
360 	}
361 
362 	/*
363 	 * Remove file.
364 	 */
365 
366 	status = system(remove_string);
367 	if (status) {
368 		fprintf(temp, "Caution - `%s' failed.\n", remove_string);
369 		fprintf(temp, "Status returned %d.\n", status);
370 	}
371 
372 	/****************************************/
373 	/*                                      */
374 	/*         .....and exit main           */
375 	/*                                      */
376 	/****************************************/
377 
378 	exit(exit_val);
379 }
380 
generate(string,level)381 int generate(string, level)
382 
383 /****************************************/
384 /*					*/
385 /*   generate recursively a tree of	*/
386 /*   directories and files:  within   	*/
387 /*   created directory, an alternating	*/
388 /*   series of files and directories 	*/
389 /*   are constructed---until tree	*/
390 /*   breadth and depth limits are	*/
391 /*   reached or an error occurs		*/
392 /*					*/
393 /****************************************/
394 		/***************************/
395 		/*                         */
396 char string[];			/*  the directory path     */
397 		/*  string below which a   */
398 		/*  tree is generated      */
399 		/*                         */
400 		/***************************/
401 
402 		/***************************/
403 		/*                         */
404 int level;			/* the tree depth variable */
405 		/*                         */
406 		/***************************/
407 {
408 	int switch_flag;
409 	int ret_val = 0;
410 	int new_ret_val, len, ret_len;
411 	char new_string[PATH_STRING_LENGTH + 1];
412 	int new_level;
413 	int i, j;		/* iteration counters */
414 	int snp_ret;
415 
416 	switch_flag = level & TRUE;
417 	if (strlen(string) >= MAX_PATH_STRING_LENGTH) {
418 
419 		/********************************/
420 		/*                              */
421 		/*   Maximum path name length   */
422 		/*          reached             */
423 		/*                              */
424 		/********************************/
425 
426 		fprintf(temp, "\nMaximum path_name length reached\n");
427 		return (-1);
428 	} else if (level < max_depth) {
429 		for (i = 0; i <= max_breadth; i++) {
430 			get_next_name();
431 			snp_ret = snprintf(new_string, sizeof(new_string),
432 				"%s/%s", string, name);
433 			if (snp_ret < 0 || snp_ret >= sizeof(new_string)) {
434 				tst_resm(TBROK, "snprintf(new_string,..) "
435 					"returned %d", snp_ret);
436 				exit(-1);
437 			}
438 
439 			/****************************************/
440 			/*                                      */
441 			/*    switch between creating files     */
442 			/*    and making directories            */
443 			/*                                      */
444 			/****************************************/
445 
446 			if (switch_flag) {
447 				switch_flag = FALSE;
448 
449 				/****************************************/
450 				/*                                      */
451 				/*        create a new file             */
452 				/*                                      */
453 				/****************************************/
454 
455 				file_id = creat(new_string, FILE_MODE);
456 				if (file_id == -1) {
457 					fprintf(temp,
458 						"\nImpossible to create file %s, errno=%d\n",
459 						new_string, errno);
460 					return (-2);
461 				}
462 #ifdef DEBUG
463 				tst_resm(TINFO, "%d  %s F\n", level,
464 					 new_string);
465 #endif
466 
467 				/****************************************/
468 				/*                                      */
469 				/*            write to it               */
470 				/*                                      */
471 				/****************************************/
472 
473 				len = strlen(new_string);
474 				for (j = 1; j <= file_length; j++) {
475 					ret_len =
476 					    write(file_id, new_string, len);
477 					if (ret_len != len) {
478 						fprintf(temp,
479 							"\nUnsuccessful write to file %s, errno=%d\n",
480 							new_string, errno);
481 						return (-3);
482 					}
483 				}
484 				close(file_id);
485 
486 				/****************************************/
487 				/*                                      */
488 				/*   and store its name in path_list    */
489 				/*                                      */
490 				/****************************************/
491 
492 				strcpy(write_string, new_string);
493 				len = strlen(write_string);
494 				write_string[len++] = 'F';
495 				write_string[len] = '\0';
496 				escrivez(write_string);
497 			} else {
498 				switch_flag = TRUE;
499 
500 				/****************************************/
501 				/*                                      */
502 				/*       or make a directory            */
503 				/*                                      */
504 				/*  (mknod can only be called when in   */
505 				/*   super user mode)                   */
506 				/*                                      */
507 				/****************************************/
508 
509 				ret_val = mkdir(new_string, DIRECTORY_MODE);
510 
511 				if (ret_val != 0) {
512 					fprintf(temp,
513 						"\nImpossible to create directory %s, errno=%d\n",
514 						new_string, errno);
515 					return (-5);
516 				}
517 #ifdef DEBUG
518 				tst_resm(TINFO, "%d  %s D\n", level,
519 					 new_string);
520 #endif
521 
522 				/****************************************/
523 				/*                                      */
524 				/*     store its name in path_list      */
525 				/*                                      */
526 				/****************************************/
527 
528 				strcpy(write_string, new_string);
529 				len = strlen(write_string);
530 				write_string[len++] = 'D';
531 				write_string[len] = '\0';
532 				escrivez(write_string);
533 
534 				/****************************************/
535 				/*                                      */
536 				/*      and generate a new level        */
537 				/*                                      */
538 				/****************************************/
539 
540 				new_level = level + 1;
541 				new_ret_val = generate(new_string, new_level);
542 				if (new_ret_val < ret_val)
543 					ret_val = new_ret_val;
544 			}
545 		}
546 
547 		/********************************/
548 		/*                              */
549 		/*    Maximum breadth reached   */
550 		/*                              */
551 		/********************************/
552 
553 		return (ret_val);
554 	} else
555 		    /********************************/
556 		/*                             */
557 		/*    Maximum depth reached    */
558 		/*                             */
559  /********************************/
560 		return 0;
561 }
562 
check()563 int check()
564 
565 /****************************************/
566 /*					*/
567 /*   check for file and directory	*/
568 /*   correctness by reading records	*/
569 /*   from the path_list and attempting	*/
570 /*   to determine if the corresponding	*/
571 /*   files or directories are as 	*/
572 /*   created 				*/
573 /*					*/
574 /****************************************/
575 {
576 	int len, path_mode, val, ret_len, j;
577 
578 	for (;;) {
579 
580 		/****************************************/
581 		/*                                      */
582 		/*  read a path string from path_list   */
583 		/*                                      */
584 		/****************************************/
585 
586 		if (fscanf(list_stream, "%s", path_string) == EOF) {
587 
588 #ifdef DEBUG
589 			tst_resm(TINFO, "\nEnd of path_list file reached \n");
590 #endif
591 
592 			return 0;
593 		}
594 #ifdef DEBUG
595 		tst_resm(TINFO, "%s\n", path_string);
596 #endif
597 
598 		len = strlen(path_string);
599 		len--;
600 		if (path_string[len] == 'F') {
601 
602 		/********************************/
603 			/*                              */
604 			/*    this should be a file     */
605 			/*                              */
606 		/********************************/
607 
608 			path_string[len] = '\0';
609 			file_id = open(path_string, READ);
610 			if (file_id <= 0) {
611 				fprintf(temp,
612 					"\nImpossible to open file %s, errno=%d\n",
613 					path_string, errno);
614 				return (-1);
615 			}
616 
617 			else {
618 				/********************************/
619 				/*                              */
620 				/*    check its contents        */
621 				/*                              */
622 				/********************************/
623 
624 				ret_len = 0;
625 				len = strlen(path_string);
626 				for (j = 1; j <= file_length; j++) {
627 					ret_len =
628 					    read(file_id, read_string, len);
629 					if (len != ret_len) {
630 						fprintf(temp,
631 							"\nFile read error for file %s, errno=%d\n",
632 							path_string, errno);
633 						return (-3);
634 					}
635 					read_string[len] = '\0';
636 					val = strcmp(read_string, path_string);
637 					if (val != 0) {
638 						fprintf(temp,
639 							"\nContents of file %s are different than expected: %s\n",
640 							path_string,
641 							read_string);
642 						return (-4);
643 					}
644 				}
645 				close(file_id);
646 			}	/* else for */
647 			if (ret_len <= 0) {
648 				fprintf(temp,
649 					"\nImpossible to read file %s, errno=%d\n",
650 					path_string, errno);
651 				return (-2);
652 			}
653 		} else {
654 
655 		/********************************/
656 			/*                              */
657 			/*  otherwise..........         */
658 			/*  it should be a directory    */
659 			/*                              */
660 		/********************************/
661 
662 			path_string[len] = '\0';
663 			path_mode = mode(path_string);
664 			if (path_mode == -1) {
665 				fprintf(temp,
666 					"\nPreviously created directory path %s was not open\n",
667 					path_string);
668 				return (-4);
669 			}
670 			if ((040000 & path_mode) != 040000) {
671 				fprintf(temp,
672 					"\nPath %s was not recognized to be a directory\n",
673 					path_string);
674 				fprintf(temp, "Its mode is %o\n", path_mode);
675 				return (-5);
676 			}
677 		}
678 	}			/* while */
679 }
680 
get_next_name()681 int get_next_name()
682 
683 /****************************************/
684 /*					*/
685 /*   get the next---in a dictionary	*/
686 /*   sense---file or directory name	*/
687 /*					*/
688 /****************************************/
689 {
690 	static int k;
691 	int i;
692 	int last_position;
693 
694 	last_position = NAME_LENGTH - 1;
695 	if (k == 0) {
696 
697 		/************************/
698 		/*                      */
699 		/*   initialize name    */
700 		/*                      */
701 		/************************/
702 
703 		for (i = 0; i < NAME_LENGTH; i++)
704 			name[i] = 'a';
705 		name[NAME_LENGTH] = '\0';
706 		k++;
707 	}
708 					    /********************************/
709 	/*                              */
710 	else
711 		increment_name(last_position);	/* i.e., beginning at the last  */
712 	/* position                     */
713 	/*                              */
714 					    /********************************/
715 	return 0;
716 }
717 
increment_name(position)718 int increment_name(position)
719 
720 /****************************************/
721 /*					*/
722 /*  recursively revise the letters in 	*/
723 /*  a name to get the lexiographically	*/
724 /*  next name				*/
725 /*					*/
726 /****************************************/
727  int position;
728 {
729 	int next_position;
730 
731 	if (name[position] == 'z')
732 		if (position == 0) {
733 			fprintf(temp,
734 				"ERROR: There are no more available names\n");
735 			exit(-1);
736 		} else {
737 			name[position] = 'a';	       /**********************/
738 			next_position = --position;	/*                    */
739 			increment_name(next_position);	/*  increment the     */
740 			/*  previous letter   */
741 			/*                    */
742 						       /**********************/
743 		}
744 				  /*********************************/
745 	/*                               */
746 	else
747 		name[position]++;	/* otherwise, increment this one */
748 	return 0;		/*                               */
749 				  /*********************************/
750 }
751 
mode(path_string)752 int mode(path_string)
753 
754 /****************************************/
755 /*					*/
756 /*   determine and return the mode of	*/
757 /*   the file named by path_string 	*/
758 /*					*/
759 /****************************************/
760  char path_string[];
761 {
762 	struct stat buf;
763 	int ret_val, mod;
764 
765 	ret_val = stat(path_string, &buf);
766 	if (ret_val == -1)
767 		return (-1);
768 	else {
769 		mod = buf.st_mode;
770 		return (mod);
771 	}
772 }
773 
escrivez(string)774 int escrivez(string)
775 
776 char string[];
777 {
778 	char write_string[PATH_STRING_LENGTH + 1];
779 	int len, ret_len;
780 
781 	strcpy(write_string, string);
782 	len = strlen(write_string);
783 	write_string[len] = '\n';
784 	len++;
785 	ret_len = write(list_id, write_string, len);
786 	if (len != ret_len) {
787 		fprintf(temp,
788 			"A string of deviant length %d written to path_list, errno=%d\n",
789 			ret_len, errno);
790 		exit(-2);
791 	}
792 	return 0;
793 }
794 
term()795 int term()
796 {
797 	int status;
798 
799 	fflush(temp);
800 	if (parent_pid == getpid()) {
801 		massmurder();	/* kill kids */
802 		fprintf(temp, "\term1 - SIGTERM received by parent.\n");
803 		fflush(temp);
804 	} else {
805 		fprintf(temp, "\tchild - got SIGTERM signal.\n");
806 		if (list_stream != NULL)
807 			fclose(list_stream);
808 		close(list_id);
809 		close(file_id);
810 		status = system(remove_string);
811 		if (status) {
812 			fprintf(temp, "Caution - ``%s'' returned status %d\n",
813 				remove_string, status);
814 		}
815 		exit(0);
816 	}
817 	return 0;
818 }
819 
massmurder()820 int massmurder()
821 {
822 	int i;
823 	for (i = 0; i < MAXCHILD; i++) {
824 		if (allchild[i]) {
825 			kill(allchild[i], SIGTERM);
826 		}
827 	}
828 	return 0;
829 }
830 
831 /** LTP Port **/
832 /*
833  * setup
834  *
835  * Do set up - here its a dummy function
836  */
setup()837 void setup()
838 {
839 	tst_tmpdir();
840 	temp = stderr;
841 }
842 
843 /*
844  * fail_exit()
845  *
846  * Exit on failure
847  */
fail_exit()848 void fail_exit()
849 {
850 	tst_brkm(TFAIL, tst_rmdir, "Test failed\n");
851 }
852 
853 /*
854  *
855  * Function: anyfail()
856  *
857  * Description: Exit a test.
858  */
anyfail()859 void anyfail()
860 {
861 	(local_flag == FAILED) ? tst_resm(TFAIL, "Test failed")
862 	    : tst_resm(TPASS, "Test passed");
863 	tst_rmdir();
864 	tst_exit();
865 }
866 
867 /*
868  * ok_exit
869  *
870  * Calling block passed the test
871  */
ok_exit()872 void ok_exit()
873 {
874 	local_flag = PASSED;
875 	return;
876 }
877 
878 /*
879  * forkfail()
880  *
881  * exit on failure
882  */
forkfail()883 void forkfail()
884 {
885 	tst_brkm(TBROK, tst_rmdir, "Reason: %s\n", strerror(errno));
886 }
887 
888 /*
889  * Function: terror
890  *
891  * Description: prints error message this may not be because some part of the
892  *              test case failed, for example fork() failed. We will log this
893  *              failure as TBROK instead of TFAIL.
894  */
terror(char * message)895 void terror(char *message)
896 {
897 	tst_resm(TBROK, "Reason: %s:%s\n", message, strerror(errno));
898 	return;
899 }
900 
901 /*
902  * instress
903  *
904  * Assume that we are always running under stress, so this function will
905  * return > 0 value always.
906  */
instress()907 int instress()
908 {
909 	tst_resm(TINFO, "System resource may be too low, fork() malloc()"
910 		 " etc are likely to fail.\n");
911 	return 1;
912 }
913