From abe65b09bbbb92f384c5b8e78014f3849b1b2ce1 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sat, 21 Sep 2013 15:23:40 +0200 Subject: [PATCH] Implement file descriptor table Needed for pnet --- sys/include/fd.h | 89 +++++++++++++++++++++++++++++++++++++++++++ sys/posix/fd.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 sys/include/fd.h create mode 100644 sys/posix/fd.c diff --git a/sys/include/fd.h b/sys/include/fd.h new file mode 100644 index 0000000000..9b5fa98bec --- /dev/null +++ b/sys/include/fd.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 INRIA. + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @addtogroup posix + * @{ + */ + +/** + * @file fd.h + * @brief Unifies diverse identifiers of RIOT to POSIX like file descriptors. + * + * @author Freie Universität Berlin + * @author Martin Lenders + * @author Christian Mehlis + */ +#ifndef FD_H +#define FD_H +#include +#include + +/** + * File descriptor table. + */ +typedef struct { + /** private status of this fd_t */ + int __active; + + /** the internal filedescriptor */ + int fd; + + /** + * Read *n* into *buf* from *fd*. Return the + * number read, -1 for errors or 0 for EOF. + */ + ssize_t (*read)(int fd, void *buf, size_t n); + + /** Write *n* bytes of *buf* to *fd*. Return the number written, or -1. */ + ssize_t (*write)(int fd, const void *buf, size_t n); + + /** Close the file descriptor *fd*. */ + int (*close)(int fd); +} fd_t; + +/** + * @brief Initializes file descriptors + * + * @return maximum number of available file descriptors. + */ +int fd_init(void); + +/** + * @brief Creates a new file descriptor. + * + * @param[in] internal_fd RIOT-internal identifier for the new FD. + * @param[in] internal_read Function to read from new FD. + * @param[in] internal_write Function to write into new FD. + * @param[in] internal_close Function to close new FD. + * + * @return 0 on success, -1 otherwise. *errno* is set accordingly. + */ +int fd_new(int internal_fd, ssize_t (*internal_read)(int, void *, size_t), + ssize_t (*internal_write)(int, const void *, size_t), + int (*internal_close)(int)); + +/** + * @brief Gets the file descriptor table entry associated with file + * descriptor *fd*. + * + * @param[in] fd A POSIX-like file descriptor. + * + * @return The file descriptor table entry associated with file descriptor + *fd* or NULL if there is non. + */ +fd_t *fd_get(int fd); + +/** + * @brief Removes file descriptor table entry associated with *fd* from table. + * + * @param[in] fd A POSIX-like file descriptor. + */ +void fd_destroy(int fd); + +#endif /* FD_H */ diff --git a/sys/posix/fd.c b/sys/posix/fd.c new file mode 100644 index 0000000000..6029826c7d --- /dev/null +++ b/sys/posix/fd.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * + * This file subject to the terms and conditions of the GNU Lesser General + * Public License. See the file LICENSE in the top level directory for more + * details. + */ + +#include +#include +#include +#include + +#include "posix_io.h" +#include "board_uart0.h" +#include "unistd.h" + +#include "fd.h" + +#if BOARD == MSB-430 +#define FD_MAX 5 +#else +#define FD_MAX 15 +#endif + +static fd_t fd_table[FD_MAX]; + +int fd_init(void) +{ + memset(fd_table, 0, sizeof(fd_t) * FD_MAX); + + posix_open(uart0_handler_pid, 0); + fd_t fd = { + .__active = 1, + .fd = uart0_handler_pid, + .read = (ssize_t ( *)(int, void *, size_t))posix_read, + .write = (ssize_t ( *)(int, const void *, size_t))posix_write, + .close = posix_close + }; + memcpy(&fd_table[STDIN_FILENO], &fd, sizeof(fd_t)); + memcpy(&fd_table[STDOUT_FILENO], &fd, sizeof(fd_t)); + memcpy(&fd_table[STDERR_FILENO], &fd, sizeof(fd_t)); + return FD_MAX; +} + +static int fd_get_next_free(void) +{ + for (int i = 0; i < FD_MAX; i++) { + fd_t *cur = &fd_table[i]; + + if (!cur->__active) { + return i; + } + } + + return -1; +} + +int fd_new(int internal_fd, ssize_t (*internal_read)(int, void *, size_t), + ssize_t (*internal_write)(int, const void *, size_t), + int (*internal_close)(int)) +{ + int fd = fd_get_next_free(); + + if (fd >= 0) { + fd_t *fd_s = fd_get(fd); + fd_s->__active = 1; + fd_s->fd = internal_fd; + fd_s->read = internal_read; + fd_s->write = internal_write; + fd_s->close = internal_close; + } + else { + errno = ENFILE; + return -1; + } + + return fd; +} + +fd_t *fd_get(int fd) +{ + if (fd >= 0 && fd < FD_MAX) { + return &fd_table[fd]; + } + + return NULL; +} + +void fd_destroy(int fd) +{ + fd_t *cur = fd_get(fd); + + if (!cur) { + return; + } + + memset(cur, 0, sizeof(fd_t)); +}