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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-newlib/] [newlib-1.17.0/] [newlib/] [libc/] [stdio64/] [fseeko64.c] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 jlechner
/*
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
<<fseeko64>>---set file position for large file
21
 
22
INDEX
23
        fseeko64
24
INDEX
25
        _fseeko64_r
26
 
27
ANSI_SYNOPSIS
28
        #include <stdio.h>
29
        int fseeko64(FILE *<[fp]>, _off64_t <[offset]>, int <[whence]>)
30
        int _fseeko64_r (struct _reent *<[ptr]>, FILE *<[fp]>,
31
                         _off64_t <[offset]>, int <[whence]>)
32
TRAD_SYNOPSIS
33
        #include <stdio.h>
34
 
35
        int fseeko64(<[fp]>, <[offset]>, <[whence]>)
36
        FILE *<[fp]>;
37
        _off64_t <[offset]>;
38
        int <[whence]>;
39
 
40
        int _fseeko64_r (<[ptr]>, <[fp]>, <[offset]>, <[whence]>)
41
        struct _reent *<[ptr]>;
42
        FILE *<[fp]>;
43
        _off64_t <[offset]>;
44
        int <[whence]>;
45
 
46
DESCRIPTION
47
Objects of type <<FILE>> can have a ``position'' that records how much
48
of the file your program has already read.  Many of the <<stdio>> functions
49
depend on this position, and many change it as a side effect.
50
 
51
You can use <<fseeko64>> to set the position for the file identified by
52
<[fp]> that was opened via <<fopen64>>.  The value of <[offset]> determines
53
the new position, in one of three ways selected by the value of <[whence]>
54
(defined as macros in `<<stdio.h>>'):
55
 
56
<<SEEK_SET>>---<[offset]> is the absolute file position (an offset
57
from the beginning of the file) desired.  <[offset]> must be positive.
58
 
59
<<SEEK_CUR>>---<[offset]> is relative to the current file position.
60
<[offset]> can meaningfully be either positive or negative.
61
 
62
<<SEEK_END>>---<[offset]> is relative to the current end of file.
63
<[offset]> can meaningfully be either positive (to increase the size
64
of the file) or negative.
65
 
66
See <<ftello64>> to determine the current file position.
67
 
68
RETURNS
69
<<fseeko64>> returns <<0>> when successful.  On failure, the
70
result is <<EOF>>.  The reason for failure is indicated in <<errno>>:
71
either <<ESPIPE>> (the stream identified by <[fp]> doesn't support
72
repositioning or wasn't opened via <<fopen64>>) or <<EINVAL>>
73
(invalid file position).
74
 
75
PORTABILITY
76
<<fseeko64>> is a glibc extension.
77
 
78
Supporting OS subroutines required: <<close>>, <<fstat64>>, <<isatty>>,
79
<<lseek64>>, <<read>>, <<sbrk>>, <<write>>.
80
*/
81
 
82
#include <stdio.h>
83
#include <time.h>
84
#include <fcntl.h>
85
#include <stdlib.h>
86
#include <errno.h>
87
#include <sys/types.h>
88
#include <sys/stat.h>
89
#include "local.h"
90
 
91
#define POS_ERR (-(_fpos64_t)1)
92
 
93
#ifdef __LARGE64_FILES
94
 
95
/*
96
 * Seek the given file to the given offset.
97
 * `Whence' must be one of the three SEEK_* macros.
98
 */
99
 
100
_off64_t
101
_DEFUN (_fseeko64_r, (ptr, fp, offset, whence),
102
     struct _reent *ptr _AND
103
     register FILE *fp _AND
104
     _off64_t offset _AND
105
     int whence)
