xref: /aosp_15_r20/external/ltp/lib/tlibio.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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 #ifndef __UCLIBC__
112 #include <aio.h>
113 #endif
114 #endif
115 #include <stdlib.h>		/* atoi, abs */
116 
117 #include "tlibio.h"		/* defines LIO* macros */
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[PATH_MAX*2];
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 	/* 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  ***********************************************************************/
lio_read_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)1108 int 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
1660 int lio_check_asyncio(char *io_type, int size, struct iosw *status)
1661 #elif defined(sgi)
1662 int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
1663 #elif defined(__linux__) && !defined(__UCLIBC__)
1664 int 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
1777 int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1778 #elif defined(sgi)
1779 int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
1780 #elif defined(__linux__) && !defined(__UCLIBC__)
1781 int 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  ***********************************************************************/
1973 struct 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"}, {
1996 LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
1997 
main(argc,argv)1998 int main(argc, argv)
1999 int argc;
2000 char **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