[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 4/6] libc: POSIX: fcntl



+ libc: POSIX: Ungefaehr ganz genau jedes Programm braucht diese
  Funktion, implementieren wir halt mal irgendwas, was so aehnlich
  aussieht. Flags, die gesetzt werden, koennen wieder abgeholt werden,
  aber haben ansonsten keine Auswirkungen.
- libc: O_BINARY ist kein POSIX, wir unterscheiden nicht zwischen Text-
  und Binaerdateien und das Gegenstueck O_TEXT fehlt auch.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/modules/include/fcntl.h         |   20 ++++++++-
 src/modules/lib/posix/posix_files.c |   83 ++++++++++++++++++++++++++++++++++-
 2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/src/modules/include/fcntl.h b/src/modules/include/fcntl.h
index dee23f5..f8211ab 100644
--- a/src/modules/include/fcntl.h
+++ b/src/modules/include/fcntl.h
@@ -36,7 +36,22 @@
 #define O_CREAT 16
 #define O_EXCL 32
 #define O_TRUNC 64
-#define O_BINARY 128
+
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+
+enum {
+    /// Liest die Flags des Filedeskriptors
+    F_GETFD,
+
+    /// Setzt die Flags ds Filedeskriptors
+    F_SETFD,
+
+    /// Liest die Flags einer Datei
+    F_GETFL,
+
+    /// Setzt die Flags einer Datei
+    F_SETFL,
+};
 
 /// Emulierter Unix-Syscall zum oeffnen von Dateien
 int open(const char* filename, int flags, ...);
@@ -44,5 +59,8 @@ int open(const char* filename, int flags, ...);
 /// Emulierter Unix-Syscall zum erstellen von Dateien
 int creat(const char *pathname, mode_t mode);
 
+/// Fuehrt unterschiedliche Aktionen (F_*) auf Dateien aus
+int fcntl(int fd, int cmd, ...);
+
 #endif //ifndef _FCNTL_H_
 
diff --git a/src/modules/lib/posix/posix_files.c b/src/modules/lib/posix/posix_files.c
index d8c17e6..4c1cf90 100644
--- a/src/modules/lib/posix/posix_files.c
+++ b/src/modules/lib/posix/posix_files.c
@@ -38,6 +38,9 @@
 struct fd_list_element {
     FILE* io_res;
     int fd;
+
+    int fd_flags;
+    int file_flags;
 };
 
 /// Liste mit den Dateideskriptoren
@@ -104,6 +107,8 @@ int fileno(FILE* io_res)
 
         fdl_element->io_res = io_res;
         fdl_element->fd = next_fd++;
+        fdl_element->fd_flags = 0;
+        fdl_element->file_flags = 0;
     }
 
     return fdl_element->fd;
@@ -149,6 +154,77 @@ FILE* fdopen(int fd, const char* mode)
 }
 
 /**
+ * Fuehrt unterschiedliche Aktionen (F_*) auf Dateien aus
+ */
+int fcntl(int fd, int cmd, ...)
+{
+    // Liste mit den Dateideskriptoren durchsuchen
+    struct fd_list_element* fdl_element = NULL;
+    int i = 0;
+    while ((fdl_element = list_get_element_at(fd_list, i))) {
+        if (fdl_element->fd == fd) {
+            break;
+        }
+        i++;
+    }
+
+    if (fdl_element == NULL) {
+        errno = EBADF;
+        return -1;
+    }
+
+    // Aktion durchfuehren
+    switch (cmd) {
+        case F_GETFD:
+            return fdl_element->fd_flags;
+
+        case F_GETFL:
+            return fdl_element->file_flags;
+
+        case F_SETFD:
+        {
+            va_list ap;
+            int arg;
+
+            va_start(ap, cmd);
+            arg = va_arg(ap, int);
+            va_end(ap);
+
+            if (arg != fdl_element->fd_flags) {
+                fprintf(stderr, "Warnung: S_SETFD ändert Flags (%#x => %#x) "
+                    "ohne Effekt\n", fdl_element->fd_flags, arg);
+            }
+
+            fdl_element->fd_flags = arg;
+            return 0;
+        }
+
+        case F_SETFL:
+        {
+            va_list ap;
+            int arg;
+
+            va_start(ap, cmd);
+            arg = va_arg(ap, int);
+            va_end(ap);
+
+            // Wenn die Flags bisher 0 sind, ist es open, das aendert. In
+            // diesem Fall wollen wir keine Warnung.
+            if ((arg != fdl_element->file_flags) && fdl_element->file_flags) {
+                fprintf(stderr, "Warnung: S_SETFL ändert Flags (%#x => %#x) "
+                    "ohne Effekt\n", fdl_element->file_flags, arg);
+            }
+
+            fdl_element->file_flags = arg;
+            return 0;
+        }
+    }
+
+    errno = EINVAL;
+    return -1;
+}
+
+/**
  * Eine Datei als Unix-Dateideskriptor oeffnen
  *
  * @param filename Dateiname
@@ -161,6 +237,7 @@ int open(const char* filename, int flags, ...)
 {
     char fopen_flags[4];
     size_t flags_size = 0;
+    int fd;
 
     // Wenn O_CREAT und O_EXCL gleichzeitig gesetzt ist, muessen wir abbrechen
     // wenn die Datei existiert.
@@ -217,7 +294,11 @@ int open(const char* filename, int flags, ...)
         errno = ENOENT;
         return -1;
     }
-    return fileno(file);
+
+    fd = fileno(file);
+    fcntl(fd, F_SETFL, flags);
+
+    return fd;
 }
 
 /**
-- 
1.6.0.2