OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [stdio/] [fseek.c] - Blame information for rev 455

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*
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
 * advertising materials, and 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
<<fseek>>, <<fseeko>>---set file position
21
 
22
INDEX
23
        fseek
24
INDEX
25
        fseeko
26
INDEX
27
        _fseek_r
28
INDEX
29
        _fseeko_r
30
 
31
ANSI_SYNOPSIS
32
        #include <stdio.h>
33
        int fseek(FILE *<[fp]>, long <[offset]>, int <[whence]>)
34
        int fseeko(FILE *<[fp]>, off_t <[offset]>, int <[whence]>)
35
        int _fseek_r(struct _reent *<[ptr]>, FILE *<[fp]>,
36
                     long <[offset]>, int <[whence]>)
37
        int _fseeko_r(struct _reent *<[ptr]>, FILE *<[fp]>,
38
                     off_t <[offset]>, int <[whence]>)
39
 
40
TRAD_SYNOPSIS
41
        #include <stdio.h>
42
        int fseek(<[fp]>, <[offset]>, <[whence]>)
43
        FILE *<[fp]>;
44
        long <[offset]>;
45
        int <[whence]>;
46
 
47
        int fseeko(<[fp]>, <[offset]>, <[whence]>)
48
        FILE *<[fp]>;
49
        off_t <[offset]>;
50
        int <[whence]>;
51
 
52
        int _fseek_r(<[ptr]>, <[fp]>, <[offset]>, <[whence]>)
53
        struct _reent *<[ptr]>;
54
        FILE *<[fp]>;
55
        long <[offset]>;
56
        int <[whence]>;
57
 
58
        int _fseeko_r(<[ptr]>, <[fp]>, <[offset]>, <[whence]>)
59
        struct _reent *<[ptr]>;
60
        FILE *<[fp]>;
61
        off_t <[offset]>;
62
        int <[whence]>;
63
 
64
DESCRIPTION
65
Objects of type <<FILE>> can have a ``position'' that records how much
66
of the file your program has already read.  Many of the <<stdio>> functions
67
depend on this position, and many change it as a side effect.
68
 
