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/] [fopencookie.c] - Blame information for rev 179

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

Line No. Rev Author Line
1 148 jeremybenn
/* Copyright (C) 2007 Eric Blake
2
 * Permission to use, copy, modify, and distribute this software
3
 * is freely granted, provided that this notice is preserved.
4
 */
5
 
6
/*
7
FUNCTION
8
<<fopencookie>>---open a stream with custom callbacks
9
 
10
INDEX
11
        fopencookie
12
 
13
ANSI_SYNOPSIS
14
        #include <stdio.h>
15
        FILE *fopencookie(const void *<[cookie]>, const char *<[mode]>,
16
                          cookie_io_functions_t <[functions]>);
17
 
18
DESCRIPTION
19
<<fopencookie>> creates a <<FILE>> stream where I/O is performed using
20
custom callbacks.  The callbacks are registered via the structure:
21
 
22
        typedef ssize_t (*cookie_read_function_t)(void *_cookie, char *_buf,
23
                                                  size_t _n);
24
        typedef ssize_t (*cookie_write_function_t)(void *_cookie,
25
                                                   const char *_buf, size_t _n);
26
        typedef int (*cookie_seek_function_t)(void *_cookie, off_t *_off,
27
                                              int _whence);
28
        typedef int (*cookie_close_function_t)(void *_cookie);
29
 
30
.       typedef struct
31
.       {
32
.               cookie_read_function_t  *read;
33
.               cookie_write_function_t *write;
34
.               cookie_seek_function_t  *seek;
35
.               cookie_close_function_t *close;
36
.       } cookie_io_functions_t;
37
 
38
The stream is opened with <[mode]> treated as in <<fopen>>.  The
39
callbacks <[functions.read]> and <[functions.write]> may only be NULL
40
when <[mode]> does not require them.
41
 
42
<[functions.read]> should return -1 on failure, or else the number of
43
bytes read (0 on EOF).  It is similar to <<read>>, except that
44
<[cookie]> will be passed as the first argument.
45
 
46
<[functions.write]> should return -1 on failure, or else the number of
47
bytes written.  It is similar to <<write>>, except that <[cookie]>
48
will be passed as the first argument.
49
 
50
<[functions.seek]> should return -1 on failure, and 0 on success, with
51
*<[_off]> set to the current file position.  It is a cross between
52
<<lseek>> and <<fseek>>, with the <[_whence]> argument interpreted in
53
the same manner.  A NULL <[functions.seek]> makes the stream behave
54
similarly to a pipe in relation to stdio functions that require
55
positioning.
56
 
57
<[functions.close]> should return -1 on failure, or 0 on success.  It
58
is similar to <<close>>, except that <[cookie]> will be passed as the
59
first argument.  A NULL <[functions.close]> merely flushes all data
60
then lets <<fclose>> succeed.  A failed close will still invalidate
61
the stream.
62
 
63
Read and write I/O functions are allowed to change the underlying
64
buffer on fully buffered or line buffered streams by calling
65
<<setvbuf>>.  They are also not required to completely fill or empty
66
the buffer.  They are not, however, allowed to change streams from
67
unbuffered to buffered or to change the state of the line buffering
68
flag.  They must also be prepared to have read or write calls occur on
69
buffers other than the one most recently specified.
70
 
71
RETURNS
72
The return value is an open FILE pointer on success.  On error,
73
<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
74
function pointer is missing or <[mode]> is invalid, ENOMEM if the
75
stream cannot be created, or EMFILE if too many streams are already
76
open.
77
 
78
PORTABILITY
79
This function is a newlib extension, copying the prototype from Linux.
80
It is not portable.  See also the <<funopen>> interface from BSD.
81
 
82
Supporting OS subroutines required: <<sbrk>>.
83
*/
84
 
85
#include <stdio.h>
86
#include <errno.h>
87
#include <sys/lock.h>
88
#include "local.h"
89
 
90
typedef struct fccookie {
91
  void *cookie;
92
  FILE *fp;
93
  cookie_read_function_t *readfn;
94
  cookie_write_function_t *writefn;
95
  cookie_seek_function_t *seekfn;
96
  cookie_close_function_t *closefn;
97
} fccookie;
98
 
99
static _READ_WRITE_RETURN_TYPE
100
_DEFUN(fcreader, (ptr, cookie, buf, n),
101
       struct _reent *ptr _AND
102
       void *cookie _AND
103
       char *buf _AND
104
       int n)
105
{
106
  int result;
107
  fccookie *c = (fccookie *) cookie;
108
  errno = 0;
109
  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
110
    ptr->_errno = errno;
111
  return result;
112
}
113
 
114
static _READ_WRITE_RETURN_TYPE
115
_DEFUN(fcwriter, (ptr, cookie, buf, n),
116
       struct _reent *ptr _AND
117
       void *cookie _AND
118
       const char *buf _AND
119
       int n)
