fpos.c revision 90792
1/*
2 * Copyright (c) 2000-2001 Sendmail, 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.37 2001/09/11 04:04:48 gshapiro Exp $")
17#include <errno.h>
18#include <setjmp.h>
19#include <sys/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 jmp_buf TellTimeOut;
28
29/*
30**  TELLALRM -- handler when timeout activated for sm_io_tell()
31**
32**  Returns flow of control to where setjmp(TellTimeOut) was set.
33**
34**	Parameters:
35**		sig -- unused
36**
37**	Returns:
38**		does not return
39**
40**	Side Effects:
41**		returns flow of control to setjmp(TellTimeOut).
42**
43**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
44**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
45**		DOING.
46*/
47
48/* ARGSUSED0 */
49static void
50tellalrm(sig)
51	int sig;
52{
53	longjmp(TellTimeOut, 1);
54}
55
56/*
57**  SM_IO_TELL -- position the file pointer
58**
59**	Paramters:
60**		fp -- the file pointer to get repositioned
61**		timeout -- time to complete the tell (milliseconds)
62**
63**	Returns:
64**		Success -- the repositioned location.
65**		Failure -- -1 (minus 1) and sets errno
66*/
67
68long
69sm_io_tell(fp, timeout)
70	register SM_FILE_T *fp;
71	int SM_NONVOLATILE timeout;
72{
73	register off_t pos;
74	SM_EVENT *evt = NULL;
75
76	SM_REQUIRE_ISA(fp, SmFileMagic);
77	if (fp->f_seek == NULL)
78	{
79		errno = ESPIPE;			/* historic practice */
80		return -1L;
81	}
82
83	if (timeout == SM_TIME_DEFAULT)
84		timeout = fp->f_timeout;
85	if (timeout == SM_TIME_IMMEDIATE)
86	{
87		/*
88		**  Filling the buffer will take time and we are wanted to
89		**  return immediately. So...
90		*/
91
92		errno = EAGAIN;
93		return -1L;
94	}
95
96	/*
97	**  Find offset of underlying I/O object, then adjust byte position
98	**  may adjust seek offset on append stream
99	*/
100
101	(void) sm_flush(fp, (int *) &timeout);
102
103	/* This is where we start the timeout */
104	if (timeout != SM_TIME_FOREVER)
105	{
106		if (setjmp(TellTimeOut) != 0)
107		{
108			errno = EAGAIN;
109			return -1L;
110		}
111
112		evt = sm_seteventm(timeout, tellalrm, 0);
113	}
114
115	if (fp->f_flags & SMOFF)
116		pos = fp->f_lseekoff;
117	else
118	{
119		/* XXX only set the timeout here? */
120		pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR);
121		if (pos == -1L)
122			goto clean;
123	}
124	if (fp->f_flags & SMRD)
125	{
126		/*
127		**  Reading.  Any unread characters (including
128		**  those from ungetc) cause the position to be
129		**  smaller than that in the underlying object.
130		*/
131
132		pos -= fp->f_r;
133		if (HASUB(fp))
134			pos -= fp->f_ur;
135	}
136	else if (fp->f_flags & SMWR && fp->f_p != NULL)
137	{
138		/*
139		**  Writing.  Any buffered characters cause the
140		**  position to be greater than that in the
141		**  underlying object.
142		*/
143
144		pos += fp->f_p - fp->f_bf.smb_base;
145	}
146
147clean:
148	/*  We're back. So undo our timeout and handler */
149	if (evt != NULL)
150		sm_clrevent(evt);
151	return pos;
152}
153