/* eread.c -- Copyright 1994, 1996 Liam R. E. Quin. All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. */ /* $Id: eread.c,v 1.4 1996/05/14 16:36:33 lee Exp $ * Error checking version of read(), taken from Liam Quin's * unreleased error handling library and stripped down somewhat. */ #include "globals.h" #include "error.h" #include #include #ifdef HAVE_STRING_H # include #else # include #endif #include #ifdef HAVE_FCNTL_H # ifdef HAVE_SYSV_FCNTL_H # include # endif # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #include "lqutil.h" /* * LQU_Eread * Utilities/Files * * This routine provides an error-checking wrapper around the * read(2) system call. If the underlying read() returns -1, * a diagnostic message is printed using by calling Error at the * given Severity (bitwise or'd with E_SYS if appropriate). * The message includes What, which should be a * short, succinct summary of the purpose of the file, and Name, * which is normally given as the name of the file, but could be * any string. * * the number of bytes read on success, or -1 on an error. * If E_FATAL was given, LQU_Eread does not return after an error. * * nBytesRead = LQU_Eread(E_FATAL, "passwd", "list of users", 0, p, 12); * * *

There are several error flags, such as E_BUG, that include E_FATAL. * See for the current list.

*

The example does not need to check to see whether nBytesRead is * less than 0, since in that case the program would exit. LQU_Eread can, * however, return a number other than ByteCount, just as the underlying * system call read(2) can, and in the same circumstances. The caller * of LQU_Eread should therefore check that the expected number of bytes * were returned.

*
*
*/ API int LQU_Eread(Severity, Name, What, fd, Buffer, ByteCount) int Severity; CONST char *Name; CONST char *What; int fd; char *Buffer; int ByteCount; { int Result; int e; errno = 0; Result = read(fd, Buffer, ByteCount); if (Result >= 0) { return Result; } /* Save errno so we can restore it again after printing an error message, * in case Error() changes it: */ e = errno; if (!Name) { Name = "[null filename]"; Severity |= E_BUG; } if (!What) { What = "[null description]"; Severity |= E_BUG; } if (fd < 0) { Error(Severity|E_BUG, "%s (%s) - LQE_read(): file descriptor %d invalid", Name, What, fd ); errno = e; return -1; } switch (errno) { #ifdef EBADF case EBADF: Error(Severity|E_BUG|E_SYS, "%s (%s): LQE_read: %d is not an open file descriptor", Name, What, fd ); errno = e; return -1; #endif #ifdef EWOULDBLOCK case EWOULDBLOCK: /* BSD style non-blocking I/O -- this isn't an error condition */ return Result; #else /* don't trap both EAGAIN and EWOULDBLOCK, * since they are often the same error number! */ # ifdef EAGAIN case EAGAIN: # ifdef O_NONBLOCK /* POSIX style non-blocking I/O -- this also isn't an error. */ return Result; # else Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): unexpected error (EAGAIN)" Name, What, fd ); errno = e; return Result; # endif # endif #endif #ifdef EBADMSG case EBADMSG: /* say what? this is unlikely at best! */ Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): Stream data corrupted? ", Name, What, fd ); errno = e; return Result; #endif #ifdef EFAULT case EFAULT: Error(Severity|E_SYS|E_BUG, "%s (%s): LQE_read(fd=%d): Buffer (0x%x) outside valid memory", Name, What, fd, Buffer ); errno = e; return Result; #endif #ifdef EINTR case EINTR: Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): system call interrupted by signal", Name, What, fd ); errno = e; return Result; #endif #ifdef EINVAL case EINVAL: Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): file position is negative", Name, What, fd ); errno = e; return Result; #endif #ifdef EIO case EIO: Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): physical I/O error, or attempt\n\ %s: to read from a terminal in a backgrounded process", Name, What, fd, Name ); errno = e; return Result; #endif #ifdef EISDIR case EISDIR: Error(Severity|E_SYS, "%s (%s): LQE_read(fd=%d): Can't read a network-mounted directory", Name, What, fd ); errno = e; return Result; #endif } Error(Severity|E_SYS, "%s (%s) - LQE_read(): couldn't read %d bytes", Name, What, ByteCount ); errno = e; return Result; }