]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/stdio/ftell.c
Add two missing eventhandler.h headers
[FreeBSD/FreeBSD.git] / lib / libc / stdio / ftell.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
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  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #if defined(LIBC_SCCS) && !defined(lint)
36 static char sccsid[] = "@(#)ftell.c     8.2 (Berkeley) 5/4/95";
37 #endif /* LIBC_SCCS and not lint */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include "namespace.h"
42 #include <sys/types.h>
43 #include <errno.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include "un-namespace.h"
47 #include "local.h"
48 #include "libc_private.h"
49
50 /*
51  * standard ftell function.
52  */
53 long
54 ftell(FILE *fp)
55 {
56         off_t rv;
57
58         rv = ftello(fp);
59         if (rv > LONG_MAX) {
60                 errno = EOVERFLOW;
61                 return (-1);
62         }
63         return (rv);
64 }
65
66 /*
67  * ftello: return current offset.
68  */
69 off_t
70 ftello(FILE *fp)
71 {
72         fpos_t rv;
73         int ret;
74
75         FLOCKFILE(fp);
76         ret = _ftello(fp, &rv);
77         FUNLOCKFILE(fp);
78         if (ret)
79                 return (-1);
80         if (rv < 0) {   /* Unspecified value because of ungetc() at 0 */
81                 errno = ESPIPE;
82                 return (-1);
83         }
84         return (rv);
85 }
86
87 int
88 _ftello(FILE *fp, fpos_t *offset)
89 {
90         fpos_t pos;
91         size_t n;
92
93         if (fp->_seek == NULL) {
94                 errno = ESPIPE;                 /* historic practice */
95                 return (1);
96         }
97
98         /*
99          * Find offset of underlying I/O object, then
100          * adjust for buffered bytes.
101          */
102         if (!(fp->_flags & __SRD) && (fp->_flags & __SWR) &&
103             fp->_p != NULL && fp->_p - fp->_bf._base > 0 &&
104             ((fp->_flags & __SAPP) || (fp->_flags2 & __S2OAP))) {
105                 pos = _sseek(fp, (fpos_t)0, SEEK_END);
106                 if (pos == -1)
107                         return (1);
108         } else if (fp->_flags & __SOFF)
109                 pos = fp->_offset;
110         else {
111                 pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
112                 if (pos == -1)
113                         return (1);
114         }
115         if (fp->_flags & __SRD) {
116                 /*
117                  * Reading.  Any unread characters (including
118                  * those from ungetc) cause the position to be
119                  * smaller than that in the underlying object.
120                  */
121                 if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) {
122                         fp->_flags |= __SERR;
123                         errno = EIO;
124                         return (1);
125                 }
126                 if (HASUB(fp))
127                         pos -= fp->_r;  /* Can be negative at this point. */
128         } else if ((fp->_flags & __SWR) && fp->_p != NULL &&
129             (n = fp->_p - fp->_bf._base) > 0) {
130                 /*
131                  * Writing.  Any buffered characters cause the
132                  * position to be greater than that in the
133                  * underlying object.
134                  */
135                 if (pos > OFF_MAX - n) {
136                         errno = EOVERFLOW;
137                         return (1);
138                 }
139                 pos += n;
140         }
141         *offset = pos;
142         return (0);
143 }