source: rtems/cpukit/libnetworking/rtems/rtems_syscall.c @ 3b7c123

4.115
Last change on this file since 3b7c123 was 3b7c123, checked in by Sebastian Huber <sebastian.huber@…>, on 03/13/12 at 10:33:51

Filesystem: Reference counting for locations

o A new data structure rtems_filesystem_global_location_t was

introduced to be used for

o the mount point location in the mount table entry,
o the file system root location in the mount table entry,
o the root directory location in the user environment, and
o the current directory location in the user environment.

During the path evaluation global start locations are obtained to
ensure that the current file system instance will be not unmounted in
the meantime.

o The user environment uses now reference counting and is protected

from concurrent access.

o The path evaluation process was completely rewritten and simplified.

The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation
method. Recursive calls in the path evaluation have been replaced
with iteration to avoid stack overflows. Only the evaluation of
symbolic links is recursive. No dynamic memory allocations and
intermediate buffers are used in the high level path evaluation. No
global locks are held during the file system instance specific path
evaluation process.

o Recursive symbolic link evaluation is now limited by

RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value
via sysconf().

o The device file system (devFS) uses now no global variables and

allocation from the workspace. Node names are allocated from the
heap.

o The upper layer lseek() performs now some parameter checks.
o The upper layer ftruncate() performs now some parameter checks.
o unmask() is now restricted to the RWX flags and protected from

concurrent access.

o The fchmod_h and rmnod_h file system node handlers are now a file

system operation.

o The unlink_h operation has been removed. All nodes are now destroyed

with the rmnod_h operation.

o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system

operations.

o The path evaluation and file system operations are now protected by

per file system instance lock and unlock operations.

o Fix and test file descriptor duplicate in fcntl().
o New test fstests/fsnofs01.

  • Property mode set to 100644
