Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4874 Rev 4921
Line 99... Line 99...
99
*/
99
*/
Line 100... Line 100...
100
 
100
 
101
#include <_ansi.h>
101
#include <_ansi.h>
102
#include 
102
#include 
103
#include 
-
 
104
#include 
-
 
105
#include 
-
 
106
#include 
-
 
107
#include 
103
#include 
108
#include 
-
 
109
#include 
104
#include 
Line 110... Line -...
110
#include "local.h"
-
 
111
 
-
 
112
#define	POS_ERR	(-(_fpos_t)1)
-
 
113
 
-
 
114
/*
-
 
115
 * Seek the given file to the given offset.
-
 
116
 * `Whence' must be one of the three SEEK_* macros.
-
 
117
 */
105
#include "local.h"
118
 
106
 
119
int
107
int
120
_DEFUN(_fseek_r, (ptr, fp, offset, whence),
108
_DEFUN(_fseek_r, (ptr, fp, offset, whence),
121
       struct _reent *ptr _AND
109
       struct _reent *ptr _AND
122
       register FILE *fp  _AND
110
       register FILE *fp  _AND
123
       long offset        _AND
111
       long offset        _AND
124
       int whence)
-
 
125
{
-
 
126
  _fpos_t _EXFNPTR(seekfn, (struct _reent *, _PTR, _fpos_t, int));
-
 
127
  _fpos_t target;
-
 
128
  _fpos_t curoff = 0;
-
 
129
  size_t n;
-
 
130
#ifdef __USE_INTERNAL_STAT64
-
 
131
  struct stat64 st;
-
 
132
#else
-
 
133
  struct stat st;
-
 
134
#endif
-
 
135
  int havepos;
-
 
136
 
-
 
137
  /* Make sure stdio is set up.  */
-
 
138
 
-
 
139
  CHECK_INIT (ptr, fp);
-
 
140
 
-
 
141
  _flockfile (fp);
-
 
142
 
-
 
143
  /* If we've been doing some writing, and we're in append mode
-
 
144
     then we don't really know where the filepos is.  */
-
 
145
 
-
 
146
  if (fp->_flags & __SAPP && fp->_flags & __SWR)
-
 
147
    {
-
 
148
      /* So flush the buffer and seek to the end.  */
-
 
149
      _fflush_r (ptr, fp);
-
 
150
    }
-
 
151
 
-
 
152
  /* Have to be able to seek.  */
-
 
153
 
-
 
154
  if ((seekfn = fp->_seek) == NULL)
-
 
155
    {
-
 
156
      ptr->_errno = ESPIPE;	/* ??? */
-
 
157
      _funlockfile (fp);
-
 
158
      return EOF;
-
 
159
    }
-
 
160
 
-
 
161
  /*
-
 
162
   * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
-
 
163
   * After this, whence is either SEEK_SET or SEEK_END.
-
 
164
   */
-
 
165
 
-
 
166
  switch (whence)
-
 
167
    {
-
 
168
    case SEEK_CUR:
-
 
169
      /*
-
 
170
       * In order to seek relative to the current stream offset,
-
 
171
       * we have to first find the current stream offset a la
-
 
172
       * ftell (see ftell for details).
-
 
173
       */
-
 
174
      _fflush_r (ptr, fp);   /* may adjust seek offset on append stream */
-
 
175
      if (fp->_flags & __SOFF)
-
 
176
	curoff = fp->_offset;
-
 
177
      else
-
 
178
	{
-
 
179
	  curoff = seekfn (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR);
-
 
180
	  if (curoff == -1L)
-
 
181
	    {
-
 
182
	      _funlockfile (fp);
-
 
183
	      return EOF;
-
 
184
	    }
-
 
185
	}
-
 
186
      if (fp->_flags & __SRD)
-
 
187
	{
-
 
188
	  curoff -= fp->_r;
-
 
189
	  if (HASUB (fp))
-
 
190
	    curoff -= fp->_ur;
-
 
191
	}
-
 
192
      else if (fp->_flags & __SWR && fp->_p != NULL)
-
 
193
	curoff += fp->_p - fp->_bf._base;
-
 
194
 
-
 
195
      offset += curoff;
-
 
196
      whence = SEEK_SET;
-
 
197
      havepos = 1;
-
 
198
      break;
-
 
199
 
-
 
200
    case SEEK_SET:
-
 
201
    case SEEK_END:
-
 
202
      havepos = 0;
-
 
203
      break;
-
 
204
 
-
 
205
    default:
-
 
206
      ptr->_errno = EINVAL;
-
 
207
      _funlockfile (fp);
-
 
208
      return (EOF);
-
 
209
    }
-
 
210
 
-
 
211
  /*
-
 
212
   * Can only optimise if:
-
 
213
   *	reading (and not reading-and-writing);
-
 
214
   *	not unbuffered; and
-
 
215
   *	this is a `regular' Unix file (and hence seekfn==__sseek).
-
 
216
   * We must check __NBF first, because it is possible to have __NBF
-
 
217
   * and __SOPT both set.
-
 
218
   */
-
 
219
 
-
 
220
  if (fp->_bf._base == NULL)
-
 
221
    __smakebuf_r (ptr, fp);
-
 
222
  if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
-
 
223
    goto dumb;
-
 
224
  if ((fp->_flags & __SOPT) == 0)
-
 
225
    {
-
 
226
      if (seekfn != __sseek
-
 
227
	  || fp->_file < 0
-
 
228
#ifdef __USE_INTERNAL_STAT64
-
 
229
	  || _fstat64_r (ptr, fp->_file, &st)
-
 
230
#else
-
 
231
	  || _fstat_r (ptr, fp->_file, &st)
-
 
232
#endif
-
 
233
	  || (st.st_mode & S_IFMT) != S_IFREG)
-
 
234
	{
-
 
235
	  fp->_flags |= __SNPT;
-
 
236
	  goto dumb;
-
 
237
	}
-
 
238
#ifdef	HAVE_BLKSIZE
-
 
239
      fp->_blksize = st.st_blksize;
-
 
240
#else
-
 
241
      fp->_blksize = 1024;
-
 
242
#endif
-
 
243
      fp->_flags |= __SOPT;
-
 
244
    }
-
 
245
 
-
 
246
  /*
-
 
247
   * We are reading; we can try to optimise.
-
 
248
   * Figure out where we are going and where we are now.
-
 
249
   */
-
 
250
 
-
 
251
  if (whence == SEEK_SET)
-
 
252
    target = offset;
-
 
253
  else
-
 
254
    {
-
 
255
#ifdef __USE_INTERNAL_STAT64
-
 
256
      if (_fstat64_r (ptr, fp->_file, &st))
112
       int whence)
257
#else
-
 
258
      if (_fstat_r (ptr, fp->_file, &st))
-
 
259
#endif
-
 
260
	goto dumb;
-
 
261
      target = st.st_size + offset;
-
 
262
    }
-
 
263
  if ((long)target != target)
-
 
264
    {
-
 
265
      ptr->_errno = EOVERFLOW;
-
 
266
      _funlockfile (fp);
-
 
267
      return EOF;
-
 
268
    }
-
 
269
 
-
 
270
  if (!havepos)
-
 
271
    {
-
 
272
      if (fp->_flags & __SOFF)
-
 
273
	curoff = fp->_offset;
-
 
274
      else
-
 
275
	{
-
 
276
	  curoff = seekfn (ptr, fp->_cookie, 0L, SEEK_CUR);
-
 
277
	  if (curoff == POS_ERR)
-
 
278
	    goto dumb;
-
 
279
	}
-
 
280
      curoff -= fp->_r;
-
 
281
      if (HASUB (fp))
-
 
282
	curoff -= fp->_ur;
-
 
283
    }
-
 
284
 
-
 
285
  /*
-
 
286
   * Compute the number of bytes in the input buffer (pretending
-
 
287
   * that any ungetc() input has been discarded).  Adjust current
-
 
288
   * offset backwards by this count so that it represents the
-
 
289
   * file offset for the first byte in the current input buffer.
-
 
290
   */
-
 
291
 
-
 
292
  if (HASUB (fp))
-
 
293
    {
-
 
294
      curoff += fp->_r;       /* kill off ungetc */
-
 
295
      n = fp->_up - fp->_bf._base;
-
 
296
      curoff -= n;
-
 
297
      n += fp->_ur;
-
 
298
    }
-
 
299
  else
-
 
300
    {
-
 
301
      n = fp->_p - fp->_bf._base;
-
 
302
      curoff -= n;
-
 
303
      n += fp->_r;
-
 
304
    }
-
 
305
 
-
 
306
  /*
-
 
307
   * If the target offset is within the current buffer,
-
 
308
   * simply adjust the pointers, clear EOF, undo ungetc(),
-
 
309
   * and return.
-
 
310
   */
-
 
311
 
-
 
312
  if (target >= curoff && target < curoff + n)
-
 
313
    {
-
 
314
      register int o = target - curoff;
-
 
315
 
-
 
316
      fp->_p = fp->_bf._base + o;
-
 
317
      fp->_r = n - o;
-
 
318
      if (HASUB (fp))
-
 
319
	FREEUB (ptr, fp);
-
 
320
      fp->_flags &= ~__SEOF;
-
 
321
      memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
-
 
322
      _funlockfile (fp);
-
 
323
      return 0;
-
 
324
    }
-
 
325
 
-
 
326
  /*
-
 
327
   * The place we want to get to is not within the current buffer,
-
 
328
   * but we can still be kind to the kernel copyout mechanism.
-
 
329
   * By aligning the file offset to a block boundary, we can let
-
 
330
   * the kernel use the VM hardware to map pages instead of
-
 
331
   * copying bytes laboriously.  Using a block boundary also
-
 
332
   * ensures that we only read one block, rather than two.
-
 
333
   */
-
 
334
 
-
 
335
  curoff = target & ~(fp->_blksize - 1);
-
 
336
  if (seekfn (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR)
-
 
337
    goto dumb;
-
 
338
  fp->_r = 0;
-
 
339
  fp->_p = fp->_bf._base;
-
 
340
  if (HASUB (fp))
-
 
341
    FREEUB (ptr, fp);
-
 
342
  fp->_flags &= ~__SEOF;
-
 
343
  n = target - curoff;
-
 
344
  if (n)
-
 
345
    {
-
 
346
      if (__srefill_r (ptr, fp) || fp->_r < n)
-
 
347
	goto dumb;
-
 
348
      fp->_p += n;
-
 
349
      fp->_r -= n;
-
 
350
    }
-
 
351
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
-
 
352
  _funlockfile (fp);
-
 
353
  return 0;
-
 
354
 
-
 
355
  /*
-
 
356
   * We get here if we cannot optimise the seek ... just
-
 
357
   * do it.  Allow the seek function to change fp->_bf._base.
-
 
358
   */
-
 
359
 
-
 
360
dumb:
-
 
361
  if (_fflush_r (ptr, fp)
-
 
362
      || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
-
 
363
    {
-
 
364
      _funlockfile (fp);
-
 
365
      return EOF;
-
 
366
    }
-
 
367
  /* success: clear EOF indicator and discard ungetc() data */
-
 
368
  if (HASUB (fp))
-
 
369
    FREEUB (ptr, fp);
-
 
370
  fp->_p = fp->_bf._base;
-
 
371
  fp->_r = 0;
-
 
372
  /* fp->_w = 0; *//* unnecessary (I think...) */
-
 
373
  fp->_flags &= ~__SEOF;
-
 
374
  /* Reset no-optimization flag after successful seek.  The
-
 
375
     no-optimization flag may be set in the case of a read
-
 
376
     stream that is flushed which by POSIX/SUSv3 standards,
-
 
377
     means that a corresponding seek must not optimize.  The
-
 
378
     optimization is then allowed if no subsequent flush
-
 
379
     is performed.  */
-
 
380
  fp->_flags &= ~__SNPT;
-
 
381
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
-
 
382
  _funlockfile (fp);
113
{
Line 383... Line 114...
383
  return 0;
114
  return _fseeko_r (ptr, fp, offset, whence);
Line 384... Line 115...
384
}
115
}