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