1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * and/or other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 /*
19 FUNCTION
20 <<ftello64>>---return position in a stream or file
21 
22 INDEX
23 	ftello64
24 INDEX
25 	_ftello64_r
26 
27 SYNOPSIS
28 	#include <stdio.h>
29 	_off64_t ftello64(FILE *<[fp]>);
30 	_off64_t _ftello64_r(struct _reent *<[ptr]>, FILE *<[fp]>);
31 
32 DESCRIPTION
33 Objects of type <<FILE>> can have a ``position'' that records how much
34 of the file your program has already read.  Many of the <<stdio>> functions
35 depend on this position, and many change it as a side effect.
36 
37 The result of <<ftello64>> is the current position for a large file
38 identified by <[fp]>.  If you record this result, you can later
39 use it with <<fseeko64>> to return the file to this
40 position.  The difference between <<ftello>> and <<ftello64>> is that
41 <<ftello>> returns <<off_t>> and <<ftello64>> is designed to work
42 for large files (>2GB) and returns <<_off64_t>>.
43 
44 In the current implementation, <<ftello64>> simply uses a character
45 count to represent the file position; this is the same number that
46 would be recorded by <<fgetpos64>>.
47 
48 The function exists only if the __LARGE64_FILES flag is defined.
49 An error occurs if the <[fp]> was not opened via <<fopen64>>.
50 
51 RETURNS
52 <<ftello64>> returns the file position, if possible.  If it cannot do
53 this, it returns <<-1>>.  Failure occurs on streams that do not support
54 positioning or not opened via <<fopen64>>; the global <<errno>> indicates
55 this condition with the value <<ESPIPE>>.
56 
57 PORTABILITY
58 <<ftello64>> is a glibc extension.
59 
60 No supporting OS subroutines are required.
61 */
62 
63 #if defined(LIBC_SCCS) && !defined(lint)
64 static char sccsid[] = "%W% (Berkeley) %G%";
65 #endif /* LIBC_SCCS and not lint */
66 
67 /*
68  * ftello64: return current offset.
69  */
70 
71 #define _DEFAULT_SOURCE
72 #include <stdio.h>
73 #include <errno.h>
74 #include "../stdio/local.h"
75 
76 #ifdef __LARGE64_FILES
77 
78 _off64_t
ftello64(register FILE * fp)79 ftello64 (
80 	register FILE * fp)
81 {
82   _fpos64_t pos;
83 
84   /* Only do 64-bit tell on large file.  */
85   if (!(fp->_flags & __SL64))
86     return (_off64_t) ftello (fp);
87 
88   /* Ensure stdio is set up.  */
89 
90   CHECK_INIT (ptr, fp);
91 
92   _newlib_flockfile_start(fp);
93 
94   if (fp->_seek64 == NULL)
95     {
96       _REENT_ERRNO(ptr) = ESPIPE;
97       _newlib_flockfile_exit(fp);
98       return (_off64_t) -1;
99     }
100 
101   /* Find offset of underlying I/O object, then adjust for buffered bytes. */
102   if (!(fp->_flags & __SRD) && (fp->_flags & __SWR) &&
103       fp->_p != NULL && fp->_p - fp->_bf._base > 0 &&
104       (fp->_flags & __SAPP))
105     {
106       pos = fp->_seek64 (fp->_cookie, (_fpos64_t) 0, SEEK_END);
107       if (pos == (_fpos64_t) -1)
108 	{
109           _newlib_flockfile_exit (fp);
110           return (_off64_t) -1;
111 	}
112     }
113   else if (fp->_flags & __SOFF)
114     pos = fp->_offset;
115   else
116     {
117       pos = fp->_seek64 (fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
118       if (pos == (_fpos64_t) -1)
119         {
120           _newlib_flockfile_exit(fp);
121           return (_off64_t) pos;
122         }
123     }
124   if (fp->_flags & __SRD)
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       pos -= fp->_r;
132       if (HASUB (fp))
133 	pos -= fp->_ur;
134     }
135   else if (fp->_flags & __SWR && fp->_p != NULL)
136     {
137       /*
138        * Writing.  Any buffered characters cause the
139        * position to be greater than that in the
140        * underlying object.
141        */
142       pos += fp->_p - fp->_bf._base;
143     }
144 
145   _newlib_flockfile_end(fp);
146   return (_off64_t) pos;
147 }
148 
149 #endif /* __LARGE64_FILES */
150