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

[tyndur-devel] [PATCH 5/7] libc: Erstellen und Auslesen von PPBs



+ libc: Funktionen zum Erstellen und zum anschließend Auslesen eines
  Prozessparameterblocks

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/modules/include/init.h |    7 +
 src/modules/lib/param.c    |  264 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 271 insertions(+), 0 deletions(-)
 create mode 100644 src/modules/lib/param.c

diff --git a/src/modules/include/init.h b/src/modules/include/init.h
index d431cee..eb29b3a 100644
--- a/src/modules/include/init.h
+++ b/src/modules/include/init.h
@@ -30,11 +30,13 @@
 
 #include <types.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 #define INIT_PID 1
 
 extern void stdio_init(void);
 
+struct proc_param_block;
 
 void init_service_register(char* name);
 pid_t init_service_get(char* name);
@@ -42,10 +44,15 @@ char *init_service_get_name(pid_t pid);
 
 void init_process_exit(int result);
 pid_t init_execute(const char* cmd);
+int ppb_from_argv(const char* const argv[]);
 
 int cmdline_get_argc(const char* args);
 void cmdline_copy_argv(char* args, const char** argv, size_t argc);
 
+bool ppb_is_valid(struct proc_param_block* ppb, size_t ppb_size);
+int ppb_get_argc(struct proc_param_block* ppb, size_t ppb_size);
+void ppb_copy_argv(struct proc_param_block* ppb, size_t ppb_size,
+    char** argv, int argc);
 
 
 #ifdef _USE_START_
