xref: /titanic_44/usr/src/cmd/sendmail/libsm/fseek.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*49218d4fSjbeck SM_RCSID("@(#)$Id: fseek.c,v 1.47 2005/06/14 23:07:20 ca Exp $")
197c478bd9Sstevel@tonic-gate #include <sys/types.h>
207c478bd9Sstevel@tonic-gate #include <sys/stat.h>
217c478bd9Sstevel@tonic-gate #include <fcntl.h>
227c478bd9Sstevel@tonic-gate #include <stdlib.h>
237c478bd9Sstevel@tonic-gate #include <errno.h>
247c478bd9Sstevel@tonic-gate #include <setjmp.h>
25*49218d4fSjbeck #include <sm/time.h>
267c478bd9Sstevel@tonic-gate #include <sm/signal.h>
277c478bd9Sstevel@tonic-gate #include <sm/io.h>
287c478bd9Sstevel@tonic-gate #include <sm/assert.h>
297c478bd9Sstevel@tonic-gate #include <sm/clock.h>
307c478bd9Sstevel@tonic-gate #include "local.h"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #define POS_ERR	(-(off_t)1)
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate static void	seekalrm __P((int));
357c478bd9Sstevel@tonic-gate static jmp_buf SeekTimeOut;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate **  SEEKALRM -- handler when timeout activated for sm_io_seek()
397c478bd9Sstevel@tonic-gate **
407c478bd9Sstevel@tonic-gate **  Returns flow of control to where setjmp(SeekTimeOut) was set.
417c478bd9Sstevel@tonic-gate **
427c478bd9Sstevel@tonic-gate **	Parameters:
437c478bd9Sstevel@tonic-gate **		sig -- unused
447c478bd9Sstevel@tonic-gate **
457c478bd9Sstevel@tonic-gate **	Returns:
467c478bd9Sstevel@tonic-gate **		does not return
477c478bd9Sstevel@tonic-gate **
487c478bd9Sstevel@tonic-gate **	Side Effects:
497c478bd9Sstevel@tonic-gate **		returns flow of control to setjmp(SeekTimeOut).
507c478bd9Sstevel@tonic-gate **
517c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
527c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
537c478bd9Sstevel@tonic-gate **		DOING.
547c478bd9Sstevel@tonic-gate */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
577c478bd9Sstevel@tonic-gate static void
seekalrm(sig)587c478bd9Sstevel@tonic-gate seekalrm(sig)
597c478bd9Sstevel@tonic-gate 	int sig;
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	longjmp(SeekTimeOut, 1);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate **  SM_IO_SEEK -- position the file pointer
667c478bd9Sstevel@tonic-gate **
677c478bd9Sstevel@tonic-gate **	Parameters:
687c478bd9Sstevel@tonic-gate **		fp -- the file pointer to be seek'd
697c478bd9Sstevel@tonic-gate **		timeout -- time to complete seek (milliseconds)
707c478bd9Sstevel@tonic-gate **		offset -- seek offset based on 'whence'
717c478bd9Sstevel@tonic-gate **		whence -- indicates where seek is relative from.
727c478bd9Sstevel@tonic-gate **			One of SM_IO_SEEK_{CUR,SET,END}.
737c478bd9Sstevel@tonic-gate **	Returns:
747c478bd9Sstevel@tonic-gate **		Failure: returns -1 (minus 1) and sets errno
757c478bd9Sstevel@tonic-gate **		Success: returns 0 (zero)
767c478bd9Sstevel@tonic-gate */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate int
sm_io_seek(fp,timeout,offset,whence)797c478bd9Sstevel@tonic-gate sm_io_seek(fp, timeout, offset, whence)
807c478bd9Sstevel@tonic-gate 	register SM_FILE_T *fp;
817c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE timeout;
827c478bd9Sstevel@tonic-gate 	long SM_NONVOLATILE offset;
837c478bd9Sstevel@tonic-gate 	int SM_NONVOLATILE whence;
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	bool havepos;
867c478bd9Sstevel@tonic-gate 	off_t target, curoff;
877c478bd9Sstevel@tonic-gate 	size_t n;
887c478bd9Sstevel@tonic-gate 	struct stat st;
897c478bd9Sstevel@tonic-gate 	int ret;
907c478bd9Sstevel@tonic-gate 	SM_EVENT *evt = NULL;
917c478bd9Sstevel@tonic-gate 	register off_t (*seekfn) __P((SM_FILE_T *, off_t, int));
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	SM_REQUIRE_ISA(fp, SmFileMagic);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/* make sure stdio is set up */
967c478bd9Sstevel@tonic-gate 	if (!Sm_IO_DidInit)
977c478bd9Sstevel@tonic-gate 		sm_init();
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	/* Have to be able to seek. */
1007c478bd9Sstevel@tonic-gate 	if ((seekfn = fp->f_seek) == NULL)
1017c478bd9Sstevel@tonic-gate 	{
1027c478bd9Sstevel@tonic-gate 		errno = ESPIPE;			/* historic practice */
1037c478bd9Sstevel@tonic-gate 		return -1;
1047c478bd9Sstevel@tonic-gate 	}
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_DEFAULT)
1077c478bd9Sstevel@tonic-gate 		timeout = fp->f_timeout;
1087c478bd9Sstevel@tonic-gate 	if (timeout == SM_TIME_IMMEDIATE)
1097c478bd9Sstevel@tonic-gate 	{
1107c478bd9Sstevel@tonic-gate 		/*
1117c478bd9Sstevel@tonic-gate 		**  Filling the buffer will take time and we are wanted to
1127c478bd9Sstevel@tonic-gate 		**  return immediately. So...
1137c478bd9Sstevel@tonic-gate 		*/
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 		errno = EAGAIN;
1167c478bd9Sstevel@tonic-gate 		return -1;
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #define SM_SET_ALARM()						\
1207c478bd9Sstevel@tonic-gate 	if (timeout != SM_TIME_FOREVER)				\
1217c478bd9Sstevel@tonic-gate 	{							\
1227c478bd9Sstevel@tonic-gate 		if (setjmp(SeekTimeOut) != 0)			\
1237c478bd9Sstevel@tonic-gate 		{						\
1247c478bd9Sstevel@tonic-gate 			errno = EAGAIN;				\
1257c478bd9Sstevel@tonic-gate 			return -1;				\
1267c478bd9Sstevel@tonic-gate 		}						\
1277c478bd9Sstevel@tonic-gate 		evt = sm_seteventm(timeout, seekalrm, 0);	\
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/*
1317c478bd9Sstevel@tonic-gate 	**  Change any SM_IO_SEEK_CUR to SM_IO_SEEK_SET, and check `whence'
1327c478bd9Sstevel@tonic-gate 	**  argument. After this, whence is either SM_IO_SEEK_SET or
1337c478bd9Sstevel@tonic-gate 	**  SM_IO_SEEK_END.
1347c478bd9Sstevel@tonic-gate 	*/
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	switch (whence)
1377c478bd9Sstevel@tonic-gate 	{
1387c478bd9Sstevel@tonic-gate 	  case SM_IO_SEEK_CUR:
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 		/*
1417c478bd9Sstevel@tonic-gate 		**  In order to seek relative to the current stream offset,
1427c478bd9Sstevel@tonic-gate 		**  we have to first find the current stream offset a la
1437c478bd9Sstevel@tonic-gate 		**  ftell (see ftell for details).
1447c478bd9Sstevel@tonic-gate 		*/
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		/* may adjust seek offset on append stream */
1477c478bd9Sstevel@tonic-gate 		sm_flush(fp, (int *) &timeout);
1487c478bd9Sstevel@tonic-gate 		SM_SET_ALARM();
1497c478bd9Sstevel@tonic-gate 		if (fp->f_flags & SMOFF)
1507c478bd9Sstevel@tonic-gate 			curoff = fp->f_lseekoff;
1517c478bd9Sstevel@tonic-gate 		else
1527c478bd9Sstevel@tonic-gate 		{
1537c478bd9Sstevel@tonic-gate 			curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR);
1547c478bd9Sstevel@tonic-gate 			if (curoff == -1L)
1557c478bd9Sstevel@tonic-gate 			{
1567c478bd9Sstevel@tonic-gate 				ret = -1;
1577c478bd9Sstevel@tonic-gate 				goto clean;
1587c478bd9Sstevel@tonic-gate 			}
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 		if (fp->f_flags & SMRD)
1617c478bd9Sstevel@tonic-gate 		{
1627c478bd9Sstevel@tonic-gate 			curoff -= fp->f_r;
1637c478bd9Sstevel@tonic-gate 			if (HASUB(fp))
1647c478bd9Sstevel@tonic-gate 				curoff -= fp->f_ur;
1657c478bd9Sstevel@tonic-gate 		}
1667c478bd9Sstevel@tonic-gate 		else if (fp->f_flags & SMWR && fp->f_p != NULL)
1677c478bd9Sstevel@tonic-gate 			curoff += fp->f_p - fp->f_bf.smb_base;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 		offset += curoff;
1707c478bd9Sstevel@tonic-gate 		whence = SM_IO_SEEK_SET;
1717c478bd9Sstevel@tonic-gate 		havepos = true;
1727c478bd9Sstevel@tonic-gate 		break;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	  case SM_IO_SEEK_SET:
1757c478bd9Sstevel@tonic-gate 	  case SM_IO_SEEK_END:
1767c478bd9Sstevel@tonic-gate 		SM_SET_ALARM();
1777c478bd9Sstevel@tonic-gate 		curoff = 0;		/* XXX just to keep gcc quiet */
1787c478bd9Sstevel@tonic-gate 		havepos = false;
1797c478bd9Sstevel@tonic-gate 		break;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	  default:
1827c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1837c478bd9Sstevel@tonic-gate 		return -1;
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/*
1877c478bd9Sstevel@tonic-gate 	**  Can only optimise if:
1887c478bd9Sstevel@tonic-gate 	**	reading (and not reading-and-writing);
1897c478bd9Sstevel@tonic-gate 	**	not unbuffered; and
1907c478bd9Sstevel@tonic-gate 	**	this is a `regular' Unix file (and hence seekfn==sm_stdseek).
1917c478bd9Sstevel@tonic-gate 	**  We must check SMNBF first, because it is possible to have SMNBF
1927c478bd9Sstevel@tonic-gate 	**  and SMSOPT both set.
1937c478bd9Sstevel@tonic-gate 	*/
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	if (fp->f_bf.smb_base == NULL)
1967c478bd9Sstevel@tonic-gate 		sm_makebuf(fp);
1977c478bd9Sstevel@tonic-gate 	if (fp->f_flags & (SMWR | SMRW | SMNBF | SMNPT))
1987c478bd9Sstevel@tonic-gate 		goto dumb;
1997c478bd9Sstevel@tonic-gate 	if ((fp->f_flags & SMOPT) == 0)
2007c478bd9Sstevel@tonic-gate 	{
2017c478bd9Sstevel@tonic-gate 		if (seekfn != sm_stdseek ||
2027c478bd9Sstevel@tonic-gate 		    fp->f_file < 0 || fstat(fp->f_file, &st) ||
2037c478bd9Sstevel@tonic-gate 		    (st.st_mode & S_IFMT) != S_IFREG)
2047c478bd9Sstevel@tonic-gate 		{
2057c478bd9Sstevel@tonic-gate 			fp->f_flags |= SMNPT;
2067c478bd9Sstevel@tonic-gate 			goto dumb;
2077c478bd9Sstevel@tonic-gate 		}
2087c478bd9Sstevel@tonic-gate 		fp->f_blksize = st.st_blksize;
2097c478bd9Sstevel@tonic-gate 		fp->f_flags |= SMOPT;
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/*
2137c478bd9Sstevel@tonic-gate 	**  We are reading; we can try to optimise.
2147c478bd9Sstevel@tonic-gate 	**  Figure out where we are going and where we are now.
2157c478bd9Sstevel@tonic-gate 	*/
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (whence == SM_IO_SEEK_SET)
2187c478bd9Sstevel@tonic-gate 		target = offset;
2197c478bd9Sstevel@tonic-gate 	else
2207c478bd9Sstevel@tonic-gate 	{
2217c478bd9Sstevel@tonic-gate 		if (fstat(fp->f_file, &st))
2227c478bd9Sstevel@tonic-gate 			goto dumb;
2237c478bd9Sstevel@tonic-gate 		target = st.st_size + offset;
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	if (!havepos)
2277c478bd9Sstevel@tonic-gate 	{
2287c478bd9Sstevel@tonic-gate 		if (fp->f_flags & SMOFF)
2297c478bd9Sstevel@tonic-gate 			curoff = fp->f_lseekoff;
2307c478bd9Sstevel@tonic-gate 		else
2317c478bd9Sstevel@tonic-gate 		{
2327c478bd9Sstevel@tonic-gate 			curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR);
2337c478bd9Sstevel@tonic-gate 			if (curoff == POS_ERR)
2347c478bd9Sstevel@tonic-gate 				goto dumb;
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 		curoff -= fp->f_r;
2377c478bd9Sstevel@tonic-gate 		if (HASUB(fp))
2387c478bd9Sstevel@tonic-gate 			curoff -= fp->f_ur;
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/*
2427c478bd9Sstevel@tonic-gate 	**  Compute the number of bytes in the input buffer (pretending
2437c478bd9Sstevel@tonic-gate 	**  that any ungetc() input has been discarded).  Adjust current
2447c478bd9Sstevel@tonic-gate 	**  offset backwards by this count so that it represents the
2457c478bd9Sstevel@tonic-gate 	**  file offset for the first byte in the current input buffer.
2467c478bd9Sstevel@tonic-gate 	*/
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	if (HASUB(fp))
2497c478bd9Sstevel@tonic-gate 	{
2507c478bd9Sstevel@tonic-gate 		curoff += fp->f_r;	/* kill off ungetc */
2517c478bd9Sstevel@tonic-gate 		n = fp->f_up - fp->f_bf.smb_base;
2527c478bd9Sstevel@tonic-gate 		curoff -= n;
2537c478bd9Sstevel@tonic-gate 		n += fp->f_ur;
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 	else
2567c478bd9Sstevel@tonic-gate 	{
2577c478bd9Sstevel@tonic-gate 		n = fp->f_p - fp->f_bf.smb_base;
2587c478bd9Sstevel@tonic-gate 		curoff -= n;
2597c478bd9Sstevel@tonic-gate 		n += fp->f_r;
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	**  If the target offset is within the current buffer,
2647c478bd9Sstevel@tonic-gate 	**  simply adjust the pointers, clear SMFEOF, undo ungetc(),
2657c478bd9Sstevel@tonic-gate 	**  and return.  (If the buffer was modified, we have to
2667c478bd9Sstevel@tonic-gate 	**  skip this; see getln in fget.c.)
2677c478bd9Sstevel@tonic-gate 	*/
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	if (target >= curoff && target < curoff + (off_t) n)
2707c478bd9Sstevel@tonic-gate 	{
2717c478bd9Sstevel@tonic-gate 		register int o = target - curoff;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		fp->f_p = fp->f_bf.smb_base + o;
2747c478bd9Sstevel@tonic-gate 		fp->f_r = n - o;
2757c478bd9Sstevel@tonic-gate 		if (HASUB(fp))
2767c478bd9Sstevel@tonic-gate 			FREEUB(fp);
2777c478bd9Sstevel@tonic-gate 		fp->f_flags &= ~SMFEOF;
2787c478bd9Sstevel@tonic-gate 		ret = 0;
2797c478bd9Sstevel@tonic-gate 		goto clean;
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	/*
2837c478bd9Sstevel@tonic-gate 	**  The place we want to get to is not within the current buffer,
2847c478bd9Sstevel@tonic-gate 	**  but we can still be kind to the kernel copyout mechanism.
2857c478bd9Sstevel@tonic-gate 	**  By aligning the file offset to a block boundary, we can let
2867c478bd9Sstevel@tonic-gate 	**  the kernel use the VM hardware to map pages instead of
2877c478bd9Sstevel@tonic-gate 	**  copying bytes laboriously.  Using a block boundary also
2887c478bd9Sstevel@tonic-gate 	**  ensures that we only read one block, rather than two.
2897c478bd9Sstevel@tonic-gate 	*/
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	curoff = target & ~(fp->f_blksize - 1);
2927c478bd9Sstevel@tonic-gate 	if ((*seekfn)(fp, curoff, SM_IO_SEEK_SET) == POS_ERR)
2937c478bd9Sstevel@tonic-gate 		goto dumb;
2947c478bd9Sstevel@tonic-gate 	fp->f_r = 0;
2957c478bd9Sstevel@tonic-gate 	fp->f_p = fp->f_bf.smb_base;
2967c478bd9Sstevel@tonic-gate 	if (HASUB(fp))
2977c478bd9Sstevel@tonic-gate 		FREEUB(fp);
2987c478bd9Sstevel@tonic-gate 	fp->f_flags &= ~SMFEOF;
2997c478bd9Sstevel@tonic-gate 	n = target - curoff;
3007c478bd9Sstevel@tonic-gate 	if (n)
3017c478bd9Sstevel@tonic-gate 	{
3027c478bd9Sstevel@tonic-gate 		/* Note: SM_TIME_FOREVER since fn timeout already set */
3037c478bd9Sstevel@tonic-gate 		if (sm_refill(fp, SM_TIME_FOREVER) || fp->f_r < (int) n)
3047c478bd9Sstevel@tonic-gate 			goto dumb;
3057c478bd9Sstevel@tonic-gate 		fp->f_p += n;
3067c478bd9Sstevel@tonic-gate 		fp->f_r -= n;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	ret = 0;
3107c478bd9Sstevel@tonic-gate clean:
3117c478bd9Sstevel@tonic-gate 	/*  We're back. So undo our timeout and handler */
3127c478bd9Sstevel@tonic-gate 	if (evt != NULL)
3137c478bd9Sstevel@tonic-gate 		sm_clrevent(evt);
3147c478bd9Sstevel@tonic-gate 	return ret;
3157c478bd9Sstevel@tonic-gate dumb:
3167c478bd9Sstevel@tonic-gate 	/*
3177c478bd9Sstevel@tonic-gate 	**  We get here if we cannot optimise the seek ... just
3187c478bd9Sstevel@tonic-gate 	**  do it.  Allow the seek function to change fp->f_bf.smb_base.
3197c478bd9Sstevel@tonic-gate 	*/
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	/* Note: SM_TIME_FOREVER since fn timeout already set */
3227c478bd9Sstevel@tonic-gate 	ret = SM_TIME_FOREVER;
3237c478bd9Sstevel@tonic-gate 	if (sm_flush(fp, &ret) != 0 ||
3247c478bd9Sstevel@tonic-gate 	    (*seekfn)(fp, (off_t) offset, whence) == POS_ERR)
3257c478bd9Sstevel@tonic-gate 	{
3267c478bd9Sstevel@tonic-gate 		ret = -1;
3277c478bd9Sstevel@tonic-gate 		goto clean;
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/* success: clear SMFEOF indicator and discard ungetc() data */
3317c478bd9Sstevel@tonic-gate 	if (HASUB(fp))
3327c478bd9Sstevel@tonic-gate 		FREEUB(fp);
3337c478bd9Sstevel@tonic-gate 	fp->f_p = fp->f_bf.smb_base;
3347c478bd9Sstevel@tonic-gate 	fp->f_r = 0;
3357c478bd9Sstevel@tonic-gate 	fp->f_flags &= ~SMFEOF;
3367c478bd9Sstevel@tonic-gate 	ret = 0;
3377c478bd9Sstevel@tonic-gate 	goto clean;
3387c478bd9Sstevel@tonic-gate }
339