/* * Copyright (c) 2000-2002, 2005 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/generic.h" SM_RCSID("@(#)$Id: fread.c,v 1.18 2006/07/14 14:42:25 ca Exp $") #include "sm/error.h" #include "sm/io.h" #include "sm/assert.h" #include "sm/memops.h" #include "io-int.h" /* ** SM_IO_READ -- read data from the file pointer ** ** Parameters: ** fp -- file pointer to read from ** buf -- location to place read data ** size -- size of each chunk of data ** bytesread -- number of bytes read (output) ** ** Returns: ** usual sm_error code */ sm_ret_T sm_io_read(sm_file_T *fp, uchar *buf, size_t size, ssize_t *bytesread) { size_t ltr; uchar *p; int r; sm_ret_T res; SM_IS_FP(fp); if (f_read(*fp) == NULL) return sm_error_perm(SM_EM_IO, ENODEV); /* ** 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. */ ltr = size; if (ltr == 0) { *bytesread = 0; return SM_SUCCESS; } if (f_r(*fp) < 0) f_r(*fp) = 0; p = buf; while ((int) ltr > (r = f_r(*fp))) { if (r > 0) { (void) sm_memcpy((void *) p, (void *) f_p(*fp), (size_t) r); f_p(*fp) += r; f_r(*fp) = 0; /* same as f_r(*fp) -= r */ p += r; ltr -= r; } /* non blocking and have data? return with that */ /* XXX is this correct? */ if (!sm_io_blocking(fp) && r > 0) { *bytesread = size - ltr; if (*bytesread > 0) return SM_SUCCESS; return sm_error_temp(SM_EM_IO, EAGAIN); } res = sm_refill(fp); if (sm_is_err(res)) { /* no more input: return partial result */ *bytesread = size - ltr; if (*bytesread > 0 && (sm_is_temp_err(res) || res == SM_IO_EOF)) return SM_SUCCESS; return res; } } (void) sm_memcpy((void *) p, (void *) f_p(*fp), ltr); f_r(*fp) -= ltr; f_p(*fp) += ltr; *bytesread = size; return SM_SUCCESS; }