1:
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
33:
34: #include <sys/types.h>
35: #include <sys/stat.h>
36: #include <fcntl.h>
37: #include <stdio.h>
38: #include <stdlib.h>
39: #include <errno.h>
40: #include "local.h"
41:
42: #define POS_ERR (-(fpos_t)1)
43:
44: 45: 46: 47:
48: int
49: fseeko(FILE *fp, off_t offset, int whence)
50: {
51: fpos_t (*seekfn)(void *, fpos_t, int);
52: fpos_t target, curoff;
53: size_t n;
54: struct stat st;
55: int havepos;
56:
57:
58: if (!__sdidinit)
59: __sinit();
60:
61: 62: 63:
64: if ((seekfn = fp->_seek) == NULL || isatty(__sfileno(fp))) {
65: __sseterr(fp, ESPIPE);
66: return (EOF);
67: }
68:
69: 70: 71: 72:
73: FLOCKFILE(fp);
74: switch (whence) {
75:
76: case SEEK_CUR:
77: 78: 79: 80: 81:
82: __sflush(fp);
83: if (fp->_flags & __SOFF)
84: curoff = fp->_offset;
85: else {
86: curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
87: if (curoff == (fpos_t)-1) {
88: FUNLOCKFILE(fp);
89: return (EOF);
90: }
91: }
92: if (fp->_flags & __SRD) {
93: curoff -= fp->_r;
94: if (HASUB(fp))
95: curoff -= fp->_ur;
96: } else if (fp->_flags & __SWR && fp->_p != NULL)
97: curoff += fp->_p - fp->_bf._base;
98:
99: offset += curoff;
100: whence = SEEK_SET;
101: havepos = 1;
102: break;
103:
104: case SEEK_SET:
105: case SEEK_END:
106: curoff = 0;
107: havepos = 0;
108: break;
109:
110: default:
111: FUNLOCKFILE(fp);
112: __sseterr(fp, EINVAL);
113: return (EOF);
114: }
115:
116: 117: 118: 119: 120: 121: 122: 123:
124: if (fp->_bf._base == NULL)
125: __smakebuf(fp);
126: if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
127: goto dumb;
128: if ((fp->_flags & __SOPT) == 0) {
129: if (seekfn != __sseek ||
130: fp->_file < 0 || __libc_fstat(fp->_file, &st) ||
131: (st.st_mode & S_IFMT) != S_IFREG) {
132: fp->_flags |= __SNPT;
133: goto dumb;
134: }
135: fp->_blksize = st.st_blksize;
136: fp->_flags |= __SOPT;
137: }
138:
139: 140: 141: 142:
143: if (whence == SEEK_SET)
144: target = offset;
145: else {
146: if (__libc_fstat(fp->_file, &st))
147: goto dumb;
148: target = st.st_size + offset;
149: }
150:
151: if (!havepos) {
152: if (fp->_flags & __SOFF)
153: curoff = fp->_offset;
154: else {
155: curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
156: if (curoff == POS_ERR)
157: goto dumb;
158: }
159: curoff -= fp->_r;
160: if (HASUB(fp))
161: curoff -= fp->_ur;
162: }
163:
164: 165: 166: 167: 168: 169:
170: if (HASUB(fp)) {
171: curoff += fp->_r;
172: n = fp->_up - fp->_bf._base;
173: curoff -= n;
174: n += fp->_ur;
175: } else {
176: n = fp->_p - fp->_bf._base;
177: curoff -= n;
178: n += fp->_r;
179: }
180:
181: 182: 183: 184: 185: 186:
187: if ((fp->_flags & __SMOD) == 0 &&
188: target >= curoff && target < curoff + n) {
189: int o = target - curoff;
190:
191: fp->_p = fp->_bf._base + o;
192: fp->_r = n - o;
193: if (HASUB(fp))
194: FREEUB(fp);
195: fp->_flags &= ~__SEOF;
196: FUNLOCKFILE(fp);
197: return (0);
198: }
199:
200: 201: 202: 203: 204: 205: 206: 207:
208: curoff = target & ~(fp->_blksize - 1);
209: if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR)
210: goto dumb;
211: fp->_r = 0;
212: fp->_p = fp->_bf._base;
213: if (HASUB(fp))
214: FREEUB(fp);
215: fp->_flags &= ~__SEOF;
216: n = target - curoff;
217: if (n) {
218: if (__srefill(fp) || fp->_r < n)
219: goto dumb;
220: fp->_p += n;
221: fp->_r -= n;
222: }
223: FUNLOCKFILE(fp);
224: return (0);
225:
226: 227: 228: 229:
230: dumb:
231: if (__sflush(fp) ||
232: (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
233: FUNLOCKFILE(fp);
234: return (EOF);
235: }
236:
237: if (HASUB(fp))
238: FREEUB(fp);
239: fp->_p = fp->_bf._base;
240: fp->_r = 0;
241:
242: fp->_flags &= ~__SEOF;
243: FUNLOCKFILE(fp);
244: return (0);
245: }
246:
247: 248: 249:
250: #if defined(__alpha__) && defined(__indr_reference)
251: __indr_reference(fseeko, fseek);
252: #else
253: int
254: fseek(FILE *fp, long offset, int whence)
255: {
256: off_t off = offset;
257:
258: return(fseeko(fp, off, whence));
259: }
260: #endif
261: __weak_alias(fseek64, fseeko);