120
{
121
  int result;
122
  fccookie *c = (fccookie *) cookie;
123
  if (c->fp->_flags & __SAPP && c->fp->_seek)
124
    {
125
#ifdef __LARGE64_FILES
126
      c->fp->_seek64 (ptr, cookie, 0, SEEK_END);
127
#else
128
      c->fp->_seek (ptr, cookie, 0, SEEK_END);
129
#endif
130
    }
131
  errno = 0;
132
  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
133
    ptr->_errno = errno;
134
  return result;
135
}
136
 
137
static _fpos_t
138
_DEFUN(fcseeker, (ptr, cookie, pos, whence),
139
       struct _reent *ptr _AND
140
       void *cookie _AND
141
       _fpos_t pos _AND
142
       int whence)
143
{
144
  fccookie *c = (fccookie *) cookie;
145
#ifndef __LARGE64_FILES
146
  off_t offset = (off_t) pos;
147
#else /* __LARGE64_FILES */
148
  _off64_t offset = (_off64_t) pos;
149
#endif /* __LARGE64_FILES */
150
 
151
  errno = 0;
152
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
153
    ptr->_errno = errno;
154
#ifdef __LARGE64_FILES
155
  else if ((_fpos_t)offset != offset)
156
    {
157
      ptr->_errno = EOVERFLOW;
158
      offset = -1;
159
    }
160
#endif /* __LARGE64_FILES */
161
  return (_fpos_t) offset;
162
}
163
 
164
#ifdef __LARGE64_FILES
165
static _fpos64_t
166
_DEFUN(fcseeker64, (ptr, cookie, pos, whence),
167
       struct _reent *ptr _AND
168
       void *cookie _AND
169
       _fpos64_t pos _AND
170
       int whence)
171
{
172
  _off64_t offset;
173
  fccookie *c = (fccookie *) cookie;
174
  errno = 0;
175
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
176
    ptr->_errno = errno;
177
  return (_fpos64_t) offset;
178
}
179
#endif /* __LARGE64_FILES */
180
 
181
static int
182
_DEFUN(fccloser, (ptr, cookie),
183
       struct _reent *ptr _AND
184
       void *cookie)
185
{
186
  int result = 0;
187
  fccookie *c = (fccookie *) cookie;
188
  if (c->closefn)
189
    {
190
      errno = 0;
191
      if ((result = c->closefn (c->cookie)) < 0 && errno)
192
        ptr->_errno = errno;
193
    }
194
  _free_r (ptr, c);
195
  return result;
196
}
197
 
198
FILE *
199
_DEFUN(_fopencookie_r, (ptr, cookie, mode, functions),
200
       struct _reent *ptr _AND
201
       void *cookie _AND
202
       const char *mode _AND
203
       cookie_io_functions_t functions)
204
{
205
  FILE *fp;
206
  fccookie *c;
207
  int flags;
208
  int dummy;
209
 
210
  if ((flags = __sflags (ptr, mode, &dummy)) == 0)
211
    return NULL;
212
  if (((flags & (__SRD | __SRW)) && !functions.read)
213
      || ((flags & (__SWR | __SRW)) && !functions.write))
214
    {
215
      ptr->_errno = EINVAL;
216
      return NULL;
217
    }
218
  if ((fp = __sfp (ptr)) == NULL)
219
    return NULL;
220
  if ((c = (fccookie *) _malloc_r (ptr, sizeof *c)) == NULL)
221
    {
222
      __sfp_lock_acquire ();
223
      fp->_flags = 0;            /* release */
224
#ifndef __SINGLE_THREAD__
225
      __lock_close_recursive (fp->_lock);
226
#endif
227
      __sfp_lock_release ();
228
      return NULL;
229
    }
230
 
231
  _flockfile (fp);
232
  fp->_file = -1;
233
  fp->_flags = flags;
234
  c->cookie = cookie;
235
  c->fp = fp;
236
  fp->_cookie = c;
237
  c->readfn = functions.read;
238
  fp->_read = fcreader;
239
  c->writefn = functions.write;
240
  fp->_write = fcwriter;
241
  c->seekfn = functions.seek;
242
  fp->_seek = functions.seek ? fcseeker : NULL;
243
#ifdef __LARGE64_FILES
244
  fp->_seek64 = functions.seek ? fcseeker64 : NULL;
245
  fp->_flags |= __SL64;
246
#endif
247
  c->closefn = functions.close;
248
  fp->_close = fccloser;
249
  _funlockfile (fp);
250
  return fp;
251
}
252
 
253
#ifndef _REENT_ONLY
254
FILE *
255
_DEFUN(fopencookie, (cookie, mode, functions),
256
       void *cookie _AND
257
       const char *mode _AND
258
       cookie_io_functions_t functions)
259
{
260
  return _fopencookie_r (_REENT, cookie, mode, functions);
261
}
262
#endif /* !_REENT_ONLY */

powered by: WebSVN 2.1.0

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