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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [newlib/] [libc/] [stdio/] [fseek.c] - Blame information for rev 829

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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