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  */
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 
stride_bounds(int offset,int stride,int nstrides,int bytes_per_stride,int * min,int * max)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  ***********************************************************************/
lio_set_debug(int level)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  ***********************************************************************/
lio_parse_io_arg1(char * string)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  ***********************************************************************/
lio_help1(char * prefix)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  ***********************************************************************/
lio_parse_io_arg2(char * string,char ** badtoken)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  ***********************************************************************/
lio_help2(char * prefix)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  ***********************************************************************/
lio_async_signal_handler(int sig)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  ***********************************************************************/
lio_async_callback_handler(union sigval sigval)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  ***********************************************************************/
lio_random_methods(long curr_mask)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 
wait4sync_io(int fd,int read)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  ***********************************************************************/
lio_write_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)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  ***********************************************************************/
lio_read_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)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 != 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 
main(argc,argv)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