/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fread.c,v 1.28 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include "local.h" /* ** SM_IO_READ -- read data from the file pointer ** ** Parameters: ** fp -- file pointer to read from ** timeout -- time to complete the read ** buf -- location to place read data ** size -- size of each chunk of data ** ** Returns: ** Failure: returns 0 (zero) _and_ sets errno ** Success: returns the number of whole chunks read. ** ** A read returning 0 (zero) is only an indication of error when errno ** has been set. */ size_t sm_io_read(fp, timeout, buf, size) SM_FILE_T *fp; int timeout; void *buf; size_t size; { register size_t resid = size; register char *p; register int r; SM_REQUIRE_ISA(fp, SmFileMagic); if (fp->f_read == NULL) { errno = ENODEV; return 0; } /* ** The ANSI standard requires a return value of 0 for a count ** or a size of 0. Peculiarily, it imposes no such requirements ** on fwrite; it only requires read to be broken. */ if (resid == 0) return 0; if (fp->f_r < 0) fp->f_r = 0; p = buf; while ((int) resid > (r = fp->f_r)) { (void) memcpy((void *) p, (void *) fp->f_p, (size_t) r); fp->f_p += r; /* fp->f_r = 0 ... done in sm_refill */ p += r; resid -= r; if ((fp->f_flags & SMNOW) != 0 && r > 0) { /* ** Take whatever we have available. Spend no more time ** trying to get all that has been requested. ** This is needed on some file types (such as ** SASL) that would jam when given extra, untimely ** reads. */ fp->f_r -= r; return size - resid; } if (sm_refill(fp, timeout) != 0) { /* no more input: return partial result */ return size - resid; } } (void) memcpy((void *) p, (void *) fp->f_p, resid); fp->f_r -= resid; fp->f_p += resid; return size; }