fpos.c revision 302408
1281466Sandrew/* 2281466Sandrew * Copyright (c) 2000-2001, 2004 Proofpoint, Inc. and its suppliers. 3281466Sandrew * All rights reserved. 4281466Sandrew * Copyright (c) 1990, 1993 5281466Sandrew * The Regents of the University of California. All rights reserved. 6281466Sandrew * 7281466Sandrew * This code is derived from software contributed to Berkeley by 8281466Sandrew * Chris Torek. 9281466Sandrew * 10281466Sandrew * By using this file, you agree to the terms and conditions set 11281466Sandrew * forth in the LICENSE file which can be found at the top level of 12281466Sandrew * the sendmail distribution. 13281466Sandrew */ 14281466Sandrew 15281466Sandrew#include <sm/gen.h> 16281466SandrewSM_RCSID("@(#)$Id: fpos.c,v 1.40 2013-11-22 20:51:42 ca Exp $") 17281466Sandrew#include <errno.h> 18281466Sandrew#include <setjmp.h> 19281466Sandrew#include <sm/time.h> 20281466Sandrew#include <sm/heap.h> 21281466Sandrew#include <sm/signal.h> 22281466Sandrew#include <sm/clock.h> 23281466Sandrew#include <sm/io.h> 24281466Sandrew#include <sm/assert.h> 25281466Sandrew#include "local.h" 26281466Sandrew 27281466Sandrewstatic void tellalrm __P((int)); 28281466Sandrewstatic jmp_buf TellTimeOut; 29281466Sandrew 30281466Sandrew/* 31281466Sandrew** TELLALRM -- handler when timeout activated for sm_io_tell() 32281466Sandrew** 33281466Sandrew** Returns flow of control to where setjmp(TellTimeOut) was set. 34281466Sandrew** 35281466Sandrew** Parameters: 36281466Sandrew** sig -- unused 37281466Sandrew** 38281466Sandrew** Returns: 39281466Sandrew** does not return 40281466Sandrew** 41281466Sandrew** Side Effects: 42281466Sandrew** returns flow of control to setjmp(TellTimeOut). 43281466Sandrew** 44281466Sandrew** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 45281466Sandrew** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 46281466Sandrew** DOING. 47281466Sandrew*/ 48281466Sandrew 49281466Sandrew/* ARGSUSED0 */ 50281466Sandrewstatic void 51281466Sandrewtellalrm(sig) 52281466Sandrew int sig; 53281466Sandrew{ 54281466Sandrew longjmp(TellTimeOut, 1); 55281466Sandrew} 56281466Sandrew 57281466Sandrew/* 58281466Sandrew** SM_IO_TELL -- position the file pointer 59281466Sandrew** 60281466Sandrew** Paramters: 61281466Sandrew** fp -- the file pointer to get repositioned 62281466Sandrew** timeout -- time to complete the tell (milliseconds) 63281466Sandrew** 64281466Sandrew** Returns: 65281466Sandrew** Success -- the repositioned location. 66281466Sandrew** Failure -- -1 (minus 1) and sets errno 67281466Sandrew*/ 68281466Sandrew 69281466Sandrewlong 70281466Sandrewsm_io_tell(fp, timeout) 71281466Sandrew register SM_FILE_T *fp; 72281466Sandrew int SM_NONVOLATILE timeout; 73281466Sandrew{ 74281466Sandrew register off_t pos; 75281466Sandrew SM_EVENT *evt = NULL; 76281466Sandrew 77281466Sandrew SM_REQUIRE_ISA(fp, SmFileMagic); 78281466Sandrew if (fp->f_seek == NULL) 79281466Sandrew { 80281466Sandrew errno = ESPIPE; /* historic practice */ 81281466Sandrew return -1L; 82281466Sandrew } 83281466Sandrew 84281466Sandrew if (timeout == SM_TIME_DEFAULT) 85281466Sandrew timeout = fp->f_timeout; 86281466Sandrew if (timeout == SM_TIME_IMMEDIATE) 87281466Sandrew { 88281466Sandrew /* 89281466Sandrew ** Filling the buffer will take time and we are wanted to 90281466Sandrew ** return immediately. So... 91281466Sandrew */ 92281466Sandrew 93281466Sandrew errno = EAGAIN; 94281466Sandrew return -1L; 95281466Sandrew } 96281466Sandrew 97281466Sandrew /* 98281466Sandrew ** Find offset of underlying I/O object, then adjust byte position 99281466Sandrew ** may adjust seek offset on append stream 100281466Sandrew */ 101281466Sandrew 102281466Sandrew (void) sm_flush(fp, (int *) &timeout); 103281466Sandrew 104281466Sandrew /* This is where we start the timeout */ 105283363Sandrew if (timeout != SM_TIME_FOREVER) 106283363Sandrew { 107283363Sandrew if (setjmp(TellTimeOut) != 0) 108283363Sandrew { 109283363Sandrew errno = EAGAIN; 110283363Sandrew return -1L; 111283363Sandrew } 112283363Sandrew 113283363Sandrew evt = sm_seteventm(timeout, tellalrm, 0); 114283363Sandrew } 115283363Sandrew 116283363Sandrew if (fp->f_flags & SMOFF) 117283363Sandrew pos = fp->f_lseekoff; 118283363Sandrew else 119283363Sandrew { 120283363Sandrew /* XXX only set the timeout here? */ 121283363Sandrew pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); 122283363Sandrew if (pos == -1L) 123281466Sandrew goto clean; 124281466Sandrew } 125281466Sandrew if (fp->f_flags & SMRD) 126281466Sandrew { 127281466Sandrew /* 128281466Sandrew ** Reading. Any unread characters (including 129281466Sandrew ** those from ungetc) cause the position to be 130281466Sandrew ** smaller than that in the underlying object. 131281466Sandrew */ 132281466Sandrew 133281466Sandrew pos -= fp->f_r; 134281466Sandrew if (HASUB(fp)) 135281466Sandrew pos -= fp->f_ur; 136281466Sandrew } 137281466Sandrew else if (fp->f_flags & SMWR && fp->f_p != NULL) 138281466Sandrew { 139281466Sandrew /* 140281466Sandrew ** Writing. Any buffered characters cause the 141281466Sandrew ** position to be greater than that in the 142281466Sandrew ** underlying object. 143281466Sandrew */ 144281466Sandrew 145281466Sandrew pos += fp->f_p - fp->f_bf.smb_base; 146281466Sandrew } 147281466Sandrew 148281466Sandrewclean: 149281466Sandrew /* We're back. So undo our timeout and handler */ 150281466Sandrew if (evt != NULL) 151281466Sandrew sm_clrevent(evt); 152281466Sandrew return pos; 153281466Sandrew} 154281466Sandrew