1//#include <_syslist.h>
2
3#include <sys/types.h> /* for off_t */
4
5/* defined in barrelfish/debug.h */
6void debug_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
7
8/* Some targets provides their own versions of this functions.  Those
9   targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS.  */
10
11typedef int   fsopen_fn_t(const char *, int);
12typedef int   fsread_fn_t(int, void *buf, size_t);
13typedef int   fswrite_fn_t(int, const void *, size_t);
14typedef int   fsclose_fn_t(int);
15typedef off_t fslseek_fn_t(int, off_t, int);
16
17#define FAIL_FN() \
18do { \
19    debug_printf("***** %s:%s() called. Something is probably wrong! Maybe " \
20                 "you forgot to call vfs_init().\n", __FILE__,__FUNCTION__); \
21    return -1; \
22} while (0)
23
24static int open_fail(const char *pathname, int flags)      { FAIL_FN(); }
25static int read_fail(int fd, void *buf, size_t len)        { FAIL_FN(); }
26static int write_fail(int fd, const void *buf, size_t len) { FAIL_FN(); }
27static int close_fail(int fd)                              { FAIL_FN(); }
28static off_t lseek_fail(int fd, off_t off, int whence)     { FAIL_FN(); }
29
30static struct {
31    fsopen_fn_t  *open;
32    fsread_fn_t  *read;
33    fswrite_fn_t *write;
34    fsclose_fn_t *close;
35    fslseek_fn_t *lseek;
36} fs_ops = {
37    .open = open_fail,
38    .read = read_fail,
39    .write = write_fail,
40    .close = close_fail,
41    .lseek = lseek_fail
42};
43
44void
45newlib_register_fsops__(fsopen_fn_t *open_fn,
46                        fsread_fn_t *read_fn,
47                        fswrite_fn_t *write_fn,
48                        fsclose_fn_t *close_fn,
49                        fslseek_fn_t *lseek_fn)
50{
51    fs_ops.open  = open_fn  ? open_fn  : open_fail;
52    fs_ops.read  = read_fn  ? read_fn  : read_fail;
53    fs_ops.write = write_fn ? write_fn : write_fail;
54    fs_ops.close = close_fn ? close_fn : close_fail;
55    fs_ops.lseek = lseek_fn ? lseek_fn : lseek_fail;
56}
57
58
59#ifdef _REENT_ONLY
60#ifndef REENTRANT_SYSCALLS_PROVIDED
61#define REENTRANT_SYSCALLS_PROVIDED
62#endif
63#endif
64
65#ifndef REENTRANT_SYSCALLS_PROVIDED
66
67/* We use the errno variable used by the system dependent layer.  */
68#undef errno
69extern int errno;
70
71ssize_t
72static xwrite(int fd, const void *buf, size_t count)
73{
74    return fs_ops.write(fd, buf, count);
75}
76
77_ssize_t
78_DEFUN (_write_r, (ptr, fd, buf, cnt),
79     struct _reent *ptr _AND
80     int fd _AND
81     _CONST _PTR buf _AND
82     size_t cnt)
83{
84  _ssize_t ret;
85
86  errno = 0;
87  if ((ret = (_ssize_t)xwrite (fd, buf, cnt)) == -1 && errno != 0)
88    ptr->_errno = errno;
89  return ret;
90}
91
92static ssize_t
93xread(int fd, void *buf, size_t count)
94{
95    return fs_ops.read(fd, buf, count);
96}
97
98_ssize_t
99_DEFUN (_read_r, (ptr, fd, buf, cnt),
100     struct _reent *ptr _AND
101     int fd _AND
102     _PTR buf _AND
103     size_t cnt)
104{
105  _ssize_t ret;
106
107
108  errno = 0;
109  if ((ret = (_ssize_t)xread (fd, buf, cnt)) == -1 && errno != 0)
110    ptr->_errno = errno;
111  return ret;
112}
113
114
115static int
116xclose(int fd)
117{
118    return fs_ops.close(fd);
119}
120
121int
122_DEFUN(_close_r, (ptr, fd),
123     struct _reent *ptr _AND
124     int fd)
125{
126  int ret;
127
128  errno = 0;
129  if ((ret = xclose (fd)) == -1 && errno != 0)
130    ptr->_errno = errno;
131  return ret;
132}
133
134
135static int
136xopen(const char *pathname, int flags, ...)
137{
138    return fs_ops.open(pathname, flags);
139}
140
141int
142_DEFUN (_open_r, (ptr, file, flags, mode),
143     struct _reent *ptr _AND
144     _CONST char *file _AND
145     int flags _AND
146     int mode)
147{
148  int ret;
149
150  errno = 0;
151  if ((ret = xopen (file, flags, mode)) == -1 && errno != 0)
152    ptr->_errno = errno;
153  return ret;
154}
155
156static off_t
157xlseek(int fd, off_t offset, int whence)
158{
159    return fs_ops.lseek(fd, offset, whence);
160}
161
162_off_t
163_DEFUN (_lseek_r, (ptr, fd, pos, whence),
164     struct _reent *ptr _AND
165     int fd _AND
166     _off_t pos _AND
167     int whence)
168{
169  _off_t ret;
170
171  errno = 0;
172  if ((ret = xlseek (fd, pos, whence)) == (_off_t) -1 && errno != 0)
173    ptr->_errno = errno;
174  return ret;
175}
176
177/* we don't provide an fstat function.  It's only use seems to be in:
178 * stdio/makebuf.c:59, which we don't really care about. Programs can use libvfs
179 * or libposixcompat for this functionality  */
180static off_t
181xfstat(int fd, void *stat)
182{
183    return -1;
184}
185
186int
187_fstat_r (struct _reent *ptr, int fd, struct stat *pstat)
188{
189  int ret;
190
191  errno = 0;
192  if ((ret = xfstat (fd, pstat)) == -1 && errno != 0)
193    ptr->_errno = errno;
194  return ret;
195}
196
197#endif /* ! defined (REENTRANT_SYSCALLS_PROVIDED) */
198