106
{
107
  _fpos64_t _EXFUN ((*seekfn), (struct _reent *, void *, _fpos64_t, int));
108
  _fpos64_t target, curoff;
109
  size_t n;
110
 
111
  struct stat64 st;
112
  int havepos;
113
 
114
  /* Only do 64-bit seek on large file.  */
115
  if (!(fp->_flags & __SL64))
116
    {
117
      if ((_off_t) offset != offset)
118
        {
119
          ptr->_errno = EOVERFLOW;
120
          return EOF;
121
        }
122
      return (_off64_t) _fseeko_r (ptr, fp, offset, whence);
123
    }
124
 
125
  /* Make sure stdio is set up.  */
126
 
127
  CHECK_INIT (ptr, fp);
128
 
129
  _flockfile (fp);
130
 
131
  curoff = fp->_offset;
132
 
133
  /* If we've been doing some writing, and we're in append mode
134
     then we don't really know where the filepos is.  */
135
 
136
  if (fp->_flags & __SAPP && fp->_flags & __SWR)
137
    {
138
      /* So flush the buffer and seek to the end.  */
139
      _fflush_r (ptr, fp);
140
    }
141
 
142
  /* Have to be able to seek.  */
143
 
144
  if ((seekfn = fp->_seek64) == NULL)
145
    {
146
      ptr->_errno = ESPIPE;     /* ??? */
147
      _funlockfile(fp);
148
      return EOF;
149
    }
150
 
151
  /*
152
   * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
153
   * After this, whence is either SEEK_SET or SEEK_END.
154
   */
155
 
156
  switch (whence)
157
    {
158
    case SEEK_CUR:
159
      /*
160
       * In order to seek relative to the current stream offset,
161
       * we have to first find the current stream offset a la
162
       * ftell (see ftell for details).
163
       */
164
      _fflush_r (ptr, fp);   /* may adjust seek offset on append stream */
165
      if (fp->_flags & __SOFF)
166
        curoff = fp->_offset;
167
      else
168
        {
169
          curoff = seekfn (ptr, fp->_cookie, (_fpos64_t) 0, SEEK_CUR);
170
          if (curoff == -1L)
171
            {
172
              _funlockfile(fp);
173
              return EOF;
174
            }
175
        }
176
      if (fp->_flags & __SRD)
177
        {
178
          curoff -= fp->_r;
179
          if (HASUB (fp))
180
            curoff -= fp->_ur;
181
        }
182
      else if (fp->_flags & __SWR && fp->_p != NULL)
183
        curoff += fp->_p - fp->_bf._base;
184
 
185
      offset += curoff;
186
      whence = SEEK_SET;
187
      havepos = 1;
188
      break;
189
 
190
    case SEEK_SET:
191
    case SEEK_END:
192
      havepos = 0;
193
      break;
194
 
195
    default:
196
      ptr->_errno = EINVAL;
197
      _funlockfile(fp);
198
      return (EOF);
199
    }
200
 
201
  /*
202
   * Can only optimise if:
203
   *    reading (and not reading-and-writing);
204
   *    not unbuffered; and
205
   *    this is a `regular' Unix file (and hence seekfn==__sseek).
206
   * We must check __NBF first, because it is possible to have __NBF
207
   * and __SOPT both set.
208
   */
209
 
210
  if (fp->_bf._base == NULL)
211
    __smakebuf_r (ptr, fp);
212
  if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
213
    goto dumb;
214
  if ((fp->_flags & __SOPT) == 0)
215
    {
216
      if (seekfn != __sseek64
217
          || fp->_file < 0
218
          || _fstat64_r (ptr, fp->_file, &st)
219
          || (st.st_mode & S_IFMT) != S_IFREG)
220
        {
221
          fp->_flags |= __SNPT;
222
          goto dumb;
223
        }
224
#ifdef  HAVE_BLKSIZE
225
      fp->_blksize = st.st_blksize;
226
#else
227
      fp->_blksize = 1024;
228
#endif
229
      fp->_flags |= __SOPT;
230
    }
231
 
232
  /*
233
   * We are reading; we can try to optimise.
234
   * Figure out where we are going and where we are now.
235
   */
236
 
237
  if (whence == SEEK_SET)
238
    target = offset;
239
  else
240
    {
241
      if (_fstat64_r (ptr, fp->_file, &st))
242
        goto dumb;
243
      target = st.st_size + offset;
244
    }
245
 
246
  if (!havepos)
247
    {
248
      if (fp->_flags & __SOFF)
249
        curoff = fp->_offset;
250
      else
251
        {
252
          curoff = seekfn (ptr, fp->_cookie, (_fpos64_t)0, SEEK_CUR);
253
          if (curoff == POS_ERR)
254
            goto dumb;
255
        }
256
      curoff -= fp->_r;
257
      if (HASUB (fp))
258
        curoff -= fp->_ur;
259
    }
260
 
261
  /*
262
   * Compute the number of bytes in the input buffer (pretending
263
   * that any ungetc() input has been discarded).  Adjust current
264
   * offset backwards by this count so that it represents the
265
   * file offset for the first byte in the current input buffer.
266
   */
267
 
268
  if (HASUB (fp))
269
    {
270
      curoff += fp->_r;       /* kill off ungetc */
271
      n = fp->_up - fp->_bf._base;
272
      curoff -= n;
273
      n += fp->_ur;
274
    }
275
  else
276
    {
277
      n = fp->_p - fp->_bf._base;
278
      curoff -= n;
279
      n += fp->_r;
280
    }
281
 
282
  /*
283
   * If the target offset is within the current buffer,
284
   * simply adjust the pointers, clear EOF, undo ungetc(),
285
   * and return.
286
   */
287
 
288
  if (target >= curoff && target < curoff + n)
289
    {
290
      register int o = target - curoff;
291
 
292
      fp->_p = fp->_bf._base + o;
293
      fp->_r = n - o;
294
      if (HASUB (fp))
295
        FREEUB (ptr, fp);
296
      fp->_flags &= ~__SEOF;
297
      _funlockfile(fp);
298
      return 0;
299
    }
300
 
301
  /*
302
   * The place we want to get to is not within the current buffer,
303
   * but we can still be kind to the kernel copyout mechanism.
304
   * By aligning the file offset to a block boundary, we can let
305
   * the kernel use the VM hardware to map pages instead of
306
   * copying bytes laboriously.  Using a block boundary also
307
   * ensures that we only read one block, rather than two.
308
   */
309
 
310
  curoff = target & ~((_fpos64_t)(fp->_blksize - 1));
311
  if (seekfn (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR)
312
    goto dumb;
313
  fp->_r = 0;
314
  fp->_p = fp->_bf._base;
315
  if (HASUB (fp))
316
    FREEUB (ptr, fp);
317
  fp->_flags &= ~__SEOF;
318
  n = target - curoff;
319
  if (n)
320
    {
321
      if (__srefill_r (ptr, fp) || fp->_r < n)
322
        goto dumb;
323
      fp->_p += n;
324
      fp->_r -= n;
325
    }
326
  _funlockfile(fp);
327
  return 0;
328
 
329
  /*
330
   * We get here if we cannot optimise the seek ... just
331
   * do it.  Allow the seek function to change fp->_bf._base.
332
   */
333
 
334
dumb:
335
  if (_fflush_r (ptr, fp)
336
      || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
337
    {
338
      _funlockfile(fp);
339
      return EOF;
340
    }
341
  /* success: clear EOF indicator and discard ungetc() data */
342
  if (HASUB (fp))
343
    FREEUB (ptr, fp);
344
  fp->_p = fp->_bf._base;
345
  fp->_r = 0;
346
  /* fp->_w = 0; *//* unnecessary (I think...) */
347
  fp->_flags &= ~__SEOF;
348
  _funlockfile(fp);
349
  return 0;
350
}
351
 
352
#ifndef _REENT_ONLY
353
 
354
_off64_t
355
_DEFUN (fseeko64, (fp, offset, whence),
356
     register FILE *fp _AND
357
     _off64_t offset _AND
358
     int whence)
359
{
360
  return _fseeko64_r (_REENT, fp, offset, whence);
361
}
362
 
363
#endif /* !_REENT_ONLY */
364
 
365
#endif /* __LARGE64_FILES */

powered by: WebSVN 2.1.0

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