fpos.c revision 261194
1/* 2 * Copyright (c) 2000-2001, 2004 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * By using this file, you agree to the terms and conditions set 11 * forth in the LICENSE file which can be found at the top level of 12 * the sendmail distribution. 13 */ 14 15#include <sm/gen.h> 16SM_RCSID("@(#)$Id: fpos.c,v 1.40 2013/11/22 20:51:42 ca Exp $") 17#include <errno.h> 18#include <setjmp.h> 19#include <sm/time.h> 20#include <sm/heap.h> 21#include <sm/signal.h> 22#include <sm/clock.h> 23#include <sm/io.h> 24#include <sm/assert.h> 25#include "local.h" 26 27static void tellalrm __P((int)); 28static jmp_buf TellTimeOut; 29 30/* 31** TELLALRM -- handler when timeout activated for sm_io_tell() 32** 33** Returns flow of control to where setjmp(TellTimeOut) was set. 34** 35** Parameters: 36** sig -- unused 37** 38** Returns: 39** does not return 40** 41** Side Effects: 42** returns flow of control to setjmp(TellTimeOut). 43** 44** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 45** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 46** DOING. 47*/ 48 49/* ARGSUSED0 */ 50static void 51tellalrm(sig) 52 int sig; 53{ 54 longjmp(TellTimeOut, 1); 55} 56 57/* 58** SM_IO_TELL -- position the file pointer 59** 60** Paramters: 61** fp -- the file pointer to get repositioned 62** timeout -- time to complete the tell (milliseconds) 63** 64** Returns: 65** Success -- the repositioned location. 66** Failure -- -1 (minus 1) and sets errno 67*/ 68 69long 70sm_io_tell(fp, timeout) 71 register SM_FILE_T *fp; 72 int SM_NONVOLATILE timeout; 73{ 74 register off_t pos; 75 SM_EVENT *evt = NULL; 76 77 SM_REQUIRE_ISA(fp, SmFileMagic); 78 if (fp->f_seek == NULL) 79 { 80 errno = ESPIPE; /* historic practice */ 81 return -1L; 82 } 83 84 if (timeout == SM_TIME_DEFAULT) 85 timeout = fp->f_timeout; 86 if (timeout == SM_TIME_IMMEDIATE) 87 { 88 /* 89 ** Filling the buffer will take time and we are wanted to 90 ** return immediately. So... 91 */ 92 93 errno = EAGAIN; 94 return -1L; 95 } 96 97 /* 98 ** Find offset of underlying I/O object, then adjust byte position 99 ** may adjust seek offset on append stream 100 */ 101 102 (void) sm_flush(fp, (int *) &timeout); 103 104 /* This is where we start the timeout */ 105 if (timeout != SM_TIME_FOREVER) 106 { 107 if (setjmp(TellTimeOut) != 0) 108 { 109 errno = EAGAIN; 110 return -1L; 111 } 112 113 evt = sm_seteventm(timeout, tellalrm, 0); 114 } 115 116 if (fp->f_flags & SMOFF) 117 pos = fp->f_lseekoff; 118 else 119 { 120 /* XXX only set the timeout here? */ 121 pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); 122 if (pos == -1L) 123 goto clean; 124 } 125 if (fp->f_flags & SMRD) 126 { 127 /* 128 ** Reading. Any unread characters (including 129 ** those from ungetc) cause the position to be 130 ** smaller than that in the underlying object. 131 */ 132 133 pos -= fp->f_r; 134 if (HASUB(fp)) 135 pos -= fp->f_ur; 136 } 137 else if (fp->f_flags & SMWR && fp->f_p != NULL) 138 { 139 /* 140 ** Writing. Any buffered characters cause the 141 ** position to be greater than that in the 142 ** underlying object. 143 */ 144 145 pos += fp->f_p - fp->f_bf.smb_base; 146 } 147 148clean: 149 /* We're back. So undo our timeout and handler */ 150 if (evt != NULL) 151 sm_clrevent(evt); 152 return pos; 153} 154