Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
      3  *
      4  * This program is free software; you can redistribute it and/or modify it
      5  * under the terms of version 2 of the GNU General Public License as
      6  * published by the Free Software Foundation.
      7  *
      8  * This program is distributed in the hope that it would be useful, but
      9  * WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     11  *
     12  * Further, this software is distributed without any warranty that it is
     13  * free of the rightful claim of any third person regarding infringement
     14  * or the like.  Any license provided herein, whether implied or
     15  * otherwise, applies only to this software file.  Patent licenses, if
     16  * any, provided herein do not apply to combinations of this program with
     17  * other software, or any other product whatsoever.
     18  *
     19  * You should have received a copy of the GNU General Public License along
     20  * with this program; if not, write the Free Software Foundation, Inc.,
     21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     22  *
     23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
     24  * Mountain View, CA  94043, or:
     25  *
     26  * http://www.sgi.com
     27  *
     28  * For further information regarding this notice, see:
     29  *
     30  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
     31  */
     32 /*
     33  *
     34  * Lib i/o
     35  *
     36  * This file contains several functions to doing reads and writes.
     37  * It was written so that a single function could be called in a test
     38  * program and only a io type field value would have to change to
     39  * do different types of io.  There is even a couple of functions that
     40  * will allow you to parse a string to determine the iotype.
     41  *
     42  * This file contains functions for writing/reading to/from open files
     43  * Prototypes:
     44  *
     45  * Functions declared in this module - see individual function code for
     46  * usage comments:
     47  *
     48  *  int	 stride_bounds(int offset, int stride, int nstrides,
     49  *		      int bytes_per_stride, int *min, int *max);
     50 
     51  *  int  lio_write_buffer(int fd, int method, char *buffer, int size,
     52  *						char **errmsg, long wrd);
     53  *  int  lio_read_buffer(int fd, int method, char *buffer, int size,
     54  *						char **errmsg, long wrd);
     55  *
     56  *  #ifdef CRAY
     57  *  int  lio_wait4asyncio(int method, int fd, struct iosw **statptr)
     58  *  int  lio_check_asyncio(char *io_type, int size, struct iosw *status)
     59  *  #endif
     60  *  #ifdef sgi
     61  *  int  lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
     62  *  int  lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
     63  *  #endif
     64  *
     65  *  int  lio_parse_io_arg1(char *string)
     66  *  void lio_help1(char *prefix);
     67  *
     68  *  int  lio_parse_io_arg2(char *string, char **badtoken)
     69  *  void lio_help2(char *prefix);
     70  *
     71  *  int  lio_set_debug(int level);
     72  *
     73  *  char Lio_SysCall[];
     74  *  struct lio_info_type Lio_info1[];
     75  *  struct lio_info_type Lio_info2[];
     76  *
     77  *  Author : Richard Logan
     78  *
     79  */
     80 
     81 #ifdef __linux__
     82 #ifndef _GNU_SOURCE
     83 #define _GNU_SOURCE
     84 #endif
     85 #define _LARGEFILE64_SOURCE
     86 #endif
     87 #include "config.h"
     88 #include <stdio.h>
     89 #include <ctype.h>
     90 #include <fcntl.h>
     91 #include <unistd.h>
     92 #include <sys/types.h>
     93 #include <sys/stat.h>
     94 #include <sys/time.h>
     95 #include <sys/param.h>
     96 #include <errno.h>
     97 #include <sys/types.h>
     98 #include <sys/file.h>
     99 #include <signal.h>
    100 #include <stdint.h>
    101 #ifdef CRAY
    102 #include <sys/secparm.h>
    103 #include <sys/iosw.h>
    104 #include <sys/listio.h>
    105 #else
    106 /* for linux or sgi */
    107 #include <sys/uio.h>		/* readv(2)/writev(2) */
    108 #include <string.h>		/* bzero */
    109 #endif
    110 #if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX)
    111 #if !defined(UCLINUX) && !defined(__UCLIBC__)
    112 #include <aio.h>
    113 #endif
    114 #endif
    115 #include <stdlib.h>		/* atoi, abs */
    116 
    117 #include "tlibio.h"		/* defines LIO* marcos */
    118 #include "random_range.h"
    119 
    120 #ifndef PATH_MAX
    121 #define PATH_MAX	MAXPATHLEN
    122 #endif
    123 
    124 #if 0				/* disabled until it's needed -- roehrich 6/11/97 */
    125 #define BUG1_workaround	1	/* Work around a condition where aio_return gives
    126 				 * a value of zero but there is no errno followup
    127 				 * and the read/write operation actually did its
    128 				 * job.   spr/pv 705244
    129 				 */
    130 #endif
    131 
    132 
    133 /*
    134  * Define the structure as used in lio_parse_arg1 and lio_help1
    135  */
    136 struct lio_info_type Lio_info1[] = {
    137 	{"s", LIO_IO_SYNC, "sync i/o"},
    138 	{"p", LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE,
    139 	 "async i/o using a loop to wait for a signal"},
    140 	{"b", LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, "async i/o using pause"},
    141 	{"a", LIO_IO_ASYNC | LIO_WAIT_RECALL,
    142 	 "async i/o using recall/aio_suspend"},
    143 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    144 	{"r",
    145 	 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
    146 	 "random sync i/o types and wait methods"},
    147 	{"R",
    148 	 LIO_RANDOM | LIO_IO_ATYPES | LIO_WAIT_ATYPES,
    149 	 "random i/o types and wait methods"},
    150 #else
    151 	{"r",
    152 	 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
    153 	 "random i/o types and wait methods"},
    154 	{"R",
    155 	 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
    156 	 "random i/o types and wait methods"},
    157 #endif
    158 	{"l", LIO_IO_SLISTIO | LIO_WAIT_RECALL, "single stride sync listio"},
    159 	{"L", LIO_IO_ALISTIO | LIO_WAIT_RECALL,
    160 	 "single stride async listio using recall"},
    161 	{"X", LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE,
    162 	 "single stride async listio using pause"},
    163 	{"v", LIO_IO_SYNCV, "single buffer sync readv/writev"},
    164 	{"P", LIO_IO_SYNCP, "sync pread/pwrite"},
    165 };
    166 
    167 /*
    168  * Define the structure used by lio_parse_arg2 and lio_help2
    169  */
    170 struct lio_info_type Lio_info2[] = {
    171 	{"sync", LIO_IO_SYNC, "sync i/o (read/write)"},
    172 	{"async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)"},
    173 	{"slistio", LIO_IO_SLISTIO, "single stride sync listio"},
    174 	{"alistio", LIO_IO_ALISTIO, "single stride async listio"},
    175 	{"syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
    176 	{"syncp", LIO_IO_SYNCP, "pread/pwrite"},
    177 	{"active", LIO_WAIT_ACTIVE, "spin on status/control values"},
    178 	{"recall", LIO_WAIT_RECALL,
    179 	 "use recall(2)/aio_suspend(3) to wait for i/o to complete"},
    180 	{"sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal"},
    181 	{"sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal"},
    182 /* nowait is a touchy thing, it's an accident that this implementation worked at all.  6/27/97 roehrich */
    183 /*    { "nowait",    LIO_WAIT_NONE,	"do not wait for async io to complete" },*/
    184 	{"random", LIO_RANDOM, "set random bit"},
    185 	{"randomall",
    186 	 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
    187 	 "all random i/o types and wait methods (except nowait)"},
    188 };
    189 
    190 char Lio_SysCall[PATH_MAX];	/* string containing last i/o system call */
    191 
    192 static volatile int Received_signal = 0;	/* number of signals received */
    193 static volatile int Rec_signal;
    194 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    195 static volatile int Received_callback = 0;	/* number of callbacks received */
    196 static volatile int Rec_callback;
    197 #endif
    198 static char Errormsg[500];
    199 static int Debug_level = 0;
    200 
    201 /***********************************************************************
    202  * stride_bounds()
    203  *
    204  * Determine the bounds of a strided request, normalized to offset.  Returns
    205  * the number of bytes needed to satisfy the request, and optionally sets
    206  * *min and *max to the mininum and maximum bytes referenced, normalized
    207  * around offset.
    208  *
    209  * Returns -1 on error - the only possible error conditions are illegal values
    210  * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
    211  *
    212  * (maule, 11/16/95)
    213  ***********************************************************************/
    214 
    215 int stride_bounds(int offset, int stride, int nstrides, int bytes_per_stride,
    216 		int *min, int *max)
    217 {
    218 	int nbytes, min_byte, max_byte;
    219 
    220 	/*
    221 	 * sanity checks ...
    222 	 */
    223 
    224 	if (nstrides < 0 || bytes_per_stride < 0) {
    225 		return -1;
    226 	}
    227 
    228 	if (stride == 0) {
    229 		stride = bytes_per_stride;
    230 	}
    231 
    232 	/*
    233 	 * Determine the # of bytes needed to satisfy the request.  This
    234 	 * value, along with the offset argument, determines the min and max
    235 	 * bytes referenced.
    236 	 */
    237 
    238 	nbytes = abs(stride) * (nstrides - 1) + bytes_per_stride;
    239 
    240 	if (stride < 0) {
    241 		max_byte = offset + bytes_per_stride - 1;
    242 		min_byte = max_byte - nbytes + 1;
    243 	} else {
    244 		min_byte = offset;
    245 		max_byte = min_byte + nbytes - 1;
    246 	}
    247 
    248 	if (min != NULL) {
    249 		*min = min_byte;
    250 	}
    251 
    252 	if (max != NULL) {
    253 		*max = max_byte;
    254 	}
    255 
    256 	return nbytes;
    257 }
    258 
    259 /***********************************************************************
    260  * This function will allow someone to set the debug level.
    261  ***********************************************************************/
    262 int lio_set_debug(int level)
    263 {
    264 	int old;
    265 
    266 	old = Debug_level;
    267 	Debug_level = level;
    268 	return old;
    269 }
    270 
    271 /***********************************************************************
    272  * This function will parse a string and return desired io-method.
    273  * Only the first character of the string is used.
    274  *
    275  * This function does not provide for meaningful option arguments,
    276  * but it supports current growfiles/btlk interface.
    277  *
    278  *  (rrl 04/96)
    279  ***********************************************************************/
    280 int lio_parse_io_arg1(char *string)
    281 {
    282 	unsigned int ind;
    283 	int found = 0;
    284 	int mask = 0;
    285 
    286 	/*
    287 	 * Determine if token is a valid string.
    288 	 */
    289 	for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
    290 	     ind++) {
    291 		if (strcmp(string, Lio_info1[ind].token) == 0) {
    292 			mask |= Lio_info1[ind].bits;
    293 			found = 1;
    294 			break;
    295 		}
    296 	}
    297 
    298 	if (found == 0) {
    299 		return -1;
    300 	}
    301 
    302 	return mask;
    303 
    304 }
    305 
    306 /***********************************************************************
    307  * This function will print a help message describing the characters
    308  * that can be parsed by lio_parse_io_arg1().
    309  * They will be printed one per line.
    310  *  (rrl 04/96)
    311  ***********************************************************************/
    312 void lio_help1(char *prefix)
    313 {
    314 	unsigned int ind;
    315 
    316 	for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
    317 	     ind++) {
    318 		printf("%s %s : %s\n", prefix, Lio_info1[ind].token,
    319 		       Lio_info1[ind].desc);
    320 	}
    321 
    322 	return;
    323 }
    324 
    325 /***********************************************************************
    326  * This function will parse a string and return the desired io-method.
    327  * This function will take a comma separated list of io type and wait
    328  * method tokens as defined in Lio_info2[].  If a token does not match
    329  * any of the tokens in Lio_info2[], it will be coverted to a number.
    330  * If it was a number, those bits are also set.
    331  *
    332  *  (rrl 04/96)
    333  ***********************************************************************/
    334 int lio_parse_io_arg2(char *string, char **badtoken)
    335 {
    336 	char *token = string;
    337 	char *cc = token;
    338 	char savecc;
    339 	int found;
    340 	int mask = 0;
    341 
    342 	int tmp;
    343 	unsigned int ind;
    344 	char chr;
    345 
    346 	if (token == NULL)
    347 		return -1;
    348 
    349 	for (;;) {
    350 		for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
    351 		savecc = *cc;
    352 		*cc = '\0';
    353 
    354 		found = 0;
    355 
    356 		/*
    357 		 * Determine if token is a valid string or number and if
    358 		 * so, add the bits to the mask.
    359 		 */
    360 		for (ind = 0;
    361 		     ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
    362 		     ind++) {
    363 			if (strcmp(token, Lio_info2[ind].token) == 0) {
    364 				mask |= Lio_info2[ind].bits;
    365 				found = 1;
    366 				break;
    367 			}
    368 		}
    369 
    370 		/*
    371 		 * If token does not match one of the defined tokens, determine
    372 		 * if it is a number, if so, add the bits.
    373 		 */
    374 		if (!found) {
    375 			if (sscanf(token, "%i%c", &tmp, &chr) == 1) {
    376 				mask |= tmp;
    377 				found = 1;
    378 			}
    379 		}
    380 
    381 		*cc = savecc;
    382 
    383 		if (!found) {	/* token is not valid */
    384 			if (badtoken != NULL)
    385 				*badtoken = token;
    386 			return (-1);
    387 		}
    388 
    389 		if (savecc == '\0')
    390 			break;
    391 
    392 		token = ++cc;
    393 	}
    394 
    395 	return mask;
    396 }
    397 
    398 /***********************************************************************
    399  * This function will print a help message describing the tokens
    400  * that can be parsed by lio_parse_io_arg2().
    401  * It will print them one per line.
    402  *
    403  * (rrl 04/96)
    404  ***********************************************************************/
    405 void lio_help2(char *prefix)
    406 {
    407 	unsigned int ind;
    408 
    409 	for (ind = 0; ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
    410 	     ind++) {
    411 		printf("%s %s : %s\n", prefix, Lio_info2[ind].token,
    412 		       Lio_info2[ind].desc);
    413 	}
    414 	return;
    415 }
    416 
    417 /***********************************************************************
    418  * This is an internal signal handler.
    419  * If the handler is called, it will increment the Received_signal
    420  * global variable.
    421  ***********************************************************************/
    422 static void lio_async_signal_handler(int sig)
    423 {
    424 	if (Debug_level)
    425 		printf
    426 		    ("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
    427 		     __FILE__, __LINE__, sig, Received_signal + 1);
    428 
    429 	Received_signal++;
    430 
    431 	return;
    432 }
    433 
    434 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    435 /***********************************************************************
    436  * This is an internal callback handler.
    437  * If the handler is called, it will increment the Received_callback
    438  * global variable.
    439  ***********************************************************************/
    440 static void lio_async_callback_handler(union sigval sigval)
    441 {
    442 	if (Debug_level)
    443 		printf
    444 		    ("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
    445 		     __FILE__, __LINE__, (long)sigval.sival_int,
    446 		     Received_callback + 1);
    447 
    448 	Received_callback++;
    449 
    450 	return;
    451 }
    452 #endif /* sgi */
    453 
    454 /***********************************************************************
    455  * lio_random_methods
    456  * This function will randomly choose an io type and wait method
    457  * from set of io types and wait methods.  Since this information
    458  * is stored in a bitmask, it randomly chooses an io type from
    459  * the io type bits specified and does the same for wait methods.
    460  *
    461  * Return Value
    462  * This function will return a value with all non choosen io type
    463  * and wait method bits cleared.  The LIO_RANDOM bit is also
    464  * cleared.  All other bits are left unchanged.
    465  *
    466  * (rrl 04/96)
    467  ***********************************************************************/
    468 int lio_random_methods(long curr_mask)
    469 {
    470 	int mask = 0;
    471 
    472 	/* remove random select, io type, and wait method bits from curr_mask */
    473 	mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
    474 
    475 	/* randomly select io type from specified io types */
    476 	mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
    477 
    478 	/* randomly select wait methods  from specified wait methods */
    479 	mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
    480 
    481 	return mask;
    482 }
    483 
    484 static void wait4sync_io(int fd, int read)
    485 {
    486 	fd_set s;
    487 	FD_ZERO(&s);
    488 	FD_SET(fd, &s);
    489 
    490 	select(fd + 1, read ? &s : NULL, read ? NULL : &s, NULL, NULL);
    491 }
    492 
    493 /***********************************************************************
    494  * Generic write function
    495  * This function can be used to do a write using write(2), writea(2),
    496  * aio_write(3), writev(2), pwrite(2),
    497  * or single stride listio(2)/lio_listio(3).
    498  * By setting the desired bits in the method
    499  * bitmask, the caller can control the type of write and the wait method
    500  * that will be used.  If no io type bits are set, write will be used.
    501  *
    502  * If async io was attempted and no wait method bits are set then the
    503  * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
    504  * aio_write(3) and lio_listio(3).
    505  *
    506  * If multiple wait methods are specified,
    507  * only one wait method will be used. The order is predetermined.
    508  *
    509  * If the call specifies a signal and one of the two signal wait methods,
    510  * a signal handler for the signal is set.  This will reset an already
    511  * set handler for this signal.
    512  *
    513  * If the LIO_RANDOM method bit is set, this function will randomly
    514  * choose a io type and wait method from bits in the method argument.
    515  *
    516  * If an error is encountered, an error message will be generated
    517  * in a internal static buffer.  If errmsg is not NULL, it will
    518  * be updated to point to the static buffer, allowing the caller
    519  * to print the error message.
    520  *
    521  * Return Value
    522  *   If a system call fails, -errno is returned.
    523  *   If LIO_WAIT_NONE bit is set, the return value is the return value
    524  *   of the system call.
    525  *   If the io did not fail, the amount of data written is returned.
    526  *	If the size the system call say was written is different
    527  *	then what was asked to be written, errmsg is updated for
    528  *	this error condition.  The return value is still the amount
    529  *	the system call says was written.
    530  *
    531  * (rrl 04/96)
    532  ***********************************************************************/
    533 int lio_write_buffer(int fd,		/* open file descriptor */
    534 		int method,	/* contains io type and wait method bitmask */
    535 		char *buffer,	/* pointer to buffer */
    536 		int size,	/* the size of the io */
    537 		int sig,	/* signal to use if async io */
    538 		char **errmsg,	/* char pointer that will be updated to point to err message */
    539 		long wrd)	/* to allow future features, use zero for now */
    540 {
    541 	int ret = 0;		/* syscall return or used to get random method */
    542 	char *io_type;		/* Holds string of type of io */
    543 	int omethod = method;
    544 	int listio_cmd;		/* Holds the listio/lio_listio cmd */
    545 #ifdef  CRAY
    546 	struct listreq request;	/* Used when a listio is wanted */
    547 	struct iosw status, *statptr[1];
    548 #else
    549 	/* for linux or sgi */
    550 	struct iovec iov;	/* iovec for writev(2) */
    551 #endif
    552 #if defined (sgi)
    553 	aiocb_t aiocbp;		/* POSIX aio control block */
    554 	aiocb_t *aiolist[1];	/* list of aio control blocks for lio_listio */
    555 	off64_t poffset;	/* pwrite(2) offset */
    556 #endif
    557 #if defined(__linux__) && !defined(__UCLIBC__)
    558 	struct aiocb aiocbp;	/* POSIX aio control block */
    559 	struct aiocb *aiolist[1];	/* list of aio control blocks for lio_listio */
    560 	off64_t poffset;	/* pwrite(2) offset */
    561 #endif
    562 	/*
    563 	 * If LIO_RANDOM bit specified, get new method randomly.
    564 	 */
    565 	if (method & LIO_RANDOM) {
    566 		if (Debug_level > 3)
    567 			printf("DEBUG %s/%d: method mask to choose from: %#o\n",
    568 			       __FILE__, __LINE__, method);
    569 		method = lio_random_methods(method);
    570 		if (Debug_level > 2)
    571 			printf("DEBUG %s/%d: random chosen method %#o\n",
    572 			       __FILE__, __LINE__, method);
    573 	}
    574 
    575 	if (errmsg != NULL)
    576 		*errmsg = Errormsg;
    577 
    578 	Rec_signal = Received_signal;	/* get the current number of signals received */
    579 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    580 	Rec_callback = Received_callback;	/* get the current number of callbacks received */
    581 #endif
    582 
    583 #ifdef  CRAY
    584 	memset(&status, 0x00, sizeof(struct iosw));
    585 	memset(&request, 0x00, sizeof(struct listreq));
    586 	statptr[0] = &status;
    587 #else
    588 	/* for linux or sgi */
    589 	memset(&iov, 0x00, sizeof(struct iovec));
    590 	iov.iov_base = buffer;
    591 	iov.iov_len = size;
    592 #endif
    593 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    594 #if defined(sgi)
    595 	memset(&aiocbp, 0x00, sizeof(aiocb_t));
    596 #else
    597 	memset(&aiocbp, 0x00, sizeof(struct aiocb));
    598 #endif
    599 	aiocbp.aio_fildes = fd;
    600 	aiocbp.aio_nbytes = size;
    601 	aiocbp.aio_buf = buffer;
    602 /*    aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
    603 	aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
    604 	aiocbp.aio_sigevent.sigev_signo = 0;
    605 #ifdef sgi
    606 	aiocbp.aio_sigevent.sigev_func = NULL;
    607 	aiocbp.aio_sigevent.sigev_value.sival_int = 0;
    608 #elif defined(__linux__) && !defined(__UCLIBC__)
    609 	aiocbp.aio_sigevent.sigev_notify_function = NULL;
    610 	aiocbp.aio_sigevent.sigev_notify_attributes = 0;
    611 #endif
    612 	aiolist[0] = &aiocbp;
    613 
    614 	if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
    615 		ret = 0;
    616 		/* If there is an error and it is not ESPIPE then kick out the error.
    617 		 * If the fd is a fifo then we have to make sure that
    618 		 * lio_random_methods() didn't select pwrite/pread; if it did then
    619 		 * switch to write/read.
    620 		 */
    621 		if (errno == ESPIPE) {
    622 			if (method & LIO_IO_SYNCP) {
    623 				if (omethod & LIO_RANDOM) {
    624 					method &= ~LIO_IO_SYNCP;
    625 					method |= LIO_IO_SYNC;
    626 					if (Debug_level > 2)
    627 						printf
    628 						    ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
    629 						     __FILE__, __LINE__,
    630 						     method);
    631 				} else if (Debug_level) {
    632 					printf
    633 					    ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
    634 					     __FILE__, __LINE__);
    635 				}
    636 			}
    637 			/* else: let it ride */
    638 		} else {
    639 			sprintf(Errormsg,
    640 				"%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d  %s",
    641 				__FILE__, __LINE__, fd, errno, strerror(errno));
    642 			return -errno;
    643 		}
    644 	}
    645 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    646 	poffset = (off64_t) ret;
    647 #endif
    648 	aiocbp.aio_offset = ret;
    649 
    650 #endif
    651 
    652 	/*
    653 	 * If the LIO_USE_SIGNAL bit is not set, only use the signal
    654 	 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
    655 	 * Otherwise there is not necessary a signal handler to trap
    656 	 * the signal.
    657 	 */
    658 	if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
    659 
    660 		sig = 0;	/* ignore signal parameter */
    661 	}
    662 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    663 	if (sig && (method & LIO_WAIT_CBTYPES))
    664 		sig = 0;	/* ignore signal parameter */
    665 #endif
    666 
    667 	/*
    668 	 * only setup signal hander if sig was specified and
    669 	 * a sig wait method was specified.
    670 	 * Doing this will change the handler for this signal.  The
    671 	 * old signal handler will not be restored.
    672 	 *** restoring the signal handler could be added ***
    673 	 */
    674 
    675 	if (sig && (method & LIO_WAIT_SIGTYPES)) {
    676 #ifdef CRAY
    677 		sigctl(SCTL_REG, sig, lio_async_signal_handler);
    678 #endif
    679 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    680 		aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    681 		aiocbp.aio_sigevent.sigev_signo = sig;
    682 		sigset(sig, lio_async_signal_handler);
    683 #endif /* sgi */
    684 	}
    685 #if defined(sgi)
    686 	else if (method & LIO_WAIT_CBTYPES) {
    687 		/* sival_int just has to be something that I can use
    688 		 * to identify the callback, and "size" happens to be handy...
    689 		 */
    690 		aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
    691 		aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
    692 		aiocbp.aio_sigevent.sigev_value.sival_int = size;
    693 	}
    694 #endif
    695 #if defined(__linux__) && !defined(__UCLIBC__)
    696 	else if (method & LIO_WAIT_CBTYPES) {
    697 		/* sival_int just has to be something that I can use
    698 		 * to identify the callback, and "size" happens to be handy...
    699 		 */
    700 		aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
    701 		aiocbp.aio_sigevent.sigev_notify_function =
    702 		    lio_async_callback_handler;
    703 		aiocbp.aio_sigevent.sigev_notify_attributes =
    704 		    (void *)(uintptr_t) size;
    705 	}
    706 #endif
    707 	/*
    708 	 * Determine the system call that will be called and produce
    709 	 * the string of the system call and place it in Lio_SysCall.
    710 	 * Also update the io_type char pointer to give brief description
    711 	 * of system call.  Execute the system call and check for
    712 	 * system call failure.  If sync i/o, return the number of
    713 	 * bytes written/read.
    714 	 */
    715 
    716 	if ((method & LIO_IO_SYNC)
    717 	    || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
    718 		/*
    719 		 * write(2) is used if LIO_IO_SYNC bit is set or not none
    720 		 * of the LIO_IO_TYPES bits are set (default).
    721 		 */
    722 
    723 		sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
    724 		io_type = "write";
    725 
    726 		if (Debug_level) {
    727 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    728 			       Lio_SysCall);
    729 		}
    730 		while (1) {
    731 			if (((ret = write(fd, buffer, size)) == -1)
    732 			    && errno != EAGAIN && errno != EINTR) {
    733 				sprintf(Errormsg,
    734 					"%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
    735 					__FILE__, __LINE__, fd, size, errno,
    736 					strerror(errno));
    737 				return -errno;
    738 			}
    739 
    740 			if (ret != -1) {
    741 				if (ret != size) {
    742 					sprintf(Errormsg,
    743 						"%s/%d write(%d, buf, %d) returned=%d",
    744 						__FILE__, __LINE__,
    745 						fd, size, ret);
    746 					size -= ret;
    747 					buffer += ret;
    748 				} else {
    749 					if (Debug_level > 1)
    750 						printf
    751 						    ("DEBUG %s/%d: write completed without error (ret %d)\n",
    752 						     __FILE__, __LINE__, ret);
    753 
    754 					return ret;
    755 				}
    756 			}
    757 			wait4sync_io(fd, 0);
    758 		}
    759 
    760 	}
    761 
    762 	else if (method & LIO_IO_ASYNC) {
    763 #ifdef CRAY
    764 		sprintf(Lio_SysCall,
    765 			"writea(%d, buf, %d, &status, %d)", fd, size, sig);
    766 		io_type = "writea";
    767 
    768 		if (Debug_level) {
    769 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    770 			       Lio_SysCall);
    771 		}
    772 
    773 		sigoff();
    774 		if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
    775 			sprintf(Errormsg,
    776 				"%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
    777 				__FILE__, __LINE__,
    778 				fd, size, sig, errno, strerror(errno));
    779 			sigon();
    780 			return -errno;
    781 		}
    782 #endif
    783 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    784 		sprintf(Lio_SysCall,
    785 			"aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
    786 			size, sig);
    787 		io_type = "aio_write";
    788 
    789 		if (Debug_level) {
    790 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    791 			       Lio_SysCall);
    792 		}
    793 
    794 		if (sig)
    795 			sighold(sig);
    796 		if ((ret = aio_write(&aiocbp)) == -1) {
    797 			sprintf(Errormsg,
    798 				"%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
    799 				__FILE__, __LINE__,
    800 				fd, size, sig, errno, strerror(errno));
    801 			if (sig)
    802 				sigrelse(sig);
    803 			return -errno;
    804 		}
    805 #endif
    806 	}
    807 	/* LIO_IO_ASYNC */
    808 	else if (method & LIO_IO_SLISTIO) {
    809 #ifdef CRAY
    810 		request.li_opcode = LO_WRITE;
    811 		request.li_fildes = fd;
    812 		request.li_buf = buffer;
    813 		request.li_nbyte = size;
    814 		request.li_status = &status;
    815 		request.li_signo = sig;
    816 		request.li_nstride = 0;
    817 		request.li_filstride = 0;
    818 		request.li_memstride = 0;
    819 
    820 		listio_cmd = LC_WAIT;
    821 		io_type = "listio(2) sync write";
    822 
    823 		sprintf(Lio_SysCall,
    824 			"listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
    825 			fd, size);
    826 
    827 		if (Debug_level) {
    828 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    829 			       Lio_SysCall);
    830 		}
    831 
    832 		sigoff();
    833 		if (listio(listio_cmd, &request, 1) == -1) {
    834 			sprintf(Errormsg,
    835 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
    836 				__FILE__, __LINE__, Lio_SysCall, fd, size,
    837 				errno, strerror(errno));
    838 			sigon();
    839 			return -errno;
    840 		}
    841 
    842 		if (Debug_level > 1)
    843 			printf("DEBUG %s/%d: %s did not return -1\n",
    844 			       __FILE__, __LINE__, Lio_SysCall);
    845 
    846 		ret = lio_check_asyncio(io_type, size, &status);
    847 		return ret;
    848 
    849 #endif
    850 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    851 
    852 		aiocbp.aio_lio_opcode = LIO_WRITE;
    853 		listio_cmd = LIO_WAIT;
    854 		io_type = "lio_listio(3) sync write";
    855 
    856 		sprintf(Lio_SysCall,
    857 			"lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
    858 			fd, size, sig);
    859 
    860 		if (Debug_level) {
    861 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    862 			       Lio_SysCall);
    863 		}
    864 
    865 		if (sig)
    866 			sighold(sig);
    867 		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
    868 			sprintf(Errormsg,
    869 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
    870 				__FILE__, __LINE__, Lio_SysCall, fd, size,
    871 				errno, strerror(errno));
    872 			if (sig)
    873 				sigrelse(sig);
    874 			return -errno;
    875 		}
    876 
    877 		if (Debug_level > 1)
    878 			printf("DEBUG %s/%d: %s did not return -1\n",
    879 			       __FILE__, __LINE__, Lio_SysCall);
    880 
    881 		ret = lio_check_asyncio(io_type, size, &aiocbp, method);
    882 		return ret;
    883 #endif
    884 	}
    885 	/* LIO_IO_SLISTIO */
    886 	else if (method & LIO_IO_ALISTIO) {
    887 #ifdef CRAY
    888 		request.li_opcode = LO_WRITE;
    889 		request.li_fildes = fd;
    890 		request.li_buf = buffer;
    891 		request.li_nbyte = size;
    892 		request.li_status = &status;
    893 		request.li_signo = sig;
    894 		request.li_nstride = 0;
    895 		request.li_filstride = 0;
    896 		request.li_memstride = 0;
    897 
    898 		listio_cmd = LC_START;
    899 		io_type = "listio(2) async write";
    900 
    901 		sprintf(Lio_SysCall,
    902 			"listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
    903 			fd, size);
    904 
    905 		if (Debug_level) {
    906 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    907 			       Lio_SysCall);
    908 		}
    909 
    910 		sigoff();
    911 		if (listio(listio_cmd, &request, 1) == -1) {
    912 			sprintf(Errormsg,
    913 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
    914 				__FILE__, __LINE__, Lio_SysCall, fd, size,
    915 				errno, strerror(errno));
    916 			sigon();
    917 			return -errno;
    918 		}
    919 #endif
    920 #if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    921 		aiocbp.aio_lio_opcode = LIO_WRITE;
    922 		listio_cmd = LIO_NOWAIT;
    923 		io_type = "lio_listio(3) async write";
    924 
    925 		sprintf(Lio_SysCall,
    926 			"lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
    927 			fd, size);
    928 
    929 		if (Debug_level) {
    930 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    931 			       Lio_SysCall);
    932 		}
    933 
    934 		if (sig)
    935 			sighold(sig);
    936 		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
    937 			sprintf(Errormsg,
    938 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
    939 				__FILE__, __LINE__, Lio_SysCall, fd, size,
    940 				errno, strerror(errno));
    941 			if (sig)
    942 				sigrelse(sig);
    943 			return -errno;
    944 		}
    945 #endif
    946 	}
    947 	/* LIO_IO_ALISTIO */
    948 #ifndef CRAY
    949 	else if (method & LIO_IO_SYNCV) {
    950 		io_type = "writev(2)";
    951 
    952 		sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
    953 
    954 		if (Debug_level) {
    955 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    956 			       Lio_SysCall);
    957 		}
    958 		if ((ret = writev(fd, &iov, 1)) == -1) {
    959 			sprintf(Errormsg,
    960 				"%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
    961 				__FILE__, __LINE__, fd, size, errno,
    962 				strerror(errno));
    963 			return -errno;
    964 		}
    965 
    966 		if (ret != size) {
    967 			sprintf(Errormsg,
    968 				"%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
    969 				__FILE__, __LINE__, fd, size, ret);
    970 		} else if (Debug_level > 1)
    971 			printf
    972 			    ("DEBUG %s/%d: writev completed without error (ret %d)\n",
    973 			     __FILE__, __LINE__, ret);
    974 
    975 		return ret;
    976 	}			/* LIO_IO_SYNCV */
    977 #endif
    978 
    979 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
    980 	else if (method & LIO_IO_SYNCP) {
    981 		io_type = "pwrite(2)";
    982 
    983 		sprintf(Lio_SysCall,
    984 			"pwrite(%d, buf, %d, %lld)", fd, size,
    985 			(long long)poffset);
    986 
    987 		if (Debug_level) {
    988 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
    989 			       Lio_SysCall);
    990 		}
    991 		if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
    992 			sprintf(Errormsg,
    993 				"%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
    994 				__FILE__, __LINE__, fd, size,
    995 				(long long)poffset, errno, strerror(errno));
    996 			return -errno;
    997 		}
    998 
    999 		if (ret != size) {
   1000 			sprintf(Errormsg,
   1001 				"%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
   1002 				__FILE__, __LINE__,
   1003 				fd, size, (long long)poffset, ret);
   1004 		} else if (Debug_level > 1)
   1005 			printf
   1006 			    ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
   1007 			     __FILE__, __LINE__, ret);
   1008 
   1009 		return ret;
   1010 	}			/* LIO_IO_SYNCP */
   1011 #endif
   1012 
   1013 	else {
   1014 		printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
   1015 		       __LINE__);
   1016 		return -1;
   1017 	}
   1018 
   1019 	/*
   1020 	 * wait for async io to complete.
   1021 	 */
   1022 #ifdef CRAY
   1023 	ret = lio_wait4asyncio(method, fd, statptr);
   1024 #endif
   1025 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1026 	ret = lio_wait4asyncio(method, fd, &aiocbp);
   1027 #endif
   1028 
   1029 	/*
   1030 	 * If there was an error waiting for async i/o to complete,
   1031 	 * return the error value (errno) to the caller.
   1032 	 * Note: Errormsg should already have been updated.
   1033 	 */
   1034 	if (ret < 0) {
   1035 		return ret;
   1036 	}
   1037 
   1038 	/*
   1039 	 * If i/o was not waited for (may not have been completed at this time),
   1040 	 * return the size that was requested.
   1041 	 */
   1042 	if (ret == 1)
   1043 		return size;
   1044 
   1045 	/*
   1046 	 * check that async io was successful.
   1047 	 * Note:  if the there was an system call failure, -errno
   1048 	 * was returned and Errormsg should already have been updated.
   1049 	 * If amount i/o was different than size, Errormsg should already
   1050 	 * have been updated but the actual i/o size if returned.
   1051 	 */
   1052 
   1053 #ifdef CRAY
   1054 	ret = lio_check_asyncio(io_type, size, &status);
   1055 #endif
   1056 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1057 	ret = lio_check_asyncio(io_type, size, &aiocbp, method);
   1058 #endif
   1059 
   1060 	return ret;
   1061 }				/* end of lio_write_buffer */
   1062 
   1063 /***********************************************************************
   1064  * Generic read function
   1065  * This function can be used to do a read using read(2), reada(2),
   1066  * aio_read(3), readv(2), pread(2),
   1067  * or single stride listio(2)/lio_listio(3).
   1068  * By setting the desired bits in the method
   1069  * bitmask, the caller can control the type of read and the wait method
   1070  * that will be used.  If no io type bits are set, read will be used.
   1071  *
   1072  * If async io was attempted and no wait method bits are set then the
   1073  * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
   1074  * aio_read(3) and lio_listio(3).
   1075  *
   1076  * If multiple wait methods are specified,
   1077  * only one wait method will be used. The order is predetermined.
   1078  *
   1079  * If the call specifies a signal and one of the two signal wait methods,
   1080  * a signal handler for the signal is set.  This will reset an already
   1081  * set handler for this signal.
   1082  *
   1083  * If the LIO_RANDOM method bit is set, this function will randomly
   1084  * choose a io type and wait method from bits in the method argument.
   1085  *
   1086  * If an error is encountered, an error message will be generated
   1087  * in a internal static buffer.  If errmsg is not NULL, it will
   1088  * be updated to point to the static buffer, allowing the caller
   1089  * to print the error message.
   1090  *
   1091  * Return Value
   1092  *   If a system call fails, -errno is returned.
   1093  *   If LIO_WAIT_NONE bit is set, the return value is the return value
   1094  *   of the system call.
   1095  *   If the io did not fail, the amount of data written is returned.
   1096  *	If the size the system call say was written is different
   1097  *	then what was asked to be written, errmsg is updated for
   1098  *	this error condition.  The return value is still the amount
   1099  *	the system call says was written.
   1100  *
   1101  * (rrl 04/96)
   1102  ***********************************************************************/
   1103 int lio_read_buffer(int fd,	/* open file descriptor */
   1104 		int method,	/* contains io type and wait method bitmask*/
   1105 		char *buffer,	/* pointer to buffer */
   1106 		int size,	/* the size of the io */
   1107 		int sig,	/* signal to use if async io */
   1108 		char **errmsg,	/* char pointer that will be updated to point to err message */
   1109 		long wrd)	/* to allow future features, use zero for now */
   1110 {
   1111 	int ret = 0;		/* syscall return or used to get random method */
   1112 	char *io_type;		/* Holds string of type of io */
   1113 	int listio_cmd;		/* Holds the listio/lio_listio cmd */
   1114 	int omethod = method;
   1115 #ifdef  CRAY
   1116 	struct listreq request;	/* Used when a listio is wanted */
   1117 	struct iosw status, *statptr[1];
   1118 #else
   1119 	/* for linux or sgi */
   1120 	struct iovec iov;	/* iovec for readv(2) */
   1121 #endif
   1122 #ifdef sgi
   1123 	aiocb_t aiocbp;		/* POSIX aio control block */
   1124 	aiocb_t *aiolist[1];	/* list of aio control blocks for lio_listio */
   1125 	off64_t poffset;	/* pread(2) offset */
   1126 #endif
   1127 #if defined (__linux__) && !defined(__UCLIBC__)
   1128 	struct aiocb aiocbp;	/* POSIX aio control block */
   1129 	struct aiocb *aiolist[1];	/* list of aio control blocks for lio_listio */
   1130 	off64_t poffset;	/* pread(2) offset */
   1131 #endif
   1132 
   1133 	/*
   1134 	 * If LIO_RANDOM bit specified, get new method randomly.
   1135 	 */
   1136 	if (method & LIO_RANDOM) {
   1137 		if (Debug_level > 3)
   1138 			printf("DEBUG %s/%d: method mask to choose from: %#o\n",
   1139 			       __FILE__, __LINE__, method);
   1140 		method = lio_random_methods(method);
   1141 		if (Debug_level > 2)
   1142 			printf("DEBUG %s/%d: random chosen method %#o\n",
   1143 			       __FILE__, __LINE__, method);
   1144 	}
   1145 
   1146 	if (errmsg != NULL)
   1147 		*errmsg = Errormsg;
   1148 
   1149 	Rec_signal = Received_signal;	/* get the current number of signals received */
   1150 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1151 	Rec_callback = Received_callback;	/* get the current number of callbacks received */
   1152 #endif
   1153 
   1154 #ifdef  CRAY
   1155 	memset(&status, 0x00, sizeof(struct iosw));
   1156 	memset(&request, 0x00, sizeof(struct listreq));
   1157 	statptr[0] = &status;
   1158 #else
   1159 	/* for linux or sgi */
   1160 	memset(&iov, 0x00, sizeof(struct iovec));
   1161 	iov.iov_base = buffer;
   1162 	iov.iov_len = size;
   1163 #endif
   1164 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1165 #if defined(sgi)
   1166 	memset(&aiocbp, 0x00, sizeof(aiocb_t));
   1167 #else
   1168 	memset(&aiocbp, 0x00, sizeof(struct aiocb));
   1169 #endif
   1170 	aiocbp.aio_fildes = fd;
   1171 	aiocbp.aio_nbytes = size;
   1172 	aiocbp.aio_buf = buffer;
   1173 /*    aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
   1174 	aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
   1175 	aiocbp.aio_sigevent.sigev_signo = 0;
   1176 #ifdef sgi
   1177 	aiocbp.aio_sigevent.sigev_func = NULL;
   1178 	aiocbp.aio_sigevent.sigev_value.sival_int = 0;
   1179 #elif defined(__linux__) && !defined(__UCLIBC__)
   1180 	aiocbp.aio_sigevent.sigev_notify_function = NULL;
   1181 	aiocbp.aio_sigevent.sigev_notify_attributes = 0;
   1182 #endif
   1183 	aiolist[0] = &aiocbp;
   1184 
   1185 	if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
   1186 		ret = 0;
   1187 		/* If there is an error and it is not ESPIPE then kick out the error.
   1188 		 * If the fd is a fifo then we have to make sure that
   1189 		 * lio_random_methods() didn't select pwrite/pread; if it did then
   1190 		 * switch to write/read.
   1191 		 */
   1192 		if (errno == ESPIPE) {
   1193 			if (method & LIO_IO_SYNCP) {
   1194 				if (omethod & LIO_RANDOM) {
   1195 					method &= ~LIO_IO_SYNCP;
   1196 					method |= LIO_IO_SYNC;
   1197 					if (Debug_level > 2)
   1198 						printf
   1199 						    ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
   1200 						     __FILE__, __LINE__,
   1201 						     method);
   1202 				} else if (Debug_level) {
   1203 					printf
   1204 					    ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
   1205 					     __FILE__, __LINE__);
   1206 				}
   1207 			}
   1208 			/* else: let it ride */
   1209 		} else {
   1210 			sprintf(Errormsg,
   1211 				"%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d  %s",
   1212 				__FILE__, __LINE__, fd, errno, strerror(errno));
   1213 			return -errno;
   1214 		}
   1215 	}
   1216 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1217 	poffset = (off64_t) ret;
   1218 #endif
   1219 	aiocbp.aio_offset = ret;
   1220 
   1221 #endif
   1222 
   1223 	/*
   1224 	 * If the LIO_USE_SIGNAL bit is not set, only use the signal
   1225 	 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
   1226 	 * Otherwise there is not necessarily a signal handler to trap
   1227 	 * the signal.
   1228 	 */
   1229 	if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
   1230 
   1231 		sig = 0;	/* ignore signal parameter */
   1232 	}
   1233 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
   1234 	if (sig && (method & LIO_WAIT_CBTYPES))
   1235 		sig = 0;	/* ignore signal parameter */
   1236 #endif
   1237 
   1238 	/*
   1239 	 * only setup signal hander if sig was specified and
   1240 	 * a sig wait method was specified.
   1241 	 * Doing this will change the handler for this signal.  The
   1242 	 * old signal handler will not be restored.
   1243 	 *** restoring the signal handler could be added ***
   1244 	 */
   1245 
   1246 	if (sig && (method & LIO_WAIT_SIGTYPES)) {
   1247 #ifdef CRAY
   1248 		sigctl(SCTL_REG, sig, lio_async_signal_handler);
   1249 #endif
   1250 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1251 		aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
   1252 		aiocbp.aio_sigevent.sigev_signo = sig;
   1253 		sigset(sig, lio_async_signal_handler);
   1254 #endif /* CRAY */
   1255 	}
   1256 #if defined(sgi)
   1257 	else if (method & LIO_WAIT_CBTYPES) {
   1258 		aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
   1259 		aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
   1260 		/* sival_int just has to be something that I can use
   1261 		 * to identify the callback, and "size" happens to be handy...
   1262 		 */
   1263 		aiocbp.aio_sigevent.sigev_value.sival_int = size;
   1264 	}
   1265 #endif
   1266 #if defined(__linux__) && !defined(__UCLIBC__)
   1267 	else if (method & LIO_WAIT_CBTYPES) {
   1268 		aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
   1269 		aiocbp.aio_sigevent.sigev_notify_function =
   1270 		    lio_async_callback_handler;
   1271 		/* sival_int just has to be something that I can use
   1272 		 * to identify the callback, and "size" happens to be handy...
   1273 		 */
   1274 		aiocbp.aio_sigevent.sigev_notify_attributes =
   1275 		    (void *)(uintptr_t) size;
   1276 	}
   1277 #endif
   1278 
   1279 	/*
   1280 	 * Determine the system call that will be called and produce
   1281 	 * the string of the system call and place it in Lio_SysCall.
   1282 	 * Also update the io_type char pointer to give brief description
   1283 	 * of system call.  Execute the system call and check for
   1284 	 * system call failure.  If sync i/o, return the number of
   1285 	 * bytes written/read.
   1286 	 */
   1287 
   1288 	if ((method & LIO_IO_SYNC)
   1289 	    || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
   1290 		/*
   1291 		 * read(2) is used if LIO_IO_SYNC bit is set or not none
   1292 		 * of the LIO_IO_TYPES bits are set (default).
   1293 		 */
   1294 
   1295 		sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
   1296 		io_type = "read";
   1297 
   1298 		if (Debug_level) {
   1299 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1300 			       Lio_SysCall);
   1301 		}
   1302 
   1303 		while (1) {
   1304 			if (((ret = read(fd, buffer, size)) == -1)
   1305 			    && errno != EINTR && errno != EAGAIN) {
   1306 				sprintf(Errormsg,
   1307 					"%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
   1308 					__FILE__, __LINE__, fd, size, errno,
   1309 					strerror(errno));
   1310 				return -errno;
   1311 			}
   1312 
   1313 			if (ret == 0)
   1314 				return 0;
   1315 			if (ret != -1) {
   1316 				if (ret != size) {
   1317 					sprintf(Errormsg,
   1318 						"%s/%d read(%d, buf, %d) returned=%d",
   1319 						__FILE__, __LINE__,
   1320 						fd, size, ret);
   1321 					size -= ret;
   1322 					buffer += ret;
   1323 				} else {
   1324 					if (Debug_level > 1)
   1325 						printf
   1326 						    ("DEBUG %s/%d: read completed without error (ret %d)\n",
   1327 						     __FILE__, __LINE__, ret);
   1328 
   1329 					return ret;
   1330 				}
   1331 			}
   1332 			wait4sync_io(fd, 1);
   1333 		}
   1334 
   1335 	}
   1336 
   1337 	else if (method & LIO_IO_ASYNC) {
   1338 #ifdef CRAY
   1339 		sprintf(Lio_SysCall,
   1340 			"reada(%d, buf, %d, &status, %d)", fd, size, sig);
   1341 		io_type = "reada";
   1342 
   1343 		if (Debug_level) {
   1344 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1345 			       Lio_SysCall);
   1346 		}
   1347 
   1348 		sigoff();
   1349 		if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
   1350 			sprintf(Errormsg,
   1351 				"%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
   1352 				__FILE__, __LINE__,
   1353 				fd, size, sig, errno, strerror(errno));
   1354 			sigon();
   1355 			return -errno;
   1356 		}
   1357 #endif
   1358 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1359 		sprintf(Lio_SysCall,
   1360 			"aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
   1361 			size, sig);
   1362 		io_type = "aio_read";
   1363 
   1364 		if (Debug_level) {
   1365 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1366 			       Lio_SysCall);
   1367 		}
   1368 
   1369 		if (sig)
   1370 			sighold(sig);
   1371 		if ((ret = aio_read(&aiocbp)) == -1) {
   1372 			sprintf(Errormsg,
   1373 				"%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
   1374 				__FILE__, __LINE__,
   1375 				fd, size, sig, errno, strerror(errno));
   1376 			if (sig)
   1377 				sigrelse(sig);
   1378 			return -errno;
   1379 		}
   1380 #endif
   1381 	}
   1382 	/* LIO_IO_ASYNC */
   1383 	else if (method & LIO_IO_SLISTIO) {
   1384 #ifdef CRAY
   1385 		request.li_opcode = LO_READ;
   1386 		request.li_fildes = fd;
   1387 		request.li_buf = buffer;
   1388 		request.li_nbyte = size;
   1389 		request.li_status = &status;
   1390 		request.li_signo = sig;
   1391 		request.li_nstride = 0;
   1392 		request.li_filstride = 0;
   1393 		request.li_memstride = 0;
   1394 
   1395 		listio_cmd = LC_WAIT;
   1396 		io_type = "listio(2) sync read";
   1397 
   1398 		sprintf(Lio_SysCall,
   1399 			"listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
   1400 			fd, size);
   1401 
   1402 		if (Debug_level) {
   1403 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1404 			       Lio_SysCall);
   1405 		}
   1406 
   1407 		sigoff();
   1408 		if (listio(listio_cmd, &request, 1) == -1) {
   1409 			sprintf(Errormsg,
   1410 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
   1411 				__FILE__, __LINE__, Lio_SysCall, fd, size,
   1412 				errno, strerror(errno));
   1413 			sigon();
   1414 			return -errno;
   1415 		}
   1416 
   1417 		if (Debug_level > 1)
   1418 			printf("DEBUG %s/%d: %s did not return -1\n",
   1419 			       __FILE__, __LINE__, Lio_SysCall);
   1420 
   1421 		ret = lio_check_asyncio(io_type, size, &status);
   1422 		return ret;
   1423 #endif
   1424 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1425 		aiocbp.aio_lio_opcode = LIO_READ;
   1426 		listio_cmd = LIO_WAIT;
   1427 		io_type = "lio_listio(3) sync read";
   1428 
   1429 		sprintf(Lio_SysCall,
   1430 			"lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
   1431 			fd, size);
   1432 
   1433 		if (Debug_level) {
   1434 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1435 			       Lio_SysCall);
   1436 		}
   1437 
   1438 		if (sig)
   1439 			sighold(sig);
   1440 		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
   1441 			sprintf(Errormsg,
   1442 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
   1443 				__FILE__, __LINE__, Lio_SysCall, fd, size,
   1444 				errno, strerror(errno));
   1445 			if (sig)
   1446 				sigrelse(sig);
   1447 			return -errno;
   1448 		}
   1449 
   1450 		if (Debug_level > 1)
   1451 			printf("DEBUG %s/%d: %s did not return -1\n",
   1452 			       __FILE__, __LINE__, Lio_SysCall);
   1453 
   1454 		ret = lio_check_asyncio(io_type, size, &aiocbp, method);
   1455 		return ret;
   1456 #endif
   1457 	}
   1458 	/* LIO_IO_SLISTIO */
   1459 	else if (method & LIO_IO_ALISTIO) {
   1460 #ifdef CRAY
   1461 		request.li_opcode = LO_READ;
   1462 		request.li_fildes = fd;
   1463 		request.li_buf = buffer;
   1464 		request.li_nbyte = size;
   1465 		request.li_status = &status;
   1466 		request.li_signo = sig;
   1467 		request.li_nstride = 0;
   1468 		request.li_filstride = 0;
   1469 		request.li_memstride = 0;
   1470 
   1471 		listio_cmd = LC_START;
   1472 		io_type = "listio(2) async read";
   1473 
   1474 		sprintf(Lio_SysCall,
   1475 			"listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
   1476 			fd, size);
   1477 
   1478 		if (Debug_level) {
   1479 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1480 			       Lio_SysCall);
   1481 		}
   1482 
   1483 		sigoff();
   1484 		if (listio(listio_cmd, &request, 1) == -1) {
   1485 			sprintf(Errormsg,
   1486 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
   1487 				__FILE__, __LINE__, Lio_SysCall, fd, size,
   1488 				errno, strerror(errno));
   1489 			sigon();
   1490 			return -errno;
   1491 		}
   1492 #endif
   1493 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1494 		aiocbp.aio_lio_opcode = LIO_READ;
   1495 		listio_cmd = LIO_NOWAIT;
   1496 		io_type = "lio_listio(3) async read";
   1497 
   1498 		sprintf(Lio_SysCall,
   1499 			"lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
   1500 			fd, size);
   1501 
   1502 		if (Debug_level) {
   1503 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1504 			       Lio_SysCall);
   1505 		}
   1506 
   1507 		if (sig)
   1508 			sighold(sig);
   1509 		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
   1510 			sprintf(Errormsg,
   1511 				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
   1512 				__FILE__, __LINE__, Lio_SysCall, fd, size,
   1513 				errno, strerror(errno));
   1514 			if (sig)
   1515 				sigrelse(sig);
   1516 			return -errno;
   1517 		}
   1518 #endif
   1519 	}
   1520 	/* LIO_IO_ALISTIO */
   1521 #ifndef CRAY
   1522 	else if (method & LIO_IO_SYNCV) {
   1523 		io_type = "readv(2)";
   1524 
   1525 		sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
   1526 
   1527 		if (Debug_level) {
   1528 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1529 			       Lio_SysCall);
   1530 		}
   1531 		if ((ret = readv(fd, &iov, 1)) == -1) {
   1532 			sprintf(Errormsg,
   1533 				"%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
   1534 				__FILE__, __LINE__, fd, size, errno,
   1535 				strerror(errno));
   1536 			return -errno;
   1537 		}
   1538 
   1539 		if (ret != size) {
   1540 			sprintf(Errormsg,
   1541 				"%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
   1542 				__FILE__, __LINE__, fd, size, ret);
   1543 		} else if (Debug_level > 1)
   1544 			printf
   1545 			    ("DEBUG %s/%d: readv completed without error (ret %d)\n",
   1546 			     __FILE__, __LINE__, ret);
   1547 
   1548 		return ret;
   1549 	}			/* LIO_IO_SYNCV */
   1550 #endif
   1551 
   1552 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1553 	else if (method & LIO_IO_SYNCP) {
   1554 		io_type = "pread(2)";
   1555 
   1556 		sprintf(Lio_SysCall,
   1557 			"pread(%d, buf, %d, %lld)", fd, size,
   1558 			(long long)poffset);
   1559 
   1560 		if (Debug_level) {
   1561 			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
   1562 			       Lio_SysCall);
   1563 		}
   1564 		if ((ret = pread(fd, buffer, size, poffset)) == -1) {
   1565 			sprintf(Errormsg,
   1566 				"%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
   1567 				__FILE__, __LINE__, fd, size,
   1568 				(long long)poffset, errno, strerror(errno));
   1569 			return -errno;
   1570 		}
   1571 
   1572 		if (ret != size) {
   1573 			sprintf(Errormsg,
   1574 				"%s/%d pread(%d, buf, %d, %lld) returned=%d",
   1575 				__FILE__, __LINE__,
   1576 				fd, size, (long long)poffset, ret);
   1577 		} else if (Debug_level > 1)
   1578 			printf
   1579 			    ("DEBUG %s/%d: pread completed without error (ret %d)\n",
   1580 			     __FILE__, __LINE__, ret);
   1581 
   1582 		return ret;
   1583 	}			/* LIO_IO_SYNCP */
   1584 #endif
   1585 
   1586 	else {
   1587 		printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
   1588 		       __LINE__);
   1589 		return -1;
   1590 	}
   1591 
   1592 	/*
   1593 	 * wait for async io to complete.
   1594 	 * Note: Sync io should have returned prior to getting here.
   1595 	 */
   1596 #ifdef CRAY
   1597 	ret = lio_wait4asyncio(method, fd, statptr);
   1598 #endif
   1599 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1600 	ret = lio_wait4asyncio(method, fd, &aiocbp);
   1601 #endif
   1602 
   1603 	/*
   1604 	 * If there was an error waiting for async i/o to complete,
   1605 	 * return the error value (errno) to the caller.
   1606 	 * Note: Errormsg should already have been updated.
   1607 	 */
   1608 	if (ret < 0) {
   1609 		return ret;
   1610 	}
   1611 
   1612 	/*
   1613 	 * If i/o was not waited for (may not have been completed at this time),
   1614 	 * return the size that was requested.
   1615 	 */
   1616 	if (ret == 1)
   1617 		return size;
   1618 
   1619 	/*
   1620 	 * check that async io was successful.
   1621 	 * Note:  if the there was an system call failure, -errno
   1622 	 * was returned and Errormsg should already have been updated.
   1623 	 * If amount i/o was different than size, Errormsg should already
   1624 	 * have been updated but the actual i/o size if returned.
   1625 	 */
   1626 
   1627 #ifdef CRAY
   1628 	ret = lio_check_asyncio(io_type, size, &status);
   1629 #endif
   1630 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
   1631 	ret = lio_check_asyncio(io_type, size, &aiocbp, method);
   1632 #endif
   1633 
   1634 	return ret;
   1635 }				/* end of lio_read_buffer */
   1636 
   1637 #if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
   1638 /***********************************************************************
   1639  * This function will check that async io was successful.
   1640  * It can also be used to check sync listio since it uses the
   1641  * same method.
   1642  *
   1643  * Return Values
   1644  *  If status.sw_error is set, -status.sw_error is returned.
   1645  *  Otherwise sw_count's field value is returned.
   1646  *
   1647  * (rrl 04/96)
   1648  ***********************************************************************/
   1649 #ifdef CRAY
   1650 int lio_check_asyncio(char *io_type, int size, struct iosw *status)
   1651 #elif defined(sgi)
   1652 int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
   1653 #elif defined(__linux__) && !defined(__UCLIBC__)
   1654 int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
   1655 {
   1656 	int ret;
   1657 
   1658 #ifdef CRAY
   1659 	if (status->sw_error) {
   1660 		sprintf(Errormsg,
   1661 			"%s/%d %s, sw_error set = %d %s, sw_count = %d",
   1662 			__FILE__, __LINE__, io_type,
   1663 			status->sw_error, strerror(status->sw_error),
   1664 			status->sw_count);
   1665 		return -status->sw_error;
   1666 	} else if (status->sw_count != size) {
   1667 		sprintf(Errormsg,
   1668 			"%s/%d %s, sw_count not as expected(%d), but actual:%d",
   1669 			__FILE__, __LINE__, io_type, size, status->sw_count);
   1670 	} else if (Debug_level > 1) {
   1671 		printf
   1672 		    ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
   1673 		     __FILE__, __LINE__, io_type, status->sw_count);
   1674 	}
   1675 
   1676 	return status->sw_count;
   1677 
   1678 #else
   1679 
   1680 	int cnt = 1;
   1681 
   1682 	/* The I/O may have been synchronous with signal completion.  It doesn't
   1683 	 * make sense, but the combination could be generated.  Release the
   1684 	 * completion signal here otherwise it'll hang around and bite us
   1685 	 * later.
   1686 	 */
   1687 	if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
   1688 		sigrelse(aiocbp->aio_sigevent.sigev_signo);
   1689 
   1690 	ret = aio_error(aiocbp);
   1691 
   1692 	while (ret == EINPROGRESS) {
   1693 		ret = aio_error(aiocbp);
   1694 		++cnt;
   1695 	}
   1696 	if (cnt > 1) {
   1697 		sprintf(Errormsg,
   1698 			"%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
   1699 			__FILE__, __LINE__, io_type, cnt, method,
   1700 			(aiocbp->aio_sigevent.sigev_notify ==
   1701 			 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
   1702 			 sigev_notify == SIGEV_NONE ? "none" :
   1703 #ifdef SIGEV_CALLBACK
   1704 			 aiocbp->aio_sigevent.sigev_notify ==
   1705 			 SIGEV_CALLBACK ? "callback" :
   1706 #endif
   1707 			 aiocbp->aio_sigevent.sigev_notify ==
   1708 			 SIGEV_THREAD ? "thread" : "unknown"));
   1709 		return -ret;
   1710 	}
   1711 
   1712 	if (ret != 0) {
   1713 		sprintf(Errormsg,
   1714 			"%s/%d %s, aio_error = %d %s; random method %#o",
   1715 			__FILE__, __LINE__, io_type,
   1716 			ret, strerror(ret), method);
   1717 		return -ret;
   1718 	}
   1719 	ret = aio_return(aiocbp);
   1720 	if (ret != size) {
   1721 		sprintf(Errormsg,
   1722 			"%s/%d %s, aio_return not as expected(%d), but actual:%d",
   1723 			__FILE__, __LINE__, io_type, size, ret);
   1724 
   1725 #ifdef BUG1_workaround
   1726 		if (ret == 0) {
   1727 			ret = size;
   1728 			if (Debug_level > 1) {
   1729 				printf
   1730 				    ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
   1731 				     __FILE__, __LINE__, io_type, ret);
   1732 			}
   1733 		}
   1734 #endif /* BUG1_workaround */
   1735 
   1736 	} else if (Debug_level > 1) {
   1737 		printf
   1738 		    ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
   1739 		     __FILE__, __LINE__, io_type, ret);
   1740 	}
   1741 
   1742 	return ret;
   1743 
   1744 #endif
   1745 }				/* end of lio_check_asyncio */
   1746 #endif
   1747 
   1748 /***********************************************************************
   1749  *
   1750  * This function will wait for async io to complete.
   1751  * If multiple wait methods are specified, the order is predetermined
   1752  * to LIO_WAIT_RECALL,
   1753  * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
   1754  * then LIO_WAIT_NONE.
   1755  *
   1756  * If no wait method was specified the default wait method is: recall(2)
   1757  * or aio_suspend(3), as appropriate.
   1758  *
   1759  * Return Values
   1760  *	<0: errno of failed recall
   1761  *	0 : async io was completed
   1762  *	1 : async was not waited for, io may not have completed.
   1763  *
   1764  * (rrl 04/96)
   1765  ***********************************************************************/
   1766 #ifdef CRAY
   1767 int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
   1768 #elif defined(sgi)
   1769 int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
   1770 #elif defined(__linux__) && !defined(__UCLIBC__)
   1771 int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
   1772 {
   1773 	int cnt;
   1774 #ifdef sgi
   1775 	int ret;
   1776 	const aiocb_t *aioary[1];
   1777 #endif
   1778 #if defined(__linux__)&& !defined(__UCLIBC__)
   1779 	int ret;
   1780 	const struct aiocb *aioary[1];
   1781 #endif
   1782 
   1783 	if ((method & LIO_WAIT_RECALL)
   1784 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
   1785 	    || (method & LIO_WAIT_CBSUSPEND)
   1786 	    || (method & LIO_WAIT_SIGSUSPEND)
   1787 #endif
   1788 	    || ((method & LIO_WAIT_TYPES) == 0)) {
   1789 		/*
   1790 		 * If method has LIO_WAIT_RECALL bit set or method does
   1791 		 * not have any wait method bits set (default), use recall/aio_suspend.
   1792 		 */
   1793 #ifdef CRAY
   1794 		if (Debug_level > 2)
   1795 			printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
   1796 			       __LINE__);
   1797 		sigon();
   1798 		if (recall(fd, 1, statptr)) {
   1799 			sprintf(Errormsg,
   1800 				"%s/%d recall(%d, 1, stat) failed, errno:%d %s",
   1801 				__FILE__, __LINE__, fd, errno, strerror(errno));
   1802 			return -errno;
   1803 		}
   1804 #else
   1805 		if (Debug_level > 2)
   1806 			printf
   1807 			    ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
   1808 			     __FILE__, __LINE__,
   1809 			     (aiocbp->aio_sigevent.sigev_notify ==
   1810 			      SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
   1811 			      sigev_notify == SIGEV_NONE ? "none" :
   1812 #ifdef SIGEV_CALLBACK
   1813 			      aiocbp->aio_sigevent.sigev_notify ==
   1814 			      SIGEV_CALLBACK ? "callback" :
   1815 #endif
   1816 			      aiocbp->aio_sigevent.sigev_notify ==
   1817 			      SIGEV_THREAD ? "thread" : "unknown"));
   1818 
   1819 		aioary[0] = aiocbp;
   1820 		ret = aio_suspend(aioary, 1, NULL);
   1821 		if ((ret == -1) && (errno == EINTR)) {
   1822 			if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
   1823 				if (Debug_level > 2) {
   1824 					printf
   1825 					    ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
   1826 					     __FILE__, __LINE__);
   1827 				}
   1828 			} else {
   1829 				sprintf(Errormsg,
   1830 					"%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
   1831 					__FILE__, __LINE__,
   1832 					(aiocbp->aio_sigevent.sigev_notify ==
   1833 					 SIGEV_SIGNAL ? "signal" : aiocbp->
   1834 					 aio_sigevent.sigev_notify ==
   1835 					 SIGEV_NONE ? "none" :
   1836 #ifdef SIGEV_CALLBACK
   1837 					 aiocbp->aio_sigevent.sigev_notify ==
   1838 					 SIGEV_CALLBACK ? "callback" :
   1839 #endif
   1840 					 aiocbp->aio_sigevent.sigev_notify ==
   1841 					 SIGEV_THREAD ? "thread" : "unknown"));
   1842 				return -errno;
   1843 			}
   1844 		} else if (ret) {
   1845 			sprintf(Errormsg,
   1846 				"%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
   1847 				__FILE__, __LINE__, fd, errno, strerror(errno));
   1848 			return -errno;
   1849 		}
   1850 #endif
   1851 
   1852 	} else if (method & LIO_WAIT_ACTIVE) {
   1853 		if (Debug_level > 2)
   1854 			printf("DEBUG %s/%d: wait method : active\n", __FILE__,
   1855 			       __LINE__);
   1856 #ifdef CRAY
   1857 		sigon();
   1858 		/*
   1859 		 * loop until sw_flag, sw_count or sw_error field elements
   1860 		 * change to non-zero.
   1861 		 */
   1862 		cnt = 0;
   1863 		while ((*statptr)->sw_flag == 0 &&
   1864 		       (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
   1865 			cnt++;
   1866 		}
   1867 #else
   1868 		/* loop while aio_error() returns EINPROGRESS */
   1869 		cnt = 0;
   1870 		while (1) {
   1871 			ret = aio_error(aiocbp);
   1872 			if ((ret == 0) || (ret != EINPROGRESS)) {
   1873 				break;
   1874 			}
   1875 			++cnt;
   1876 		}
   1877 
   1878 #endif
   1879 		if (Debug_level > 5 && cnt && (cnt % 50) == 0)
   1880 			printf("DEBUG %s/%d: wait active cnt = %d\n",
   1881 			       __FILE__, __LINE__, cnt);
   1882 
   1883 	} else if (method & LIO_WAIT_SIGPAUSE) {
   1884 		if (Debug_level > 2)
   1885 			printf("DEBUG %s/%d: wait method : sigpause\n",
   1886 			       __FILE__, __LINE__);
   1887 #ifdef sgi
   1888 		/* note: don't do the sigon() for CRAY in this case.  why? -- roehrich 6/11/97 */
   1889 		if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
   1890 			sigrelse(aiocbp->aio_sigevent.sigev_signo);
   1891 		else {
   1892 			printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
   1893 			       __FILE__, __LINE__);
   1894 			return -1;
   1895 		}
   1896 #endif
   1897 		pause();
   1898 
   1899 	} else if (method & LIO_WAIT_SIGACTIVE) {
   1900 		if (Debug_level > 2)
   1901 			printf("DEBUG %s/%d: wait method : sigactive\n",
   1902 			       __FILE__, __LINE__);
   1903 #ifdef CRAY
   1904 		sigon();
   1905 #else
   1906 		if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
   1907 			sigrelse(aiocbp->aio_sigevent.sigev_signo);
   1908 		else {
   1909 			printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
   1910 			       __FILE__, __LINE__);
   1911 			return -1;
   1912 		}
   1913 #endif
   1914 		/* loop waiting for signal */
   1915 		while (Received_signal == Rec_signal) {
   1916 #ifdef CRAY
   1917 			sigon();
   1918 #else
   1919 			sigrelse(aiocbp->aio_sigevent.sigev_signo);
   1920 #endif
   1921 		}
   1922 
   1923 	} else if (method & LIO_WAIT_NONE) {
   1924 		if (Debug_level > 2)
   1925 			printf("DEBUG %s/%d: wait method : none\n", __FILE__,
   1926 			       __LINE__);
   1927 		/* It's broken because the aiocb/iosw is an automatic variable in
   1928 		 * lio_{read,write}_buffer, so when the function returns and the
   1929 		 * I/O completes there will be nowhere to write the I/O status.
   1930 		 * It doesn't cause a problem on unicos--probably because of some
   1931 		 * compiler quirk, or an accident.  It causes POSIX async I/O
   1932 		 * to core dump some threads.   spr/pv 705909.  6/27/97 roehrich
   1933 		 */
   1934 		sprintf(Errormsg,
   1935 			"%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
   1936 			__FILE__, __LINE__);
   1937 #ifdef CRAY
   1938 		sigon();
   1939 #endif
   1940 /*        return 1;*/
   1941 		return -1;
   1942 	} else {
   1943 		if (Debug_level > 2)
   1944 			printf("DEBUG %s/%d: no wait method was chosen\n",
   1945 			       __FILE__, __LINE__);
   1946 		return -1;
   1947 	}
   1948 
   1949 	return 0;
   1950 
   1951 }				/* end of lio_wait4asyncio */
   1952 
   1953 #endif /* ifndef linux */
   1954 #endif
   1955 
   1956 #if UNIT_TEST
   1957 /***********************************************************************
   1958  * The following code is provided as unit test.
   1959  * Just define add "-DUNIT_TEST=1" to the cc line.
   1960  *
   1961  * (rrl 04/96)
   1962  ***********************************************************************/
   1963 struct unit_info_t {
   1964 	int method;
   1965 	int sig;
   1966 	char *str;
   1967 } Unit_info[] = {
   1968 	{
   1969 	LIO_IO_SYNC, 0, "sync io"}, {
   1970 	LIO_IO_SYNCV, 0, "sync readv/writev"}, {
   1971 	LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
   1972 	LIO_IO_ASYNC, 0, "async io, def wait"}, {
   1973 	LIO_IO_SLISTIO, 0, "sync listio"}, {
   1974 	LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
   1975 	LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
   1976 	LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
   1977 	LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
   1978 	LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
   1979 	LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
   1980 	LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
   1981 	LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
   1982 	{
   1983 	LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
   1984 	{
   1985 	LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
   1986 LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
   1987 
   1988 int main(argc, argv)
   1989 int argc;
   1990 char **argv;
   1991 {
   1992 	extern char *optarg;
   1993 	extern int optind;
   1994 
   1995 	int fd;
   1996 	char *err;
   1997 	char buffer[4096];
   1998 	int size = 4096;
   1999 	int ret;
   2000 	int ind;
   2001 	int iter = 3;
   2002 	int method;
   2003 	int exit_status = 0;
   2004 	int c;
   2005 	int i;
   2006 	char *symbols = NULL;
   2007 	int die_on_err = 0;
   2008 
   2009 	while ((c = getopt(argc, argv, "s:di:")) != -1) {
   2010 		switch (c) {
   2011 		case 's':
   2012 			symbols = optarg;
   2013 			break;
   2014 		case 'd':
   2015 			++die_on_err;
   2016 			break;
   2017 		case 'i':
   2018 			iter = atoi(optarg);
   2019 			break;
   2020 		}
   2021 	}
   2022 
   2023 	if ((fd =
   2024 	     open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
   2025 		perror
   2026 		    ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
   2027 		exit(1);
   2028 	}
   2029 
   2030 	Debug_level = 9;
   2031 
   2032 	if (symbols != NULL) {
   2033 		if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
   2034 			printf
   2035 			    ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
   2036 			     symbols, err);
   2037 			if (die_on_err)
   2038 				exit(1);
   2039 		} else
   2040 			printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
   2041 			       symbols, method);
   2042 
   2043 		exit_status = 0;
   2044 		for (ind = 0; ind < iter; ind++) {
   2045 			memset(buffer, 'A', 4096);
   2046 			if (lseek(fd, 0, 0) == -1) {
   2047 				printf("lseek(fd,0,0), %d, failed, errno %d\n",
   2048 				       __LINE__, errno);
   2049 				++exit_status;
   2050 			}
   2051 			if ((ret = lio_write_buffer(fd, method, buffer,
   2052 						    size, SIGUSR1, &err,
   2053 						    0)) != size) {
   2054 				printf
   2055 				    ("lio_write_buffer returned -1, err = %s\n",
   2056 				     err);
   2057 			} else
   2058 				printf("lio_write_buffer returned %d\n", ret);
   2059 
   2060 			memset(buffer, 'B', 4096);
   2061 			if (lseek(fd, 0, 0) == -1) {
   2062 				printf("lseek(fd,0,0), %d, failed, errno %d\n",
   2063 				       __LINE__, errno);
   2064 				++exit_status;
   2065 			}
   2066 			if ((ret = lio_read_buffer(fd, method, buffer,
   2067 						   size, SIGUSR2, &err,
   2068 						   0)) != size) {
   2069 				printf
   2070 				    ("lio_read_buffer returned -1, err = %s\n",
   2071 				     err);
   2072 			} else
   2073 				printf("lio_read_buffer returned %d\n", ret);
   2074 
   2075 			for (i = 0; i < 4096; ++i) {
   2076 				if (buffer[i] != 'A') {
   2077 					printf("  buffer[%d] = %d\n", i,
   2078 					       buffer[i]);
   2079 					++exit_status;
   2080 					break;
   2081 				}
   2082 			}
   2083 
   2084 			if (exit_status)
   2085 				exit(exit_status);
   2086 
   2087 		}
   2088 
   2089 		unlink("unit_test_file");
   2090 		exit(0);
   2091 	}
   2092 
   2093 	for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
   2094 	     ind++) {
   2095 
   2096 		printf("\n********* write %s ***************\n",
   2097 		       Unit_info[ind].str);
   2098 		if (lseek(fd, 0, 0) == -1) {
   2099 			printf("lseek(fd,0,0), %d, failed, errno %d\n",
   2100 			       __LINE__, errno);
   2101 			++exit_status;
   2102 		}
   2103 
   2104 		memset(buffer, 'A', 4096);
   2105 		if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
   2106 					    size, Unit_info[ind].sig, &err,
   2107 					    0)) != size) {
   2108 			printf
   2109 			    (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n   err = %s\n",
   2110 			     Unit_info[ind].method, size, Unit_info[ind].sig,
   2111 			     err);
   2112 			++exit_status;
   2113 			if (die_on_err)
   2114 				exit(exit_status);
   2115 		} else {
   2116 			printf("lio_write_buffer returned %d\n", ret);
   2117 		}
   2118 
   2119 		printf("\n********* read %s ***************\n",
   2120 		       Unit_info[ind].str);
   2121 		if (lseek(fd, 0, 0) == -1) {
   2122 			printf("lseek(fd,0,0), %d, failed, errno %d\n",
   2123 			       __LINE__, errno);
   2124 			++exit_status;
   2125 		}
   2126 		memset(buffer, 'B', 4096);
   2127 		if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
   2128 					   size, Unit_info[ind].sig, &err,
   2129 					   0)) != size) {
   2130 			printf
   2131 			    (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n   err = %s\n",
   2132 			     Unit_info[ind].method, size, Unit_info[ind].sig,
   2133 			     err);
   2134 			++exit_status;
   2135 			if (die_on_err)
   2136 				exit(exit_status);
   2137 		} else {
   2138 			printf("lio_read_buffer returned %d\n", ret);
   2139 		}
   2140 
   2141 		for (i = 0; i < 4096; ++i) {
   2142 			if (buffer[i] != 'A') {
   2143 				printf("  buffer[%d] = %d\n", i, buffer[i]);
   2144 				++exit_status;
   2145 				if (die_on_err)
   2146 					exit(exit_status);
   2147 				break;
   2148 			}
   2149 		}
   2150 
   2151 		fflush(stdout);
   2152 		fflush(stderr);
   2153 		sleep(1);
   2154 
   2155 	}
   2156 
   2157 	unlink("unit_test_file");
   2158 
   2159 	exit(exit_status);
   2160 }
   2161 #endif
   2162