1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright (c) International Business Machines  Corp., 2002
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci/*
21f08c3bdfSopenharmony_ci * NAME
22f08c3bdfSopenharmony_ci *      diotest_routines.c
23f08c3bdfSopenharmony_ci *
24f08c3bdfSopenharmony_ci * DESCRIPTION
25f08c3bdfSopenharmony_ci *	Functions that are used in diotest programs.
26f08c3bdfSopenharmony_ci *	fillbuf(), bufcmp(), filecmp()
27f08c3bdfSopenharmony_ci *	forkchldrn(), waitchldrn(), killchldrn()
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci * History
30f08c3bdfSopenharmony_ci *	04/10/2002	Narasimha Sharoff
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci * RESTRICTIONS
33f08c3bdfSopenharmony_ci *	None
34f08c3bdfSopenharmony_ci*/
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#include <stdio.h>
37f08c3bdfSopenharmony_ci#include <stdlib.h>
38f08c3bdfSopenharmony_ci#include <string.h>
39f08c3bdfSopenharmony_ci#include <signal.h>
40f08c3bdfSopenharmony_ci#include <fcntl.h>
41f08c3bdfSopenharmony_ci#include <sys/types.h>
42f08c3bdfSopenharmony_ci#include <sys/wait.h>
43f08c3bdfSopenharmony_ci#include <sys/uio.h>
44f08c3bdfSopenharmony_ci#include <errno.h>
45f08c3bdfSopenharmony_ci#include <unistd.h>
46f08c3bdfSopenharmony_ci#include <ctype.h>
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci#include "diotest_routines.h"
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci/* **** Routines for buffer actions, comparisions **** */
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci/*
53f08c3bdfSopenharmony_ci * fillbuf: Fill buffer of given size with given character value
54f08c3bdfSopenharmony_ci * vfillbuf: Fill the vector array
55f08c3bdfSopenharmony_ci*/
56f08c3bdfSopenharmony_civoid fillbuf(char *buf, int count, char value)
57f08c3bdfSopenharmony_ci{
58f08c3bdfSopenharmony_ci	while (count > 0) {
59f08c3bdfSopenharmony_ci		strncpy(buf, &value, 1);
60f08c3bdfSopenharmony_ci		buf++;
61f08c3bdfSopenharmony_ci		count = count - 1;
62f08c3bdfSopenharmony_ci	}
63f08c3bdfSopenharmony_ci}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_civoid vfillbuf(struct iovec *iv, int vcnt, char value)
66f08c3bdfSopenharmony_ci{
67f08c3bdfSopenharmony_ci	int i;
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	for (i = 0; i < vcnt; iv++, i++) {
70f08c3bdfSopenharmony_ci		fillbuf(iv->iov_base, iv->iov_len, (char)value);
71f08c3bdfSopenharmony_ci	}
72f08c3bdfSopenharmony_ci}
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci/*
75f08c3bdfSopenharmony_ci * bufcmp: Compare two buffers
76f08c3bdfSopenharmony_ci * vbufcmp: Compare two buffers of two io arrays
77f08c3bdfSopenharmony_ci*/
78f08c3bdfSopenharmony_ciint bufcmp(char *b1, char *b2, int bsize)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	int i;
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci	for (i = 0; i < bsize; i++) {
83f08c3bdfSopenharmony_ci		if (strncmp(&b1[i], &b2[i], 1)) {
84f08c3bdfSopenharmony_ci			fprintf(stderr,
85f08c3bdfSopenharmony_ci				"bufcmp: offset %d: Expected: 0x%x, got 0x%x\n",
86f08c3bdfSopenharmony_ci				i, b1[i], b2[i]);
87f08c3bdfSopenharmony_ci			return (-1);
88f08c3bdfSopenharmony_ci		}
89f08c3bdfSopenharmony_ci	}
90f08c3bdfSopenharmony_ci	return (0);
91f08c3bdfSopenharmony_ci}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ciint vbufcmp(struct iovec *iv1, struct iovec *iv2, int vcnt)
94f08c3bdfSopenharmony_ci{
95f08c3bdfSopenharmony_ci	int i;
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	for (i = 0; i < vcnt; iv1++, iv2++, i++) {
98f08c3bdfSopenharmony_ci		if (bufcmp(iv1->iov_base, iv2->iov_base, iv1->iov_len) < 0) {
99f08c3bdfSopenharmony_ci			fprintf(stderr, "Vector: %d, iv1base=%s, iv2base=%s\n",
100f08c3bdfSopenharmony_ci				i, (char *)iv1->iov_base,
101f08c3bdfSopenharmony_ci				(char *)iv2->iov_base);
102f08c3bdfSopenharmony_ci			return (-1);
103f08c3bdfSopenharmony_ci		}
104f08c3bdfSopenharmony_ci	}
105f08c3bdfSopenharmony_ci	return 0;
106f08c3bdfSopenharmony_ci}
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_ci/*
109f08c3bdfSopenharmony_ci * compare_files: Compares two files
110f08c3bdfSopenharmony_ci*/
111f08c3bdfSopenharmony_ciint filecmp(char *f1, char *f2)
112f08c3bdfSopenharmony_ci{
113f08c3bdfSopenharmony_ci	int i;
114f08c3bdfSopenharmony_ci	int fd1, fd2;
115f08c3bdfSopenharmony_ci	int ret1, ret2 = 0;
116f08c3bdfSopenharmony_ci	char buf1[BUFSIZ], buf2[BUFSIZ];
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	/* Open the file for read */
119f08c3bdfSopenharmony_ci	if ((fd1 = open(f1, O_RDONLY)) == -1) {
120f08c3bdfSopenharmony_ci		fprintf(stderr, "compare_files: open failed %s: %s",
121f08c3bdfSopenharmony_ci			f1, strerror(errno));
122f08c3bdfSopenharmony_ci		return (-1);
123f08c3bdfSopenharmony_ci	}
124f08c3bdfSopenharmony_ci	if ((fd2 = open(f2, O_RDONLY)) == -1) {
125f08c3bdfSopenharmony_ci		fprintf(stderr, "compare_files: open failed %s: %s",
126f08c3bdfSopenharmony_ci			f2, strerror(errno));
127f08c3bdfSopenharmony_ci		close(fd1);
128f08c3bdfSopenharmony_ci		return (-1);
129f08c3bdfSopenharmony_ci	}
130f08c3bdfSopenharmony_ci
131f08c3bdfSopenharmony_ci	/* Compare the files */
132f08c3bdfSopenharmony_ci	while ((ret1 = read(fd1, buf1, BUFSIZ)) > 0) {
133f08c3bdfSopenharmony_ci		ret2 = read(fd2, buf2, BUFSIZ);
134f08c3bdfSopenharmony_ci		if (ret1 != ret2) {
135f08c3bdfSopenharmony_ci			fprintf(stderr, "compare_file: file length mistmatch:");
136f08c3bdfSopenharmony_ci			fprintf(stderr, "read: %d from %s, %d from %s",
137f08c3bdfSopenharmony_ci				ret1, f1, ret2, f2);
138f08c3bdfSopenharmony_ci			close(fd1);
139f08c3bdfSopenharmony_ci			close(fd2);
140f08c3bdfSopenharmony_ci			return (-1);
141f08c3bdfSopenharmony_ci		}
142f08c3bdfSopenharmony_ci		for (i = 0; i < ret1; i++) {
143f08c3bdfSopenharmony_ci			if (strncmp(&buf1[i], &buf2[i], 1)) {
144f08c3bdfSopenharmony_ci				fprintf(stderr, "compare_file: char mismatch:");
145f08c3bdfSopenharmony_ci				fprintf(stderr, " %s offset %d: 0x%02x %c  ",
146f08c3bdfSopenharmony_ci					f1, i, buf1[i],
147f08c3bdfSopenharmony_ci					isprint(buf1[i]) ? buf1[1] : '.');
148f08c3bdfSopenharmony_ci				fprintf(stderr, " %s offset %d: 0x%02x %c\n",
149f08c3bdfSopenharmony_ci					f2, i, buf2[i],
150f08c3bdfSopenharmony_ci					isprint(buf2[i]) ? buf2[i] : '.');
151f08c3bdfSopenharmony_ci				close(fd1);
152f08c3bdfSopenharmony_ci				close(fd2);
153f08c3bdfSopenharmony_ci				return (-1);
154f08c3bdfSopenharmony_ci			}
155f08c3bdfSopenharmony_ci		}
156f08c3bdfSopenharmony_ci	}
157f08c3bdfSopenharmony_ci	close(fd1);
158f08c3bdfSopenharmony_ci	close(fd2);
159f08c3bdfSopenharmony_ci	return 0;
160f08c3bdfSopenharmony_ci}
161f08c3bdfSopenharmony_ci
162f08c3bdfSopenharmony_ci/* **** Routines to create, wait and destroy child processes **** */
163f08c3bdfSopenharmony_ci
164f08c3bdfSopenharmony_ci/*
165f08c3bdfSopenharmony_ci * forkchldrn: fork the given number of children and set the function
166f08c3bdfSopenharmony_ci *		that child should execute.
167f08c3bdfSopenharmony_ci*/
168f08c3bdfSopenharmony_ciint forkchldrn(int **pidlst, int numchld, int action, int (*chldfunc) ())
169f08c3bdfSopenharmony_ci{
170f08c3bdfSopenharmony_ci	int i, cpid;
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci	if ((*pidlst = ((int *)malloc(sizeof(int) * numchld))) == 0) {
173f08c3bdfSopenharmony_ci		fprintf(stderr, "forkchldrn: calloc failed for pidlst: %s\n",
174f08c3bdfSopenharmony_ci			strerror(errno));
175f08c3bdfSopenharmony_ci		return (-1);
176f08c3bdfSopenharmony_ci	}
177f08c3bdfSopenharmony_ci	for (i = 0; i < numchld; i++) {
178f08c3bdfSopenharmony_ci		if ((cpid = fork()) < 0) {
179f08c3bdfSopenharmony_ci			fprintf(stderr,
180f08c3bdfSopenharmony_ci				"forkchldrn: fork child %d failed, %s\n", i,
181f08c3bdfSopenharmony_ci				strerror(errno));
182f08c3bdfSopenharmony_ci			killchldrn(pidlst, i, SIGTERM);
183f08c3bdfSopenharmony_ci			return (-1);
184f08c3bdfSopenharmony_ci		}
185f08c3bdfSopenharmony_ci		if (cpid == 0)
186f08c3bdfSopenharmony_ci			exit((*chldfunc) (i, action));
187f08c3bdfSopenharmony_ci		else
188f08c3bdfSopenharmony_ci			*(*pidlst + i) = cpid;
189f08c3bdfSopenharmony_ci	}
190f08c3bdfSopenharmony_ci	return 0;
191f08c3bdfSopenharmony_ci}
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ci/*
194f08c3bdfSopenharmony_ci * killchldrn: signal the children listed in pidlst with the given signal
195f08c3bdfSopenharmony_ci *
196f08c3bdfSopenharmony_ci*/
197f08c3bdfSopenharmony_ciint killchldrn(int **pidlst, int numchld, int sig)
198f08c3bdfSopenharmony_ci{
199f08c3bdfSopenharmony_ci	int i, cpid, errflag = 0;
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_ci	for (i = 0; i < numchld; i++) {
202f08c3bdfSopenharmony_ci		cpid = *(*pidlst + i);
203f08c3bdfSopenharmony_ci		if (cpid > 0) {
204f08c3bdfSopenharmony_ci			if (kill(cpid, sig) < 0) {
205f08c3bdfSopenharmony_ci				fprintf(stderr,
206f08c3bdfSopenharmony_ci					"killchldrn: kill %d failed, %s\n",
207f08c3bdfSopenharmony_ci					cpid, strerror(errno));
208f08c3bdfSopenharmony_ci				errflag--;
209f08c3bdfSopenharmony_ci			}
210f08c3bdfSopenharmony_ci		}
211f08c3bdfSopenharmony_ci	}
212f08c3bdfSopenharmony_ci	return (errflag);
213f08c3bdfSopenharmony_ci}
214f08c3bdfSopenharmony_ci
215f08c3bdfSopenharmony_ci/*
216f08c3bdfSopenharmony_ci * waitchldrn: wait for child process listed in pidlst to finish.
217f08c3bdfSopenharmony_ci*/
218f08c3bdfSopenharmony_ciint waitchldrn(int **pidlst, int numchld)
219f08c3bdfSopenharmony_ci{
220f08c3bdfSopenharmony_ci	int i, cpid, ret, errflag = 0;
221f08c3bdfSopenharmony_ci	int status;
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	for (i = 0; i < numchld; i++) {
224f08c3bdfSopenharmony_ci		cpid = *(*pidlst + i);
225f08c3bdfSopenharmony_ci		if (cpid == 0)
226f08c3bdfSopenharmony_ci			continue;
227f08c3bdfSopenharmony_ci		if ((ret = waitpid(cpid, &status, 0)) != cpid) {
228f08c3bdfSopenharmony_ci			fprintf(stderr,
229f08c3bdfSopenharmony_ci				"waitchldrn: wait failed for child %d, pid %d: %s\n",
230f08c3bdfSopenharmony_ci				i, cpid, strerror(errno));
231f08c3bdfSopenharmony_ci			errflag--;
232f08c3bdfSopenharmony_ci		}
233f08c3bdfSopenharmony_ci		if (status)
234f08c3bdfSopenharmony_ci			errflag = -1;
235f08c3bdfSopenharmony_ci	}
236f08c3bdfSopenharmony_ci	return (errflag);
237f08c3bdfSopenharmony_ci}
238