diff --git a/src/modules/lib/param.c b/src/modules/lib/param.c
new file mode 100644
index 0000000..c3a4f60
--- /dev/null
+++ b/src/modules/lib/param.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2010 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <syscall.h>
+#include <page.h>
+
+enum ppb_entry_type {
+    PPB_CMDLINE_ARG = 1,
+    PPB_ENV_VAR,
+};
+
+struct ppb_entry {
+    enum ppb_entry_type type;
+    ptrdiff_t           value;
+    size_t              len;
+};
+
+struct proc_param_block {
+    size_t              num;
+    struct ppb_entry    entries[];
+};
+
+struct ppb_builder {
+    struct proc_param_block*    ppb;
+    size_t                      ppb_dir_size;
+    size_t                      ppb_dir_used;
+    size_t                      ppb_data_used;
+};
+
+extern pid_t __init_exec(const char* cmd, int ppb_shm_id);
+
+static struct ppb_builder* ppb_builder_init(void)
+{
+    struct ppb_builder* b;
+
+    b = malloc(sizeof(*b));
+    if (b == NULL) {
+        return NULL;
+    }
+
+    b->ppb              = mem_allocate(PAGE_SIZE, 0);
+    b->ppb_dir_size     = PAGE_SIZE;
+    b->ppb_dir_used     = sizeof(struct proc_param_block);
+    b->ppb_data_used    = 0;
+
+    memset(b->ppb, 0, PAGE_SIZE);
+
+    return b;
+}
+
+static void* pgrealloc(void* old, size_t old_size, size_t new_size)
+{
+    void* new;
+
+    new = mem_allocate(new_size, 0);
+    if (new == NULL) {
+        return NULL;
+    }
+
+    memcpy(new, old, old_size);
+    mem_free(old, old_size);
+
+    return new;
+}
+
+static int ppb_add_entry(struct ppb_builder* b, enum ppb_entry_type type,
+    const void* value, size_t len)
+{
+    size_t used;
+    int index;
+    void* new;
+
+    /* Verzeichnis vergroessern falls noetig */
+    used = b->ppb_dir_used + sizeof(struct ppb_entry);
+
+    if (used > b->ppb_dir_size) {
+        new = pgrealloc(b->ppb, b->ppb_dir_size, NUM_PAGES(used));
+        if (new == NULL) {
+            return -ENOMEM;
+        }
+
+        b->ppb = new;
+        b->ppb_dir_size = NUM_PAGES(b->ppb_dir_used);
+    }
+
+    /* Daten eintragen */
+    index = b->ppb->num++;
+    b->ppb->entries[index].type  = type;
+    b->ppb->entries[index].value = (ptrdiff_t) value;
+    b->ppb->entries[index].len   = len;
+
+    b->ppb_dir_used += sizeof(struct ppb_entry);
+    b->ppb_data_used += len;
+
+    return 0;
+}
+
+static int ppb_builder_finish(struct ppb_builder* b)
+{
+    int shm;
+    size_t size;
+    uint8_t* p;
+    int i, num_entries;
+    ptrdiff_t offset;
+    struct ppb_entry* entry;
+
+    /* Shared Memory anlegen */
+    size = b->ppb_dir_used + b->ppb_data_used;
+
+    shm = create_shared_memory(size);
+    if (shm < 0) {
+        return shm;
+    }
+
+    p = open_shared_memory(shm);
+    if (p == NULL) {
+        return -ENOMEM;
+    }
+
+    /* Daten kopieren*/
+    num_entries = b->ppb->num;
+    offset = b->ppb_dir_used;
+
+    for (i = 0; i < num_entries; i++) {
+        entry = &b->ppb->entries[i];
+        memcpy(p + offset, (void*) entry->value, entry->len);
+        entry->value = offset;
+        offset += entry->len;
+    }
+
+    memcpy(p, b->ppb, b->ppb_dir_used);
+
+    /* Strukturen freigeben */
+    mem_free(b->ppb, NUM_PAGES(b->ppb_dir_used));
+    free(b);
+
+    return shm;
+}
+
+int ppb_from_argv(const char* const argv[])
+{
+    struct ppb_builder* b;
+    int shm;
+    const char* const* p;
+
+    b = ppb_builder_init();
+    if (b == NULL) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    p = argv;
+    while (*p != NULL) {
+        ppb_add_entry(b, PPB_CMDLINE_ARG, *p, strlen(*p) + 1);
+        p++;
+    }
+
+    shm = ppb_builder_finish(b);
+    if (shm < 0) {
+        errno = -shm;
+        return -1;
+    }
+
+    return shm;
+}
+
+bool ppb_is_valid(struct proc_param_block* ppb, size_t ppb_size)
+{
+    size_t offset;
+    size_t len;
+    int i;
+
+    len = sizeof(*ppb) + ppb->num + sizeof(*ppb->entries);
+    if (ppb_size < len) {
+        return false;
+    }
+
+    ppb_size -= len;
+    for (i = 0; i < ppb->num; i++) {
+        len = ppb->entries[i].len;
+        if (ppb_size < len) {
+            return false;
+        }
+
+        offset = ppb->entries[i].value;
+        if (offset > ppb_size || offset + len > ppb_size) {
+            return false;
+        }
+
+        ppb_size -= len;
+    }
+
+    return true;
+}
+
+int ppb_get_argc(struct proc_param_block* ppb, size_t ppb_size)
+{
+    int i;
+    int argc = 0;
+
+    if (!ppb_is_valid(ppb, ppb_size)) {
+        return -EINVAL;
+    }
+
+    for (i = 0; i < ppb->num; i++) {
+        if (ppb->entries[i].type == PPB_CMDLINE_ARG) {
+            argc++;
+        }
+    }
+
+    return argc;
+}
+
+void ppb_copy_argv(struct proc_param_block* ppb, size_t ppb_size,
+    char** argv, int argc)
+{
+    int i;
+    int arg;
+
+    if (!ppb_is_valid(ppb, ppb_size)) {
+        return;
+    }
+
+    arg = 0;
+    for (i = 0; i < ppb->num; i++) {
+        if (ppb->entries[i].type == PPB_CMDLINE_ARG) {
+            argv[arg++] = ((char*) ppb) + ppb->entries[i].value;
+            if (arg == argc) {
+                break;
+            }
+        }
+    }
+
+    argv[argc] = NULL;
+}
-- 
1.6.0.2