Home | History | Annotate | Download | only in direct_io
      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 */
     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 
     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 */
     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 
     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 */
    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 */
    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 */
    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 */
    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