1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993 5*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 8*7c478bd9Sstevel@tonic-gate * Chris Torek. 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 11*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 12*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 16*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: fread.c,v 1.26 2001/02/28 20:54:03 ca Exp $") 17*7c478bd9Sstevel@tonic-gate #include <string.h> 18*7c478bd9Sstevel@tonic-gate #include <errno.h> 19*7c478bd9Sstevel@tonic-gate #include <sm/io.h> 20*7c478bd9Sstevel@tonic-gate #include <sm/assert.h> 21*7c478bd9Sstevel@tonic-gate #include "local.h" 22*7c478bd9Sstevel@tonic-gate 23*7c478bd9Sstevel@tonic-gate /* 24*7c478bd9Sstevel@tonic-gate ** SM_IO_READ -- read data from the file pointer 25*7c478bd9Sstevel@tonic-gate ** 26*7c478bd9Sstevel@tonic-gate ** Parameters: 27*7c478bd9Sstevel@tonic-gate ** fp -- file pointer to read from 28*7c478bd9Sstevel@tonic-gate ** timeout -- time to complete the read 29*7c478bd9Sstevel@tonic-gate ** buf -- location to place read data 30*7c478bd9Sstevel@tonic-gate ** size -- size of each chunk of data 31*7c478bd9Sstevel@tonic-gate ** 32*7c478bd9Sstevel@tonic-gate ** Returns: 33*7c478bd9Sstevel@tonic-gate ** Failure: returns 0 (zero) _and_ sets errno 34*7c478bd9Sstevel@tonic-gate ** Success: returns the number of whole chunks read. 35*7c478bd9Sstevel@tonic-gate ** 36*7c478bd9Sstevel@tonic-gate ** A read returning 0 (zero) is only an indication of error when errno 37*7c478bd9Sstevel@tonic-gate ** has been set. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate size_t 41*7c478bd9Sstevel@tonic-gate sm_io_read(fp, timeout, buf, size) 42*7c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 43*7c478bd9Sstevel@tonic-gate int timeout; 44*7c478bd9Sstevel@tonic-gate void *buf; 45*7c478bd9Sstevel@tonic-gate size_t size; 46*7c478bd9Sstevel@tonic-gate { 47*7c478bd9Sstevel@tonic-gate register size_t resid = size; 48*7c478bd9Sstevel@tonic-gate register char *p; 49*7c478bd9Sstevel@tonic-gate register int r; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate SM_REQUIRE_ISA(fp, SmFileMagic); 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate if (fp->f_read == NULL) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate errno = ENODEV; 56*7c478bd9Sstevel@tonic-gate return 0; 57*7c478bd9Sstevel@tonic-gate } 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate ** The ANSI standard requires a return value of 0 for a count 61*7c478bd9Sstevel@tonic-gate ** or a size of 0. Peculiarily, it imposes no such requirements 62*7c478bd9Sstevel@tonic-gate ** on fwrite; it only requires read to be broken. 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate if (resid == 0) 66*7c478bd9Sstevel@tonic-gate return 0; 67*7c478bd9Sstevel@tonic-gate if (fp->f_r < 0) 68*7c478bd9Sstevel@tonic-gate fp->f_r = 0; 69*7c478bd9Sstevel@tonic-gate p = buf; 70*7c478bd9Sstevel@tonic-gate while ((int) resid > (r = fp->f_r)) 71*7c478bd9Sstevel@tonic-gate { 72*7c478bd9Sstevel@tonic-gate (void) memcpy((void *) p, (void *) fp->f_p, (size_t) r); 73*7c478bd9Sstevel@tonic-gate fp->f_p += r; 74*7c478bd9Sstevel@tonic-gate /* fp->f_r = 0 ... done in sm_refill */ 75*7c478bd9Sstevel@tonic-gate p += r; 76*7c478bd9Sstevel@tonic-gate resid -= r; 77*7c478bd9Sstevel@tonic-gate if ((fp->f_flags & SMNOW) != 0 && r > 0) 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate ** Take whatever we have available. Spend no more time 81*7c478bd9Sstevel@tonic-gate ** trying to get all that has been requested. 82*7c478bd9Sstevel@tonic-gate ** This is needed on some file types (such as 83*7c478bd9Sstevel@tonic-gate ** SASL) that would jam when given extra, untimely 84*7c478bd9Sstevel@tonic-gate ** reads. 85*7c478bd9Sstevel@tonic-gate */ 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate fp->f_r -= r; 88*7c478bd9Sstevel@tonic-gate return size - resid; 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate if (sm_refill(fp, timeout) != 0) 91*7c478bd9Sstevel@tonic-gate { 92*7c478bd9Sstevel@tonic-gate /* no more input: return partial result */ 93*7c478bd9Sstevel@tonic-gate return size - resid; 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate (void) memcpy((void *) p, (void *) fp->f_p, resid); 97*7c478bd9Sstevel@tonic-gate fp->f_r -= resid; 98*7c478bd9Sstevel@tonic-gate fp->f_p += resid; 99*7c478bd9Sstevel@tonic-gate return size; 100*7c478bd9Sstevel@tonic-gate } 101