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