xref: /third_party/ltp/lib/tlibio.c (revision f08c3bdf)
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>
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 */
136struct 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 */
170struct 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
190char Lio_SysCall[PATH_MAX];	/* string containing last i/o system call */
191
192static volatile int Received_signal = 0;	/* number of signals received */
193static volatile int Rec_signal;
194#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
195static volatile int Received_callback = 0;	/* number of callbacks received */
196static volatile int Rec_callback;
197#endif
198static char Errormsg[PATH_MAX*2];
199static 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
215int 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 ***********************************************************************/
262int 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 ***********************************************************************/
280int 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 ***********************************************************************/
312void 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 ***********************************************************************/
334int 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 ***********************************************************************/
405void 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 ***********************************************************************/
422static 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 ***********************************************************************/
440static 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 ***********************************************************************/
468int 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
484static 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 ***********************************************************************/
533int 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	/* as we cycle writes in case of partial writes, we have to report up
543	 * total bytes written
544	 */
545	int totally_written = 0;
546	char *io_type;		/* Holds string of type of io */
547	int omethod = method;
548	int listio_cmd;		/* Holds the listio/lio_listio cmd */
549#ifdef  CRAY
550	struct listreq request;	/* Used when a listio is wanted */
551	struct iosw status, *statptr[1];
552#else
553	/* for linux or sgi */
554	struct iovec iov;	/* iovec for writev(2) */
555#endif
556#if defined (sgi)
557	aiocb_t aiocbp;		/* POSIX aio control block */
558	aiocb_t *aiolist[1];	/* list of aio control blocks for lio_listio */
559	off64_t poffset;	/* pwrite(2) offset */
560#endif
561#if defined(__linux__) && !defined(__UCLIBC__)
562	struct aiocb aiocbp;	/* POSIX aio control block */
563	struct aiocb *aiolist[1];	/* list of aio control blocks for lio_listio */
564	off64_t poffset;	/* pwrite(2) offset */
565#endif
566	/*
567	 * If LIO_RANDOM bit specified, get new method randomly.
568	 */
569	if (method & LIO_RANDOM) {
570		if (Debug_level > 3)
571			printf("DEBUG %s/%d: method mask to choose from: %#o\n",
572			       __FILE__, __LINE__, method);
573		method = lio_random_methods(method);
574		if (Debug_level > 2)
575			printf("DEBUG %s/%d: random chosen method %#o\n",
576			       __FILE__, __LINE__, method);
577	}
578
579	if (errmsg != NULL)
580		*errmsg = Errormsg;
581
582	Rec_signal = Received_signal;	/* get the current number of signals received */
583#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
584	Rec_callback = Received_callback;	/* get the current number of callbacks received */
585#endif
586
587#ifdef  CRAY
588	memset(&status, 0x00, sizeof(struct iosw));
589	memset(&request, 0x00, sizeof(struct listreq));
590	statptr[0] = &status;
591#else
592	/* for linux or sgi */
593	memset(&iov, 0x00, sizeof(struct iovec));
594	iov.iov_base = buffer;
595	iov.iov_len = size;
596#endif
597#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
598#if defined(sgi)
599	memset(&aiocbp, 0x00, sizeof(aiocb_t));
600#else
601	memset(&aiocbp, 0x00, sizeof(struct aiocb));
602#endif
603	aiocbp.aio_fildes = fd;
604	aiocbp.aio_nbytes = size;
605	aiocbp.aio_buf = buffer;
606/*    aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
607	aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
608	aiocbp.aio_sigevent.sigev_signo = 0;
609#ifdef sgi
610	aiocbp.aio_sigevent.sigev_func = NULL;
611	aiocbp.aio_sigevent.sigev_value.sival_int = 0;
612#elif defined(__linux__) && !defined(__UCLIBC__)
613	aiocbp.aio_sigevent.sigev_notify_function = NULL;
614	aiocbp.aio_sigevent.sigev_notify_attributes = 0;
615#endif
616	aiolist[0] = &aiocbp;
617
618	if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
619		ret = 0;
620		/* If there is an error and it is not ESPIPE then kick out the error.
621		 * If the fd is a fifo then we have to make sure that
622		 * lio_random_methods() didn't select pwrite/pread; if it did then
623		 * switch to write/read.
624		 */
625		if (errno == ESPIPE) {
626			if (method & LIO_IO_SYNCP) {
627				if (omethod & LIO_RANDOM) {
628					method &= ~LIO_IO_SYNCP;
629					method |= LIO_IO_SYNC;
630					if (Debug_level > 2)
631						printf
632						    ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
633						     __FILE__, __LINE__,
634						     method);
635				} else if (Debug_level) {
636					printf
637					    ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
638					     __FILE__, __LINE__);
639				}
640			}
641			/* else: let it ride */
642		} else {
643			sprintf(Errormsg,
644				"%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d  %s",
645				__FILE__, __LINE__, fd, errno, strerror(errno));
646			return -errno;
647		}
648	}
649#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
650	poffset = (off64_t) ret;
651#endif
652	aiocbp.aio_offset = ret;
653
654#endif
655
656	/*
657	 * If the LIO_USE_SIGNAL bit is not set, only use the signal
658	 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
659	 * Otherwise there is not necessary a signal handler to trap
660	 * the signal.
661	 */
662	if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
663
664		sig = 0;	/* ignore signal parameter */
665	}
666#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
667	if (sig && (method & LIO_WAIT_CBTYPES))
668		sig = 0;	/* ignore signal parameter */
669#endif
670
671	/*
672	 * only setup signal hander if sig was specified and
673	 * a sig wait method was specified.
674	 * Doing this will change the handler for this signal.  The
675	 * old signal handler will not be restored.
676	 *** restoring the signal handler could be added ***
677	 */
678
679	if (sig && (method & LIO_WAIT_SIGTYPES)) {
680#ifdef CRAY
681		sigctl(SCTL_REG, sig, lio_async_signal_handler);
682#endif
683#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
684		aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
685		aiocbp.aio_sigevent.sigev_signo = sig;
686		sigset(sig, lio_async_signal_handler);
687#endif /* sgi */
688	}
689#if defined(sgi)
690	else if (method & LIO_WAIT_CBTYPES) {
691		/* sival_int just has to be something that I can use
692		 * to identify the callback, and "size" happens to be handy...
693		 */
694		aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
695		aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
696		aiocbp.aio_sigevent.sigev_value.sival_int = size;
697	}
698#endif
699#if defined(__linux__) && !defined(__UCLIBC__)
700	else if (method & LIO_WAIT_CBTYPES) {
701		/* sival_int just has to be something that I can use
702		 * to identify the callback, and "size" happens to be handy...
703		 */
704		aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
705		aiocbp.aio_sigevent.sigev_notify_function =
706		    lio_async_callback_handler;
707		aiocbp.aio_sigevent.sigev_notify_attributes =
708		    (void *)(uintptr_t) size;
709	}
710#endif
711	/*
712	 * Determine the system call that will be called and produce
713	 * the string of the system call and place it in Lio_SysCall.
714	 * Also update the io_type char pointer to give brief description
715	 * of system call.  Execute the system call and check for
716	 * system call failure.  If sync i/o, return the number of
717	 * bytes written/read.
718	 */
719
720	if ((method & LIO_IO_SYNC)
721	    || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
722		/*
723		 * write(2) is used if LIO_IO_SYNC bit is set or not none
724		 * of the LIO_IO_TYPES bits are set (default).
725		 */
726
727		sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
728		io_type = "write";
729
730		if (Debug_level) {
731			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
732			       Lio_SysCall);
733		}
734		while (1) {
735			if (((ret = write(fd, buffer, size)) == -1)
736			    && errno != EAGAIN && errno != EINTR) {
737				sprintf(Errormsg,
738					"%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
739					__FILE__, __LINE__, fd, size, errno,
740					strerror(errno));
741				return -errno;
742			}
743
744			if (ret != -1) {
745				if (ret != size) {
746					sprintf(Errormsg,
747						"%s/%d write(%d, buf, %d) returned=%d",
748						__FILE__, __LINE__,
749						fd, size, ret);
750					size -= ret;
751					buffer += ret;
752					totally_written += ret;
753				} else {
754					if (Debug_level > 1)
755						printf
756						    ("DEBUG %s/%d: write completed without error (ret %d)\n",
757						     __FILE__, __LINE__, ret);
758
759					return totally_written + ret;
760				}
761			}
762			wait4sync_io(fd, 0);
763		}
764
765	}
766
767	else if (method & LIO_IO_ASYNC) {
768#ifdef CRAY
769		sprintf(Lio_SysCall,
770			"writea(%d, buf, %d, &status, %d)", fd, size, sig);
771		io_type = "writea";
772
773		if (Debug_level) {
774			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
775			       Lio_SysCall);
776		}
777
778		sigoff();
779		if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
780			sprintf(Errormsg,
781				"%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
782				__FILE__, __LINE__,
783				fd, size, sig, errno, strerror(errno));
784			sigon();
785			return -errno;
786		}
787#endif
788#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
789		sprintf(Lio_SysCall,
790			"aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
791			size, sig);
792		io_type = "aio_write";
793
794		if (Debug_level) {
795			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
796			       Lio_SysCall);
797		}
798
799		if (sig)
800			sighold(sig);
801		if ((ret = aio_write(&aiocbp)) == -1) {
802			sprintf(Errormsg,
803				"%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
804				__FILE__, __LINE__,
805				fd, size, sig, errno, strerror(errno));
806			if (sig)
807				sigrelse(sig);
808			return -errno;
809		}
810#endif
811	}
812	/* LIO_IO_ASYNC */
813	else if (method & LIO_IO_SLISTIO) {
814#ifdef CRAY
815		request.li_opcode = LO_WRITE;
816		request.li_fildes = fd;
817		request.li_buf = buffer;
818		request.li_nbyte = size;
819		request.li_status = &status;
820		request.li_signo = sig;
821		request.li_nstride = 0;
822		request.li_filstride = 0;
823		request.li_memstride = 0;
824
825		listio_cmd = LC_WAIT;
826		io_type = "listio(2) sync write";
827
828		sprintf(Lio_SysCall,
829			"listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
830			fd, size);
831
832		if (Debug_level) {
833			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
834			       Lio_SysCall);
835		}
836
837		sigoff();
838		if (listio(listio_cmd, &request, 1) == -1) {
839			sprintf(Errormsg,
840				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
841				__FILE__, __LINE__, Lio_SysCall, fd, size,
842				errno, strerror(errno));
843			sigon();
844			return -errno;
845		}
846
847		if (Debug_level > 1)
848			printf("DEBUG %s/%d: %s did not return -1\n",
849			       __FILE__, __LINE__, Lio_SysCall);
850
851		ret = lio_check_asyncio(io_type, size, &status);
852		return ret;
853
854#endif
855#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
856
857		aiocbp.aio_lio_opcode = LIO_WRITE;
858		listio_cmd = LIO_WAIT;
859		io_type = "lio_listio(3) sync write";
860
861		sprintf(Lio_SysCall,
862			"lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
863			fd, size, sig);
864
865		if (Debug_level) {
866			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
867			       Lio_SysCall);
868		}
869
870		if (sig)
871			sighold(sig);
872		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
873			sprintf(Errormsg,
874				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
875				__FILE__, __LINE__, Lio_SysCall, fd, size,
876				errno, strerror(errno));
877			if (sig)
878				sigrelse(sig);
879			return -errno;
880		}
881
882		if (Debug_level > 1)
883			printf("DEBUG %s/%d: %s did not return -1\n",
884			       __FILE__, __LINE__, Lio_SysCall);
885
886		ret = lio_check_asyncio(io_type, size, &aiocbp, method);
887		return ret;
888#endif
889	}
890	/* LIO_IO_SLISTIO */
891	else if (method & LIO_IO_ALISTIO) {
892#ifdef CRAY
893		request.li_opcode = LO_WRITE;
894		request.li_fildes = fd;
895		request.li_buf = buffer;
896		request.li_nbyte = size;
897		request.li_status = &status;
898		request.li_signo = sig;
899		request.li_nstride = 0;
900		request.li_filstride = 0;
901		request.li_memstride = 0;
902
903		listio_cmd = LC_START;
904		io_type = "listio(2) async write";
905
906		sprintf(Lio_SysCall,
907			"listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
908			fd, size);
909
910		if (Debug_level) {
911			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
912			       Lio_SysCall);
913		}
914
915		sigoff();
916		if (listio(listio_cmd, &request, 1) == -1) {
917			sprintf(Errormsg,
918				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
919				__FILE__, __LINE__, Lio_SysCall, fd, size,
920				errno, strerror(errno));
921			sigon();
922			return -errno;
923		}
924#endif
925#if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
926		aiocbp.aio_lio_opcode = LIO_WRITE;
927		listio_cmd = LIO_NOWAIT;
928		io_type = "lio_listio(3) async write";
929
930		sprintf(Lio_SysCall,
931			"lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
932			fd, size);
933
934		if (Debug_level) {
935			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
936			       Lio_SysCall);
937		}
938
939		if (sig)
940			sighold(sig);
941		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
942			sprintf(Errormsg,
943				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
944				__FILE__, __LINE__, Lio_SysCall, fd, size,
945				errno, strerror(errno));
946			if (sig)
947				sigrelse(sig);
948			return -errno;
949		}
950#endif
951	}
952	/* LIO_IO_ALISTIO */
953#ifndef CRAY
954	else if (method & LIO_IO_SYNCV) {
955		io_type = "writev(2)";
956
957		sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
958
959		if (Debug_level) {
960			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
961			       Lio_SysCall);
962		}
963		if ((ret = writev(fd, &iov, 1)) == -1) {
964			sprintf(Errormsg,
965				"%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
966				__FILE__, __LINE__, fd, size, errno,
967				strerror(errno));
968			return -errno;
969		}
970
971		if (ret != size) {
972			sprintf(Errormsg,
973				"%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
974				__FILE__, __LINE__, fd, size, ret);
975		} else if (Debug_level > 1)
976			printf
977			    ("DEBUG %s/%d: writev completed without error (ret %d)\n",
978			     __FILE__, __LINE__, ret);
979
980		return ret;
981	}			/* LIO_IO_SYNCV */
982#endif
983
984#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
985	else if (method & LIO_IO_SYNCP) {
986		io_type = "pwrite(2)";
987
988		sprintf(Lio_SysCall,
989			"pwrite(%d, buf, %d, %lld)", fd, size,
990			(long long)poffset);
991
992		if (Debug_level) {
993			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
994			       Lio_SysCall);
995		}
996		if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
997			sprintf(Errormsg,
998				"%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
999				__FILE__, __LINE__, fd, size,
1000				(long long)poffset, errno, strerror(errno));
1001			return -errno;
1002		}
1003
1004		if (ret != size) {
1005			sprintf(Errormsg,
1006				"%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
1007				__FILE__, __LINE__,
1008				fd, size, (long long)poffset, ret);
1009		} else if (Debug_level > 1)
1010			printf
1011			    ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
1012			     __FILE__, __LINE__, ret);
1013
1014		return ret;
1015	}			/* LIO_IO_SYNCP */
1016#endif
1017
1018	else {
1019		printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1020		       __LINE__);
1021		return -1;
1022	}
1023
1024	/*
1025	 * wait for async io to complete.
1026	 */
1027#ifdef CRAY
1028	ret = lio_wait4asyncio(method, fd, statptr);
1029#endif
1030#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1031	ret = lio_wait4asyncio(method, fd, &aiocbp);
1032#endif
1033
1034	/*
1035	 * If there was an error waiting for async i/o to complete,
1036	 * return the error value (errno) to the caller.
1037	 * Note: Errormsg should already have been updated.
1038	 */
1039	if (ret < 0) {
1040		return ret;
1041	}
1042
1043	/*
1044	 * If i/o was not waited for (may not have been completed at this time),
1045	 * return the size that was requested.
1046	 */
1047	if (ret == 1)
1048		return size;
1049
1050	/*
1051	 * check that async io was successful.
1052	 * Note:  if the there was an system call failure, -errno
1053	 * was returned and Errormsg should already have been updated.
1054	 * If amount i/o was different than size, Errormsg should already
1055	 * have been updated but the actual i/o size if returned.
1056	 */
1057
1058#ifdef CRAY
1059	ret = lio_check_asyncio(io_type, size, &status);
1060#endif
1061#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1062	ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1063#endif
1064
1065	return ret;
1066}				/* end of lio_write_buffer */
1067
1068/***********************************************************************
1069 * Generic read function
1070 * This function can be used to do a read using read(2), reada(2),
1071 * aio_read(3), readv(2), pread(2),
1072 * or single stride listio(2)/lio_listio(3).
1073 * By setting the desired bits in the method
1074 * bitmask, the caller can control the type of read and the wait method
1075 * that will be used.  If no io type bits are set, read will be used.
1076 *
1077 * If async io was attempted and no wait method bits are set then the
1078 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1079 * aio_read(3) and lio_listio(3).
1080 *
1081 * If multiple wait methods are specified,
1082 * only one wait method will be used. The order is predetermined.
1083 *
1084 * If the call specifies a signal and one of the two signal wait methods,
1085 * a signal handler for the signal is set.  This will reset an already
1086 * set handler for this signal.
1087 *
1088 * If the LIO_RANDOM method bit is set, this function will randomly
1089 * choose a io type and wait method from bits in the method argument.
1090 *
1091 * If an error is encountered, an error message will be generated
1092 * in a internal static buffer.  If errmsg is not NULL, it will
1093 * be updated to point to the static buffer, allowing the caller
1094 * to print the error message.
1095 *
1096 * Return Value
1097 *   If a system call fails, -errno is returned.
1098 *   If LIO_WAIT_NONE bit is set, the return value is the return value
1099 *   of the system call.
1100 *   If the io did not fail, the amount of data written is returned.
1101 *	If the size the system call say was written is different
1102 *	then what was asked to be written, errmsg is updated for
1103 *	this error condition.  The return value is still the amount
1104 *	the system call says was written.
1105 *
1106 * (rrl 04/96)
1107 ***********************************************************************/
1108int lio_read_buffer(int fd,	/* open file descriptor */
1109		int method,	/* contains io type and wait method bitmask*/
1110		char *buffer,	/* pointer to buffer */
1111		int size,	/* the size of the io */
1112		int sig,	/* signal to use if async io */
1113		char **errmsg,	/* char pointer that will be updated to point to err message */
1114		long wrd)	/* to allow future features, use zero for now */
1115{
1116	int ret = 0;		/* syscall return or used to get random method */
1117	/* as we cycle reads in case of partial reads, we have to report up
1118	 * total bytes read
1119	 */
1120	int totally_read = 0;
1121	char *io_type;		/* Holds string of type of io */
1122	int listio_cmd;		/* Holds the listio/lio_listio cmd */
1123	int omethod = method;
1124#ifdef  CRAY
1125	struct listreq request;	/* Used when a listio is wanted */
1126	struct iosw status, *statptr[1];
1127#else
1128	/* for linux or sgi */
1129	struct iovec iov;	/* iovec for readv(2) */
1130#endif
1131#ifdef sgi
1132	aiocb_t aiocbp;		/* POSIX aio control block */
1133	aiocb_t *aiolist[1];	/* list of aio control blocks for lio_listio */
1134	off64_t poffset;	/* pread(2) offset */
1135#endif
1136#if defined (__linux__) && !defined(__UCLIBC__)
1137	struct aiocb aiocbp;	/* POSIX aio control block */
1138	struct aiocb *aiolist[1];	/* list of aio control blocks for lio_listio */
1139	off64_t poffset;	/* pread(2) offset */
1140#endif
1141
1142	/*
1143	 * If LIO_RANDOM bit specified, get new method randomly.
1144	 */
1145	if (method & LIO_RANDOM) {
1146		if (Debug_level > 3)
1147			printf("DEBUG %s/%d: method mask to choose from: %#o\n",
1148			       __FILE__, __LINE__, method);
1149		method = lio_random_methods(method);
1150		if (Debug_level > 2)
1151			printf("DEBUG %s/%d: random chosen method %#o\n",
1152			       __FILE__, __LINE__, method);
1153	}
1154
1155	if (errmsg != NULL)
1156		*errmsg = Errormsg;
1157
1158	Rec_signal = Received_signal;	/* get the current number of signals received */
1159#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1160	Rec_callback = Received_callback;	/* get the current number of callbacks received */
1161#endif
1162
1163#ifdef  CRAY
1164	memset(&status, 0x00, sizeof(struct iosw));
1165	memset(&request, 0x00, sizeof(struct listreq));
1166	statptr[0] = &status;
1167#else
1168	/* for linux or sgi */
1169	memset(&iov, 0x00, sizeof(struct iovec));
1170	iov.iov_base = buffer;
1171	iov.iov_len = size;
1172#endif
1173#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1174#if defined(sgi)
1175	memset(&aiocbp, 0x00, sizeof(aiocb_t));
1176#else
1177	memset(&aiocbp, 0x00, sizeof(struct aiocb));
1178#endif
1179	aiocbp.aio_fildes = fd;
1180	aiocbp.aio_nbytes = size;
1181	aiocbp.aio_buf = buffer;
1182/*    aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1183	aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1184	aiocbp.aio_sigevent.sigev_signo = 0;
1185#ifdef sgi
1186	aiocbp.aio_sigevent.sigev_func = NULL;
1187	aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1188#elif defined(__linux__) && !defined(__UCLIBC__)
1189	aiocbp.aio_sigevent.sigev_notify_function = NULL;
1190	aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1191#endif
1192	aiolist[0] = &aiocbp;
1193
1194	if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
1195		ret = 0;
1196		/* If there is an error and it is not ESPIPE then kick out the error.
1197		 * If the fd is a fifo then we have to make sure that
1198		 * lio_random_methods() didn't select pwrite/pread; if it did then
1199		 * switch to write/read.
1200		 */
1201		if (errno == ESPIPE) {
1202			if (method & LIO_IO_SYNCP) {
1203				if (omethod & LIO_RANDOM) {
1204					method &= ~LIO_IO_SYNCP;
1205					method |= LIO_IO_SYNC;
1206					if (Debug_level > 2)
1207						printf
1208						    ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
1209						     __FILE__, __LINE__,
1210						     method);
1211				} else if (Debug_level) {
1212					printf
1213					    ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1214					     __FILE__, __LINE__);
1215				}
1216			}
1217			/* else: let it ride */
1218		} else {
1219			sprintf(Errormsg,
1220				"%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d  %s",
1221				__FILE__, __LINE__, fd, errno, strerror(errno));
1222			return -errno;
1223		}
1224	}
1225#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1226	poffset = (off64_t) ret;
1227#endif
1228	aiocbp.aio_offset = ret;
1229
1230#endif
1231
1232	/*
1233	 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1234	 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1235	 * Otherwise there is not necessarily a signal handler to trap
1236	 * the signal.
1237	 */
1238	if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
1239
1240		sig = 0;	/* ignore signal parameter */
1241	}
1242#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1243	if (sig && (method & LIO_WAIT_CBTYPES))
1244		sig = 0;	/* ignore signal parameter */
1245#endif
1246
1247	/*
1248	 * only setup signal hander if sig was specified and
1249	 * a sig wait method was specified.
1250	 * Doing this will change the handler for this signal.  The
1251	 * old signal handler will not be restored.
1252	 *** restoring the signal handler could be added ***
1253	 */
1254
1255	if (sig && (method & LIO_WAIT_SIGTYPES)) {
1256#ifdef CRAY
1257		sigctl(SCTL_REG, sig, lio_async_signal_handler);
1258#endif
1259#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1260		aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1261		aiocbp.aio_sigevent.sigev_signo = sig;
1262		sigset(sig, lio_async_signal_handler);
1263#endif /* CRAY */
1264	}
1265#if defined(sgi)
1266	else if (method & LIO_WAIT_CBTYPES) {
1267		aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1268		aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1269		/* sival_int just has to be something that I can use
1270		 * to identify the callback, and "size" happens to be handy...
1271		 */
1272		aiocbp.aio_sigevent.sigev_value.sival_int = size;
1273	}
1274#endif
1275#if defined(__linux__) && !defined(__UCLIBC__)
1276	else if (method & LIO_WAIT_CBTYPES) {
1277		aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
1278		aiocbp.aio_sigevent.sigev_notify_function =
1279		    lio_async_callback_handler;
1280		/* sival_int just has to be something that I can use
1281		 * to identify the callback, and "size" happens to be handy...
1282		 */
1283		aiocbp.aio_sigevent.sigev_notify_attributes =
1284		    (void *)(uintptr_t) size;
1285	}
1286#endif
1287
1288	/*
1289	 * Determine the system call that will be called and produce
1290	 * the string of the system call and place it in Lio_SysCall.
1291	 * Also update the io_type char pointer to give brief description
1292	 * of system call.  Execute the system call and check for
1293	 * system call failure.  If sync i/o, return the number of
1294	 * bytes written/read.
1295	 */
1296
1297	if ((method & LIO_IO_SYNC)
1298	    || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
1299		/*
1300		 * read(2) is used if LIO_IO_SYNC bit is set or not none
1301		 * of the LIO_IO_TYPES bits are set (default).
1302		 */
1303
1304		sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
1305		io_type = "read";
1306
1307		if (Debug_level) {
1308			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1309			       Lio_SysCall);
1310		}
1311
1312		while (1) {
1313			if (((ret = read(fd, buffer, size)) == -1)
1314			    && errno != EINTR && errno != EAGAIN) {
1315				sprintf(Errormsg,
1316					"%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1317					__FILE__, __LINE__, fd, size, errno,
1318					strerror(errno));
1319				return -errno;
1320			}
1321
1322			if (ret == 0)
1323				return 0;
1324			if (ret != -1) {
1325				if (ret != size) {
1326					sprintf(Errormsg,
1327						"%s/%d read(%d, buf, %d) returned=%d",
1328						__FILE__, __LINE__,
1329						fd, size, ret);
1330					size -= ret;
1331					buffer += ret;
1332					totally_read += ret;
1333				} else {
1334					if (Debug_level > 1)
1335						printf
1336						    ("DEBUG %s/%d: read completed without error (ret %d)\n",
1337						     __FILE__, __LINE__, ret);
1338
1339					return totally_read + ret;
1340				}
1341			}
1342			wait4sync_io(fd, 1);
1343		}
1344
1345	}
1346
1347	else if (method & LIO_IO_ASYNC) {
1348#ifdef CRAY
1349		sprintf(Lio_SysCall,
1350			"reada(%d, buf, %d, &status, %d)", fd, size, sig);
1351		io_type = "reada";
1352
1353		if (Debug_level) {
1354			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1355			       Lio_SysCall);
1356		}
1357
1358		sigoff();
1359		if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1360			sprintf(Errormsg,
1361				"%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1362				__FILE__, __LINE__,
1363				fd, size, sig, errno, strerror(errno));
1364			sigon();
1365			return -errno;
1366		}
1367#endif
1368#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1369		sprintf(Lio_SysCall,
1370			"aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
1371			size, sig);
1372		io_type = "aio_read";
1373
1374		if (Debug_level) {
1375			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1376			       Lio_SysCall);
1377		}
1378
1379		if (sig)
1380			sighold(sig);
1381		if ((ret = aio_read(&aiocbp)) == -1) {
1382			sprintf(Errormsg,
1383				"%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1384				__FILE__, __LINE__,
1385				fd, size, sig, errno, strerror(errno));
1386			if (sig)
1387				sigrelse(sig);
1388			return -errno;
1389		}
1390#endif
1391	}
1392	/* LIO_IO_ASYNC */
1393	else if (method & LIO_IO_SLISTIO) {
1394#ifdef CRAY
1395		request.li_opcode = LO_READ;
1396		request.li_fildes = fd;
1397		request.li_buf = buffer;
1398		request.li_nbyte = size;
1399		request.li_status = &status;
1400		request.li_signo = sig;
1401		request.li_nstride = 0;
1402		request.li_filstride = 0;
1403		request.li_memstride = 0;
1404
1405		listio_cmd = LC_WAIT;
1406		io_type = "listio(2) sync read";
1407
1408		sprintf(Lio_SysCall,
1409			"listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1410			fd, size);
1411
1412		if (Debug_level) {
1413			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1414			       Lio_SysCall);
1415		}
1416
1417		sigoff();
1418		if (listio(listio_cmd, &request, 1) == -1) {
1419			sprintf(Errormsg,
1420				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1421				__FILE__, __LINE__, Lio_SysCall, fd, size,
1422				errno, strerror(errno));
1423			sigon();
1424			return -errno;
1425		}
1426
1427		if (Debug_level > 1)
1428			printf("DEBUG %s/%d: %s did not return -1\n",
1429			       __FILE__, __LINE__, Lio_SysCall);
1430
1431		ret = lio_check_asyncio(io_type, size, &status);
1432		return ret;
1433#endif
1434#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1435		aiocbp.aio_lio_opcode = LIO_READ;
1436		listio_cmd = LIO_WAIT;
1437		io_type = "lio_listio(3) sync read";
1438
1439		sprintf(Lio_SysCall,
1440			"lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1441			fd, size);
1442
1443		if (Debug_level) {
1444			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1445			       Lio_SysCall);
1446		}
1447
1448		if (sig)
1449			sighold(sig);
1450		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1451			sprintf(Errormsg,
1452				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1453				__FILE__, __LINE__, Lio_SysCall, fd, size,
1454				errno, strerror(errno));
1455			if (sig)
1456				sigrelse(sig);
1457			return -errno;
1458		}
1459
1460		if (Debug_level > 1)
1461			printf("DEBUG %s/%d: %s did not return -1\n",
1462			       __FILE__, __LINE__, Lio_SysCall);
1463
1464		ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1465		return ret;
1466#endif
1467	}
1468	/* LIO_IO_SLISTIO */
1469	else if (method & LIO_IO_ALISTIO) {
1470#ifdef CRAY
1471		request.li_opcode = LO_READ;
1472		request.li_fildes = fd;
1473		request.li_buf = buffer;
1474		request.li_nbyte = size;
1475		request.li_status = &status;
1476		request.li_signo = sig;
1477		request.li_nstride = 0;
1478		request.li_filstride = 0;
1479		request.li_memstride = 0;
1480
1481		listio_cmd = LC_START;
1482		io_type = "listio(2) async read";
1483
1484		sprintf(Lio_SysCall,
1485			"listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1486			fd, size);
1487
1488		if (Debug_level) {
1489			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1490			       Lio_SysCall);
1491		}
1492
1493		sigoff();
1494		if (listio(listio_cmd, &request, 1) == -1) {
1495			sprintf(Errormsg,
1496				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1497				__FILE__, __LINE__, Lio_SysCall, fd, size,
1498				errno, strerror(errno));
1499			sigon();
1500			return -errno;
1501		}
1502#endif
1503#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1504		aiocbp.aio_lio_opcode = LIO_READ;
1505		listio_cmd = LIO_NOWAIT;
1506		io_type = "lio_listio(3) async read";
1507
1508		sprintf(Lio_SysCall,
1509			"lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1510			fd, size);
1511
1512		if (Debug_level) {
1513			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1514			       Lio_SysCall);
1515		}
1516
1517		if (sig)
1518			sighold(sig);
1519		if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1520			sprintf(Errormsg,
1521				"%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1522				__FILE__, __LINE__, Lio_SysCall, fd, size,
1523				errno, strerror(errno));
1524			if (sig)
1525				sigrelse(sig);
1526			return -errno;
1527		}
1528#endif
1529	}
1530	/* LIO_IO_ALISTIO */
1531#ifndef CRAY
1532	else if (method & LIO_IO_SYNCV) {
1533		io_type = "readv(2)";
1534
1535		sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
1536
1537		if (Debug_level) {
1538			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1539			       Lio_SysCall);
1540		}
1541		if ((ret = readv(fd, &iov, 1)) == -1) {
1542			sprintf(Errormsg,
1543				"%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1544				__FILE__, __LINE__, fd, size, errno,
1545				strerror(errno));
1546			return -errno;
1547		}
1548
1549		if (ret != size) {
1550			sprintf(Errormsg,
1551				"%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1552				__FILE__, __LINE__, fd, size, ret);
1553		} else if (Debug_level > 1)
1554			printf
1555			    ("DEBUG %s/%d: readv completed without error (ret %d)\n",
1556			     __FILE__, __LINE__, ret);
1557
1558		return ret;
1559	}			/* LIO_IO_SYNCV */
1560#endif
1561
1562#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1563	else if (method & LIO_IO_SYNCP) {
1564		io_type = "pread(2)";
1565
1566		sprintf(Lio_SysCall,
1567			"pread(%d, buf, %d, %lld)", fd, size,
1568			(long long)poffset);
1569
1570		if (Debug_level) {
1571			printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1572			       Lio_SysCall);
1573		}
1574		if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1575			sprintf(Errormsg,
1576				"%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1577				__FILE__, __LINE__, fd, size,
1578				(long long)poffset, errno, strerror(errno));
1579			return -errno;
1580		}
1581
1582		if (ret != size) {
1583			sprintf(Errormsg,
1584				"%s/%d pread(%d, buf, %d, %lld) returned=%d",
1585				__FILE__, __LINE__,
1586				fd, size, (long long)poffset, ret);
1587		} else if (Debug_level > 1)
1588			printf
1589			    ("DEBUG %s/%d: pread completed without error (ret %d)\n",
1590			     __FILE__, __LINE__, ret);
1591
1592		return ret;
1593	}			/* LIO_IO_SYNCP */
1594#endif
1595
1596	else {
1597		printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1598		       __LINE__);
1599		return -1;
1600	}
1601
1602	/*
1603	 * wait for async io to complete.
1604	 * Note: Sync io should have returned prior to getting here.
1605	 */
1606#ifdef CRAY
1607	ret = lio_wait4asyncio(method, fd, statptr);
1608#endif
1609#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1610	ret = lio_wait4asyncio(method, fd, &aiocbp);
1611#endif
1612
1613	/*
1614	 * If there was an error waiting for async i/o to complete,
1615	 * return the error value (errno) to the caller.
1616	 * Note: Errormsg should already have been updated.
1617	 */
1618	if (ret < 0) {
1619		return ret;
1620	}
1621
1622	/*
1623	 * If i/o was not waited for (may not have been completed at this time),
1624	 * return the size that was requested.
1625	 */
1626	if (ret == 1)
1627		return size;
1628
1629	/*
1630	 * check that async io was successful.
1631	 * Note:  if the there was an system call failure, -errno
1632	 * was returned and Errormsg should already have been updated.
1633	 * If amount i/o was different than size, Errormsg should already
1634	 * have been updated but the actual i/o size if returned.
1635	 */
1636
1637#ifdef CRAY
1638	ret = lio_check_asyncio(io_type, size, &status);
1639#endif
1640#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1641	ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1642#endif
1643
1644	return ret;
1645}				/* end of lio_read_buffer */
1646
1647#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
1648/***********************************************************************
1649 * This function will check that async io was successful.
1650 * It can also be used to check sync listio since it uses the
1651 * same method.
1652 *
1653 * Return Values
1654 *  If status.sw_error is set, -status.sw_error is returned.
1655 *  Otherwise sw_count's field value is returned.
1656 *
1657 * (rrl 04/96)
1658 ***********************************************************************/
1659#ifdef CRAY
1660int lio_check_asyncio(char *io_type, int size, struct iosw *status)
1661#elif defined(sgi)
1662int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
1663#elif defined(__linux__) && !defined(__UCLIBC__)
1664int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
1665{
1666	int ret;
1667
1668#ifdef CRAY
1669	if (status->sw_error) {
1670		sprintf(Errormsg,
1671			"%s/%d %s, sw_error set = %d %s, sw_count = %d",
1672			__FILE__, __LINE__, io_type,
1673			status->sw_error, strerror(status->sw_error),
1674			status->sw_count);
1675		return -status->sw_error;
1676	} else if (status->sw_count != size) {
1677		sprintf(Errormsg,
1678			"%s/%d %s, sw_count not as expected(%d), but actual:%d",
1679			__FILE__, __LINE__, io_type, size, status->sw_count);
1680	} else if (Debug_level > 1) {
1681		printf
1682		    ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1683		     __FILE__, __LINE__, io_type, status->sw_count);
1684	}
1685
1686	return status->sw_count;
1687
1688#else
1689
1690	int cnt = 1;
1691
1692	/* The I/O may have been synchronous with signal completion.  It doesn't
1693	 * make sense, but the combination could be generated.  Release the
1694	 * completion signal here otherwise it'll hang around and bite us
1695	 * later.
1696	 */
1697	if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1698		sigrelse(aiocbp->aio_sigevent.sigev_signo);
1699
1700	ret = aio_error(aiocbp);
1701
1702	while (ret == EINPROGRESS) {
1703		ret = aio_error(aiocbp);
1704		++cnt;
1705	}
1706	if (cnt > 1) {
1707		sprintf(Errormsg,
1708			"%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1709			__FILE__, __LINE__, io_type, cnt, method,
1710			(aiocbp->aio_sigevent.sigev_notify ==
1711			 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1712			 sigev_notify == SIGEV_NONE ? "none" :
1713#ifdef SIGEV_CALLBACK
1714			 aiocbp->aio_sigevent.sigev_notify ==
1715			 SIGEV_CALLBACK ? "callback" :
1716#endif
1717			 aiocbp->aio_sigevent.sigev_notify ==
1718			 SIGEV_THREAD ? "thread" : "unknown"));
1719		return -ret;
1720	}
1721
1722	if (ret != 0) {
1723		sprintf(Errormsg,
1724			"%s/%d %s, aio_error = %d %s; random method %#o",
1725			__FILE__, __LINE__, io_type,
1726			ret, strerror(ret), method);
1727		return -ret;
1728	}
1729	ret = aio_return(aiocbp);
1730	if (ret != size) {
1731		sprintf(Errormsg,
1732			"%s/%d %s, aio_return not as expected(%d), but actual:%d",
1733			__FILE__, __LINE__, io_type, size, ret);
1734
1735#ifdef BUG1_workaround
1736		if (ret == 0) {
1737			ret = size;
1738			if (Debug_level > 1) {
1739				printf
1740				    ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1741				     __FILE__, __LINE__, io_type, ret);
1742			}
1743		}
1744#endif /* BUG1_workaround */
1745
1746	} else if (Debug_level > 1) {
1747		printf
1748		    ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1749		     __FILE__, __LINE__, io_type, ret);
1750	}
1751
1752	return ret;
1753
1754#endif
1755}				/* end of lio_check_asyncio */
1756#endif
1757
1758/***********************************************************************
1759 *
1760 * This function will wait for async io to complete.
1761 * If multiple wait methods are specified, the order is predetermined
1762 * to LIO_WAIT_RECALL,
1763 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1764 * then LIO_WAIT_NONE.
1765 *
1766 * If no wait method was specified the default wait method is: recall(2)
1767 * or aio_suspend(3), as appropriate.
1768 *
1769 * Return Values
1770 *	<0: errno of failed recall
1771 *	0 : async io was completed
1772 *	1 : async was not waited for, io may not have completed.
1773 *
1774 * (rrl 04/96)
1775 ***********************************************************************/
1776#ifdef CRAY
1777int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1778#elif defined(sgi)
1779int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
1780#elif defined(__linux__) && !defined(__UCLIBC__)
1781int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
1782{
1783	int cnt;
1784#ifdef sgi
1785	int ret;
1786	const aiocb_t *aioary[1];
1787#endif
1788#if defined(__linux__)&& !defined(__UCLIBC__)
1789	int ret;
1790	const struct aiocb *aioary[1];
1791#endif
1792
1793	if ((method & LIO_WAIT_RECALL)
1794#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1795	    || (method & LIO_WAIT_CBSUSPEND)
1796	    || (method & LIO_WAIT_SIGSUSPEND)
1797#endif
1798	    || ((method & LIO_WAIT_TYPES) == 0)) {
1799		/*
1800		 * If method has LIO_WAIT_RECALL bit set or method does
1801		 * not have any wait method bits set (default), use recall/aio_suspend.
1802		 */
1803#ifdef CRAY
1804		if (Debug_level > 2)
1805			printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
1806			       __LINE__);
1807		sigon();
1808		if (recall(fd, 1, statptr)) {
1809			sprintf(Errormsg,
1810				"%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1811				__FILE__, __LINE__, fd, errno, strerror(errno));
1812			return -errno;
1813		}
1814#else
1815		if (Debug_level > 2)
1816			printf
1817			    ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
1818			     __FILE__, __LINE__,
1819			     (aiocbp->aio_sigevent.sigev_notify ==
1820			      SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1821			      sigev_notify == SIGEV_NONE ? "none" :
1822#ifdef SIGEV_CALLBACK
1823			      aiocbp->aio_sigevent.sigev_notify ==
1824			      SIGEV_CALLBACK ? "callback" :
1825#endif
1826			      aiocbp->aio_sigevent.sigev_notify ==
1827			      SIGEV_THREAD ? "thread" : "unknown"));
1828
1829		aioary[0] = aiocbp;
1830		ret = aio_suspend(aioary, 1, NULL);
1831		if ((ret == -1) && (errno == EINTR)) {
1832			if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
1833				if (Debug_level > 2) {
1834					printf
1835					    ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1836					     __FILE__, __LINE__);
1837				}
1838			} else {
1839				sprintf(Errormsg,
1840					"%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1841					__FILE__, __LINE__,
1842					(aiocbp->aio_sigevent.sigev_notify ==
1843					 SIGEV_SIGNAL ? "signal" : aiocbp->
1844					 aio_sigevent.sigev_notify ==
1845					 SIGEV_NONE ? "none" :
1846#ifdef SIGEV_CALLBACK
1847					 aiocbp->aio_sigevent.sigev_notify ==
1848					 SIGEV_CALLBACK ? "callback" :
1849#endif
1850					 aiocbp->aio_sigevent.sigev_notify ==
1851					 SIGEV_THREAD ? "thread" : "unknown"));
1852				return -errno;
1853			}
1854		} else if (ret) {
1855			sprintf(Errormsg,
1856				"%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1857				__FILE__, __LINE__, fd, errno, strerror(errno));
1858			return -errno;
1859		}
1860#endif
1861
1862	} else if (method & LIO_WAIT_ACTIVE) {
1863		if (Debug_level > 2)
1864			printf("DEBUG %s/%d: wait method : active\n", __FILE__,
1865			       __LINE__);
1866#ifdef CRAY
1867		sigon();
1868		/*
1869		 * loop until sw_flag, sw_count or sw_error field elements
1870		 * change to non-zero.
1871		 */
1872		cnt = 0;
1873		while ((*statptr)->sw_flag == 0 &&
1874		       (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
1875			cnt++;
1876		}
1877#else
1878		/* loop while aio_error() returns EINPROGRESS */
1879		cnt = 0;
1880		while (1) {
1881			ret = aio_error(aiocbp);
1882			if (ret != EINPROGRESS) {
1883				break;
1884			}
1885			++cnt;
1886		}
1887
1888#endif
1889		if (Debug_level > 5 && cnt && (cnt % 50) == 0)
1890			printf("DEBUG %s/%d: wait active cnt = %d\n",
1891			       __FILE__, __LINE__, cnt);
1892
1893	} else if (method & LIO_WAIT_SIGPAUSE) {
1894		if (Debug_level > 2)
1895			printf("DEBUG %s/%d: wait method : sigpause\n",
1896			       __FILE__, __LINE__);
1897#ifdef sgi
1898		/* note: don't do the sigon() for CRAY in this case.  why? -- roehrich 6/11/97 */
1899		if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1900			sigrelse(aiocbp->aio_sigevent.sigev_signo);
1901		else {
1902			printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1903			       __FILE__, __LINE__);
1904			return -1;
1905		}
1906#endif
1907		pause();
1908
1909	} else if (method & LIO_WAIT_SIGACTIVE) {
1910		if (Debug_level > 2)
1911			printf("DEBUG %s/%d: wait method : sigactive\n",
1912			       __FILE__, __LINE__);
1913#ifdef CRAY
1914		sigon();
1915#else
1916		if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1917			sigrelse(aiocbp->aio_sigevent.sigev_signo);
1918		else {
1919			printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1920			       __FILE__, __LINE__);
1921			return -1;
1922		}
1923#endif
1924		/* loop waiting for signal */
1925		while (Received_signal == Rec_signal) {
1926#ifdef CRAY
1927			sigon();
1928#else
1929			sigrelse(aiocbp->aio_sigevent.sigev_signo);
1930#endif
1931		}
1932
1933	} else if (method & LIO_WAIT_NONE) {
1934		if (Debug_level > 2)
1935			printf("DEBUG %s/%d: wait method : none\n", __FILE__,
1936			       __LINE__);
1937		/* It's broken because the aiocb/iosw is an automatic variable in
1938		 * lio_{read,write}_buffer, so when the function returns and the
1939		 * I/O completes there will be nowhere to write the I/O status.
1940		 * It doesn't cause a problem on unicos--probably because of some
1941		 * compiler quirk, or an accident.  It causes POSIX async I/O
1942		 * to core dump some threads.   spr/pv 705909.  6/27/97 roehrich
1943		 */
1944		sprintf(Errormsg,
1945			"%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1946			__FILE__, __LINE__);
1947#ifdef CRAY
1948		sigon();
1949#endif
1950/*        return 1;*/
1951		return -1;
1952	} else {
1953		if (Debug_level > 2)
1954			printf("DEBUG %s/%d: no wait method was chosen\n",
1955			       __FILE__, __LINE__);
1956		return -1;
1957	}
1958
1959	return 0;
1960
1961}				/* end of lio_wait4asyncio */
1962
1963#endif /* ifndef linux */
1964#endif
1965
1966#if UNIT_TEST
1967/***********************************************************************
1968 * The following code is provided as unit test.
1969 * Just define add "-DUNIT_TEST=1" to the cc line.
1970 *
1971 * (rrl 04/96)
1972 ***********************************************************************/
1973struct unit_info_t {
1974	int method;
1975	int sig;
1976	char *str;
1977} Unit_info[] = {
1978	{
1979	LIO_IO_SYNC, 0, "sync io"}, {
1980	LIO_IO_SYNCV, 0, "sync readv/writev"}, {
1981	LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
1982	LIO_IO_ASYNC, 0, "async io, def wait"}, {
1983	LIO_IO_SLISTIO, 0, "sync listio"}, {
1984	LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
1985	LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
1986	LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
1987	LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
1988	LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
1989	LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
1990	LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
1991	LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
1992	{
1993	LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
1994	{
1995	LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
1996LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
1997
1998int main(argc, argv)
1999int argc;
2000char **argv;
2001{
2002	extern char *optarg;
2003	extern int optind;
2004
2005	int fd;
2006	char *err;
2007	char buffer[4096];
2008	int size = 4096;
2009	int ret;
2010	int ind;
2011	int iter = 3;
2012	int method;
2013	int exit_status = 0;
2014	int c;
2015	int i;
2016	char *symbols = NULL;
2017	int die_on_err = 0;
2018
2019	while ((c = getopt(argc, argv, "s:di:")) != -1) {
2020		switch (c) {
2021		case 's':
2022			symbols = optarg;
2023			break;
2024		case 'd':
2025			++die_on_err;
2026			break;
2027		case 'i':
2028			iter = atoi(optarg);
2029			break;
2030		}
2031	}
2032
2033	if ((fd =
2034	     open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
2035		perror
2036		    ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
2037		exit(1);
2038	}
2039
2040	Debug_level = 9;
2041
2042	if (symbols != NULL) {
2043		if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
2044			printf
2045			    ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
2046			     symbols, err);
2047			if (die_on_err)
2048				exit(1);
2049		} else
2050			printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
2051			       symbols, method);
2052
2053		exit_status = 0;
2054		for (ind = 0; ind < iter; ind++) {
2055			memset(buffer, 'A', 4096);
2056			if (lseek(fd, 0, 0) == -1) {
2057				printf("lseek(fd,0,0), %d, failed, errno %d\n",
2058				       __LINE__, errno);
2059				++exit_status;
2060			}
2061			if ((ret = lio_write_buffer(fd, method, buffer,
2062						    size, SIGUSR1, &err,
2063						    0)) != size) {
2064				printf
2065				    ("lio_write_buffer returned -1, err = %s\n",
2066				     err);
2067			} else
2068				printf("lio_write_buffer returned %d\n", ret);
2069
2070			memset(buffer, 'B', 4096);
2071			if (lseek(fd, 0, 0) == -1) {
2072				printf("lseek(fd,0,0), %d, failed, errno %d\n",
2073				       __LINE__, errno);
2074				++exit_status;
2075			}
2076			if ((ret = lio_read_buffer(fd, method, buffer,
2077						   size, SIGUSR2, &err,
2078						   0)) != size) {
2079				printf
2080				    ("lio_read_buffer returned -1, err = %s\n",
2081				     err);
2082			} else
2083				printf("lio_read_buffer returned %d\n", ret);
2084
2085			for (i = 0; i < 4096; ++i) {
2086				if (buffer[i] != 'A') {
2087					printf("  buffer[%d] = %d\n", i,
2088					       buffer[i]);
2089					++exit_status;
2090					break;
2091				}
2092			}
2093
2094			if (exit_status)
2095				exit(exit_status);
2096
2097		}
2098
2099		unlink("unit_test_file");
2100		exit(0);
2101	}
2102
2103	for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
2104	     ind++) {
2105
2106		printf("\n********* write %s ***************\n",
2107		       Unit_info[ind].str);
2108		if (lseek(fd, 0, 0) == -1) {
2109			printf("lseek(fd,0,0), %d, failed, errno %d\n",
2110			       __LINE__, errno);
2111			++exit_status;
2112		}
2113
2114		memset(buffer, 'A', 4096);
2115		if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
2116					    size, Unit_info[ind].sig, &err,
2117					    0)) != size) {
2118			printf
2119			    (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n   err = %s\n",
2120			     Unit_info[ind].method, size, Unit_info[ind].sig,
2121			     err);
2122			++exit_status;
2123			if (die_on_err)
2124				exit(exit_status);
2125		} else {
2126			printf("lio_write_buffer returned %d\n", ret);
2127		}
2128
2129		printf("\n********* read %s ***************\n",
2130		       Unit_info[ind].str);
2131		if (lseek(fd, 0, 0) == -1) {
2132			printf("lseek(fd,0,0), %d, failed, errno %d\n",
2133			       __LINE__, errno);
2134			++exit_status;
2135		}
2136		memset(buffer, 'B', 4096);
2137		if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
2138					   size, Unit_info[ind].sig, &err,
2139					   0)) != size) {
2140			printf
2141			    (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n   err = %s\n",
2142			     Unit_info[ind].method, size, Unit_info[ind].sig,
2143			     err);
2144			++exit_status;
2145			if (die_on_err)
2146				exit(exit_status);
2147		} else {
2148			printf("lio_read_buffer returned %d\n", ret);
2149		}
2150
2151		for (i = 0; i < 4096; ++i) {
2152			if (buffer[i] != 'A') {
2153				printf("  buffer[%d] = %d\n", i, buffer[i]);
2154				++exit_status;
2155				if (die_on_err)
2156					exit(exit_status);
2157				break;
2158			}
2159		}
2160
2161		fflush(stdout);
2162		fflush(stderr);
2163		sleep(1);
2164
2165	}
2166
2167	unlink("unit_test_file");
2168
2169	exit(exit_status);
2170}
2171#endif
2172