69
You can use <<fseek>>/<<fseeko>> to set the position for the file identified by
70
<[fp]>.  The value of <[offset]> determines the new position, in one
71
of three ways selected by the value of <[whence]> (defined as macros
72
in `<<stdio.h>>'):
73
 
74
<<SEEK_SET>>---<[offset]> is the absolute file position (an offset
75
from the beginning of the file) desired.  <[offset]> must be positive.
76
 
77
<<SEEK_CUR>>---<[offset]> is relative to the current file position.
78
<[offset]> can meaningfully be either positive or negative.
79
 
80
<<SEEK_END>>---<[offset]> is relative to the current end of file.
81
<[offset]> can meaningfully be either positive (to increase the size
82
of the file) or negative.
83
 
84
See <<ftell>>/<<ftello>> to determine the current file position.
85
 
86
RETURNS
87
<<fseek>>/<<fseeko>> return <<0>> when successful.  On failure, the
88
result is <<EOF>>.  The reason for failure is indicated in <<errno>>:
89
either <<ESPIPE>> (the stream identified by <[fp]> doesn't support
90
repositioning) or <<EINVAL>> (invalid file position).
91
 
92
PORTABILITY
93
ANSI C requires <<fseek>>.
94
 
95
<<fseeko>> is defined by the Single Unix specification.
96
 
97
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
98
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
99
*/
100
 
101
#include <_ansi.h>
102
#include <reent.h>
103
#include <stdio.h>
104
#include <string.h>
105
#include <time.h>
106
#include <fcntl.h>
107
#include <stdlib.h>
108
#include <errno.h>
109
#include <sys/stat.h>
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
 */
118
 
119
int
120
_DEFUN(_fseek_r, (ptr, fp, offset, whence),
121
       struct _reent *ptr _AND
122
       register FILE *fp  _AND
123
       long offset        _AND
124
       int whence)
125
{
126
  _fpos_t _EXFUN((*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))
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
      return EOF;
267
    }
268
 
269
  if (!havepos)
270
    {
271
      if (fp->_flags & __SOFF)
272
        curoff = fp->_offset;
273
      else
274
        {
275
          curoff = seekfn (ptr, fp->_cookie, 0L, SEEK_CUR);
276
          if (curoff == POS_ERR)
277
            goto dumb;
278
        }
279
      curoff -= fp->_r;
280
      if (HASUB (fp))
281
        curoff -= fp->_ur;
282
    }
283
 
284
  /*
285
   * Compute the number of bytes in the input buffer (pretending
286
   * that any ungetc() input has been discarded).  Adjust current
287
   * offset backwards by this count so that it represents the
288
   * file offset for the first byte in the current input buffer.
289
   */
290
 
291
  if (HASUB (fp))
292
    {
293
      curoff += fp->_r;       /* kill off ungetc */
294
      n = fp->_up - fp->_bf._base;
295
      curoff -= n;
296
      n += fp->_ur;
297
    }
298
  else
299
    {
300
      n = fp->_p - fp->_bf._base;
301
      curoff -= n;
302
      n += fp->_r;
303
    }
304
 
305
  /*
306
   * If the target offset is within the current buffer,
307
   * simply adjust the pointers, clear EOF, undo ungetc(),
308
   * and return.
309
   */
310
 
311
  if (target >= curoff && target < curoff + n)
312
    {
313
      register int o = target - curoff;
314
 
315
      fp->_p = fp->_bf._base + o;
316
      fp->_r = n - o;
317
      if (HASUB (fp))
318
        FREEUB (ptr, fp);
319
      fp->_flags &= ~__SEOF;
320
      memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
321
      _funlockfile (fp);
322
      return 0;
323
    }
324
 
325
  /*
326
   * The place we want to get to is not within the current buffer,
327
   * but we can still be kind to the kernel copyout mechanism.
328
   * By aligning the file offset to a block boundary, we can let
329
   * the kernel use the VM hardware to map pages instead of
330
   * copying bytes laboriously.  Using a block boundary also
331
   * ensures that we only read one block, rather than two.
332
   */
333
 
334
  curoff = target & ~(fp->_blksize - 1);
335
  if (seekfn (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR)
336
    goto dumb;
337
  fp->_r = 0;
338
  fp->_p = fp->_bf._base;
339
  if (HASUB (fp))
340
    FREEUB (ptr, fp);
341
  fp->_flags &= ~__SEOF;
342
  n = target - curoff;
343
  if (n)
344
    {
345
      if (__srefill_r (ptr, fp) || fp->_r < n)
346
        goto dumb;
347
      fp->_p += n;
348
      fp->_r -= n;
349
    }
350
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
351
  _funlockfile (fp);
352
  return 0;
353
 
354
  /*
355
   * We get here if we cannot optimise the seek ... just
356
   * do it.  Allow the seek function to change fp->_bf._base.
357
   */
358
 
359
dumb:
360
  if (_fflush_r (ptr, fp)
361
      || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
362
    {
363
      _funlockfile (fp);
364
      return EOF;
365
    }
366
  /* success: clear EOF indicator and discard ungetc() data */
367
  if (HASUB (fp))
368
    FREEUB (ptr, fp);
369
  fp->_p = fp->_bf._base;
370
  fp->_r = 0;
371
  /* fp->_w = 0; *//* unnecessary (I think...) */
372
  fp->_flags &= ~__SEOF;
373
  /* Reset no-optimization flag after successful seek.  The
374
     no-optimization flag may be set in the case of a read
375
     stream that is flushed which by POSIX/SUSv3 standards,
376
     means that a corresponding seek must not optimize.  The
377
     optimization is then allowed if no subsequent flush
378
     is performed.  */
379
  fp->_flags &= ~__SNPT;
380
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
381
  _funlockfile (fp);
382
  return 0;
383
}
384
 
385
#ifndef _REENT_ONLY
386
 
387
int
388
_DEFUN(fseek, (fp, offset, whence),
389
       register FILE *fp _AND
390
       long offset       _AND
391
       int whence)
392
{
393
  return _fseek_r (_REENT, fp, offset, whence);
394
}
395
 
396
#endif /* !_REENT_ONLY */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.