Fix the creation of the dumpdir directory in stress_floppy Makefile
[ltp-debian.git] / lib / tlibio.c
blobdd5dc02af8d7121d46d6c748136890b8d138c9e2
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
26 * http://www.sgi.com
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
34 * Lib i/o
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.
42 * This file contains functions for writing/reading to/from open files
43 * Prototypes:
45 * Functions declared in this module - see individual function code for
46 * usage comments:
48 * int stride_bounds(int offset, int stride, int nstrides,
49 * int bytes_per_stride, int *min, int *max);
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);
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
65 * int lio_parse_io_arg1(char *string)
66 * void lio_help1(char *prefix);
68 * int lio_parse_io_arg2(char *string, char **badtoken)
69 * void lio_help2(char *prefix);
71 * int lio_set_debug(int level);
73 * char Lio_SysCall[];
74 * struct lio_info_type Lio_info1[];
75 * struct lio_info_type Lio_info2[];
77 * Author : Richard Logan
81 #ifdef __linux__
82 #define _GNU_SOURCE
83 #define _LARGEFILE64_SOURCE
84 #endif
85 #include <stdio.h>
86 #include <ctype.h>
87 #include <fcntl.h>
88 #include <unistd.h>
89 #include <sys/types.h>
90 #include <sys/stat.h>
91 #include <sys/time.h>
92 #include <sys/param.h>
93 #include <errno.h>
94 #include <sys/types.h>
95 #include <sys/file.h>
96 #include <signal.h>
97 #include <stdint.h>
98 #ifdef CRAY
99 #include <sys/secparm.h>
100 #include <sys/iosw.h>
101 #include <sys/listio.h>
102 #else
103 /* for linux or sgi */
104 #include <sys/uio.h> /* readv(2)/writev(2) */
105 #include <string.h> /* bzero */
106 #endif
107 #if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX)
108 #if !defined(UCLINUX) && !defined(__UCLIBC__)
109 #include <aio.h>
110 #endif
111 #endif
112 #include <stdlib.h> /* atoi, abs */
114 #include "tlibio.h" /* defines LIO* marcos */
116 #ifndef PATH_MAX
117 #define PATH_MAX MAXPATHLEN
118 #endif
120 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
121 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
122 * a value of zero but there is no errno followup
123 * and the read/write operation actually did its
124 * job. spr/pv 705244
126 #endif
129 static void lio_async_signal_handler();
130 #ifdef sgi
131 static void lio_async_callback_handler();
132 #endif
135 * Define the structure as used in lio_parse_arg1 and lio_help1
137 struct lio_info_type Lio_info1[] = {
138 { "s", LIO_IO_SYNC, "sync i/o" },
139 { "p", LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, "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, "async i/o using recall/aio_suspend" },
142 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
143 { "r",
144 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random sync i/o types and wait methods" },
145 { "R",
146 LIO_RANDOM|LIO_IO_ATYPES|LIO_WAIT_ATYPES, "random i/o types and wait methods" },
147 #else
148 { "r",
149 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
150 { "R",
151 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
152 #endif
153 { "l", LIO_IO_SLISTIO|LIO_WAIT_RECALL, "single stride sync listio" },
154 { "L", LIO_IO_ALISTIO|LIO_WAIT_RECALL, "single stride async listio using recall" },
155 { "X", LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, "single stride async listio using pause" },
156 { "v", LIO_IO_SYNCV, "single buffer sync readv/writev" },
157 { "P", LIO_IO_SYNCP, "sync pread/pwrite" },
161 * Define the structure used by lio_parse_arg2 and lio_help2
163 struct lio_info_type Lio_info2[] = {
164 { "sync", LIO_IO_SYNC, "sync i/o (read/write)"},
165 { "async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)" },
166 { "slistio", LIO_IO_SLISTIO, "single stride sync listio" },
167 { "alistio", LIO_IO_ALISTIO, "single stride async listio" },
168 { "syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
169 { "syncp", LIO_IO_SYNCP, "pread/pwrite"},
170 { "active", LIO_WAIT_ACTIVE, "spin on status/control values" },
171 { "recall", LIO_WAIT_RECALL, "use recall(2)/aio_suspend(3) to wait for i/o to complete" },
172 { "sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal" },
173 { "sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal" },
174 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
175 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
176 { "random", LIO_RANDOM, "set random bit" },
177 { "randomall",
178 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES,
179 "all random i/o types and wait methods (except nowait)" },
182 char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
184 static volatile int Received_signal = 0; /* number of signals received */
185 static volatile int Rec_signal;
186 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
187 static volatile int Received_callback = 0; /* number of callbacks received */
188 static volatile int Rec_callback;
189 #endif
190 static char Errormsg[500];
191 static int Debug_level = 0;
195 /***********************************************************************
196 * stride_bounds()
198 * Determine the bounds of a strided request, normalized to offset. Returns
199 * the number of bytes needed to satisfy the request, and optionally sets
200 * *min and *max to the mininum and maximum bytes referenced, normalized
201 * around offset.
203 * Returns -1 on error - the only possible error conditions are illegal values
204 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
206 * (maule, 11/16/95)
207 ***********************************************************************/
210 stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max)
211 int offset;
212 int stride;
213 int nstrides;
214 int bytes_per_stride;
215 int *min;
216 int *max;
218 int nbytes, min_byte, max_byte;
221 * sanity checks ...
224 if (nstrides < 0 || bytes_per_stride < 0) {
225 return -1;
228 if (stride == 0) {
229 stride = bytes_per_stride;
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.
239 nbytes = abs(stride) * (nstrides-1) + bytes_per_stride;
241 if (stride < 0) {
242 max_byte = offset + bytes_per_stride - 1;
243 min_byte = max_byte - nbytes + 1;
244 } else {
245 min_byte = offset;
246 max_byte = min_byte + nbytes - 1;
249 if (min != NULL) {
250 *min = min_byte;
253 if (max != NULL) {
254 *max = max_byte;
257 return nbytes;
260 /***********************************************************************
261 * This function will allow someone to set the debug level.
262 ***********************************************************************/
264 lio_set_debug(level)
266 int old;
268 old = Debug_level;
269 Debug_level = level;
270 return old;
273 /***********************************************************************
274 * This function will parse a string and return desired io-method.
275 * Only the first character of the string is used.
277 * This function does not provide for meaningful option arguments,
278 * but it supports current growfiles/btlk interface.
280 * (rrl 04/96)
281 ***********************************************************************/
283 lio_parse_io_arg1(char *string)
285 unsigned int ind;
286 int found=0;
287 int mask=0;
290 * Determine if token is a valid string.
292 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
293 if ( strcmp(string, Lio_info1[ind].token) == 0 ) {
294 mask |= Lio_info1[ind].bits;
295 found = 1;
296 break;
300 if ( found == 0 ) {
301 return -1;
304 return mask;
308 /***********************************************************************
309 * This function will print a help message describing the characters
310 * that can be parsed by lio_parse_io_arg1().
311 * They will be printed one per line.
312 * (rrl 04/96)
313 ***********************************************************************/
314 void
315 lio_help1(char *prefix)
317 unsigned int ind;
319 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
320 printf("%s %s : %s\n", prefix,
321 Lio_info1[ind].token, Lio_info1[ind].desc);
324 return;
327 /***********************************************************************
328 * This function will parse a string and return the desired io-method.
329 * This function will take a comma separated list of io type and wait
330 * method tokens as defined in Lio_info2[]. If a token does not match
331 * any of the tokens in Lio_info2[], it will be coverted to a number.
332 * If it was a number, those bits are also set.
334 * (rrl 04/96)
335 ***********************************************************************/
337 lio_parse_io_arg2(char *string, char **badtoken)
339 char *token = string;
340 char *cc = token;
341 char savecc;
342 int found;
343 int mask=0;
345 int tmp;
346 unsigned int ind;
347 char chr;
349 if ( token == NULL )
350 return -1;
352 for (;;) {
353 for (; ((*cc != ',') && (*cc != '\0')); cc++);
354 savecc = *cc;
355 *cc = '\0';
357 found = 0;
360 * Determine if token is a valid string or number and if
361 * so, add the bits to the mask.
363 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
364 if ( strcmp(token, Lio_info2[ind].token) == 0 ) {
365 mask |= Lio_info2[ind].bits;
366 found = 1;
367 break;
372 * If token does not match one of the defined tokens, determine
373 * if it is a number, if so, add the bits.
375 if ( !found ) {
376 if (sscanf(token, "%i%c", &tmp, &chr) == 1 ) {
377 mask |= tmp;
378 found=1;
382 *cc = savecc;
384 if (!found) { /* token is not valid */
385 if ( badtoken != NULL)
386 *badtoken = token;
387 return(-1);
390 if (savecc == '\0')
391 break;
393 token = ++cc;
396 return mask;
399 /***********************************************************************
400 * This function will print a help message describing the tokens
401 * that can be parsed by lio_parse_io_arg2().
402 * It will print them one per line.
404 * (rrl 04/96)
405 ***********************************************************************/
406 void
407 lio_help2(char *prefix)
409 unsigned int ind;
411 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
412 printf("%s %s : %s\n", prefix,
413 Lio_info2[ind].token, Lio_info2[ind].desc);
415 return;
418 /***********************************************************************
419 * This is an internal signal handler.
420 * If the handler is called, it will increment the Received_signal
421 * global variable.
422 ***********************************************************************/
423 static void
424 lio_async_signal_handler(int sig)
426 if ( Debug_level )
427 printf("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
428 __FILE__, __LINE__, sig, Received_signal+1);
430 Received_signal++;
432 return;
435 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
436 /***********************************************************************
437 * This is an internal callback handler.
438 * If the handler is called, it will increment the Received_callback
439 * global variable.
440 ***********************************************************************/
441 static void
442 lio_async_callback_handler(sigval_t sigval)
444 if ( Debug_level )
445 printf("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
446 __FILE__, __LINE__, (long)sigval.sival_int, Received_callback+1);
448 Received_callback++;
450 return;
452 #endif /* sgi */
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.
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.
466 * (rrl 04/96)
467 ***********************************************************************/
469 lio_random_methods(long curr_mask)
471 int mask=0;
472 long random_bit();
474 /* remove random select, io type, and wait method bits from curr_mask */
475 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
477 /* randomly select io type from specified io types */
478 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
480 /* randomly select wait methods from specified wait methods */
481 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
483 return mask;
486 static void wait4sync_io(int fd, int read)
488 fd_set s;
489 FD_ZERO(&s);
490 FD_SET(fd, &s);
492 select(fd+1, read ? &s : NULL, read ? NULL : &s, NULL, NULL);
495 /***********************************************************************
496 * Generic write function
497 * This function can be used to do a write using write(2), writea(2),
498 * aio_write(3), writev(2), pwrite(2),
499 * or single stride listio(2)/lio_listio(3).
500 * By setting the desired bits in the method
501 * bitmask, the caller can control the type of write and the wait method
502 * that will be used. If no io type bits are set, write will be used.
504 * If async io was attempted and no wait method bits are set then the
505 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
506 * aio_write(3) and lio_listio(3).
508 * If multiple wait methods are specified,
509 * only one wait method will be used. The order is predetermined.
511 * If the call specifies a signal and one of the two signal wait methods,
512 * a signal handler for the signal is set. This will reset an already
513 * set handler for this signal.
515 * If the LIO_RANDOM method bit is set, this function will randomly
516 * choose a io type and wait method from bits in the method argument.
518 * If an error is encountered, an error message will be generated
519 * in a internal static buffer. If errmsg is not NULL, it will
520 * be updated to point to the static buffer, allowing the caller
521 * to print the error message.
523 * Return Value
524 * If a system call fails, -errno is returned.
525 * If LIO_WAIT_NONE bit is set, the return value is the return value
526 * of the system call.
527 * If the io did not fail, the amount of data written is returned.
528 * If the size the system call say was written is different
529 * then what was asked to be written, errmsg is updated for
530 * this error condition. The return value is still the amount
531 * the system call says was written.
533 * (rrl 04/96)
534 ***********************************************************************/
536 lio_write_buffer(fd, method, buffer, size, sig, errmsg, wrd)
537 int fd; /* open file descriptor */
538 int method; /* contains io type and wait method bitmask */
539 char *buffer; /* pointer to buffer */
540 int size; /* the size of the io */
541 int sig; /* signal to use if async io */
542 char **errmsg; /* char pointer that will be updated to point to err message */
543 long wrd; /* to allow future features, use zero for now */
545 int ret = 0; /* syscall return or used to get random method */
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
567 * If LIO_RANDOM bit specified, get new method randomly.
569 if ( method & LIO_RANDOM ) {
570 if( Debug_level > 3 )
571 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
572 method = lio_random_methods(method);
573 if ( Debug_level > 2 )
574 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
577 if ( errmsg != NULL )
578 *errmsg = Errormsg;
580 Rec_signal=Received_signal; /* get the current number of signals received */
581 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
582 Rec_callback=Received_callback; /* get the current number of callbacks received */
583 #endif
585 #ifdef CRAY
586 memset(&status, 0x00, sizeof(struct iosw));
587 memset(&request, 0x00, sizeof(struct listreq));
588 statptr[0] = &status;
589 #else
590 /* for linux or sgi */
591 memset(&iov, 0x00, sizeof(struct iovec));
592 iov.iov_base = buffer;
593 iov.iov_len = size;
594 #endif
595 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
596 #if defined(sgi)
597 memset(&aiocbp, 0x00, sizeof(aiocb_t));
598 #else
599 memset(&aiocbp, 0x00, sizeof(struct aiocb));
600 #endif
601 aiocbp.aio_fildes = fd;
602 aiocbp.aio_nbytes = size;
603 aiocbp.aio_buf = buffer;
604 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
605 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
606 aiocbp.aio_sigevent.sigev_signo = 0;
607 #ifdef sgi
608 aiocbp.aio_sigevent.sigev_func = NULL;
609 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
610 #elif defined(__linux__) && !defined(__UCLIBC__)
611 aiocbp.aio_sigevent.sigev_notify_function = NULL;
612 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
613 #endif
614 aiolist[0] = &aiocbp;
616 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
617 ret = 0;
618 /* If there is an error and it is not ESPIPE then kick out the error.
619 * If the fd is a fifo then we have to make sure that
620 * lio_random_methods() didn't select pwrite/pread; if it did then
621 * switch to write/read.
623 if( errno == ESPIPE ){
624 if( method & LIO_IO_SYNCP ){
625 if( omethod & LIO_RANDOM ){
626 method &= ~LIO_IO_SYNCP;
627 method |= LIO_IO_SYNC;
628 if( Debug_level > 2 )
629 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
631 else if( Debug_level ){
632 printf("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
633 __FILE__, __LINE__ );
636 /* else: let it ride */
638 else{
639 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
640 __FILE__, __LINE__, fd, errno, strerror(errno));
641 return -errno;
644 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
645 poffset = (off64_t)ret;
646 #endif
647 aiocbp.aio_offset = ret;
649 #endif
652 * If the LIO_USE_SIGNAL bit is not set, only use the signal
653 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
654 * Otherwise there is not necessary a signal handler to trap
655 * the signal.
657 if ( sig && !(method & LIO_USE_SIGNAL) &&
658 ! (method & LIO_WAIT_SIGTYPES) ){
660 sig=0; /* ignore signal parameter */
663 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
664 if ( sig && (method & LIO_WAIT_CBTYPES) )
665 sig=0; /* ignore signal parameter */
666 #endif
669 * only setup signal hander if sig was specified and
670 * a sig wait method was specified.
671 * Doing this will change the handler for this signal. The
672 * old signal handler will not be restored.
673 *** restoring the signal handler could be added ***
676 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
677 #ifdef CRAY
678 sigctl(SCTL_REG, sig, lio_async_signal_handler);
679 #endif
680 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
681 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
682 aiocbp.aio_sigevent.sigev_signo = sig;
683 sigset(sig, lio_async_signal_handler);
684 #endif /* sgi */
686 #if defined(sgi)
687 else if( method & LIO_WAIT_CBTYPES ){
688 /* sival_int just has to be something that I can use
689 * to identify the callback, and "size" happens to be handy...
691 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
692 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
693 aiocbp.aio_sigevent.sigev_value.sival_int = size;
695 #endif
696 #if defined(__linux__) && !defined(__UCLIBC__)
697 else if( method & LIO_WAIT_CBTYPES ){
698 /* sival_int just has to be something that I can use
699 * to identify the callback, and "size" happens to be handy...
701 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
702 aiocbp.aio_sigevent.sigev_notify_function = lio_async_callback_handler;
703 aiocbp.aio_sigevent.sigev_notify_attributes = (void*)(uintptr_t)size;
705 #endif
707 * Determine the system call that will be called and produce
708 * the string of the system call and place it in Lio_SysCall.
709 * Also update the io_type char pointer to give brief description
710 * of system call. Execute the system call and check for
711 * system call failure. If sync i/o, return the number of
712 * bytes written/read.
715 if ( (method & LIO_IO_SYNC) || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0 ){
717 * write(2) is used if LIO_IO_SYNC bit is set or not none
718 * of the LIO_IO_TYPES bits are set (default).
721 sprintf(Lio_SysCall,
722 "write(%d, buf, %d)", fd, size);
723 io_type="write";
725 if ( Debug_level ) {
726 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
728 while(1) {
729 if (((ret = write(fd, buffer, size)) == -1) && errno!=EAGAIN && errno!=EINTR) {
730 sprintf(Errormsg, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
731 __FILE__, __LINE__,
732 fd, size, errno, strerror(errno));
733 return -errno;
736 if(ret!=-1) {
737 if ( ret != size ) {
738 sprintf(Errormsg,
739 "%s/%d write(%d, buf, %d) returned=%d",
740 __FILE__, __LINE__,
741 fd, size, ret);
742 size-=ret;
743 buffer+=ret;
745 else {
746 if ( Debug_level > 1 )
747 printf("DEBUG %s/%d: write completed without error (ret %d)\n",
748 __FILE__, __LINE__, ret);
750 return ret;
753 wait4sync_io(fd, 0);
758 else if ( method & LIO_IO_ASYNC ) {
759 #ifdef CRAY
760 sprintf(Lio_SysCall,
761 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
762 io_type="writea";
764 if ( Debug_level ) {
765 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
768 sigoff();
769 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
770 sprintf(Errormsg,
771 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
772 __FILE__, __LINE__,
773 fd, size, sig, errno, strerror(errno));
774 sigon();
775 return -errno;
777 #endif
778 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
779 sprintf(Lio_SysCall,
780 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
781 io_type="aio_write";
783 if ( Debug_level ) {
784 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
787 if( sig )
788 sighold( sig );
789 if ((ret = aio_write(&aiocbp)) == -1) {
790 sprintf(Errormsg,
791 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
792 __FILE__, __LINE__,
793 fd, size, sig, errno, strerror(errno));
794 if( sig )
795 sigrelse( sig );
796 return -errno;
798 #endif
799 } /* LIO_IO_ASYNC */
801 else if ( method & LIO_IO_SLISTIO ) {
802 #ifdef CRAY
803 request.li_opcode = LO_WRITE;
804 request.li_fildes = fd;
805 request.li_buf = buffer;
806 request.li_nbyte = size;
807 request.li_status = &status;
808 request.li_signo = sig;
809 request.li_nstride = 0;
810 request.li_filstride = 0;
811 request.li_memstride = 0;
813 listio_cmd=LC_WAIT;
814 io_type="listio(2) sync write";
816 sprintf(Lio_SysCall,
817 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
818 fd, size);
820 if ( Debug_level ) {
821 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
824 sigoff();
825 if ( listio(listio_cmd, &request, 1) == -1 ) {
826 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
827 __FILE__, __LINE__,
828 Lio_SysCall, fd, size, errno, strerror(errno));
829 sigon();
830 return -errno;
833 if ( Debug_level > 1 )
834 printf("DEBUG %s/%d: %s did not return -1\n",
835 __FILE__, __LINE__, Lio_SysCall);
837 ret=lio_check_asyncio(io_type, size, &status);
838 return ret;
840 #endif
841 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
843 aiocbp.aio_lio_opcode = LIO_WRITE;
844 listio_cmd=LIO_WAIT;
845 io_type="lio_listio(3) sync write";
847 sprintf(Lio_SysCall,
848 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
849 fd, size, sig );
851 if ( Debug_level ) {
852 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
855 if( sig )
856 sighold( sig );
857 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
858 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
859 __FILE__, __LINE__,
860 Lio_SysCall, fd, size, errno, strerror(errno));
861 if( sig )
862 sigrelse( sig );
863 return -errno;
866 if ( Debug_level > 1 )
867 printf("DEBUG %s/%d: %s did not return -1\n",
868 __FILE__, __LINE__, Lio_SysCall);
870 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
871 return ret;
872 #endif
873 } /* LIO_IO_SLISTIO */
875 else if ( method & LIO_IO_ALISTIO ) {
876 #ifdef CRAY
877 request.li_opcode = LO_WRITE;
878 request.li_fildes = fd;
879 request.li_buf = buffer;
880 request.li_nbyte = size;
881 request.li_status = &status;
882 request.li_signo = sig;
883 request.li_nstride = 0;
884 request.li_filstride = 0;
885 request.li_memstride = 0;
887 listio_cmd=LC_START;
888 io_type="listio(2) async write";
890 sprintf(Lio_SysCall,
891 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
892 fd, size);
894 if ( Debug_level ) {
895 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
898 sigoff();
899 if ( listio(listio_cmd, &request, 1) == -1 ) {
900 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
901 __FILE__, __LINE__,
902 Lio_SysCall, fd, size, errno, strerror(errno));
903 sigon();
904 return -errno;
906 #endif
907 #if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
908 aiocbp.aio_lio_opcode = LIO_WRITE;
909 listio_cmd=LIO_NOWAIT;
910 io_type="lio_listio(3) async write";
912 sprintf(Lio_SysCall,
913 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
914 fd, size);
916 if ( Debug_level ) {
917 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
920 if( sig )
921 sighold( sig );
922 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
923 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
924 __FILE__, __LINE__,
925 Lio_SysCall, fd, size, errno, strerror(errno));
926 if( sig )
927 sigrelse( sig );
928 return -errno;
930 #endif
931 }/* LIO_IO_ALISTIO */
933 #ifndef CRAY
934 else if ( method & LIO_IO_SYNCV ) {
935 io_type="writev(2)";
937 sprintf(Lio_SysCall,
938 "writev(%d, &iov, 1) nbyte:%d", fd, size);
940 if ( Debug_level ) {
941 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
943 if ((ret = writev(fd, &iov, 1)) == -1) {
944 sprintf(Errormsg, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
945 __FILE__, __LINE__,
946 fd, size, errno, strerror(errno));
947 return -errno;
950 if ( ret != size ) {
951 sprintf(Errormsg,
952 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
953 __FILE__, __LINE__,
954 fd, size, ret);
956 else if ( Debug_level > 1 )
957 printf("DEBUG %s/%d: writev completed without error (ret %d)\n",
958 __FILE__, __LINE__, ret);
960 return ret;
961 } /* LIO_IO_SYNCV */
962 #endif
964 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
965 else if ( method & LIO_IO_SYNCP ) {
966 io_type="pwrite(2)";
968 sprintf(Lio_SysCall,
969 "pwrite(%d, buf, %d, %lld)", fd, size, (long long)poffset);
971 if ( Debug_level ) {
972 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
974 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
975 sprintf(Errormsg, "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
976 __FILE__, __LINE__,
977 fd, size, (long long)poffset, errno, strerror(errno));
978 return -errno;
981 if ( ret != size ) {
982 sprintf(Errormsg,
983 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
984 __FILE__, __LINE__,
985 fd, size, (long long)poffset, ret);
987 else if ( Debug_level > 1 )
988 printf("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
989 __FILE__, __LINE__, ret);
991 return ret;
992 } /* LIO_IO_SYNCP */
993 #endif
995 else {
996 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
997 return -1;
1001 * wait for async io to complete.
1003 #ifdef CRAY
1004 ret=lio_wait4asyncio(method, fd, statptr);
1005 #endif
1006 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1007 ret=lio_wait4asyncio(method, fd, &aiocbp);
1008 #endif
1011 * If there was an error waiting for async i/o to complete,
1012 * return the error value (errno) to the caller.
1013 * Note: Errormsg should already have been updated.
1015 if ( ret < 0 ) {
1016 return ret;
1020 * If i/o was not waited for (may not have been completed at this time),
1021 * return the size that was requested.
1023 if ( ret == 1 )
1024 return size;
1027 * check that async io was successful.
1028 * Note: if the there was an system call failure, -errno
1029 * was returned and Errormsg should already have been updated.
1030 * If amount i/o was different than size, Errormsg should already
1031 * have been updated but the actual i/o size if returned.
1034 #ifdef CRAY
1035 ret=lio_check_asyncio(io_type, size, &status);
1036 #endif
1037 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1038 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1039 #endif
1041 return ret;
1042 } /* end of lio_write_buffer */
1044 /***********************************************************************
1045 * Generic read function
1046 * This function can be used to do a read using read(2), reada(2),
1047 * aio_read(3), readv(2), pread(2),
1048 * or single stride listio(2)/lio_listio(3).
1049 * By setting the desired bits in the method
1050 * bitmask, the caller can control the type of read and the wait method
1051 * that will be used. If no io type bits are set, read will be used.
1053 * If async io was attempted and no wait method bits are set then the
1054 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1055 * aio_read(3) and lio_listio(3).
1057 * If multiple wait methods are specified,
1058 * only one wait method will be used. The order is predetermined.
1060 * If the call specifies a signal and one of the two signal wait methods,
1061 * a signal handler for the signal is set. This will reset an already
1062 * set handler for this signal.
1064 * If the LIO_RANDOM method bit is set, this function will randomly
1065 * choose a io type and wait method from bits in the method argument.
1067 * If an error is encountered, an error message will be generated
1068 * in a internal static buffer. If errmsg is not NULL, it will
1069 * be updated to point to the static buffer, allowing the caller
1070 * to print the error message.
1072 * Return Value
1073 * If a system call fails, -errno is returned.
1074 * If LIO_WAIT_NONE bit is set, the return value is the return value
1075 * of the system call.
1076 * If the io did not fail, the amount of data written is returned.
1077 * If the size the system call say was written is different
1078 * then what was asked to be written, errmsg is updated for
1079 * this error condition. The return value is still the amount
1080 * the system call says was written.
1082 * (rrl 04/96)
1083 ***********************************************************************/
1085 lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd)
1086 int fd; /* open file descriptor */
1087 int method; /* contains io type and wait method bitmask */
1088 char *buffer; /* pointer to buffer */
1089 int size; /* the size of the io */
1090 int sig; /* signal to use if async io */
1091 char **errmsg; /* char pointer that will be updated to point to err message */
1092 long wrd; /* to allow future features, use zero for now */
1094 int ret = 0; /* syscall return or used to get random method */
1095 char *io_type; /* Holds string of type of io */
1096 int listio_cmd; /* Holds the listio/lio_listio cmd */
1097 int omethod = method;
1098 #ifdef CRAY
1099 struct listreq request; /* Used when a listio is wanted */
1100 struct iosw status, *statptr[1];
1101 #else
1102 /* for linux or sgi */
1103 struct iovec iov; /* iovec for readv(2) */
1104 #endif
1105 #ifdef sgi
1106 aiocb_t aiocbp; /* POSIX aio control block */
1107 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1108 off64_t poffset; /* pread(2) offset */
1109 #endif
1110 #if defined (__linux__) && !defined(__UCLIBC__)
1111 struct aiocb aiocbp; /* POSIX aio control block */
1112 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
1113 off64_t poffset; /* pread(2) offset */
1114 #endif
1117 * If LIO_RANDOM bit specified, get new method randomly.
1119 if ( method & LIO_RANDOM ) {
1120 if( Debug_level > 3 )
1121 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
1122 method = lio_random_methods(method);
1123 if ( Debug_level > 2 )
1124 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
1127 if ( errmsg != NULL )
1128 *errmsg = Errormsg;
1130 Rec_signal=Received_signal; /* get the current number of signals received */
1131 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1132 Rec_callback=Received_callback; /* get the current number of callbacks received */
1133 #endif
1135 #ifdef CRAY
1136 memset(&status, 0x00, sizeof(struct iosw));
1137 memset(&request, 0x00, sizeof(struct listreq));
1138 statptr[0] = &status;
1139 #else
1140 /* for linux or sgi */
1141 memset(&iov, 0x00, sizeof(struct iovec));
1142 iov.iov_base = buffer;
1143 iov.iov_len = size;
1144 #endif
1145 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1146 #if defined(sgi)
1147 memset(&aiocbp, 0x00, sizeof(aiocb_t));
1148 #else
1149 memset(&aiocbp, 0x00, sizeof(struct aiocb));
1150 #endif
1151 aiocbp.aio_fildes = fd;
1152 aiocbp.aio_nbytes = size;
1153 aiocbp.aio_buf = buffer;
1154 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1155 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1156 aiocbp.aio_sigevent.sigev_signo = 0;
1157 #ifdef sgi
1158 aiocbp.aio_sigevent.sigev_func = NULL;
1159 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1160 #elif defined(__linux__) && !defined(__UCLIBC__)
1161 aiocbp.aio_sigevent.sigev_notify_function = NULL;
1162 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1163 #endif
1164 aiolist[0] = &aiocbp;
1166 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
1167 ret = 0;
1168 /* If there is an error and it is not ESPIPE then kick out the error.
1169 * If the fd is a fifo then we have to make sure that
1170 * lio_random_methods() didn't select pwrite/pread; if it did then
1171 * switch to write/read.
1173 if( errno == ESPIPE ){
1174 if( method & LIO_IO_SYNCP ){
1175 if( omethod & LIO_RANDOM ){
1176 method &= ~LIO_IO_SYNCP;
1177 method |= LIO_IO_SYNC;
1178 if( Debug_level > 2 )
1179 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
1181 else if( Debug_level ){
1182 printf("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1183 __FILE__, __LINE__ );
1186 /* else: let it ride */
1188 else{
1189 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1190 __FILE__, __LINE__, fd, errno, strerror(errno));
1191 return -errno;
1194 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1195 poffset = (off64_t)ret;
1196 #endif
1197 aiocbp.aio_offset = ret;
1199 #endif
1202 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1203 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1204 * Otherwise there is not necessarily a signal handler to trap
1205 * the signal.
1207 if ( sig && !(method & LIO_USE_SIGNAL) &&
1208 ! (method & LIO_WAIT_SIGTYPES) ){
1210 sig=0; /* ignore signal parameter */
1213 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1214 if ( sig && (method & LIO_WAIT_CBTYPES) )
1215 sig=0; /* ignore signal parameter */
1216 #endif
1219 * only setup signal hander if sig was specified and
1220 * a sig wait method was specified.
1221 * Doing this will change the handler for this signal. The
1222 * old signal handler will not be restored.
1223 *** restoring the signal handler could be added ***
1226 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
1227 #ifdef CRAY
1228 sigctl(SCTL_REG, sig, lio_async_signal_handler);
1229 #endif
1230 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1231 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1232 aiocbp.aio_sigevent.sigev_signo = sig;
1233 sigset(sig, lio_async_signal_handler);
1234 #endif /* CRAY */
1236 #if defined(sgi)
1237 else if( method & LIO_WAIT_CBTYPES ){
1238 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1239 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1240 /* sival_int just has to be something that I can use
1241 * to identify the callback, and "size" happens to be handy...
1243 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1245 #endif
1246 #if defined(__linux__) && !defined(__UCLIBC__)
1247 else if( method & LIO_WAIT_CBTYPES ){
1248 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
1249 aiocbp.aio_sigevent.sigev_notify_function = lio_async_callback_handler;
1250 /* sival_int just has to be something that I can use
1251 * to identify the callback, and "size" happens to be handy...
1253 aiocbp.aio_sigevent.sigev_notify_attributes = (void*)(uintptr_t)size;
1255 #endif
1258 * Determine the system call that will be called and produce
1259 * the string of the system call and place it in Lio_SysCall.
1260 * Also update the io_type char pointer to give brief description
1261 * of system call. Execute the system call and check for
1262 * system call failure. If sync i/o, return the number of
1263 * bytes written/read.
1266 if ( (method & LIO_IO_SYNC) || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0 ){
1268 * read(2) is used if LIO_IO_SYNC bit is set or not none
1269 * of the LIO_IO_TYPES bits are set (default).
1272 sprintf(Lio_SysCall,
1273 "read(%d, buf, %d)", fd, size);
1274 io_type="read";
1276 if ( Debug_level ) {
1277 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1280 while(1) {
1281 if (((ret = read(fd, buffer, size)) == -1) && errno!=EINTR && errno!=EAGAIN) {
1282 sprintf(Errormsg, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1283 __FILE__, __LINE__,
1284 fd, size, errno, strerror(errno));
1285 return -errno;
1288 if(ret==0) return 0;
1289 if(ret!=-1) {
1290 if ( ret != size ) {
1291 sprintf(Errormsg,
1292 "%s/%d read(%d, buf, %d) returned=%d",
1293 __FILE__, __LINE__,
1294 fd, size, ret);
1295 size-=ret;
1296 buffer+=ret;
1298 else {
1299 if ( Debug_level > 1 )
1300 printf("DEBUG %s/%d: read completed without error (ret %d)\n",
1301 __FILE__, __LINE__, ret);
1303 return ret;
1306 wait4sync_io(fd, 1);
1311 else if ( method & LIO_IO_ASYNC ) {
1312 #ifdef CRAY
1313 sprintf(Lio_SysCall,
1314 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1315 io_type="reada";
1317 if ( Debug_level ) {
1318 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1321 sigoff();
1322 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1323 sprintf(Errormsg,
1324 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1325 __FILE__, __LINE__,
1326 fd, size, sig, errno, strerror(errno));
1327 sigon();
1328 return -errno;
1330 #endif
1331 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1332 sprintf(Lio_SysCall,
1333 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
1334 io_type="aio_read";
1336 if ( Debug_level ) {
1337 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1340 if( sig )
1341 sighold( sig );
1342 if ((ret = aio_read(&aiocbp)) == -1) {
1343 sprintf(Errormsg,
1344 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1345 __FILE__, __LINE__,
1346 fd, size, sig, errno, strerror(errno));
1347 if( sig )
1348 sigrelse( sig );
1349 return -errno;
1351 #endif
1352 } /* LIO_IO_ASYNC */
1354 else if ( method & LIO_IO_SLISTIO ) {
1355 #ifdef CRAY
1356 request.li_opcode = LO_READ;
1357 request.li_fildes = fd;
1358 request.li_buf = buffer;
1359 request.li_nbyte = size;
1360 request.li_status = &status;
1361 request.li_signo = sig;
1362 request.li_nstride = 0;
1363 request.li_filstride = 0;
1364 request.li_memstride = 0;
1366 listio_cmd=LC_WAIT;
1367 io_type="listio(2) sync read";
1369 sprintf(Lio_SysCall,
1370 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1371 fd, size);
1373 if ( Debug_level ) {
1374 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1377 sigoff();
1378 if ( listio(listio_cmd, &request, 1) == -1 ) {
1379 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1380 __FILE__, __LINE__,
1381 Lio_SysCall, fd, size, errno, strerror(errno));
1382 sigon();
1383 return -errno;
1386 if ( Debug_level > 1 )
1387 printf("DEBUG %s/%d: %s did not return -1\n",
1388 __FILE__, __LINE__, Lio_SysCall);
1390 ret=lio_check_asyncio(io_type, size, &status);
1391 return ret;
1392 #endif
1393 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1394 aiocbp.aio_lio_opcode = LIO_READ;
1395 listio_cmd=LIO_WAIT;
1396 io_type="lio_listio(3) sync read";
1398 sprintf(Lio_SysCall,
1399 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1400 fd, size);
1402 if ( Debug_level ) {
1403 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1406 if( sig )
1407 sighold( sig );
1408 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1409 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1410 __FILE__, __LINE__,
1411 Lio_SysCall, fd, size, errno, strerror(errno));
1412 if( sig )
1413 sigrelse( sig );
1414 return -errno;
1417 if ( Debug_level > 1 )
1418 printf("DEBUG %s/%d: %s did not return -1\n",
1419 __FILE__, __LINE__, Lio_SysCall);
1421 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1422 return ret;
1423 #endif
1424 }/* LIO_IO_SLISTIO */
1426 else if ( method & LIO_IO_ALISTIO ) {
1427 #ifdef CRAY
1428 request.li_opcode = LO_READ;
1429 request.li_fildes = fd;
1430 request.li_buf = buffer;
1431 request.li_nbyte = size;
1432 request.li_status = &status;
1433 request.li_signo = sig;
1434 request.li_nstride = 0;
1435 request.li_filstride = 0;
1436 request.li_memstride = 0;
1438 listio_cmd=LC_START;
1439 io_type="listio(2) async read";
1441 sprintf(Lio_SysCall,
1442 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1443 fd, size);
1445 if ( Debug_level ) {
1446 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1449 sigoff();
1450 if ( listio(listio_cmd, &request, 1) == -1 ) {
1451 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1452 __FILE__, __LINE__,
1453 Lio_SysCall, fd, size, errno, strerror(errno));
1454 sigon();
1455 return -errno;
1457 #endif
1458 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1459 aiocbp.aio_lio_opcode = LIO_READ;
1460 listio_cmd=LIO_NOWAIT;
1461 io_type="lio_listio(3) async read";
1463 sprintf(Lio_SysCall,
1464 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1465 fd, size);
1467 if ( Debug_level ) {
1468 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1471 if( sig )
1472 sighold( sig );
1473 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1474 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1475 __FILE__, __LINE__,
1476 Lio_SysCall, fd, size, errno, strerror(errno));
1477 if( sig )
1478 sigrelse( sig );
1479 return -errno;
1481 #endif
1482 } /* LIO_IO_ALISTIO */
1484 #ifndef CRAY
1485 else if ( method & LIO_IO_SYNCV ) {
1486 io_type="readv(2)";
1488 sprintf(Lio_SysCall,
1489 "readv(%d, &iov, 1) nbyte:%d", fd, size);
1491 if ( Debug_level ) {
1492 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1494 if ((ret = readv(fd, &iov, 1)) == -1) {
1495 sprintf(Errormsg, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1496 __FILE__, __LINE__,
1497 fd, size, errno, strerror(errno));
1498 return -errno;
1501 if ( ret != size ) {
1502 sprintf(Errormsg,
1503 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1504 __FILE__, __LINE__,
1505 fd, size, ret);
1507 else if ( Debug_level > 1 )
1508 printf("DEBUG %s/%d: readv completed without error (ret %d)\n",
1509 __FILE__, __LINE__, ret);
1511 return ret;
1512 } /* LIO_IO_SYNCV */
1513 #endif
1515 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1516 else if ( method & LIO_IO_SYNCP ) {
1517 io_type="pread(2)";
1519 sprintf(Lio_SysCall,
1520 "pread(%d, buf, %d, %lld)", fd, size, (long long)poffset);
1522 if ( Debug_level ) {
1523 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1525 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1526 sprintf(Errormsg, "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1527 __FILE__, __LINE__,
1528 fd, size, (long long)poffset, errno, strerror(errno));
1529 return -errno;
1532 if ( ret != size ) {
1533 sprintf(Errormsg,
1534 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1535 __FILE__, __LINE__,
1536 fd, size, (long long)poffset, ret);
1538 else if ( Debug_level > 1 )
1539 printf("DEBUG %s/%d: pread completed without error (ret %d)\n",
1540 __FILE__, __LINE__, ret);
1542 return ret;
1543 } /* LIO_IO_SYNCP */
1544 #endif
1546 else {
1547 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
1548 return -1;
1552 * wait for async io to complete.
1553 * Note: Sync io should have returned prior to getting here.
1555 #ifdef CRAY
1556 ret=lio_wait4asyncio(method, fd, statptr);
1557 #endif
1558 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1559 ret=lio_wait4asyncio(method, fd, &aiocbp);
1560 #endif
1563 * If there was an error waiting for async i/o to complete,
1564 * return the error value (errno) to the caller.
1565 * Note: Errormsg should already have been updated.
1567 if ( ret < 0 ) {
1568 return ret;
1572 * If i/o was not waited for (may not have been completed at this time),
1573 * return the size that was requested.
1575 if ( ret == 1 )
1576 return size;
1579 * check that async io was successful.
1580 * Note: if the there was an system call failure, -errno
1581 * was returned and Errormsg should already have been updated.
1582 * If amount i/o was different than size, Errormsg should already
1583 * have been updated but the actual i/o size if returned.
1586 #ifdef CRAY
1587 ret=lio_check_asyncio(io_type, size, &status);
1588 #endif
1589 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1590 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1591 #endif
1593 return ret;
1594 } /* end of lio_read_buffer */
1597 #if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
1598 /***********************************************************************
1599 * This function will check that async io was successful.
1600 * It can also be used to check sync listio since it uses the
1601 * same method.
1603 * Return Values
1604 * If status.sw_error is set, -status.sw_error is returned.
1605 * Otherwise sw_count's field value is returned.
1607 * (rrl 04/96)
1608 ***********************************************************************/
1609 #ifdef CRAY
1610 int lio_check_asyncio(char *io_type, int size, struct iosw *status)
1611 #elif defined(sgi)
1612 int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
1613 #elif defined(__linux__) && !defined(__UCLIBC__)
1614 int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
1616 int ret;
1618 #ifdef CRAY
1619 if ( status->sw_error ) {
1620 sprintf(Errormsg,
1621 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1622 __FILE__, __LINE__, io_type,
1623 status->sw_error, strerror(status->sw_error), status->sw_count);
1624 return -status->sw_error;
1626 else if ( status->sw_count != size ) {
1627 sprintf(Errormsg,
1628 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1629 __FILE__, __LINE__, io_type,
1630 size, status->sw_count);
1632 else if ( Debug_level > 1 ) {
1633 printf("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1634 __FILE__, __LINE__, io_type, status->sw_count);
1637 return status->sw_count;
1639 #else
1641 int cnt = 1;
1643 /* The I/O may have been synchronous with signal completion. It doesn't
1644 * make sense, but the combination could be generated. Release the
1645 * completion signal here otherwise it'll hang around and bite us
1646 * later.
1648 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1649 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1651 ret = aio_error( aiocbp );
1653 while( ret == EINPROGRESS ){
1654 ret = aio_error( aiocbp );
1655 ++cnt;
1657 if( cnt > 1 ){
1658 sprintf(Errormsg,
1659 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1660 __FILE__, __LINE__, io_type, cnt, method,
1661 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1662 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1663 #ifdef SIGEV_CALLBACK
1664 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1665 #endif
1666 aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" :
1667 "unknown") );
1668 return -ret;
1671 if( ret != 0 ){
1672 sprintf(Errormsg,
1673 "%s/%d %s, aio_error = %d %s; random method %#o",
1674 __FILE__, __LINE__, io_type,
1675 ret, strerror(ret),
1676 method );
1677 return -ret;
1679 ret = aio_return( aiocbp );
1680 if( ret != size ){
1681 sprintf(Errormsg,
1682 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1683 __FILE__, __LINE__, io_type,
1684 size, ret);
1686 #ifdef BUG1_workaround
1687 if( ret == 0 ){
1688 ret = size;
1689 if( Debug_level > 1 ){
1690 printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1691 __FILE__, __LINE__, io_type, ret);
1694 #endif /* BUG1_workaround */
1697 else if( Debug_level > 1 ){
1698 printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1699 __FILE__, __LINE__, io_type, ret);
1702 return ret;
1704 #endif
1705 } /* end of lio_check_asyncio */
1706 #endif
1708 /***********************************************************************
1710 * This function will wait for async io to complete.
1711 * If multiple wait methods are specified, the order is predetermined
1712 * to LIO_WAIT_RECALL,
1713 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1714 * then LIO_WAIT_NONE.
1716 * If no wait method was specified the default wait method is: recall(2)
1717 * or aio_suspend(3), as appropriate.
1719 * Return Values
1720 * <0: errno of failed recall
1721 * 0 : async io was completed
1722 * 1 : async was not waited for, io may not have completed.
1724 * (rrl 04/96)
1725 ***********************************************************************/
1726 #ifdef CRAY
1727 int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1728 #elif defined(sgi)
1729 int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
1730 #elif defined(__linux__) && !defined(__UCLIBC__)
1731 int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
1733 int cnt;
1734 #ifdef sgi
1735 int ret;
1736 const aiocb_t *aioary[1];
1737 #endif
1738 #if defined(__linux__)&& !defined(__UCLIBC__)
1739 int ret;
1740 const struct aiocb *aioary[1];
1741 #endif
1743 if ( (method & LIO_WAIT_RECALL)
1744 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1745 || (method & LIO_WAIT_CBSUSPEND)
1746 || (method & LIO_WAIT_SIGSUSPEND)
1747 #endif
1748 || ((method & LIO_WAIT_TYPES) == 0) ){
1750 * If method has LIO_WAIT_RECALL bit set or method does
1751 * not have any wait method bits set (default), use recall/aio_suspend.
1753 #ifdef CRAY
1754 if ( Debug_level > 2 )
1755 printf("DEBUG %s/%d: wait method : recall\n", __FILE__, __LINE__);
1756 sigon();
1757 if ( recall(fd, 1, statptr) ) {
1758 sprintf(Errormsg, "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1759 __FILE__, __LINE__,
1760 fd, errno, strerror(errno));
1761 return -errno;
1763 #else
1764 if ( Debug_level > 2 )
1765 printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__, __LINE__,
1766 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1767 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1768 #ifdef SIGEV_CALLBACK
1769 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1770 #endif
1771 aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" :
1772 "unknown") );
1774 aioary[0] = aiocbp;
1775 ret = aio_suspend( aioary, 1, NULL );
1776 if( (ret == -1) && (errno == EINTR) ){
1777 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ){
1778 if( Debug_level > 2 ){
1779 printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1780 __FILE__, __LINE__ );
1783 else {
1784 sprintf(Errormsg, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1785 __FILE__, __LINE__,
1786 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1787 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1788 #ifdef SIGEV_CALLBACK
1789 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1790 #endif
1791 aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD ? "thread" :
1792 "unknown") );
1793 return -errno;
1796 else if ( ret ) {
1797 sprintf(Errormsg, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1798 __FILE__, __LINE__,
1799 fd, errno, strerror(errno));
1800 return -errno;
1802 #endif
1804 } else if ( method & LIO_WAIT_ACTIVE ) {
1805 if ( Debug_level > 2 )
1806 printf("DEBUG %s/%d: wait method : active\n", __FILE__, __LINE__);
1807 #ifdef CRAY
1808 sigon();
1810 * loop until sw_flag, sw_count or sw_error field elements
1811 * change to non-zero.
1813 cnt=0;
1814 while ( (*statptr)->sw_flag == 0 &&
1815 (*statptr)->sw_count == 0 &&
1816 (*statptr)->sw_error == 0 ) {
1817 cnt++;
1819 #else
1820 /* loop while aio_error() returns EINPROGRESS */
1821 cnt=0;
1822 while(1){
1823 ret = aio_error( aiocbp );
1824 if( (ret == 0) || (ret != EINPROGRESS) ){
1825 break;
1827 ++cnt;
1830 #endif
1831 if ( Debug_level > 5 && cnt && (cnt % 50) == 0 )
1832 printf("DEBUG %s/%d: wait active cnt = %d\n",
1833 __FILE__, __LINE__, cnt);
1835 } else if ( method & LIO_WAIT_SIGPAUSE ) {
1836 if ( Debug_level > 2 )
1837 printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__, __LINE__);
1838 #ifdef sgi
1839 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1840 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1841 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1842 else {
1843 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1844 return -1;
1846 #endif
1847 pause();
1849 } else if ( method & LIO_WAIT_SIGACTIVE ) {
1850 if ( Debug_level > 2 )
1851 printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__, __LINE__);
1852 #ifdef CRAY
1853 sigon();
1854 #else
1855 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1856 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1857 else {
1858 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1859 return -1;
1861 #endif
1862 /* loop waiting for signal */
1863 while ( Received_signal == Rec_signal ){
1864 #ifdef CRAY
1865 sigon();
1866 #else
1867 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1868 #endif
1871 } else if ( method & LIO_WAIT_NONE ) {
1872 if ( Debug_level > 2 )
1873 printf("DEBUG %s/%d: wait method : none\n", __FILE__, __LINE__);
1874 /* It's broken because the aiocb/iosw is an automatic variable in
1875 * lio_{read,write}_buffer, so when the function returns and the
1876 * I/O completes there will be nowhere to write the I/O status.
1877 * It doesn't cause a problem on unicos--probably because of some
1878 * compiler quirk, or an accident. It causes POSIX async I/O
1879 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1881 sprintf(Errormsg, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1882 __FILE__, __LINE__ );
1883 #ifdef CRAY
1884 sigon();
1885 #endif
1886 /* return 1;*/
1887 return -1;
1889 else {
1890 if( Debug_level > 2 )
1891 printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__, __LINE__ );
1892 return -1;
1895 return 0;
1897 } /* end of lio_wait4asyncio */
1899 #endif /* ifndef linux */
1900 #endif
1902 #if UNIT_TEST
1903 /***********************************************************************
1904 * The following code is provided as unit test.
1905 * Just define add "-DUNIT_TEST=1" to the cc line.
1907 * (rrl 04/96)
1908 ***********************************************************************/
1909 struct unit_info_t {
1910 int method;
1911 int sig;
1912 char *str;
1913 } Unit_info[] = {
1914 { LIO_IO_SYNC, 0, "sync io" },
1915 { LIO_IO_SYNCV, 0, "sync readv/writev" },
1916 { LIO_IO_SYNCP, 0, "sync pread/pwrite" },
1917 { LIO_IO_ASYNC, 0, "async io, def wait" },
1918 { LIO_IO_SLISTIO, 0, "sync listio" },
1919 { LIO_IO_ALISTIO, 0, "async listio, def wait" },
1920 { LIO_IO_ASYNC|LIO_WAIT_ACTIVE, 0, "async active" },
1921 { LIO_IO_ASYNC|LIO_WAIT_RECALL, 0, "async recall/suspend" },
1922 { LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause" },
1923 { LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive" },
1924 { LIO_IO_ALISTIO|LIO_WAIT_ACTIVE, 0, "async listio active" },
1925 { LIO_IO_ALISTIO|LIO_WAIT_RECALL, 0, "async listio recall" },
1926 { LIO_IO_ALISTIO|LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive" },
1927 { LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause" },
1928 { LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2" },
1929 { LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2" },
1933 main(argc, argv)
1934 int argc;
1935 char **argv;
1937 extern char *optarg;
1938 extern int optind;
1940 int fd;
1941 char *err;
1942 char buffer[4096];
1943 int size=4096;
1944 int ret;
1945 int ind;
1946 int iter=3;
1947 int method;
1948 int exit_status = 0;
1949 int c;
1950 int i;
1951 char *symbols = NULL;
1952 int die_on_err = 0;
1954 while( (c = getopt(argc,argv,"s:di:")) != -1 ){
1955 switch(c){
1956 case 's': symbols = optarg; break;
1957 case 'd': ++die_on_err; break;
1958 case 'i': iter = atoi(optarg); break;
1962 if ((fd=open("unit_test_file", O_CREAT|O_RDWR|O_TRUNC, 0777)) == -1 ) {
1963 perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
1964 exit(1);
1967 Debug_level=9;
1969 if ( symbols != NULL ) {
1970 if ( (method=lio_parse_io_arg2(symbols, &err)) == -1 ){
1971 printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
1972 symbols, err);
1973 if( die_on_err )
1974 exit(1);
1976 else
1977 printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols, method);
1979 exit_status = 0;
1980 for(ind=0; ind < iter; ind++ ) {
1981 memset( buffer, 'A', 4096 );
1982 if( lseek(fd, 0, 0) == -1 ){
1983 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1984 __LINE__, errno );
1985 ++exit_status;
1987 if ((ret=lio_write_buffer(fd, method, buffer,
1988 size, SIGUSR1, &err, 0)) != size ) {
1989 printf("lio_write_buffer returned -1, err = %s\n", err);
1990 } else
1991 printf("lio_write_buffer returned %d\n", ret);
1993 memset( buffer, 'B', 4096 );
1994 if( lseek(fd, 0, 0) == -1 ){
1995 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1996 __LINE__, errno );
1997 ++exit_status;
1999 if ((ret=lio_read_buffer(fd, method, buffer,
2000 size, SIGUSR2, &err, 0)) != size ) {
2001 printf("lio_read_buffer returned -1, err = %s\n", err);
2002 } else
2003 printf("lio_read_buffer returned %d\n", ret);
2005 for( i = 0; i < 4096; ++i ){
2006 if( buffer[i] != 'A' ){
2007 printf(" buffer[%d] = %d\n", i, buffer[i] );
2008 ++exit_status;
2009 break;
2013 if( exit_status )
2014 exit(exit_status);
2018 unlink("unit_test_file");
2019 exit(0);
2022 for(ind=0; ind < sizeof(Unit_info)/sizeof(struct unit_info_t); ind++ ) {
2024 printf("\n********* write %s ***************\n", Unit_info[ind].str);
2025 if( lseek(fd, 0, 0) == -1 ){
2026 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2027 __LINE__, errno );
2028 ++exit_status;
2031 memset( buffer, 'A', 4096 );
2032 if ((ret=lio_write_buffer(fd, Unit_info[ind].method, buffer,
2033 size, Unit_info[ind].sig, &err, 0)) != size ) {
2034 printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2035 Unit_info[ind].method, size, Unit_info[ind].sig, err);
2036 ++exit_status;
2037 if( die_on_err )
2038 exit(exit_status);
2039 } else{
2040 printf("lio_write_buffer returned %d\n", ret);
2043 printf("\n********* read %s ***************\n", Unit_info[ind].str);
2044 if( lseek(fd, 0, 0) == -1 ){
2045 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2046 __LINE__, errno );
2047 ++exit_status;
2049 memset( buffer, 'B', 4096 );
2050 if ((ret=lio_read_buffer(fd, Unit_info[ind].method, buffer,
2051 size, Unit_info[ind].sig, &err, 0)) != size ) {
2052 printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2053 Unit_info[ind].method, size, Unit_info[ind].sig, err);
2054 ++exit_status;
2055 if( die_on_err )
2056 exit(exit_status);
2057 } else {
2058 printf("lio_read_buffer returned %d\n", ret);
2061 for( i = 0; i < 4096; ++i ){
2062 if( buffer[i] != 'A' ){
2063 printf(" buffer[%d] = %d\n", i, buffer[i] );
2064 ++exit_status;
2065 if( die_on_err )
2066 exit(exit_status);
2067 break;
2071 fflush(stdout);
2072 fflush(stderr);
2073 sleep(1);
2077 unlink("unit_test_file");
2079 exit(exit_status);
2081 #endif