Home | History | Annotate | Download | only in disktest
      1 /*
      2 * Disktest
      3 * Copyright (c) International Business Machines Corp., 2001
      4 *
      5 *
      6 * This program is free software; you can redistribute it and/or modify
      7 * it under the terms of the GNU General Public License as published by
      8 * the Free Software Foundation; either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 * GNU General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU General Public License
     17 * along with this program; if not, write to the Free Software
     18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     19 *
     20 *  Please send e-mail to yardleyb (at) us.ibm.com if you have
     21 *  questions or comments.
     22 *
     23 *  Project Website:  TBD
     24 *
     25 * $Id: parse.c,v 1.8 2009/02/26 12:02:23 subrata_modak Exp $
     26 *
     27 */
     28 #include <sys/types.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <stdarg.h>
     32 #include <signal.h>
     33 #include <time.h>
     34 #include <errno.h>
     35 #include <fcntl.h>
     36 #include <string.h>
     37 #include <ctype.h>
     38 #include <sys/stat.h>
     39 
     40 #include "globals.h"
     41 #include "threading.h"
     42 #include "main.h"
     43 #include "usage.h"
     44 #include "sfunc.h"
     45 #include "parse.h"
     46 
     47 int fill_cld_args(int argc, char **argv, child_args_t * args)
     48 {
     49 	extern char *optarg;
     50 	extern int optind;
     51 	extern unsigned long glb_flags;
     52 
     53 	signed char c;
     54 	char *leftovers;
     55 
     56 	while ((c =
     57 		getopt(argc, argv,
     58 		       "?a:A:B:cC:dD:E:f:Fh:I:K:L:m:M:nN:o:p:P:qQrR:s:S:t:T:wvV:z"))
     59 	       != -1) {
     60 		switch (c) {
     61 		case ':':
     62 			pMsg(WARN, args, "Missing argument for perameter.\n");
     63 			usage();
     64 			return (-1);
     65 		case 'V':
     66 #ifdef _DEBUG
     67 			if (optarg == NULL) {
     68 				pMsg(WARN, args,
     69 				     "-%c option requires an argument.\n", c);
     70 				exit(1);
     71 			}
     72 			if (!isdigit(optarg[0])) {
     73 				pMsg(WARN, args,
     74 				     "-%c argument is non numeric.\n", c);
     75 				exit(1);
     76 			}
     77 			gbl_dbg_lvl = atoi(optarg);
     78 #else
     79 			pMsg(ERR, args,
     80 			     "Debug code not compiled in, recompile with _DEBUG directive.\n",
     81 			     c);
     82 			exit(1);
     83 #endif
     84 			break;
     85 		case 'd':
     86 			glb_flags |= GLB_FLG_QUIET;
     87 			args->flags |= CLD_FLG_DUMP;
     88 			break;
     89 		case 'a':
     90 			if (optarg == NULL) {
     91 				pMsg(WARN, args,
     92 				     "-%c option requires an argument.\n", c);
     93 				return (-1);
     94 			}
     95 			if (!isdigit(optarg[0])) {
     96 				pMsg(WARN, args,
     97 				     "-%c arguments is non numeric.\n", c);
     98 				return (-1);
     99 			}
    100 			args->seed = (unsigned int)strtol(optarg, NULL, 0);
    101 			break;
    102 		case 'A':
    103 			if (optarg == NULL) {
    104 				pMsg(WARN, args,
    105 				     "-%c option requires an argument.\n", c);
    106 				exit(1);
    107 			}
    108 			if (strchr(optarg, 'g')) {
    109 				glb_flags |= GLB_FLG_KILL;
    110 			}
    111 			if (strchr(optarg, 'c')) {
    112 				args->flags &= ~CLD_FLG_ALLDIE;
    113 			}
    114 			if (strchr(optarg, 'm')) {
    115 				args->flags |= CLD_FLG_ERR_MARK;
    116 			}
    117 			if (strchr(optarg, 'r')) {
    118 				args->flags &= ~CLD_FLG_ERR_REREAD;
    119 			}
    120 			if (strchr(optarg, 's')) {
    121 				args->flags &= ~CLD_FLG_LBA_SYNC;
    122 			}
    123 			if (strchr(optarg, 'S')) {
    124 				args->flags |= CLD_FLG_IO_SERIAL;
    125 			}
    126 			if (strchr(optarg, 'w')) {
    127 				args->flags |= CLD_FLG_WRITE_ONCE;
    128 			}
    129 			if (strchr(optarg, 'W')) {
    130 				args->flags |= CLD_FLG_UNIQ_WRT;
    131 			}
    132 			if (strchr(optarg, 't')) {
    133 				args->flags |= CLD_FLG_TMO_ERROR;
    134 			}
    135 			break;
    136 		case 'q':
    137 			glb_flags |= GLB_FLG_QUIET;
    138 			break;
    139 		case 'Q':
    140 			glb_flags |= GLB_FLG_SUPRESS;
    141 			break;
    142 		case 'v':
    143 			pMsg(INFO, args, "Version %s\n", VER_STR);
    144 			exit(0);
    145 		case 'p':
    146 			if (optarg == NULL) {
    147 				pMsg(WARN, args,
    148 				     "-%c option requires an argument.\n", c);
    149 				return (-1);
    150 			}
    151 			if (args->flags & (CLD_FLG_LINEAR | CLD_FLG_RANDOM)) {
    152 				pMsg(WARN, args,
    153 				     "Only one seek type, -p, can be specified.\n");
    154 				return (-1);
    155 			}
    156 			/* seek pattern type */
    157 			if (strchr(optarg, 'L'))
    158 				args->flags |= CLD_FLG_LINEAR;
    159 			else if (strchr(optarg, 'l'))
    160 				args->flags |=
    161 				    (CLD_FLG_LINEAR | CLD_FLG_NTRLVD);
    162 			else if (strchr(optarg, 'R'))
    163 				args->flags |= CLD_FLG_RANDOM;
    164 			else if (strchr(optarg, 'r'))
    165 				args->flags |=
    166 				    (CLD_FLG_RANDOM | CLD_FLG_NTRLVD);
    167 			else {
    168 				pMsg(WARN, args, "Unknown Seek pattern\n");
    169 				usage();
    170 				return (-1);
    171 			}
    172 			if (strchr(optarg, 'U') || strchr(optarg, 'u'))
    173 				if ((args->flags & (CLD_FLG_LINEAR)) &&
    174 				    !(args->flags & CLD_FLG_LUND))
    175 					args->flags |= CLD_FLG_LUNU;
    176 			if (strchr(optarg, 'D') || strchr(optarg, 'd'))
    177 				if ((args->flags & (CLD_FLG_LINEAR)) &&
    178 				    !(args->flags & CLD_FLG_LUNU))
    179 					args->flags |= CLD_FLG_LUND;
    180 			break;
    181 		case 'B':
    182 			if (!isdigit(optarg[0])) {
    183 				pMsg(WARN, args,
    184 				     "-%c arguments is non numeric.\n", c);
    185 				return (-1);
    186 			}
    187 			if (strchr(optarg, ':') != NULL) {	/* we are given a range of transfer sizes */
    188 				args->flags |= CLD_FLG_RTRSIZ;
    189 				args->ltrsiz = strtoul(optarg, &leftovers, 10);
    190 				if (leftovers == strchr(leftovers, 'k')) {	/* first value had a 'k' */
    191 					args->ltrsiz *= 2;
    192 					leftovers++;
    193 				} else if (leftovers == strchr(leftovers, 'm')) {	/* first value had a 'm' */
    194 					args->ltrsiz *= (2 * 1024);
    195 					leftovers++;
    196 				} else {
    197 					if (args->ltrsiz > 256)
    198 						args->ltrsiz /= BLK_SIZE;
    199 				}
    200 				if (!isdigit(leftovers[1])) {
    201 					pMsg(WARN, args,
    202 					     "-%c arguments is non numeric.\n",
    203 					     c);
    204 					return (-1);
    205 				}
    206 				args->htrsiz =
    207 				    atol((char *)strchr(leftovers, ':') + 1);
    208 				if ((strchr(leftovers, 'k')) != NULL) {	/* second value had a 'k' */
    209 					args->htrsiz *= 2;
    210 				} else if ((strchr(leftovers, 'm')) != NULL) {	/* second value had a 'm' */
    211 					args->htrsiz *= (2 * 1024);
    212 				} else {
    213 					if (args->htrsiz > 256)
    214 						args->htrsiz /= BLK_SIZE;
    215 				}
    216 			} else {	/* only a single value given for transfer size */
    217 				args->ltrsiz = atoi(optarg);
    218 				if (strchr(optarg, 'k')) {
    219 					args->ltrsiz *= 2;
    220 				} else if (strchr(optarg, 'm')) {
    221 					args->ltrsiz *= (2 * 1024);
    222 				} else {
    223 					if (args->ltrsiz > 256)
    224 						args->ltrsiz /= BLK_SIZE;
    225 				}
    226 				args->htrsiz = args->ltrsiz;
    227 			}
    228 #ifdef _DEBUG
    229 			PDBG5(DBUG, args, "Parsed Transfer size: %ld\n",
    230 			      args->htrsiz);
    231 #endif
    232 			break;
    233 		case 'c':
    234 			if (args->flags & CLD_FLG_PTYPS) {
    235 				pMsg(WARN, args,
    236 				     "Please specify only one pattern type\n");
    237 				usage();
    238 				return (-1);
    239 			}
    240 			args->flags |= CLD_FLG_CPTYPE;
    241 			break;
    242 		case 'n':
    243 			if (args->flags & CLD_FLG_PTYPS) {
    244 				pMsg(WARN, args,
    245 				     "Please specify only one pattern type\n");
    246 				usage();
    247 				return (-1);
    248 			}
    249 			args->flags |= CLD_FLG_LPTYPE;
    250 			break;
    251 		case 'f':
    252 			if (optarg == NULL) {
    253 				pMsg(WARN, args,
    254 				     "-%c option requires an argument.\n", c);
    255 				return (-1);
    256 			}
    257 			if (args->flags & CLD_FLG_PTYPS) {
    258 				pMsg(WARN, args,
    259 				     "Please specify only one pattern type\n");
    260 				usage();
    261 				return (-1);
    262 			}
    263 			args->pattern = my_strtofft(optarg);
    264 			args->flags |= CLD_FLG_FPTYPE;
    265 			break;
    266 		case 'F':
    267 			/* the filespec is a list of filespecs in a file */
    268 			args->flags |= CLD_FLG_FSLIST;
    269 			break;
    270 		case 'z':
    271 			if (args->flags & CLD_FLG_PTYPS) {
    272 				pMsg(WARN, args,
    273 				     "Please specify only one pattern type\n");
    274 				usage();
    275 				return (-1);
    276 			}
    277 			args->flags |= CLD_FLG_RPTYPE;
    278 			break;
    279 		case 'h':
    280 			if (optarg == NULL) {
    281 				pMsg(WARN, args,
    282 				     "-%c option requires an argument.\n", c);
    283 				return (-1);
    284 			}
    285 			if (!isdigit(optarg[0])) {
    286 				pMsg(WARN, args,
    287 				     "-%c arguments is non numeric.\n", c);
    288 				usage();
    289 				return (-1);
    290 			}
    291 			args->flags |= CLD_FLG_HBEAT;
    292 			args->hbeat = atoi(optarg);
    293 			if (strchr(optarg, 'm')) {	/* multiply by sec */
    294 				args->hbeat *= 60;
    295 			} else if (strchr(optarg, 'h')) {	/* multiply sec*min */
    296 				args->hbeat *= (time_t) (60 * 60);
    297 			} else if (strchr(optarg, 'd')) {	/* multiply by sec*min*hours */
    298 				args->hbeat *= (time_t) (60 * 60 * 24);
    299 			}
    300 			break;
    301 		case 'D':
    302 			if (optarg == NULL) {
    303 				pMsg(WARN, args,
    304 				     "-%c option requires an argument.\n", c);
    305 				return (-1);
    306 			}
    307 			if (!isdigit(optarg[0])) {
    308 				pMsg(WARN, args,
    309 				     "-%c arguments is non numeric.\n", c);
    310 				usage();
    311 				return (-1);
    312 			}
    313 			args->rperc = atoi(optarg);
    314 			args->wperc = atoi((char *)(strchr(optarg, ':') + 1));
    315 			args->flags |= CLD_FLG_DUTY;
    316 			break;
    317 		case 'r':
    318 			args->flags |= CLD_FLG_R;
    319 			break;
    320 		case 'w':
    321 			args->flags |= CLD_FLG_W;
    322 			break;
    323 		case 'o':
    324 			if (optarg == NULL) {
    325 				pMsg(WARN, args,
    326 				     "-%c option requires an argument.\n", c);
    327 				return (-1);
    328 			}
    329 			args->offset = atol(optarg);
    330 			args->flags |= CLD_FLG_OFFSET;
    331 			break;
    332 		case 'R':
    333 			if (optarg == NULL) {
    334 				pMsg(WARN, args,
    335 				     "-%c option requires an argument.\n", c);
    336 				return (-1);
    337 			}
    338 			if (strchr(optarg, ':') != NULL) {	/* we are given a retry delay */
    339 				args->retries = strtol(optarg, &leftovers, 10);
    340 				args->retry_delay =
    341 				    (time_t) atol((char *)strchr(leftovers, ':')
    342 						  + 1);
    343 			} else {	/* only a retry count given */
    344 				args->retries = atoi(optarg);
    345 			}
    346 			break;
    347 		case 'M':
    348 			if (optarg == NULL) {
    349 				pMsg(WARN, args,
    350 				     "-%c option requires an argument.\n", c);
    351 				return (-1);
    352 			}
    353 			args->flags |= CLD_FLG_ALT_MARK;
    354 			args->alt_mark = my_strtofft(optarg);
    355 			break;
    356 		case 'm':
    357 			args->flags |= CLD_FLG_MBLK;
    358 			if (optarg == NULL) {
    359 				pMsg(WARN, args,
    360 				     "-%c option requires an argument.\n", c);
    361 				return (-1);
    362 			}
    363 			if (strchr(optarg, 'l')) {	/* returns NULL if char is not found */
    364 				args->flags |= CLD_FLG_MRK_LBA;
    365 			}
    366 			if (strchr(optarg, 'p')) {
    367 				args->flags |= CLD_FLG_MRK_PASS;
    368 			}
    369 			if (strchr(optarg, 't')) {
    370 				args->flags |= CLD_FLG_MRK_TIME;
    371 			}
    372 			if (strchr(optarg, 's')) {
    373 				args->flags |= CLD_FLG_MRK_SEED;
    374 			}
    375 			if (strchr(optarg, 'h')) {
    376 				args->flags |= CLD_FLG_MRK_HOST;
    377 			}
    378 			if (strchr(optarg, 'f')) {
    379 				args->flags |= CLD_FLG_MRK_TARGET;
    380 			}
    381 			if (strchr(optarg, 'a')) {
    382 				args->flags |= CLD_FLG_MRK_ALL;
    383 			}
    384 			if (!strchr(optarg, 'l') &&
    385 			    !strchr(optarg, 'p') &&
    386 			    !strchr(optarg, 't') &&
    387 			    !strchr(optarg, 's') &&
    388 			    !strchr(optarg, 'h') &&
    389 			    !strchr(optarg, 'f') && !strchr(optarg, 'a')) {
    390 				pMsg(WARN, args,
    391 				     "Unknown header mark option\n");
    392 				return (-1);
    393 			}
    394 			break;
    395 		case 'E':
    396 			if (optarg == NULL) {
    397 				pMsg(WARN, args,
    398 				     "-%c option requires an argument.\n", c);
    399 				return (-1);
    400 			}
    401 			if (!isdigit(optarg[0])) {
    402 				pMsg(WARN, args,
    403 				     "-%c arguments are non numeric.\n", c);
    404 				usage();
    405 				return (-1);
    406 			}
    407 			args->flags |= CLD_FLG_CMPR;
    408 			args->cmp_lng = strtol(optarg, NULL, 0);
    409 			if (strchr(optarg, 'k')) {	/* multiply by 2^10 */
    410 				args->cmp_lng <<= 10;
    411 			} else if (strchr(optarg, 'K')) {	/* multiply 10^3 */
    412 				args->cmp_lng *= 1000;
    413 			} else if (strchr(optarg, 'm')) {	/* multiply by 2^20 */
    414 				args->cmp_lng <<= 20;
    415 			} else if (strchr(optarg, 'M')) {	/* multiply by 10^6 */
    416 				args->cmp_lng *= 1000000;
    417 			}
    418 			break;
    419 		case 'N':
    420 			if (optarg == NULL) {
    421 				pMsg(WARN, args,
    422 				     "-%c option requires an argument.\n", c);
    423 				return (-1);
    424 			}
    425 			if (!isdigit(optarg[0])) {
    426 				pMsg(WARN, args,
    427 				     "-%c arguments are non numeric.\n", c);
    428 				return (-1);
    429 			}
    430 			args->flags |= CLD_FLG_VSIZ;
    431 			args->vsiz = my_strtofft(optarg);
    432 			if (strchr(optarg, 'k')) {	/* multiply by 2^10 */
    433 				args->vsiz <<= 10;
    434 			} else if (strchr(optarg, 'K')) {	/* multiply 10^3 */
    435 				args->vsiz *= 1000;
    436 			} else if (strchr(optarg, 'm')) {	/* multiply by 2^20 */
    437 				args->vsiz <<= 20;
    438 			} else if (strchr(optarg, 'M')) {	/* multiply by 10^6 */
    439 				args->vsiz *= 1000000;
    440 			} else if (strchr(optarg, 'g')) {	/* multiply by 2^30 */
    441 				args->vsiz <<= 30;
    442 			} else if (strchr(optarg, 'G')) {	/* multiply by 10^9 */
    443 				args->vsiz *= 1000000000;
    444 			}
    445 			break;
    446 		case 'I':
    447 			if (optarg == NULL) {
    448 				pMsg(WARN, args,
    449 				     "-%c option requires an argument.\n", c);
    450 				return (-1);
    451 			}
    452 			if (strchr(optarg, 'R') || strchr(optarg, 'r')) {
    453 				if (!(args->flags & CLD_FLG_BLK) &&
    454 				    !(args->flags & CLD_FLG_FILE)) {
    455 					args->flags |= CLD_FLG_RAW;
    456 				} else {
    457 					pMsg(WARN, args,
    458 					     "Can only specify one IO type\n");
    459 					return (-1);
    460 				}
    461 			}
    462 			if (strchr(optarg, 'B') || strchr(optarg, 'b')) {
    463 				if (!(args->flags & CLD_FLG_RAW) &&
    464 				    !(args->flags & CLD_FLG_FILE)) {
    465 					args->flags |= CLD_FLG_BLK;
    466 				} else {
    467 					pMsg(WARN, args,
    468 					     "Can only specify one IO type\n");
    469 					return (-1);
    470 				}
    471 			}
    472 			if (strchr(optarg, 'F') || strchr(optarg, 'f')) {
    473 				if (!(args->flags & CLD_FLG_RAW) &&
    474 				    !(args->flags & CLD_FLG_BLK)) {
    475 					args->flags |= CLD_FLG_FILE;
    476 				} else {
    477 					pMsg(WARN, args,
    478 					     "Can only specify one IO type\n");
    479 					return (-1);
    480 				}
    481 			}
    482 			if (strchr(optarg, 'D') || strchr(optarg, 'd')) {
    483 				args->flags |= CLD_FLG_DIRECT;
    484 			}
    485 			if (strchr(optarg, 's')) {
    486 				args->sync_interval =
    487 				    strtoul((char *)strchr(optarg, 's') + 1,
    488 					    NULL, 10);
    489 #ifdef _DEBUG
    490 				PDBG3(DBUG, args, "Parsed sync interval: %ld\n",
    491 				      args->sync_interval);
    492 #endif
    493 				if ((args->flags & CLD_FLG_DIRECT)) {
    494 					pMsg(ERR, args,
    495 					     "Can't specify sync with Direct IO\n");
    496 					return (-1);
    497 				}
    498 				args->flags |= CLD_FLG_WFSYNC;
    499 			}
    500 			break;
    501 		case 't':
    502 			if (optarg == NULL) {
    503 				pMsg(WARN, args,
    504 				     "-%c option requires an argument.\n", c);
    505 				return (-1);
    506 			}
    507 
    508 			if (strchr(optarg, ':') != NULL) {	/* we are given a option for delay & timeout */
    509 				args->delayTimeMin =
    510 				    strtoul(optarg, &leftovers, 10);
    511 				/* check to see if we have one or more then one ':' */
    512 				if ((char *)strchr(optarg, ':') ==
    513 				    (char *)strrchr(optarg, ':')) {
    514 					/* only one ':', assume no random delayTime, and ioTimeout */
    515 					args->delayTimeMax = args->delayTimeMin;
    516 					args->ioTimeout =
    517 					    (time_t) atol((char *)
    518 							  strchr(leftovers,
    519 								 ':') + 1);
    520 				} else {
    521 					/* more then one ':', assume random delayTime, and ioTimeout */
    522 					args->delayTimeMax =
    523 					    strtoul(leftovers + 1, &leftovers,
    524 						    10);
    525 					args->ioTimeout =
    526 					    (time_t) atol((char *)
    527 							  strchr(leftovers,
    528 								 ':') + 1);
    529 				}
    530 				if (strchr(leftovers, 'm')) {	/* multiply by sec */
    531 					args->ioTimeout *= 60;
    532 				} else if (strchr(leftovers, 'h')) {	/* multiply sec*min */
    533 					args->ioTimeout *= (time_t) (60 * 60);
    534 				} else if (strchr(leftovers, 'd')) {	/* multiply by sec*min*hours */
    535 					args->ioTimeout *=
    536 					    (time_t) (60 * 60 * 24);
    537 				}
    538 			} else {
    539 				args->delayTimeMin =
    540 				    strtoul(optarg, NULL, 10);
    541 				args->delayTimeMax = args->delayTimeMin;
    542 			}
    543 			break;
    544 		case 'T':
    545 			if (optarg == NULL) {
    546 				pMsg(WARN, args,
    547 				     "-%c option requires an argument.\n", c);
    548 				return (-1);
    549 			}
    550 			args->run_time = atoi(optarg);
    551 			args->flags |= CLD_FLG_TMD;
    552 			if (strchr(optarg, 'm')) {	/* multiply by sec */
    553 				args->run_time *= 60;
    554 			} else if (strchr(optarg, 'h')) {	/* multiply sec*min */
    555 				args->run_time *= (time_t) (60 * 60);
    556 			} else if (strchr(optarg, 'd')) {	/* multiply by sec*min*hours */
    557 				args->run_time *= (time_t) (60 * 60 * 24);
    558 			}
    559 			break;
    560 		case 'L':
    561 			if (optarg == NULL) {
    562 				pMsg(WARN, args,
    563 				     "-%c option requires an argument.\n", c);
    564 				return (-1);
    565 			}
    566 			args->seeks = atoi(optarg);
    567 			args->flags |= CLD_FLG_SKS;
    568 			if (strchr(optarg, 'k')) {	/* multiply by 2^10 */
    569 				args->seeks <<= 10;
    570 			} else if (strchr(optarg, 'K')) {	/* multiply 10^3 */
    571 				args->seeks *= 1000;
    572 			} else if (strchr(optarg, 'm')) {	/* multiply by 2^20 */
    573 				args->seeks <<= 20;
    574 			} else if (strchr(optarg, 'M')) {	/* multiply by 10^6 */
    575 				args->seeks *= 1000000;
    576 			} else if (strchr(optarg, 'g')) {	/* multiply by 2^30 */
    577 				args->seeks <<= 30;
    578 			} else if (strchr(optarg, 'G')) {	/* multiply by 10^9 */
    579 				args->seeks *= 1000000000;
    580 			}
    581 			break;
    582 		case 'C':
    583 			if (optarg == NULL) {
    584 				pMsg(WARN, args,
    585 				     "-%c option requires an argument.\n", c);
    586 				return (-1);
    587 			}
    588 			if (!isdigit(optarg[0])) {
    589 				pMsg(WARN, args,
    590 				     "-%c arguments is non numeric.\n", c);
    591 				usage();
    592 				return (-1);
    593 			}
    594 			args->flags |= CLD_FLG_CYC;
    595 			args->cycles = atol(optarg);
    596 			break;
    597 		case 'K':
    598 			if (optarg == NULL) {
    599 				pMsg(WARN, args,
    600 				     "-%c option requires an argument.\n", c);
    601 				return (-1);
    602 			}
    603 			if (!isdigit(optarg[0])) {
    604 				pMsg(WARN, args,
    605 				     "-%c arguments is non numeric.\n", c);
    606 				usage();
    607 				return (-1);
    608 			}
    609 			if (atoi(optarg) > MAX_THREADS) {
    610 				pMsg(WARN, args,
    611 				     "%u exceeds max of %u threads.\n",
    612 				     atoi(optarg), MAX_THREADS);
    613 				return (-1);
    614 			}
    615 			args->t_kids = atoi(optarg);
    616 			break;
    617 		case 'P':
    618 			if (optarg == NULL) {
    619 				pMsg(WARN, args,
    620 				     "-%c option requires an argument.\n", c);
    621 				return (-1);
    622 			}
    623 			if (strchr(optarg, 'X')) {	/* returns NULL if char is not found */
    624 				args->flags |= CLD_FLG_XFERS;
    625 			}
    626 			if (strchr(optarg, 'T')) {
    627 				args->flags |= CLD_FLG_TPUTS;
    628 			}
    629 			if (strchr(optarg, 'P')) {
    630 				glb_flags |= GLB_FLG_PERFP;
    631 			}
    632 			if (strchr(optarg, 'R')) {
    633 				args->flags |= CLD_FLG_RUNT;
    634 			}
    635 			if (strchr(optarg, 'C')) {
    636 				args->flags |= CLD_FLG_PCYC;
    637 			}
    638 			if (strchr(optarg, 'A')) {
    639 				args->flags |= CLD_FLG_PRFTYPS;
    640 			}
    641 			if (!strchr(optarg, 'P') &&
    642 			    !strchr(optarg, 'A') &&
    643 			    !strchr(optarg, 'X') &&
    644 			    !strchr(optarg, 'R') &&
    645 			    !strchr(optarg, 'C') && !strchr(optarg, 'T')) {
    646 				pMsg(WARN, args,
    647 				     "Unknown performance option\n");
    648 				return (-1);
    649 			}
    650 			break;
    651 		case 'S':
    652 			if (!isdigit((int)optarg[0])) {
    653 				pMsg(WARN, args,
    654 				     "-%c arguments is non numeric.\n", c);
    655 				return (-1);
    656 			}
    657 			args->flags |= CLD_FLG_BLK_RNG;
    658 			if (strchr(optarg, ':') != NULL) {	/* we are given a range */
    659 				args->start_blk =
    660 				    (OFF_T) strtoul(optarg, &leftovers, 0);
    661 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    662 					args->start_blk <<= 10;
    663 					leftovers++;	/* at the ':' */
    664 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    665 					args->start_blk *= 1000;
    666 					leftovers++;	/* at the ':' */
    667 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    668 					args->start_blk <<= 20;
    669 					leftovers++;	/* at the ':' */
    670 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    671 					args->start_blk *= 1000000;
    672 					leftovers++;	/* at the ':' */
    673 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    674 					args->start_blk <<= 30;
    675 					leftovers++;	/* at the ':' */
    676 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    677 					args->start_blk *= 1000000000;
    678 					leftovers++;	/* at the ':' */
    679 				}
    680 				leftovers++;	/* should be at the next value */
    681 				if (!isdigit((int)leftovers[0])) {
    682 					pMsg(WARN, args,
    683 					     "-%c arguments is non numeric.\n",
    684 					     c);
    685 					return (-1);
    686 				}
    687 				args->stop_blk =
    688 				    (OFF_T) strtoul(leftovers, &leftovers, 0);
    689 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    690 					args->stop_blk <<= 10;
    691 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    692 					args->stop_blk *= 1000;
    693 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    694 					args->stop_blk <<= 20;
    695 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    696 					args->stop_blk *= 1000000;
    697 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    698 					args->stop_blk <<= 30;
    699 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    700 					args->stop_blk *= 1000000000;
    701 				}
    702 			} else {	/* only a single value given */
    703 				args->start_blk =
    704 				    (OFF_T) strtoul(optarg, &leftovers, 0);
    705 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    706 					args->start_blk <<= 10;
    707 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    708 					args->start_blk *= 1000;
    709 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    710 					args->start_blk <<= 20;
    711 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    712 					args->start_blk *= 1000000;
    713 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    714 					args->start_blk <<= 30;
    715 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    716 					args->start_blk *= 1000000000;
    717 				}
    718 			}
    719 			break;
    720 		case 's':
    721 			if (!isdigit((int)optarg[0])) {
    722 				pMsg(WARN, args,
    723 				     "-%c argument is non numeric.\n", c);
    724 				return (-1);
    725 			}
    726 			args->flags |= CLD_FLG_LBA_RNG;
    727 			if (strchr(optarg, ':') != NULL) {	/* we are given a range */
    728 				args->start_lba =
    729 				    (OFF_T) strtoul(optarg, &leftovers, 0);
    730 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    731 					args->start_lba <<= 10;
    732 					leftovers++;	/* at the ':' */
    733 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    734 					args->start_lba *= 1000;
    735 					leftovers++;	/* at the ':' */
    736 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    737 					args->start_lba <<= 20;
    738 					leftovers++;	/* at the ':' */
    739 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    740 					args->start_lba *= 1000000;
    741 					leftovers++;	/* at the ':' */
    742 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    743 					args->start_lba <<= 30;
    744 					leftovers++;	/* at the ':' */
    745 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    746 					args->start_lba *= 1000000000;
    747 					leftovers++;	/* at the ':' */
    748 				}
    749 				leftovers++;	/* should be at the next value */
    750 				if (!isdigit((int)leftovers[0])) {
    751 					pMsg(WARN, args,
    752 					     "-%c second argument is non numeric.\n",
    753 					     c);
    754 					return (-1);
    755 				}
    756 				args->stop_lba =
    757 				    (OFF_T) strtoul(leftovers, &leftovers, 0);
    758 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    759 					args->stop_lba <<= 10;
    760 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    761 					args->stop_lba *= 1000;
    762 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    763 					args->stop_lba <<= 20;
    764 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    765 					args->stop_lba *= 1000000;
    766 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    767 					args->stop_lba <<= 30;
    768 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    769 					args->stop_lba *= 1000000000;
    770 				}
    771 			} else {	/* only a single value given */
    772 				args->start_lba =
    773 				    (OFF_T) strtoul(optarg, &leftovers, 0);
    774 				if (leftovers == strchr(leftovers, 'k')) {	/* multiply by 2^10 */
    775 					args->start_lba <<= 10;
    776 				} else if (leftovers == strchr(leftovers, 'K')) {	/* multiply 10^3 */
    777 					args->start_lba *= 1000;
    778 				} else if (leftovers == strchr(leftovers, 'm')) {	/* multiply by 2^20 */
    779 					args->start_lba <<= 20;
    780 				} else if (leftovers == strchr(leftovers, 'M')) {	/* multiply by 10^6 */
    781 					args->start_lba *= 1000000;
    782 				} else if (leftovers == strchr(leftovers, 'g')) {	/* multiply by 2^30 */
    783 					args->start_lba <<= 30;
    784 				} else if (leftovers == strchr(leftovers, 'G')) {	/* multiply by 10^9 */
    785 					args->start_lba *= 1000000000;
    786 				}
    787 			}
    788 			break;
    789 		case '?':
    790 		default:
    791 			usage();
    792 			return (-1);
    793 		}
    794 	}
    795 	if (argv[optind] == NULL) {
    796 		pMsg(WARN, args, "Unspecified target.\n");
    797 		return (-1);
    798 	}
    799 	strncpy(args->device, argv[optind], (DEV_NAME_LEN - 1));
    800 	return 0;
    801 }
    802 
    803 int make_assumptions(child_args_t * args)
    804 {
    805 	char TmpStr[80];
    806 	struct stat stat_buf;
    807 	int rv;
    808 
    809 	if (!(args->flags & CLD_FLG_IOTYPS)) {
    810 		/* use stat to get file properties, and use to set -I */
    811 		rv = stat(args->device, &stat_buf);
    812 		if (0 == rv) {
    813 			if (IS_FILE(stat_buf.st_mode)) {
    814 				strncat(args->argstr, "(-I f) ",
    815 					(MAX_ARG_LEN - 1) -
    816 					strlen(args->argstr));
    817 				args->flags |= CLD_FLG_FILE;
    818 			} else if (IS_BLK(stat_buf.st_mode)) {
    819 				strncat(args->argstr, "(-I b) ",
    820 					(MAX_ARG_LEN - 1) -
    821 					strlen(args->argstr));
    822 				args->flags |= CLD_FLG_BLK;
    823 #ifndef WINDOWS
    824 			} else if (S_ISCHR(stat_buf.st_mode)) {
    825 				strncat(args->argstr, "(-I r) ",
    826 					(MAX_ARG_LEN - 1) -
    827 					strlen(args->argstr));
    828 				args->flags |= CLD_FLG_RAW;
    829 #endif
    830 			}
    831 		} else {
    832 			pMsg(WARN, args,
    833 			     "Can't get status on %s, defaulting to file, errno = %d\n",
    834 			     args->device, GETLASTERROR());
    835 			strncat(args->argstr, "(-I f) ",
    836 				(MAX_ARG_LEN - 1) - strlen(args->argstr));
    837 			args->flags |= CLD_FLG_FILE;
    838 		}
    839 	}
    840 	if ((args->flags & CLD_FLG_WFSYNC) && (0 == args->sync_interval)) {
    841 		pMsg(INFO, args,
    842 		     "Sync interval set to zero, assuming interval of 1.\n");
    843 		args->sync_interval = 1;
    844 	}
    845 
    846 	if (args->ltrsiz <= 0) {
    847 		sprintf(TmpStr, "(-B %d) ", TRSIZ * BLK_SIZE);
    848 		strncat(args->argstr, TmpStr,
    849 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    850 		args->ltrsiz = TRSIZ;
    851 		args->htrsiz = TRSIZ;
    852 	}
    853 	if (args->flags & CLD_FLG_LBA_RNG) {
    854 		args->start_blk = args->start_lba / args->htrsiz;
    855 		if (!(args->stop_lba < 0))
    856 			args->stop_blk = args->stop_lba / args->htrsiz;
    857 	}
    858 	if (args->flags & CLD_FLG_BLK_RNG) {
    859 		args->start_lba = args->start_blk * args->htrsiz;
    860 		if (!(args->stop_blk < 0))
    861 			args->stop_lba =
    862 			    (args->stop_blk * args->htrsiz) + (args->htrsiz -
    863 							       1);
    864 	}
    865 	/* if vsiz is still not set, try and get it from the file */
    866 	if ((args->vsiz <= 0) && (args->flags & CLD_FLG_FILE)) {
    867 		if (0 != get_file_size(args->device)) {	/* file size retrieved */
    868 			args->vsiz = get_file_size(args->device);
    869 		}
    870 	}
    871 	/* if vsiz is still not set, try and get it from the device */
    872 	if ((args->vsiz <= 0) && !(args->flags & CLD_FLG_FILE)) {
    873 		args->vsiz = get_vsiz(args->device);
    874 	}
    875 	/* if vsiz is still not set, set based on given range */
    876 	if ((args->vsiz <= 0)
    877 	    && (args->flags & (CLD_FLG_LBA_RNG | CLD_FLG_BLK_RNG))) {
    878 		if (!(args->stop_lba < 0))
    879 			args->vsiz = args->stop_lba + 1;
    880 		else
    881 			args->vsiz = args->start_lba + 1;
    882 	}
    883 	/* if vsiz is still not set, then set it to the default size */
    884 	if (args->vsiz <= 0) {
    885 		args->vsiz = VSIZ;
    886 	}
    887 	if (!(args->flags & CLD_FLG_VSIZ)) {
    888 		sprintf(TmpStr, N_ASSUME, args->vsiz);
    889 		strncat(args->argstr, TmpStr,
    890 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    891 	}
    892 
    893 	if (args->stop_lba == -1) {
    894 		args->stop_lba = args->vsiz - 1;
    895 	}
    896 	if (args->stop_blk == -1) {
    897 		args->stop_blk = (args->stop_lba / (OFF_T) args->htrsiz);
    898 	}
    899 	if (args->t_kids == 0) {
    900 		sprintf(TmpStr, "(-K %d) ", KIDS);
    901 		strncat(args->argstr, TmpStr,
    902 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    903 		args->t_kids = KIDS;
    904 	}
    905 	if ((args->flags & (CLD_FLG_W | CLD_FLG_R)) == 0) {
    906 		if (args->flags & CLD_FLG_DUTY) {	/* no read/write but duty cycle specified */
    907 			if (args->rperc > 0) {
    908 				args->flags |= CLD_FLG_R;
    909 				strncat(args->argstr, "(-r) ",
    910 					(MAX_ARG_LEN - 1) -
    911 					strlen(args->argstr));
    912 			}
    913 			if (args->wperc > 0) {
    914 				args->flags |= CLD_FLG_W;
    915 				strncat(args->argstr, "(-w) ",
    916 					(MAX_ARG_LEN - 1) -
    917 					strlen(args->argstr));
    918 			}
    919 		} else {
    920 			strncat(args->argstr, "(-r) ",
    921 				(MAX_ARG_LEN - 1) - strlen(args->argstr));
    922 			args->flags |= CLD_FLG_R;
    923 		}
    924 	}
    925 	if (!(args->flags & CLD_FLG_PTYPS)) {
    926 		strncat(args->argstr, "(-c) ",
    927 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    928 		args->flags |= CLD_FLG_CPTYPE;
    929 	}
    930 	if (!(args->flags & CLD_FLG_SKTYPS)) {
    931 		strncat(args->argstr, "(-p R) ",
    932 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    933 		args->flags |= CLD_FLG_RANDOM;
    934 	}
    935 	if (!(args->flags & CLD_FLG_SKS)) {
    936 		if (args->start_blk == args->stop_blk) {	/* diskcache test, w/ no seek count set */
    937 			args->seeks = SEEKS;
    938 		} else if (args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG)) {	/* range set, w/ no seek count */
    939 			args->seeks = args->stop_blk - args->start_blk + 1;
    940 		} else {
    941 			/* if vsiz is available, calculated seeks are in terms of the largest transfer size */
    942 			args->seeks =
    943 			    (args->vsiz >
    944 			     0) ? (args->vsiz / args->htrsiz) : SEEKS;
    945 		}
    946 		if ((args->flags & CLD_FLG_LINEAR) && (args->flags & CLD_FLG_R)
    947 		    && (args->flags & CLD_FLG_W)) {
    948 			args->seeks *= 2;
    949 		}
    950 
    951 		if (!(args->flags & CLD_FLG_TMD)) {
    952 			sprintf(TmpStr, L_ASSUME, args->seeks);
    953 			strncat(args->argstr, TmpStr,
    954 				(MAX_ARG_LEN - 1) - strlen(args->argstr));
    955 		}
    956 	}
    957 	if (!(args->flags & (CLD_FLG_SKS | CLD_FLG_TMD))
    958 	    || ((args->flags & CLD_FLG_CYC)
    959 		&& !(args->flags & (CLD_FLG_SKS | CLD_FLG_TMD)))) {
    960 		args->flags |= CLD_FLG_SKS;
    961 	}
    962 	if (args->flags & (CLD_FLG_LINEAR)) {
    963 		if (!(args->flags & (CLD_FLG_LUNU | CLD_FLG_LUND))) {
    964 			strncat(args->argstr, "(-p u) ",
    965 				(MAX_ARG_LEN - 1) - strlen(args->argstr));
    966 			args->flags |= CLD_FLG_LUNU;
    967 		}
    968 	}
    969 	normalize_percs(args);
    970 	if (!(args->flags & CLD_FLG_DUTY) && (args->flags & CLD_FLG_RANDOM)
    971 	    && !(args->flags & CLD_FLG_NTRLVD)) {
    972 		sprintf(TmpStr, "(-D %d:%d) ", args->rperc, args->wperc);
    973 		strncat(args->argstr, TmpStr,
    974 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    975 		args->flags |= CLD_FLG_DUTY;
    976 	}
    977 	if ((args->delayTimeMin == 0) && (args->delayTimeMax == 0)
    978 	    && (args->ioTimeout == DEFAULT_IO_TIMEOUT)) {
    979 		strncat(args->argstr, "(-t 0:2m) ",
    980 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    981 	}
    982 	if (!(args->flags & CLD_FLG_OFFSET)) {
    983 		strncat(args->argstr, "(-o 0) ",
    984 			(MAX_ARG_LEN - 1) - strlen(args->argstr));
    985 	}
    986 
    987 	return 0;
    988 }
    989 
    990 /*
    991  * checks validity of data after parsing
    992  * args and make assumtions. returns 0 on
    993  * success and -1 on failure.
    994  */
    995 int check_conclusions(child_args_t * args)
    996 {
    997 	extern unsigned long glb_flags;
    998 	struct stat stat_buf;
    999 	int rv;
   1000 
   1001 	if ((args->flags & CLD_FLG_DUTY)
   1002 	    && ((args->flags & CLD_FLG_LINEAR)
   1003 		|| (args->flags & CLD_FLG_NTRLVD))) {
   1004 		pMsg(WARN, args,
   1005 		     "Duty cycle testing is supported for random (-pR) tests only.\n");
   1006 		return (-1);
   1007 	}
   1008 	if ((args->flags & CLD_FLG_BLK_RNG) && (args->flags & CLD_FLG_RTRSIZ)) {
   1009 		pMsg(WARN, args,
   1010 		     "Can't have unfixed block sizes and specify seek range in terms of blocks.\n");
   1011 		return (-1);
   1012 	}
   1013 	if ((args->vsiz < 0) || (args->ltrsiz < 1) || (args->htrsiz < 1)) {
   1014 		pMsg(WARN, args,
   1015 		     "Bounds exceeded for transfer size and/or volume size.\n");
   1016 		pMsg(WARN, args, MAXTRSIZ, (args->htrsiz * BLK_SIZE),
   1017 		     args->vsiz);
   1018 		return (-1);
   1019 	}
   1020 	if (args->htrsiz < args->ltrsiz) {
   1021 		pMsg(ERR, args,
   1022 		     "Min transfer size, %lu, greater then Max transfer size, %lu.\n",
   1023 		     args->ltrsiz, args->htrsiz);
   1024 		return (-1);
   1025 	}
   1026 	if (args->vsiz < (args->stop_lba - args->start_lba + 1)) {
   1027 		pMsg(ERR, args, "Volume stop block/lba exceeds volume size.\n");
   1028 		return (-1);
   1029 	}
   1030 	if (args->vsiz < args->htrsiz) {
   1031 		pMsg(WARN, args, VSIZETS, args->vsiz, args->htrsiz);
   1032 		return (-1);
   1033 	}
   1034 	if ((args->flags & CLD_FLG_TMD) == 0 && (args->seeks <= 0)) {
   1035 		pMsg(WARN, args, TSEEK, args->seeks);
   1036 		return (-1);
   1037 	}
   1038 	if ((args->flags & CLD_FLG_SKS) && (args->t_kids > args->seeks)) {
   1039 		pMsg(WARN, args,
   1040 		     "Can't have more children then max number of seeks, use -K/-L to adjust.\n");
   1041 		return (-1);
   1042 	}
   1043 	if ((args->start_blk > args->vsiz)
   1044 	    && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) {
   1045 		pMsg(WARN, args, STBGTTLBA, args->start_blk,
   1046 		     (args->vsiz / args->htrsiz));
   1047 		return (-1);
   1048 	}
   1049 	if ((args->stop_blk > args->vsiz)
   1050 	    && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) {
   1051 		pMsg(WARN, args, SBGTTLBA, args->stop_blk,
   1052 		     (args->vsiz / args->htrsiz));
   1053 		return (-1);
   1054 	}
   1055 	if ((args->start_lba > args->vsiz)
   1056 	    && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) {
   1057 		pMsg(WARN, args, STLBAGTLBA, args->start_lba, args->vsiz);
   1058 		return (-1);
   1059 	}
   1060 	if ((args->stop_lba > args->vsiz)
   1061 	    && !(args->flags & (CLD_FLG_BLK_RNG | CLD_FLG_LBA_RNG))) {
   1062 		pMsg(WARN, args, SLBAGTLBA, args->stop_lba, args->vsiz);
   1063 		return (-1);
   1064 	}
   1065 	if (args->start_blk > args->stop_blk) {
   1066 		pMsg(WARN, args, SBRSB, args->stop_blk, args->start_blk);
   1067 		return (-1);
   1068 	}
   1069 	if (args->start_lba > args->stop_lba) {
   1070 		pMsg(ERR, args, SLBARSLBA, args->stop_lba, args->start_lba);
   1071 		return (-1);
   1072 	}
   1073 	if ((args->flags & CLD_FLG_LBA_RNG) && (args->flags & CLD_FLG_BLK_RNG)) {
   1074 		pMsg(ERR, args,
   1075 		     "Can't specify range in both block and LBA, use -s or -S.\n");
   1076 		return (-1);
   1077 	}
   1078 
   1079 	/* use stat to get file properties, and test then agains specified -I */
   1080 	rv = stat(args->device, &stat_buf);
   1081 	if (0 == rv) {		/* no error on call to stat, compare against -I option */
   1082 		/* files are usually file type */
   1083 		if ((args->flags & CLD_FLG_FILE) && !IS_FILE(stat_buf.st_mode)) {
   1084 			pMsg(ERR, args,
   1085 			     "Can't open non-file filespec with file device type, -If.\n");
   1086 			return (-1);
   1087 		}
   1088 		/* block devices, are usually block type */
   1089 		if ((args->flags & CLD_FLG_BLK) && !IS_BLK(stat_buf.st_mode)) {
   1090 			pMsg(ERR, args,
   1091 			     "Can't open non-block filespec with block device type, -Ib.\n");
   1092 			return (-1);
   1093 		}
   1094 #ifndef WINDOWS
   1095 		/* raw devices, are usually character type */
   1096 		if ((args->flags & CLD_FLG_RAW) && !S_ISCHR(stat_buf.st_mode)) {
   1097 			pMsg(ERR, args,
   1098 			     "Can't open non-raw filespec with raw device type, -Ir.\n");
   1099 			return (-1);
   1100 		}
   1101 #else
   1102 		if (args->flags & CLD_FLG_RAW) {
   1103 			pMsg(ERR, args,
   1104 			     "RAW IO type not supported in Windows, use direct IO instead.\n");
   1105 			return (-1);
   1106 		}
   1107 #endif
   1108 #ifdef _DEBUG
   1109 	} else {
   1110 		PDBG1(DBUG, args,
   1111 		      "Can't get status on %s, assuming a new file, errno = %d\n",
   1112 		      args->device, GETLASTERROR());
   1113 #endif
   1114 	}
   1115 
   1116 	if ((args->hbeat > 0) && (args->flags & CLD_FLG_TMD)
   1117 	    && (args->hbeat > args->run_time)) {
   1118 		pMsg(ERR, args,
   1119 		     "Heartbeat should be at least equal to runtime, use -h/-T to adjust.\n");
   1120 		return (-1);
   1121 	}
   1122 	if ((args->hbeat > 0) && !(args->flags & CLD_FLG_PRFTYPS)) {
   1123 		pMsg(ERR, args,
   1124 		     "At least one performance option, -P, must be specified when using -h.\n");
   1125 		return (-1);
   1126 	}
   1127 	if ((args->flags & CLD_FLG_W) && !(args->flags & CLD_FLG_R)
   1128 	    && (args->flags & CLD_FLG_CMPR)) {
   1129 		pMsg(ERR, args, "Write only, ignoring option -E.\n");
   1130 	}
   1131 	if ((args->flags & CLD_FLG_TMD) && (args->flags & CLD_FLG_SKS)) {
   1132 		pMsg(ERR, args,
   1133 		     "Can't specify both -L and -T they are mutually exclusive.\n");
   1134 		return (-1);
   1135 	}
   1136 	if (((args->flags & CLD_FLG_R) && !(args->flags & CLD_FLG_W))
   1137 	    && (args->flags & CLD_FLG_ERR_MARK)) {
   1138 		pMsg(ERR, args,
   1139 		     "Can't specify mark on error, -Am, in read only mode.\n");
   1140 		return (-1);
   1141 	}
   1142 	if (!(args->flags & CLD_FLG_ALLDIE) && (args->flags & CLD_FLG_ERR_MARK)) {
   1143 		pMsg(ERR, args,
   1144 		     "Can't specify mark on error, -Am, when continue on error is set.\n");
   1145 		return (-1);
   1146 	}
   1147 	if ((glb_flags & GLB_FLG_KILL) && !(args->flags & CLD_FLG_ALLDIE)) {
   1148 		pMsg(ERR, args,
   1149 		     "Can't specify global kill, -Ag, when continue on error is set, -Ac.\n");
   1150 		return (-1);
   1151 	}
   1152 	if ((args->flags & CLD_FLG_LINEAR) && !(args->flags & CLD_FLG_NTRLVD)
   1153 	    && (args->flags & CLD_FLG_TMD)) {
   1154 		pMsg(ERR, args, "Linear read / write test can not be timed.\n");
   1155 		return (-1);
   1156 	}
   1157 	if ((args->flags & CLD_FLG_CMPR)
   1158 	    && (args->cmp_lng > (args->ltrsiz * BLK_SIZE))) {
   1159 		pMsg(ERR, args,
   1160 		     "Compare length, %lu, is greater then transfer size, %lu\n",
   1161 		     args->cmp_lng, args->ltrsiz * BLK_SIZE);
   1162 		return (-1);
   1163 	}
   1164 	if ((args->flags & CLD_FLG_OFFSET) && (args->offset > args->stop_lba)) {
   1165 		pMsg(ERR, args, LBAOFFGSLBA, args->offset, args->stop_lba);
   1166 		return (-1);
   1167 	}
   1168 	if ((args->flags & CLD_FLG_OFFSET)
   1169 	    && ((args->offset + args->ltrsiz - 1) > args->stop_lba)) {
   1170 		pMsg(ERR, args, LBAOTSGSLBA, args->offset, args->ltrsiz,
   1171 		     args->stop_lba);
   1172 		return (-1);
   1173 	}
   1174 	return 0;
   1175 }
   1176