File size: 15.9 KB
Line 
1/*
2 *  $Id$
3 */
4
5#if HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <string.h>
10#include <stdarg.h>
11/* #include <stdlib.h> */
12#include <stdio.h>
13#include <errno.h>
14
15#include <rtems.h>
16#include <rtems/libio.h>
17#include <rtems/error.h>
18#include <rtems/rtems_bsdnet.h>
19
20#include <errno.h>
21#include <sys/types.h>
22#include <sys/param.h>
23#include <sys/mbuf.h>
24#include <sys/socket.h>
25#include <sys/socketvar.h>
26#include <sys/protosw.h>
27#include <sys/proc.h>
28#include <sys/fcntl.h>
29#include <sys/filio.h>
30#include <sys/sysctl.h>
31
32#include <net/if.h>
33#include <net/route.h>
34
35/*
36 *  Since we are "in the kernel", these do not get prototyped in sys/socket.h
37 */
38ssize_t send(int, const void *, size_t, int);
39ssize_t recv(int, void *, size_t, int);
40
41/*
42 * Hooks to RTEMS I/O system
43 */
44static const rtems_filesystem_file_handlers_r socket_handlers;
45
46/*
47 * Package system call argument into mbuf.
48 */
49static int
50sockargstombuf (struct mbuf **mp, const void *buf, int buflen, int type)
51{
52        struct mbuf *m;
53
54        if ((u_int)buflen > MLEN)
55                return (EINVAL);
56        m = m_get(M_WAIT, type);
57        if (m == NULL)
58                return (ENOBUFS);
59        m->m_len = buflen;
60        memcpy (mtod(m, caddr_t), buf, buflen);
61        *mp = m;
62        if (type == MT_SONAME) {
63                struct sockaddr *sa;
64                sa = mtod(m, struct sockaddr *);
65                sa->sa_len = buflen;
66        }
67        return 0;
68}
69
70/*
71 *********************************************************************
72 *                       BSD-style entry points                      *
73 *********************************************************************
74 */
75int
76socket (int domain, int type, int protocol)
77{
78        int fd;
79        int error;
80        struct socket *so;
81
82        rtems_bsdnet_semaphore_obtain ();
83        error = socreate(domain, &so, type, protocol, NULL);
84        if (error == 0) {
85                fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers);
86                if (fd < 0)
87                        soclose (so);
88        }
89        else {
90                errno = error;
91                fd = -1;
92        }
93        rtems_bsdnet_semaphore_release ();
94        return fd;
95}
96
97int
98bind (int s, struct sockaddr *name, int namelen)
99{
100        int error;
101        int ret = -1;
102        struct socket *so;
103        struct mbuf *nam;
104
105        rtems_bsdnet_semaphore_obtain ();
106        if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
107                error = sockargstombuf (&nam, name, namelen, MT_SONAME);
108                if (error == 0) {
109                        error = sobind (so, nam);
110                        if (error == 0)
111                                ret = 0;
112                        else
113                                errno = error;
114                        m_freem (nam);
115                }
116                else {
117                        errno = error;
118                }
119        }
120        rtems_bsdnet_semaphore_release ();
121        return ret;
122}
123
124int
125connect (int s, struct sockaddr *name, int namelen)
126{
127        int error;
128        int ret = -1;
129        struct socket *so;
130        struct mbuf *nam;
131
132        rtems_bsdnet_semaphore_obtain ();
133        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
134                rtems_bsdnet_semaphore_release ();
135                return -1;
136        }
137        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
138                errno = EALREADY;
139                rtems_bsdnet_semaphore_release ();
140                return -1;
141        }
142        error = sockargstombuf (&nam, name, namelen, MT_SONAME);
143        if (error) {
144                errno = error;
145                rtems_bsdnet_semaphore_release ();
146                return -1;
147        }
148        error = soconnect (so, nam);
149        if (error)
150                goto bad;
151        if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
152                m_freem(nam);
153                errno = EINPROGRESS;
154                rtems_bsdnet_semaphore_release ();
155                return -1;
156        }
157        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
158                error = soconnsleep (so);
159                if (error)
160                        break;
161        }
162        if (error == 0) {
163                error = so->so_error;
164                so->so_error = 0;
165        }
166    bad:
167        so->so_state &= ~SS_ISCONNECTING;
168        m_freem (nam);
169        if (error)
170                errno = error;
171        else
172                ret = 0;
173        rtems_bsdnet_semaphore_release ();
174        return ret;
175}
176
177int
178listen (int s, int backlog)
179{
180        int error;
181        int ret = -1;
182        struct socket *so;
183
184        rtems_bsdnet_semaphore_obtain ();
185        if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
186                error = solisten (so, backlog);
187                if (error == 0)
188                        ret = 0;
189                else
190                        errno = error;
191        }
192        rtems_bsdnet_semaphore_release ();
193        return ret;
194}
195
196int
197accept (int s, struct sockaddr *name, int *namelen)
198{
199        int fd;
200        struct socket *head, *so;
201        struct mbuf *nam;
202
203        rtems_bsdnet_semaphore_obtain ();
204        if ((head = rtems_bsdnet_fdToSocket (s)) == NULL) {
205                rtems_bsdnet_semaphore_release ();
206                return -1;
207        }
208        if ((head->so_options & SO_ACCEPTCONN) == 0) {
209                errno = EINVAL;
210                rtems_bsdnet_semaphore_release ();
211                return -1;
212        }
213        if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
214                errno = EWOULDBLOCK;
215                rtems_bsdnet_semaphore_release ();
216                return -1;
217        }
218        while (head->so_comp.tqh_first == NULL && head->so_error == 0) {
219                if (head->so_state & SS_CANTRCVMORE) {
220                        head->so_error = ECONNABORTED;
221                        break;
222                }
223                head->so_error = soconnsleep (head);
224        }
225        if (head->so_error) {
226                errno = head->so_error;
227                head->so_error = 0;
228                rtems_bsdnet_semaphore_release ();
229                return -1;
230        }
231
232        so = head->so_comp.tqh_first;
233        TAILQ_REMOVE(&head->so_comp, so, so_list);
234        head->so_qlen--;
235
236        fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers);
237        if (fd < 0) {
238                TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
239                head->so_qlen++;
240                soconnwakeup (head);
241                rtems_bsdnet_semaphore_release ();
242                return -1;
243        }
244        so->so_state &= ~SS_COMP;
245        so->so_head = NULL;
246
247        nam = m_get(M_WAIT, MT_SONAME);
248        (void) soaccept(so, nam);
249        if (name) {
250                 /* check length before it is destroyed */
251                if (*namelen > nam->m_len)
252                        *namelen = nam->m_len;
253                memcpy (name, mtod(nam, caddr_t), *namelen);
254        }
255        m_freem(nam);
256        rtems_bsdnet_semaphore_release ();
257        return (fd);
258
259}
260
261/*
262 *  Shutdown routine
263 */
264
265int
266shutdown (int s, int how)
267{
268      struct socket *so;
269      int error;
270
271      rtems_bsdnet_semaphore_obtain ();
272      if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
273              rtems_bsdnet_semaphore_release ();
274              return -1;
275      }
276      error = soshutdown(so, how);
277      rtems_bsdnet_semaphore_release ();
278      if (error) {
279              errno = error;
280              return -1;
281      }
282      return 0;
283}
284
285/*
286 * All `transmit' operations end up calling this routine.
287 */
288ssize_t
289sendmsg (int s, const struct msghdr *mp, int flags)
290{
291        int ret = -1;
292        int error;
293        struct uio auio;
294        struct iovec *iov;
295        struct socket *so;
296        struct mbuf *to;
297        struct mbuf *control = NULL;
298        int i;
299        int len;
300
301        rtems_bsdnet_semaphore_obtain ();
302        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
303                rtems_bsdnet_semaphore_release ();
304                return -1;
305        }
306        auio.uio_iov = mp->msg_iov;
307        auio.uio_iovcnt = mp->msg_iovlen;
308        auio.uio_segflg = UIO_USERSPACE;
309        auio.uio_rw = UIO_WRITE;
310        auio.uio_offset = 0;
311        auio.uio_resid = 0;
312        iov = mp->msg_iov;
313        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
314                if ((auio.uio_resid += iov->iov_len) < 0) {
315                        errno = EINVAL;
316                        rtems_bsdnet_semaphore_release ();
317                        return -1;
318                }
319        }
320        if (mp->msg_name) {
321                error = sockargstombuf (&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
322                if (error) {
323                        errno = error;
324                        rtems_bsdnet_semaphore_release ();
325                        return -1;
326                }
327        }
328        else {
329                to = NULL;
330        }
331        if (mp->msg_control) {
332                if (mp->msg_controllen < sizeof (struct cmsghdr)) {
333                        errno = EINVAL;
334                        if (to)
335                                m_freem(to);
336                        rtems_bsdnet_semaphore_release ();
337                        return -1;
338                }
339                sockargstombuf (&control, mp->msg_control, mp->msg_controllen, MT_CONTROL);
340        }
341        else {
342                control = NULL;
343        }
344        len = auio.uio_resid;
345        error = sosend (so, to, &auio, (struct mbuf *)0, control, flags);
346        if (error) {
347                if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
348                        error = 0;
349        }
350        if (error)
351                errno = error;
352        else
353                ret = len - auio.uio_resid;
354        if (to)
355                m_freem(to);
356        rtems_bsdnet_semaphore_release ();
357        return (ret);
358}
359
360/*
361 * Send a message to a host
362 */
363ssize_t
364sendto (int s, const void *buf, size_t buflen, int flags, const struct sockaddr *to, int tolen)
365{
366        struct msghdr msg;
367        struct iovec iov;
368
369        iov.iov_base = (void *)buf;
370        iov.iov_len = buflen;
371        msg.msg_name = (caddr_t)to;
372        msg.msg_namelen = tolen;
373        msg.msg_iov = &iov;
374        msg.msg_iovlen = 1;
375        msg.msg_control = NULL;
376        msg.msg_controllen = 0;
377        return sendmsg (s, &msg, flags);
378}
379
380/*
381 * All `receive' operations end up calling this routine.
382 */
383ssize_t
384recvmsg (int s, struct msghdr *mp, int flags)
385{
386        int ret = -1;
387        int error;
388        struct uio auio;
389        struct iovec *iov;
390        struct socket *so;
391        struct mbuf *from = NULL, *control = NULL;
392        int i;
393        int len;
394
395        rtems_bsdnet_semaphore_obtain ();
396        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
397                rtems_bsdnet_semaphore_release ();
398                return -1;
399        }
400        auio.uio_iov = mp->msg_iov;
401        auio.uio_iovcnt = mp->msg_iovlen;
402        auio.uio_segflg = UIO_USERSPACE;
403        auio.uio_rw = UIO_READ;
404        auio.uio_offset = 0;
405        auio.uio_resid = 0;
406        iov = mp->msg_iov;
407        for (i = 0; i < mp->msg_iovlen; i++, iov++) {
408                if ((auio.uio_resid += iov->iov_len) < 0) {
409                        errno = EINVAL;
410                        rtems_bsdnet_semaphore_release ();
411                        return -1;
412                }
413        }
414        len = auio.uio_resid;
415        mp->msg_flags = flags;
416        error = soreceive (so, &from, &auio, (struct mbuf **)NULL,
417                        mp->msg_control ? &control : (struct mbuf **)NULL,
418                        &mp->msg_flags);
419        if (error) {
420                if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
421                        error = 0;
422        }
423        if (error) {
424                errno = error;
425        }
426        else {
427                ret = len - auio.uio_resid;
428                if (mp->msg_name) {
429                        len = mp->msg_namelen;
430                        if ((len <= 0) || (from == NULL)) {
431                                len = 0;
432                        }
433                        else {
434                                if (len > from->m_len)
435                                        len = from->m_len;
436                                memcpy (mp->msg_name, mtod(from, caddr_t), len);
437                        }
438                        mp->msg_namelen = len;
439                }
440                if (mp->msg_control) {
441                        struct mbuf *m;
442                        void *ctlbuf;
443
444                        len = mp->msg_controllen;
445                        m = control;
446                        mp->msg_controllen = 0;
447                        ctlbuf = mp->msg_control;
448
449                        while (m && (len > 0)) {
450                                unsigned int tocopy;
451
452                                if (len >= m->m_len)
453                                        tocopy = m->m_len;
454                                else {
455                                        mp->msg_flags |= MSG_CTRUNC;
456                                        tocopy = len;
457                                }
458                                memcpy(ctlbuf, mtod(m, caddr_t), tocopy);
459                                ctlbuf += tocopy;
460                                len -= tocopy;
461                                m = m->m_next;
462                        }
463                        mp->msg_controllen = ctlbuf - mp->msg_control;
464                }
465        }
466        if (from)
467                m_freem (from);
468        if (control)
469                m_freem (control);
470        rtems_bsdnet_semaphore_release ();
471        return (ret);
472}
473
474/*
475 * Receive a message from a host
476 */
477ssize_t
478recvfrom (int s, void *buf, size_t buflen, int flags, const struct sockaddr *from, int *fromlen)
479{
480        struct msghdr msg;
481        struct iovec iov;
482        int ret;
483
484        iov.iov_base = buf;
485        iov.iov_len = buflen;
486        msg.msg_name = (caddr_t)from;
487        if (fromlen)
488                msg.msg_namelen = *fromlen;
489        else
490        msg.msg_namelen = 0;
491        msg.msg_iov = &iov;
492        msg.msg_iovlen = 1;
493        msg.msg_control = NULL;
494        msg.msg_controllen = 0;
495        ret = recvmsg (s, &msg, flags);
496        if ((from != NULL) && (fromlen != NULL) && (ret >= 0))
497                *fromlen = msg.msg_namelen;
498        return ret;
499}
500
501int
502setsockopt (int s, int level, int name, const void *val, int len)
503{
504        struct socket *so;
505        struct mbuf *m = NULL;
506        int error;
507
508        rtems_bsdnet_semaphore_obtain ();
509        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
510                rtems_bsdnet_semaphore_release ();
511                return -1;
512        }
513        if (len > MLEN) {
514                errno = EINVAL;
515                rtems_bsdnet_semaphore_release ();
516                return -1;
517        }
518        if (val) {
519                error = sockargstombuf (&m, val, len, MT_SOOPTS);
520                if (error) {
521                        errno = error;
522                        rtems_bsdnet_semaphore_release ();
523                        return -1;
524                }
525        }
526        error = sosetopt(so, level, name, m);
527        if (error) {
528                errno = error;
529                rtems_bsdnet_semaphore_release ();
530                return -1;
531        }
532        rtems_bsdnet_semaphore_release ();
533        return 0;
534}
535
536int
537getsockopt (int s, int level, int name, void *aval, int *avalsize)
538{
539        struct socket *so;
540        struct mbuf *m = NULL, *m0;
541        char *val = aval;
542        int i, op, valsize;
543        int error;
544
545        rtems_bsdnet_semaphore_obtain ();
546        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
547                rtems_bsdnet_semaphore_release ();
548                return -1;
549        }
550        if (val)
551                valsize = *avalsize;
552        else
553                valsize = 0;
554        if (((error = sogetopt(so, level, name, &m)) == 0) && val && valsize && m) {
555                op = 0;
556                while (m && op < valsize) {
557                        i = valsize - op;
558                        if (i > m->m_len)
559                                i = m->m_len;
560                        memcpy (val, mtod(m, caddr_t), i);
561                        op += i;
562                        val += i;
563                        m0 = m;
564                        MFREE (m0, m);
565                }
566                *avalsize = op;
567        }
568        if (m != NULL)
569                (void) m_free(m);
570        if (error) {
571                errno = error;
572                rtems_bsdnet_semaphore_release ();
573                return -1;
574        }
575        rtems_bsdnet_semaphore_release ();
576        return 0;
577}
578
579static int
580getpeersockname (int s, struct sockaddr *name, int *namelen, int pflag)
581{
582        struct socket *so;
583        struct mbuf *m;
584        int len = *namelen;
585        int error;
586
587        rtems_bsdnet_semaphore_obtain ();
588        if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
589                rtems_bsdnet_semaphore_release ();
590                return -1;
591        }
592        m = m_getclr(M_WAIT, MT_SONAME);
593        if (m == NULL) {
594                errno = ENOBUFS;
595                rtems_bsdnet_semaphore_release ();
596                return -1;
597        }
598        if (pflag)
599                error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m);
600        else
601                error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m);
602        if (error) {
603                m_freem(m);
604                errno = error;
605                rtems_bsdnet_semaphore_release ();
606                return -1;
607        }
608        if (len > m->m_len) {
609                len = m->m_len;
610                *namelen = len;
611        }
612        memcpy (name, mtod(m, caddr_t), len);
613        m_freem (m);
614        rtems_bsdnet_semaphore_release ();
615        return 0;
616}
617
618int
619getpeername (int s, struct sockaddr *name, int *namelen)
620{
621        return getpeersockname (s, name, namelen, 1);
622}
623int
624getsockname (int s, struct sockaddr *name, int *namelen)
625{
626        return getpeersockname (s, name, namelen, 0);
627}
628
629int
630sysctl(int *name, u_int namelen, void *oldp,
631       size_t *oldlenp, void *newp, size_t newlen)
632{
633  int    error;
634        size_t j;
635
636  rtems_bsdnet_semaphore_obtain ();
637  error = userland_sysctl (0, name, namelen, oldp, oldlenp, 1, newp, newlen, &j);
638  rtems_bsdnet_semaphore_release ();
639
640  if (oldlenp)
641    *oldlenp = j;
642
643  if (error)
644  {
645    errno = error;
646    return -1;
647  }
648  return 0;
649}
650
651/*
652 ************************************************************************
653 *                      RTEMS I/O HANDLER ROUTINES                      *
654 ************************************************************************
655 */
656static int
657rtems_bsdnet_close (rtems_libio_t *iop)
658{
659        struct socket *so;
660        int error;
661
662        rtems_bsdnet_semaphore_obtain ();
663        if ((so = iop->data1) == NULL) {
664                errno = EBADF;
665                rtems_bsdnet_semaphore_release ();
666                return -1;
667        }
668        error = soclose (so);
669        rtems_bsdnet_semaphore_release ();
670        if (error) {
671                errno = error;
672                return -1;
673        }
674        return 0;
675}
676
677static ssize_t
678rtems_bsdnet_read (rtems_libio_t *iop, void *buffer, size_t count)
679{
680        return recv (iop->data0, buffer, count, 0);
681}
682
683static ssize_t
684rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, size_t count)
685{
686        return send (iop->data0, buffer, count, 0);
687}
688
689static int
690so_ioctl (rtems_libio_t *iop, struct socket *so, uint32_t   command, void *buffer)
691{
692        switch (command) {
693        case FIONBIO:
694                if (*(int *)buffer) {
695                        iop->flags |= O_NONBLOCK;
696                        so->so_state |= SS_NBIO;
697                }
698                else {
699                        iop->flags &= ~O_NONBLOCK;
700                        so->so_state &= ~SS_NBIO;
701                }
702                return 0;
703
704        case FIONREAD:
705                *(int *)buffer = so->so_rcv.sb_cc;
706                return 0;
707        }
708
709        if (IOCGROUP(command) == 'i')
710                return ifioctl (so, command, buffer, NULL);
711        if (IOCGROUP(command) == 'r')
712                return rtioctl (command, buffer, NULL);
713        return (*so->so_proto->pr_usrreqs->pru_control)(so, command, buffer, 0);
714}
715
716static int
717rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t   command, void *buffer)
718{
719        struct socket *so;
720        int error;
721
722        rtems_bsdnet_semaphore_obtain ();
723        if ((so = iop->data1) == NULL) {
724                errno = EBADF;
725                rtems_bsdnet_semaphore_release ();
726                return -1;
727        }
728        error = so_ioctl (iop, so, command, buffer);
729        rtems_bsdnet_semaphore_release ();
730        if (error) {
731                errno = error;
732                return -1;
733        }
734        return 0;
735}
736
737static int
738rtems_bsdnet_fcntl (rtems_libio_t *iop, int cmd)
739{
740        struct socket *so;
741
742        if (cmd == F_SETFL) {
743                rtems_bsdnet_semaphore_obtain ();
744                if ((so = iop->data1) == NULL) {
745                        rtems_bsdnet_semaphore_release ();
746                        return EBADF;
747                }
748                if (iop->flags & LIBIO_FLAGS_NO_DELAY)
749                        so->so_state |= SS_NBIO;
750                else
751                        so->so_state &= ~SS_NBIO;
752                rtems_bsdnet_semaphore_release ();
753        }
754        return 0;
755}
756
757static int
758rtems_bsdnet_fstat (const rtems_filesystem_location_info_t *loc, struct stat *sp)
759{
760        sp->st_mode = S_IFSOCK;
761        return 0;
762}
763
764static const rtems_filesystem_file_handlers_r socket_handlers = {
765        rtems_filesystem_default_open,          /* open */
766        rtems_bsdnet_close,                     /* close */
767        rtems_bsdnet_read,                      /* read */
768        rtems_bsdnet_write,                     /* write */
769        rtems_bsdnet_ioctl,                     /* ioctl */
770        rtems_filesystem_default_lseek,         /* lseek */
771        rtems_bsdnet_fstat,                     /* fstat */
772        rtems_filesystem_default_ftruncate,     /* ftruncate */
773        rtems_filesystem_default_fsync,         /* fsync */
774        rtems_filesystem_default_fdatasync,     /* fdatasync */
775        rtems_bsdnet_fcntl                      /* fcntl */
776};
Note: See TracBrowser for help on using the repository browser.