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 memset(buf, value, count);
59 }
60
vfillbuf(struct iovec * iv,int vcnt,char value)61 void vfillbuf(struct iovec *iv, int vcnt, char value)
62 {
63 int i;
64
65 for (i = 0; i < vcnt; iv++, i++) {
66 fillbuf(iv->iov_base, iv->iov_len, (char)value);
67 }
68 }
69
70 /*
71 * bufcmp: Compare two buffers
72 * vbufcmp: Compare two buffers of two io arrays
73 */
bufcmp(char * b1,char * b2,int bsize)74 int bufcmp(char *b1, char *b2, int bsize)
75 {
76 int i;
77
78 for (i = 0; i < bsize; i++) {
79 if (strncmp(&b1[i], &b2[i], 1)) {
80 fprintf(stderr,
81 "bufcmp: offset %d: Expected: 0x%x, got 0x%x\n",
82 i, b1[i], b2[i]);
83 return (-1);
84 }
85 }
86 return (0);
87 }
88
vbufcmp(struct iovec * iv1,struct iovec * iv2,int vcnt)89 int vbufcmp(struct iovec *iv1, struct iovec *iv2, int vcnt)
90 {
91 int i;
92
93 for (i = 0; i < vcnt; iv1++, iv2++, i++) {
94 if (bufcmp(iv1->iov_base, iv2->iov_base, iv1->iov_len) < 0) {
95 fprintf(stderr, "Vector: %d, iv1base=%s, iv2base=%s\n",
96 i, (char *)iv1->iov_base,
97 (char *)iv2->iov_base);
98 return (-1);
99 }
100 }
101 return 0;
102 }
103
104 /*
105 * compare_files: Compares two files
106 */
filecmp(char * f1,char * f2)107 int filecmp(char *f1, char *f2)
108 {
109 int i;
110 int fd1, fd2;
111 int ret1, ret2 = 0;
112 char buf1[BUFSIZ], buf2[BUFSIZ];
113
114 /* Open the file for read */
115 if ((fd1 = open(f1, O_RDONLY)) == -1) {
116 fprintf(stderr, "compare_files: open failed %s: %s",
117 f1, strerror(errno));
118 return (-1);
119 }
120 if ((fd2 = open(f2, O_RDONLY)) == -1) {
121 fprintf(stderr, "compare_files: open failed %s: %s",
122 f2, strerror(errno));
123 close(fd1);
124 return (-1);
125 }
126
127 /* Compare the files */
128 while ((ret1 = read(fd1, buf1, BUFSIZ)) > 0) {
129 ret2 = read(fd2, buf2, BUFSIZ);
130 if (ret1 != ret2) {
131 fprintf(stderr, "compare_file: file length mistmatch:");
132 fprintf(stderr, "read: %d from %s, %d from %s",
133 ret1, f1, ret2, f2);
134 close(fd1);
135 close(fd2);
136 return (-1);
137 }
138 for (i = 0; i < ret1; i++) {
139 if (strncmp(&buf1[i], &buf2[i], 1)) {
140 fprintf(stderr, "compare_file: char mismatch:");
141 fprintf(stderr, " %s offset %d: 0x%02x %c ",
142 f1, i, buf1[i],
143 isprint(buf1[i]) ? buf1[1] : '.');
144 fprintf(stderr, " %s offset %d: 0x%02x %c\n",
145 f2, i, buf2[i],
146 isprint(buf2[i]) ? buf2[i] : '.');
147 close(fd1);
148 close(fd2);
149 return (-1);
150 }
151 }
152 }
153 close(fd1);
154 close(fd2);
155 return 0;
156 }
157
158 /* **** Routines to create, wait and destroy child processes **** */
159
160 /*
161 * forkchldrn: fork the given number of children and set the function
162 * that child should execute.
163 */
forkchldrn(int ** pidlst,int numchld,int action,int (* chldfunc)())164 int forkchldrn(int **pidlst, int numchld, int action, int (*chldfunc) ())
165 {
166 int i, cpid;
167
168 if ((*pidlst = ((int *)malloc(sizeof(int) * numchld))) == 0) {
169 fprintf(stderr, "forkchldrn: calloc failed for pidlst: %s\n",
170 strerror(errno));
171 return (-1);
172 }
173 for (i = 0; i < numchld; i++) {
174 if ((cpid = fork()) < 0) {
175 fprintf(stderr,
176 "forkchldrn: fork child %d failed, %s\n", i,
177 strerror(errno));
178 killchldrn(pidlst, i, SIGTERM);
179 return (-1);
180 }
181 if (cpid == 0)
182 exit((*chldfunc) (i, action));
183 else
184 *(*pidlst + i) = cpid;
185 }
186 return 0;
187 }
188
189 /*
190 * killchldrn: signal the children listed in pidlst with the given signal
191 *
192 */
killchldrn(int ** pidlst,int numchld,int sig)193 int killchldrn(int **pidlst, int numchld, int sig)
194 {
195 int i, cpid, errflag = 0;
196
197 for (i = 0; i < numchld; i++) {
198 cpid = *(*pidlst + i);
199 if (cpid > 0) {
200 if (kill(cpid, sig) < 0) {
201 fprintf(stderr,
202 "killchldrn: kill %d failed, %s\n",
203 cpid, strerror(errno));
204 errflag--;
205 }
206 }
207 }
208 return (errflag);
209 }
210
211 /*
212 * waitchldrn: wait for child process listed in pidlst to finish.
213 */
waitchldrn(int ** pidlst,int numchld)214 int waitchldrn(int **pidlst, int numchld)
215 {
216 int i, cpid, ret, errflag = 0;
217 int status;
218
219 for (i = 0; i < numchld; i++) {
220 cpid = *(*pidlst + i);
221 if (cpid == 0)
222 continue;
223 if ((ret = waitpid(cpid, &status, 0)) != cpid) {
224 fprintf(stderr,
225 "waitchldrn: wait failed for child %d, pid %d: %s\n",
226 i, cpid, strerror(errno));
227 errflag--;
228 }
229 if (status)
230 errflag = -1;
231 }
232 return (errflag);
233 }
234