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

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



On Wed, Dec 29 14:12, Kevin Wolf wrote:
> + 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);

Wofür ist denn das genau gut?

> +
> +static struct ppb_builder* ppb_builder_init(void)
> +{
> +    struct ppb_builder* b;
> +
> +    b = malloc(sizeof(*b));
> +    if (b == NULL) {
> +        return NULL;
> +    }
> +

Hm wozu brauchst du hier ueberhaupt ganze Pages? Wenn ich das richtig
sehe, dann wird das ganze doch am Ende eh in einen SHM-Puffer kopiert
und dann freigegeben?

> +    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);

Hier eventuell noch ein
memset(((char*) new) + old_size, 0, new_size - old_size), oder?

> +
> +    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);

Ich glaube das sollte ein * sein:    ^

> +    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) {

Müsstest du hier nicht mit dem originalen ppb_size vergleichen?

> +            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;
> +}

Aber ich glaube von der Idee her finde ich das gut.

-- 
Antoine Kaufmann
<toni@xxxxxxxxxxxxxxxx>

Attachment: pgp5S5Xok550O.pgp
Description: PGP signature