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