• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
21  * NAME
22  *      diotest_routines.c
23  *
24  * DESCRIPTION
25  *	Functions that are used in diotest programs.
26  *	fillbuf(), bufcmp(), filecmp()
27  *	forkchldrn(), waitchldrn(), killchldrn()
28  *
29  * History
30  *	04/10/2002	Narasimha Sharoff
31  *
32  * RESTRICTIONS
33  *	None
34 */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <signal.h>
40 #include <fcntl.h>
41 #include <sys/types.h>
42 #include <sys/wait.h>
43 #include <sys/uio.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <ctype.h>
47 
48 #include "diotest_routines.h"
49 
50 /* **** Routines for buffer actions, comparisions **** */
51 
52 /*
53  * fillbuf: Fill buffer of given size with given character value
54  * vfillbuf: Fill the vector array
55 */
fillbuf(char * buf,int count,char value)56 void fillbuf(char *buf, int count, char value)
57 {
58 	while (count > 0) {
59 		strncpy(buf, &value, 1);
60 		buf++;
61 		count = count - 1;
62 	}
63 }
64 
vfillbuf(struct iovec * iv,int vcnt,char value)65 void vfillbuf(struct iovec *iv, int vcnt, char value)
66 {
67 	int i;
68 
69 	for (i = 0; i < vcnt; iv++, i++) {
70 		fillbuf(iv->iov_base, iv->iov_len, (char)value);
71 	}
72 }
73 
74 /*
75  * bufcmp: Compare two buffers
76  * vbufcmp: Compare two buffers of two io arrays
77 */
bufcmp(char * b1,char * b2,int bsize)78 int bufcmp(char *b1, char *b2, int bsize)
79 {
80 	int i;
81 
82 	for (i = 0; i < bsize; i++) {
83 		if (strncmp(&b1[i], &b2[i], 1)) {
84 			fprintf(stderr,
85 				"bufcmp: offset %d: Expected: 0x%x, got 0x%x\n",
86 				i, b1[i], b2[i]);
87 			return (-1);
88 		}
89 	}
90 	return (0);
91 }
92 
vbufcmp(struct iovec * iv1,struct iovec * iv2,int vcnt)93 int vbufcmp(struct iovec *iv1, struct iovec *iv2, int vcnt)
94 {
95 	int i;
96 
97 	for (i = 0; i < vcnt; iv1++, iv2++, i++) {
98 		if (bufcmp(iv1->iov_base, iv2->iov_base, iv1->iov_len) < 0) {
99 			fprintf(stderr, "Vector: %d, iv1base=%s, iv2base=%s\n",
100 				i, (char *)iv1->iov_base,
101 				(char *)iv2->iov_base);
102 			return (-1);
103 		}
104 	}
105 	return 0;
106 }
107 
108 /*
109  * compare_files: Compares two files
110 */
filecmp(char * f1,char * f2)111 int filecmp(char *f1, char *f2)
112 {
113 	int i;
114 	int fd1, fd2;
115 	int ret1, ret2 = 0;
116 	char buf1[BUFSIZ], buf2[BUFSIZ];
117 
118 	/* Open the file for read */
119 	if ((fd1 = open(f1, O_RDONLY)) == -1) {
120 		fprintf(stderr, "compare_files: open failed %s: %s",
121 			f1, strerror(errno));
122 		return (-1);
123 	}
124 	if ((fd2 = open(f2, O_RDONLY)) == -1) {
125 		fprintf(stderr, "compare_files: open failed %s: %s",
126 			f2, strerror(errno));
127 		close(fd1);
128 		return (-1);
129 	}
130 
131 	/* Compare the files */
132 	while ((ret1 = read(fd1, buf1, BUFSIZ)) > 0) {
133 		ret2 = read(fd2, buf2, BUFSIZ);
134 		if (ret1 != ret2) {
135 			fprintf(stderr, "compare_file: file length mistmatch:");
136 			fprintf(stderr, "read: %d from %s, %d from %s",
137 				ret1, f1, ret2, f2);
138 			close(fd1);
139 			close(fd2);
140 			return (-1);
141 		}
142 		for (i = 0; i < ret1; i++) {
143 			if (strncmp(&buf1[i], &buf2[i], 1)) {
144 				fprintf(stderr, "compare_file: char mismatch:");
145 				fprintf(stderr, " %s offset %d: 0x%02x %c  ",
146 					f1, i, buf1[i],
147 					isprint(buf1[i]) ? buf1[1] : '.');
148 				fprintf(stderr, " %s offset %d: 0x%02x %c\n",
149 					f2, i, buf2[i],
150 					isprint(buf2[i]) ? buf2[i] : '.');
151 				close(fd1);
152 				close(fd2);
153 				return (-1);
154 			}
155 		}
156 	}
157 	close(fd1);
158 	close(fd2);
159 	return 0;
160 }
161 
162 /* **** Routines to create, wait and destroy child processes **** */
163 
164 /*
165  * forkchldrn: fork the given number of children and set the function
166  *		that child should execute.
167 */
forkchldrn(int ** pidlst,int numchld,int action,int (* chldfunc)())168 int forkchldrn(int **pidlst, int numchld, int action, int (*chldfunc) ())
169 {
170 	int i, cpid;
171 
172 	if ((*pidlst = ((int *)malloc(sizeof(int) * numchld))) == 0) {
173 		fprintf(stderr, "forkchldrn: calloc failed for pidlst: %s\n",
174 			strerror(errno));
175 		return (-1);
176 	}
177 	for (i = 0; i < numchld; i++) {
178 		if ((cpid = fork()) < 0) {
179 			fprintf(stderr,
180 				"forkchldrn: fork child %d failed, %s\n", i,
181 				strerror(errno));
182 			killchldrn(pidlst, i, SIGTERM);
183 			return (-1);
184 		}
185 		if (cpid == 0)
186 			exit((*chldfunc) (i, action));
187 		else
188 			*(*pidlst + i) = cpid;
189 	}
190 	return 0;
191 }
192 
193 /*
194  * killchldrn: signal the children listed in pidlst with the given signal
195  *
196 */
killchldrn(int ** pidlst,int numchld,int sig)197 int killchldrn(int **pidlst, int numchld, int sig)
198 {
199 	int i, cpid, errflag = 0;
200 
201 	for (i = 0; i < numchld; i++) {
202 		cpid = *(*pidlst + i);
203 		if (cpid > 0) {
204 			if (kill(cpid, sig) < 0) {
205 				fprintf(stderr,
206 					"killchldrn: kill %d failed, %s\n",
207 					cpid, strerror(errno));
208 				errflag--;
209 			}
210 		}
211 	}
212 	return (errflag);
213 }
214 
215 /*
216  * waitchldrn: wait for child process listed in pidlst to finish.
217 */
waitchldrn(int ** pidlst,int numchld)218 int waitchldrn(int **pidlst, int numchld)
219 {
220 	int i, cpid, ret, errflag = 0;
221 	int status;
222 
223 	for (i = 0; i < numchld; i++) {
224 		cpid = *(*pidlst + i);
225 		if (cpid == 0)
226 			continue;
227 		if ((ret = waitpid(cpid, &status, 0)) != cpid) {
228 			fprintf(stderr,
229 				"waitchldrn: wait failed for child %d, pid %d: %s\n",
230 				i, cpid, strerror(errno));
231 			errflag--;
232 		}
233 		if (status)
234 			errflag = -1;
235 	}
236 	return (errflag);
237 }
238