From abe65b09bbbb92f384c5b8e78014f3849b1b2ce1 Mon Sep 17 00:00:00 2001
From: Martin Lenders <mlenders@inf.fu-berlin.de>
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 <mlenders@inf.fu-berlin.de>
+ * @author  Christian Mehlis <mehlis@inf.fu-berlin.de>
+ */
+#ifndef FD_H
+#define FD_H
+#include <stdlib.h>
+#include <sys/types.h>
+
+/**
+ * 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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));
+}
-- 
GitLab