ftell.c revision 82807
1176998Sphk/*-
2176998Sphk * Copyright (c) 1990, 1993
3176998Sphk *	The Regents of the University of California.  All rights reserved.
4176998Sphk *
5176998Sphk * This code is derived from software contributed to Berkeley by
6176998Sphk * Chris Torek.
7176998Sphk *
8176998Sphk * Redistribution and use in source and binary forms, with or without
9176998Sphk * modification, are permitted provided that the following conditions
10176998Sphk * are met:
11176998Sphk * 1. Redistributions of source code must retain the above copyright
12176998Sphk *    notice, this list of conditions and the following disclaimer.
13176998Sphk * 2. Redistributions in binary form must reproduce the above copyright
14176998Sphk *    notice, this list of conditions and the following disclaimer in the
15176998Sphk *    documentation and/or other materials provided with the distribution.
16176998Sphk * 3. All advertising materials mentioning features or use of this software
17176998Sphk *    must display the following acknowledgement:
18176998Sphk *	This product includes software developed by the University of
19176998Sphk *	California, Berkeley and its contributors.
20176998Sphk * 4. Neither the name of the University nor the names of its contributors
21176998Sphk *    may be used to endorse or promote products derived from this software
22176998Sphk *    without specific prior written permission.
23176998Sphk *
24176998Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25176998Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26176998Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27176998Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28176998Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29176998Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30179000Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31179000Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32176998Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33176998Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34176998Sphk * SUCH DAMAGE.
35176998Sphk */
36176998Sphk
37176998Sphk#if defined(LIBC_SCCS) && !defined(lint)
38176998Sphk#if 0
39176998Sphkstatic char sccsid[] = "@(#)ftell.c	8.2 (Berkeley) 5/4/95";
40176998Sphk#endif
41179000Sphkstatic const char rcsid[] =
42179000Sphk  "$FreeBSD: head/lib/libc/stdio/ftell.c 82807 2001-09-02 19:10:10Z ache $";
43179000Sphk#endif /* LIBC_SCCS and not lint */
44179000Sphk
45179000Sphk#include "namespace.h"
46179000Sphk#include <sys/types.h>
47179000Sphk#include <errno.h>
48179000Sphk#include <limits.h>
49176998Sphk#include <stdio.h>
50176998Sphk#include "un-namespace.h"
51176998Sphk#include "local.h"
52176998Sphk#include "libc_private.h"
53176998Sphk
54176998Sphk/*
55176998Sphk * standard ftell function.
56176998Sphk */
57176998Sphklong
58176998Sphkftell(fp)
59176998Sphk	register FILE *fp;
60176998Sphk{
61176998Sphk	register off_t rv;
62176998Sphk
63176998Sphk	rv = ftello(fp);
64176998Sphk	if (rv > LONG_MAX) {
65176998Sphk		errno = EOVERFLOW;
66176998Sphk		return (-1);
67176998Sphk	}
68176998Sphk	return (rv);
69176998Sphk}
70176998Sphk
71176998Sphk/*
72176998Sphk * ftello: return current offset.
73176998Sphk */
74176998Sphkoff_t
75176998Sphkftello(fp)
76179000Sphk	register FILE *fp;
77176998Sphk{
78176998Sphk	fpos_t rv;
79176998Sphk	int ret;
80176998Sphk
81219027Sphk	FLOCKFILE(fp);
82179000Sphk	ret = _ftello(fp, &rv);
83176998Sphk	FUNLOCKFILE(fp);
84176998Sphk	if (ret)
85219027Sphk		return (-1);
86176998Sphk	if (rv < 0) {   /* Unspecified value because of ungetc() at 0 */
87176998Sphk		errno = ESPIPE;
88176998Sphk		return (-1);
89176998Sphk	}
90176998Sphk	return (rv);
91176998Sphk}
92176998Sphk
93176998Sphkint
94176998Sphk_ftello(fp, offset)
95176998Sphk	register FILE *fp;
96176998Sphk	fpos_t *offset;
97176998Sphk{
98176998Sphk	register fpos_t pos;
99176998Sphk	size_t n;
100176998Sphk
101176998Sphk	if (fp->_seek == NULL) {
102176998Sphk		errno = ESPIPE;			/* historic practice */
103176998Sphk		return (1);
104176998Sphk	}
105176998Sphk
106176998Sphk	/*
107176998Sphk	 * Find offset of underlying I/O object, then
108176998Sphk	 * adjust for buffered bytes.
109176998Sphk	 */
110176998Sphk	if (fp->_flags & __SOFF)
111176998Sphk		pos = fp->_offset;
112176998Sphk	else {
113176998Sphk		pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
114176998Sphk		if (pos == -1)
115176998Sphk			return (1);
116	}
117	if (fp->_flags & __SRD) {
118		/*
119		 * Reading.  Any unread characters (including
120		 * those from ungetc) cause the position to be
121		 * smaller than that in the underlying object.
122		 */
123		if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) {
124			fp->_flags |= __SERR;
125			errno = EIO;
126			return (1);
127		}
128		if (HASUB(fp))
129			pos -= fp->_r;  /* Can be negative at this point. */
130	} else if ((fp->_flags & __SWR) && fp->_p != NULL) {
131		/*
132		 * Writing.  Any buffered characters cause the
133		 * position to be greater than that in the
134		 * underlying object.
135		 */
136		n = fp->_p - fp->_bf._base;
137		if (pos > OFF_MAX - n) {
138			errno = EOVERFLOW;
139			return (1);
140		}
141		pos += n;
142	}
143	*offset = pos;
144	return (0);
145}
146