/************************************************* */
/* Rule Set Based Access Control                   */
/* Implementation of PM data structures            */
/* Author and (c) 1999,2000: Amon Ott              */
/*                                                 */
/* Last modified: 18/Sep/2000                      */
/************************************************* */

#include <linux/types.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/vmalloc.h>
#include <linux/quotaops.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <rsbac/aci_data_structures.h>
#include <rsbac/pm_types.h>
#include <rsbac/pm_data_structures.h>
#include <rsbac/pm_getname.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include <rsbac/fs.h>
#include <rsbac/adf.h>
#include <rsbac/aci.h>
#include <rsbac/proc_fs.h>
#include <linux/string.h>
#include <linux/smp_lock.h>

#ifndef NULL
#define NULL ((void *) 0)
#endif

/************************************************************************** */
/*                          Global Variables                                */
/************************************************************************** */

/* The following global variables are needed for access to PM data.         */

static struct rsbac_pm_task_set_list_head_t   task_set_list_head;
static struct rsbac_pm_tp_set_list_head_t     tp_set_list_head;
static struct rsbac_pm_ru_set_list_head_t     ru_set_list_head;
static struct rsbac_pm_pp_set_list_head_t     pp_set_list_head;
static struct rsbac_pm_in_pp_set_list_head_t  in_pp_set_list_head;
static struct rsbac_pm_out_pp_set_list_head_t  out_pp_set_list_head;

static struct rsbac_pm_task_list_head_t   task_list_head;
static struct rsbac_pm_class_list_head_t  class_list_head;
static struct rsbac_pm_na_list_head_t     na_list_head;
static struct rsbac_pm_cs_list_head_t     cs_list_head;
static struct rsbac_pm_tp_list_head_t     tp_list_head;
static struct rsbac_pm_pp_list_head_t     pp_list_head;
static struct rsbac_pm_tkt_list_head_t    tkt_list_head;

/**************************************************/
/*       Declarations of external functions       */
/**************************************************/

int sys_write(u_int,char *, u_int);

/**************************************************/
/*       Declarations of internal functions       */
/**************************************************/

/* As some function use later defined functions, we declare those here.   */

  /* add_*_item() are called in read_*_list(), but defined later,         */
  /* so we declare them here.                                             */

/****************/
/* Helper lists */
/****************/
  
  static struct rsbac_pm_task_set_sublist_item_t * 
         add_task_set_subitem(struct rsbac_pm_task_set_list_item_t *,
                              rsbac_pm_task_id_t);

  static struct rsbac_pm_task_set_list_item_t* 
         add_task_set_item(rsbac_pm_task_set_id_t);

  static struct rsbac_pm_tp_set_sublist_item_t * 
         add_tp_set_subitem(struct rsbac_pm_tp_set_list_item_t *,
                            rsbac_pm_tp_id_t);

  static struct rsbac_pm_tp_set_list_item_t* 
         add_tp_set_item(rsbac_pm_tp_set_id_t);

  static struct rsbac_pm_ru_set_sublist_item_t * 
         add_ru_set_subitem(struct rsbac_pm_ru_set_list_item_t *,
                            rsbac_uid_t);

  static struct rsbac_pm_ru_set_list_item_t* 
         add_ru_set_item(rsbac_pm_ru_set_id_t);

  static struct rsbac_pm_pp_set_sublist_item_t * 
         add_pp_set_subitem(struct rsbac_pm_pp_set_list_item_t *,
                              rsbac_pm_purpose_id_t);

  static struct rsbac_pm_pp_set_list_item_t* 
         add_pp_set_item(rsbac_pm_pp_set_id_t);

  static struct rsbac_pm_in_pp_set_sublist_item_t * 
         add_in_pp_set_subitem(struct rsbac_pm_in_pp_set_list_item_t *,
                               rsbac_pm_purpose_id_t);

  static struct rsbac_pm_in_pp_set_list_item_t* 
         add_in_pp_set_item(rsbac_pm_in_pp_set_id_t);

  static struct rsbac_pm_out_pp_set_sublist_item_t * 
         add_out_pp_set_subitem(struct rsbac_pm_out_pp_set_list_item_t *,
                               rsbac_pm_purpose_id_t);

  static struct rsbac_pm_out_pp_set_list_item_t* 
         add_out_pp_set_item(rsbac_pm_out_pp_set_id_t);

/**************/
/* Main lists */
/**************/

  static struct rsbac_pm_task_list_item_t* 
         add_task_item(struct rsbac_pm_task_data_t);

  static struct rsbac_pm_class_list_item_t* 
         add_class_item(struct rsbac_pm_class_data_t);

  static struct rsbac_pm_na_list_item_t* 
         add_na_item(struct rsbac_pm_na_data_t);

  static struct rsbac_pm_cs_list_item_t* 
         add_cs_item(struct rsbac_pm_cs_data_t);

  static struct rsbac_pm_tp_list_item_t* 
         add_tp_item(struct rsbac_pm_tp_data_t);

  static struct rsbac_pm_pp_list_item_t* 
         add_pp_item(struct rsbac_pm_pp_data_t);

  static struct rsbac_pm_tkt_list_item_t* 
         add_tkt_item(struct rsbac_pm_tkt_data_t);

/************************************************* */
/*               Internal Help functions           */
/************************************************* */

/* These help functions do NOT handle data consistency protection by        */
/* rw-spinlocks! This is done exclusively by non-internal functions!        */

/************************************************************************** */
/* Read/Write functions                                                     */
/* The read functions are only called from rsbac_init_pm(), the write functions*/
/* are called on every change from all functions that modify data.          */

/****************/
/* Helper lists */
/****************/

/* read_task_set_list() */
/* reading a system wide PM list from root filesystem */

static int read_task_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             i;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_task_set_list_item_t * item;
    rsbac_pm_task_set_id_t          id;
    rsbac_pm_task_id_t              sub_id;
    int                             len;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_TASK_SET_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_task_set_lists(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_TASK_SET_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_task_set_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_TASK_SET_LIST_VERSION);
            task_set_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &id,
	                             sizeof(id),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        item = add_task_set_item(id);
                if (!item)
                  {
                    printk(KERN_WARNING
                           "read_task_set_list(): could not add item %u!\n",
                           id);
                    tmperr = 0;
                  }
                else
                  {
                    read_count++;
                    tmperr = file.f_op->read(&file,
	                                     (char *) &len,
	                                     sizeof(len),
	                                     &file.f_pos);
                    /* if successful, read and add len subitems */
	            if (tmperr > 0)
                      {
                        for(i=0;i<len;i++)
                          {
                            tmperr = file.f_op->read(&file,
	                                             (char *) &sub_id,
	                                             sizeof(sub_id),
	                                             &file.f_pos);
	                    if(tmperr > 0)
	                      {
	                        if (!add_task_set_subitem(item,
                                                          sub_id))
                                  {
                                    printk(KERN_WARNING
                                           "read_task_set_list(): could not add sub-item!\n");
                                    i = len;
                                    tmperr = -1;
                                  }
	                      }
	                    else
	                      {
	                        i = len;
	                        tmperr = -1;
	                      }
                          }
                      }
                  }
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_task_set_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_task_set_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_task_set_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_task_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_task_set_list_item_t * current_p = NULL;
    struct rsbac_pm_task_set_sublist_item_t * sub_item_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes, buflen = 0;
    int             tmperr = 0;
    u_long          flags;
    u_int           aci_version = RSBAC_PM_TASK_SET_LIST_VERSION;
    char          * buffer = NULL;
    boolean         vmalloc_used = FALSE;

    /* test no_write */
    if(task_set_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&task_set_list_head.lock, &flags);
    /* calculate buflen */
    buflen = task_set_list_head.count *
              (sizeof(current_p->id) /* one set id each */
               + sizeof(int) )       /* sublist len */
             + sizeof(u_int);        /* version */
    current_p = task_set_list_head.head;
    while (current_p) 
      {
        buflen += current_p->sublist_length * sizeof(sub_item_p->id);
        current_p = current_p->next;
      }
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_task_set_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&task_set_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    current_p = task_set_list_head.head;
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->id),
	       sizeof(current_p->id));
        write_count += sizeof(current_p->id);
        memcpy(buffer+write_count,
               (char *) &(current_p->sublist_length),
               sizeof(current_p->sublist_length));
        write_count += sizeof(current_p->sublist_length);
        sub_item_p = current_p->sublist_head;
        while (sub_item_p)
          {
            memcpy(buffer+write_count,
                   (char *) &(sub_item_p->id),
                   sizeof(sub_item_p->id));
            write_count += sizeof(sub_item_p->id);
            sub_item_p = sub_item_p->next;
          }
        current_p = current_p->next;
      }
    /* unprotect this list */
    rsbac_read_unlock(&task_set_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);
    
    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_TASK_SET_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_task_set_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_task_set_list(): %lu main lists written.\n",
             task_set_list_head.count);
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_task_set_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/************************/
/* read_tp_set_list() */
/* reading a system wide PM list from root filesystem */

static int read_tp_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             i;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_tp_set_list_item_t * item;
    rsbac_pm_tp_set_id_t          id;
    rsbac_pm_tp_id_t              sub_id;
    int                             len;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_TP_SET_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_tp_set_lists(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_TP_SET_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_tp_set_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_TP_SET_LIST_VERSION);
            tp_set_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &id,
	                             sizeof(id),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        item = add_tp_set_item(id);
                if (!item)
                  {
                    printk(KERN_WARNING
                           "read_tp_set_list(): could not add item %i!\n",
                           id);
                    tmperr = 0;
                  }
                else
                  {
                    read_count++;
                    tmperr = file.f_op->read(&file,
	                                     (char *) &len,
	                                     sizeof(len),
	                                     &file.f_pos);
                    /* if successful, read and add len subitems */
	            if (tmperr > 0)
                      {
                        for(i=0;i<len;i++)
                          {
                            tmperr = file.f_op->read(&file,
	                                             (char *) &sub_id,
	                                             sizeof(sub_id),
	                                             &file.f_pos);
	                    if(tmperr > 0)
	                      {
	                        if (!add_tp_set_subitem(item,
                                                          sub_id))
                                  {
                                    printk(KERN_WARNING
                                           "read_tp_set_list(): could not add sub-item!\n");
                                    i = len;
                                    tmperr = -1;
                                  }
	                      }
	                    else
	                      {
	                        i = len;
	                        tmperr = -1;
	                      }
                          }
                      }
                  }
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_tp_set_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_tp_set_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_tp_set_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_tp_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_tp_set_list_item_t * current_p = NULL;
    struct rsbac_pm_tp_set_sublist_item_t * sub_item_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes, buflen = 0;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_TP_SET_LIST_VERSION;

    /* test no_write */
    if(tp_set_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&tp_set_list_head.lock, &flags);
    /* calculate buflen */
    buflen = tp_set_list_head.count *
              (sizeof(current_p->id) /* one set id each */
               + sizeof(int) )       /* sublist len */
             + sizeof(u_int);        /* version */
    current_p = tp_set_list_head.head;
    while (current_p) 
      {
        buflen += current_p->sublist_length * sizeof(sub_item_p->id);
        current_p = current_p->next;
      }
    /* allocate mem */
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_tp_set_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&tp_set_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = tp_set_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->id),
	       sizeof(current_p->id));
        write_count += sizeof(current_p->id);
        memcpy(buffer+write_count,
               (char *) &(current_p->sublist_length),
               sizeof(current_p->sublist_length));
        write_count += sizeof(current_p->sublist_length);
        sub_item_p = current_p->sublist_head;
        while (sub_item_p)
          {
            memcpy(buffer+write_count,
                   (char *) &(sub_item_p->id),
                   sizeof(sub_item_p->id));
            write_count += sizeof(sub_item_p->id);
            sub_item_p = sub_item_p->next;
          }
        current_p = current_p->next;
      }
    /* unprotect this list */
    rsbac_read_unlock(&tp_set_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_TP_SET_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_tp_set_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_tp_set_list(): %u main lists written.\n",
             tp_set_list_head.count);
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_tp_set_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/************************/
/* read_ru_set_list() */
/* reading a system wide PM list from root filesystem */

static int read_ru_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             i;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_ru_set_list_item_t * item;
    rsbac_pm_ru_set_id_t            id;
    rsbac_uid_t                     sub_id;
    rsbac_old_uid_t                 old_sub_id;
    int                             len;
    mm_segment_t oldfs;
    u_int           aci_version;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_RU_SET_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_ru_set_lists(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        switch(aci_version)
          {
            case RSBAC_PM_RU_SET_LIST_VERSION:
              break;
            case RSBAC_PM_OLD_RU_SET_LIST_VERSION:
              printk(KERN_WARNING
                     "read_ru_set_list(): old version %u, new is %u - upconverting!\n",
                     aci_version, RSBAC_PM_RU_SET_LIST_VERSION);
              break;
            default:
              printk(KERN_WARNING
                     "read_ru_set_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                     aci_version, RSBAC_PM_RU_SET_LIST_VERSION);
              ru_set_list_head.no_write = TRUE;
              err = -RSBAC_EREADFAILED;
              goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &id,
	                             sizeof(id),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        item = add_ru_set_item(id);
                if (!item)
                  {
                    printk(KERN_WARNING
                           "read_ru_set_list(): could not add item %i!\n",
                           id);
                    tmperr = 0;
                  }
                else
                  {
                    read_count++;
                    tmperr = file.f_op->read(&file,
	                                     (char *) &len,
	                                     sizeof(len),
	                                     &file.f_pos);
                    /* if successful, read and add len subitems */
	            if (tmperr > 0)
                      {
                        for(i=0;i<len;i++)
                          {
                            switch(aci_version)
                              {
                                case RSBAC_PM_RU_SET_LIST_VERSION:
                                  tmperr = file.f_op->read(&file,
                                                           (char *) &sub_id,
	                                                   sizeof(sub_id),
	                                                   &file.f_pos);
                                  break;
                                case RSBAC_PM_OLD_RU_SET_LIST_VERSION:
                                  tmperr = file.f_op->read(&file,
                                                           (char *) &old_sub_id,
                                                           sizeof(old_sub_id),
                                                           &file.f_pos);
                                  sub_id = old_sub_id;
                                  break;
                                default:
                                  break;
                              }
	                    if(tmperr > 0)
	                      {
	                        if (!add_ru_set_subitem(item,
                                                        sub_id))
                                  {
                                    printk(KERN_WARNING
                                           "read_ru_set_list(): could not add sub-item!\n");
                                    i = len;
                                    tmperr = -1;
                                  }
	                      }
	                    else
	                      {
	                        i = len;
	                        tmperr = -1;
	                      }
                          }
                      }
                  }
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_ru_set_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_ru_set_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_ru_set_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_ru_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_ru_set_list_item_t * current_p = NULL;
    struct rsbac_pm_ru_set_sublist_item_t * sub_item_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes, buflen = 0;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_RU_SET_LIST_VERSION;

    /* test no_write */
    if(ru_set_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&ru_set_list_head.lock, &flags);
    /* calculate buflen */
    buflen = ru_set_list_head.count *
              (sizeof(current_p->id) /* one set id each */
               + sizeof(int) )       /* sublist len */
             + sizeof(u_int);        /* version */
    current_p = ru_set_list_head.head;
    while (current_p) 
      {
        buflen += current_p->sublist_length * sizeof(sub_item_p->id);
        current_p = current_p->next;
      }
    /* allocate mem */
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_ru_set_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&ru_set_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = ru_set_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->id),
	       sizeof(current_p->id));
        write_count += sizeof(current_p->id);
        memcpy(buffer+write_count,
               (char *) &(current_p->sublist_length),
               sizeof(current_p->sublist_length));
        write_count += sizeof(current_p->sublist_length);
        sub_item_p = current_p->sublist_head;
        while (sub_item_p)
          {
            memcpy(buffer+write_count,
                   (char *) &(sub_item_p->id),
                   sizeof(sub_item_p->id));
            write_count += sizeof(sub_item_p->id);
            sub_item_p = sub_item_p->next;
          }
        current_p = current_p->next;
      }
    /* unprotect this list */
    rsbac_read_unlock(&ru_set_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);
    
    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_RU_SET_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_ru_set_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_ru_set_list(): %u main lists written.\n",
             ru_set_list_head.count);
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_ru_set_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/************************/
/* read_pp_set_list() */
/* reading a system wide PM list from root filesystem */

static int read_pp_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             i;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_pp_set_list_item_t * item;
    rsbac_pm_pp_set_id_t            id;
    rsbac_pm_purpose_id_t           sub_id;
    int                             len;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_PP_SET_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_pp_set_lists(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_PP_SET_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_pp_set_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_PP_SET_LIST_VERSION);
            pp_set_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &id,
	                             sizeof(id),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        item = add_pp_set_item(id);
                if (!item)
                  {
                    printk(KERN_WARNING
                           "read_pp_set_list(): could not add item %i!\n",
                           id);
                    tmperr = 0;
                  }
                else
                  {
                    read_count++;
                    tmperr = file.f_op->read(&file,
	                                     (char *) &len,
	                                     sizeof(len),
	                                     &file.f_pos);
                    /* if successful, read and add len subitems */
	            if (tmperr > 0)
                      {
                        for(i=0;i<len;i++)
                          {
                            tmperr = file.f_op->read(&file,
	                                             (char *) &sub_id,
	                                             sizeof(sub_id),
	                                             &file.f_pos);
	                    if(tmperr > 0)
	                      {
	                        if (!add_pp_set_subitem(item,
                                                          sub_id))
                                  {
                                    printk(KERN_WARNING
                                           "read_pp_set_list(): could not add sub-item!\n");
                                    i = len;
                                    tmperr = -1;
                                  }
	                      }
	                    else
	                      {
	                        i = len;
	                        tmperr = -1;
	                      }
                          }
                      }
                  }
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_pp_set_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_pp_set_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_pp_set_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_pp_set_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_pp_set_list_item_t * current_p = NULL;
    struct rsbac_pm_pp_set_sublist_item_t * sub_item_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes, buflen = 0;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_PP_SET_LIST_VERSION;

    /* test no_write */
    if(pp_set_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    /* calculate buflen */
    buflen = pp_set_list_head.count *
              (sizeof(current_p->id) /* one set id each */
               + sizeof(int) )       /* sublist len */
             + sizeof(u_int);        /* version */
    current_p = pp_set_list_head.head;
    while (current_p) 
      {
        buflen += current_p->sublist_length * sizeof(sub_item_p->id);
        current_p = current_p->next;
      }
    /* allocate mem */
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_pp_set_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&pp_set_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = pp_set_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->id),
	       sizeof(current_p->id));
        write_count += sizeof(current_p->id);
        memcpy(buffer+write_count,
               (char *) &(current_p->sublist_length),
               sizeof(current_p->sublist_length));
        write_count += sizeof(current_p->sublist_length);
        sub_item_p = current_p->sublist_head;
        while (sub_item_p)
          {
            memcpy(buffer+write_count,
                   (char *) &(sub_item_p->id),
                   sizeof(sub_item_p->id));
            write_count += sizeof(sub_item_p->id);
            sub_item_p = sub_item_p->next;
          }
        current_p = current_p->next;
      }
    /* unprotect this list */
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);
    
    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_PP_SET_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_pp_set_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_pp_set_list(): %lu main lists written.\n",
             pp_set_list_head.count);
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_pp_set_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/**************/
/* Main lists */
/**************/

/* read_task_list() */
/* reading a system wide PM list from root filesystem */

static int read_task_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_task_data_t     task_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_TASK_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_task_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_TASK_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_task_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_TASK_LIST_VERSION);
            task_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &task_data,
	                             sizeof(task_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_task_item(task_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_task_list(): read item %i\n",
                     task_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_task_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_task_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_task_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_task_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_task_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_TASK_LIST_VERSION;

    /* test no_write */
    if(task_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&task_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + task_list_head.count * sizeof(*task_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_task_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&task_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = task_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&task_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);
    
    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_TASK_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_task_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_task_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_task_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */


/******************/
/* read_class_list() */
/* reading a system wide PM list from root filesystem */

static int read_class_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_class_data_t     class_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_CLASS_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_class_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_CLASS_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_class_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_CLASS_LIST_VERSION);
            class_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &class_data,
	                             sizeof(class_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_class_item(class_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_class_list(): read item %i\n",
                     class_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_class_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_class_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_class_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_class_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_class_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_CLASS_LIST_VERSION;

    /* test no_write */
    if(class_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&class_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + class_list_head.count * sizeof(*class_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_class_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&class_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = class_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&class_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_CLASS_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_class_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_class_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_class_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */


/******************/
/* read_na_list() */
/* reading a system wide PM list from root filesystem */

static int read_na_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_na_data_t     na_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_NA_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_na_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_NA_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_na_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_NA_LIST_VERSION);
            na_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &na_data,
	                             sizeof(na_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_na_item(na_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_na_list(): read item %i\n",
                     na_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_na_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_na_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_na_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_na_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_na_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_NA_LIST_VERSION;

    /* test no_write */
    if(na_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&na_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + na_list_head.count * sizeof(*na_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_task_set_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&na_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = na_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&na_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_NA_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_na_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_na_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_na_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */


/******************/
/* read_cs_list() */
/* reading a system wide PM list from root filesystem */

static int read_cs_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_cs_data_t     cs_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_CS_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_cs_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_CS_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_cs_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_CS_LIST_VERSION);
            cs_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &cs_data,
	                             sizeof(cs_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_cs_item(cs_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_cs_list(): read item %i\n",
                     cs_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_cs_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_cs_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_cs_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_cs_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_cs_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_CS_LIST_VERSION;

    /* test no_write */
    if(cs_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&cs_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + cs_list_head.count * sizeof(*cs_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_cs_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&cs_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = cs_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&cs_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_CS_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_cs_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_cs_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_cs_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */


/******************/
/* read_tp_list() */
/* reading a system wide PM list from root filesystem */

static int read_tp_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_tp_data_t     tp_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_TP_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_tp_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_TP_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_tp_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_TP_LIST_VERSION);
            tp_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &tp_data,
	                             sizeof(tp_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_tp_item(tp_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_tp_list(): read item %i\n",
                     tp_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_tp_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_tp_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_tp_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_tp_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_tp_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_TP_LIST_VERSION;

    /* test no_write */
    if(tp_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&tp_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + tp_list_head.count * sizeof(*tp_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_tp_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&tp_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = tp_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&tp_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_TP_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_tp_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_tp_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_tp_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/******************/
/* read_pp_list() */
/* reading a system wide PM list from root filesystem */

static int read_pp_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_pp_data_t     pp_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_PP_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_pp_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        if (aci_version != RSBAC_PM_PP_LIST_VERSION)
          {
            printk(KERN_WARNING
                   "read_pp_list(): wrong version %u, expected %u - skipping file and setting no_write for DEV list!\n",
                   aci_version, RSBAC_PM_PP_LIST_VERSION);
            pp_list_head.no_write = TRUE;
            err = -RSBAC_EREADFAILED;
            goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &pp_data,
	                             sizeof(pp_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        add_pp_item(pp_data);
	        read_count++;
/*                if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_pp_list(): read item %i\n",
                     pp_data.id);
*/
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_pp_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_pp_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_pp_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_pp_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_pp_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_PP_LIST_VERSION;

    /* test no_write */
    if(pp_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&pp_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + pp_list_head.count * sizeof(*pp_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_pp_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&pp_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = pp_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&pp_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_PP_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_pp_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_pp_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_pp_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/*******************/
/* read_tkt_list() */
/* reading a system wide PM list from root filesystem */

static int read_tkt_list(void)
  {
    struct file                     file;
    int                             err = 0;
    int                             tmperr;
    u_long                          read_count = 0;
    struct rsbac_pm_tkt_data_t      tkt_data;
    u_int           aci_version;
    mm_segment_t oldfs;

        /* open file */
        if ((err = rsbac_read_open (RSBAC_PM_TKT_LIST_NAME,
                                    &file,
                                    ROOT_DEV) ))
          return(err);

        /* OK, now we can start reading */
        /* There is a read function for this file, so read as many items */
        /* as possible. A positive return value means a read success,   */
        /* 0 end of file and a negative value an error.                 */

        /* Set current user space to kernel space, because read() writes */
        /* to user space */
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        /* read and compare version */
        tmperr = file.f_op->read(&file,
                                 (char *) &aci_version,
                                 sizeof(aci_version),
                                 &file.f_pos);
        /* error? */
	if (tmperr < sizeof(aci_version))
	  {
            printk(KERN_WARNING
                   "read_tkt_list(): read error from file!\n");
            err = -RSBAC_EREADFAILED;
            goto end_read;
          }
        /* if wrong aci version, set no_write and skip */
        switch(aci_version)
          {
            case RSBAC_PM_TKT_LIST_VERSION:
              break;
            case RSBAC_PM_OLD_TKT_LIST_VERSION:
              printk(KERN_WARNING
                     "read_tkt_list(): old version %u, new is %u - no upconversion possible, tickets are dropped!\n",
                     aci_version, RSBAC_PM_TKT_LIST_VERSION);
              err = -RSBAC_EREADFAILED;
              goto end_read;
              break;
            default:
              printk(KERN_WARNING
                     "read_tkt_list(): wrong version %u, expected %u - skipping file and setting no_write for ticket list!\n",
                     aci_version, RSBAC_PM_TKT_LIST_VERSION);
              tkt_list_head.no_write = TRUE;
              err = -RSBAC_EREADFAILED;
              goto end_read;
	  }
	do
	  {
	    tmperr = file.f_op->read(&file,
	                             (char *) &tkt_data,
	                             sizeof(tkt_data),
	                             &file.f_pos);
            /* if successful, add item without writing to disk */
	    if (tmperr > 0)
	      {
	        if(tkt_data.valid_until >= CURRENT_TIME)
	          {
                    add_tkt_item(tkt_data);
	            read_count++;
/*                  if (rsbac_debug_ds_pm) printk(KERN_DEBUG "read_tkt_list(): read item %i\n",
                      tkt_data.id);
*/
                  }
                else
                  {
                    printk(KERN_INFO "read_tkt_list(): item %i is outdated, skipped\n",
                           tkt_data.id);
                    tkt_list_head.dirty = TRUE;
                  }
	      }
	  }
	while (tmperr > 0); /* end of do */

	if (tmperr < 0)
	  {
            printk(KERN_WARNING "%s\n",
                    "read_tkt_list(): read error from file!");
            err = -RSBAC_EREADFAILED;
          }

end_read:
        /* Set current user space back to user space, because read() writes */
        /* to user space */
        set_fs(oldfs);

        if (rsbac_debug_ds_pm)
          printk(KERN_DEBUG "read_tkt_list(): %lu entries read.\n",
                 read_count);
        /* We do not need this file any more */
        rsbac_read_close(&file);
        
        return(err);
  }; /* end of read_tkt_list() */

/********************/

#ifndef CONFIG_RSBAC_NO_WRITE
static int write_tkt_list(void)
  {
    struct file                     file;
    int                             err = 0;
    struct rsbac_pm_tkt_list_item_t * current_p;
    mm_segment_t oldfs;
    u_long          write_count = 0, written = 0, bytes;
    int             tmperr = 0;
    u_long          flags;
    char          * buffer = NULL;
    u_long          buflen;
    boolean         vmalloc_used = FALSE;
    u_int           aci_version = RSBAC_PM_TKT_LIST_VERSION;

    /* test no_write */
    if(tkt_list_head.no_write)
      return(-RSBAC_ENOTWRITABLE);
    /* protect this list */
    rsbac_read_lock(&tkt_list_head.lock, &flags);
    /* allocate mem */
    buflen = sizeof(aci_version) + tkt_list_head.count * sizeof(*tkt_list_head.head);
    /* try to kmalloc, but only, if < max. kmalloc-cache_size */
    if(buflen < RSBAC_MAX_KMALLOC)
      buffer = (char *) kmalloc(buflen, GFP_KERNEL);
    /* If kmalloc failed, use vmalloc instead */
    if(!buffer)
      {
        buffer = (char *) vmalloc(buflen);
        vmalloc_used = TRUE;
        if(rsbac_debug_write)
          printk(KERN_DEBUG
                 "write_tkt_list(): vmalloc used!\n");
      }
    if(!buffer)
      {
        /* unprotect this list */
        rsbac_read_unlock(&tkt_list_head.lock, &flags);
        return(-RSBAC_ENOMEM);
      }
    /* copy version */
    memcpy(buffer,
           (char *) &aci_version,
           sizeof(aci_version));
    write_count = sizeof(aci_version);
    /* copy list */
    current_p = tkt_list_head.head;
    while (current_p) 
      {
        memcpy(buffer+write_count,
               (char *) &(current_p->data),
	       sizeof(current_p->data));
        current_p = current_p->next;
        write_count += sizeof(current_p->data);
      }
    /* unprotect this list */
    rsbac_read_unlock(&tkt_list_head.lock, &flags);

    /* get rsbac write-to-disk semaphore */
    down(&rsbac_write_sem);

    /* open file */
    if ((err = rsbac_write_open(RSBAC_PM_TKT_LIST_NAME,
                                &file,
                                ROOT_DEV) ))
      {
        up(&rsbac_write_sem);
        /* free buffer */
        if(vmalloc_used)
          vfree(buffer);
        else
          kfree(buffer);
        return(err);
      }

    /* OK, now we can start writing the buffer. */
    /* Set current user space to kernel space, because write() reads    */
    /* from user space */
    oldfs = get_fs();
    set_fs(KERNEL_DS);

    while ((written < write_count) && (tmperr >= 0)) 
      {
        bytes = min(write_count - written, RSBAC_MAX_WRITE_CHUNK);
        tmperr = file.f_op->write(&file,
                                  buffer+written,
	                          bytes,
	                          &file.f_pos);
        if(tmperr > 0)
          {
            written += tmperr;
          }
      }
    if (tmperr < 0)
      {
        printk(KERN_WARNING
               "write_tkt_list(): write error %i on file!\n",
               tmperr);
        err |= -RSBAC_EWRITEFAILED;
      }
    /* Set current user space back to user space, because write() reads */
    /* from user space */
    set_fs(oldfs);

    if (rsbac_debug_write)
      printk(KERN_DEBUG "write_tkt_list(): %lu entries written.\n",
             write_count / sizeof(current_p->data));
    /* End of write access                     */
    rsbac_write_close(&file);
    /* free overall sem */
    up(&rsbac_write_sem);
    /* free buffer */
    if(vmalloc_used)
      vfree(buffer);
    else
      kfree(buffer);
    return(err);
  }; /* end of write_tkt_list() */
#endif /* ifndef CONFIG_RSBAC_NO_WRITE */

/************************************************************************** */
/* The lookup functions return NULL, if the item is not found, and a        */
/* pointer to the item otherwise.                                           */

/****************/
/* Helper lists */
/****************/

/* lookup_task_set_subitem() */
/* lookup task set sub item, return pointer */
static struct rsbac_pm_task_set_sublist_item_t *
  lookup_task_set_subitem(struct rsbac_pm_task_set_list_item_t * set,
                          rsbac_pm_task_id_t task)
    {
      struct rsbac_pm_task_set_sublist_item_t  * curr;

      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != task) )
        curr = curr->next;
      return (curr);
    };

/* lookup_task_set() */
/* lookup task set item */
static struct rsbac_pm_task_set_list_item_t *
  lookup_task_set(rsbac_pm_task_set_id_t task_set)
    {
      struct rsbac_pm_task_set_list_item_t  * curr = task_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == task_set) )
        return (curr);
      else
        curr = task_set_list_head.head;
        while (curr && (curr->id != task_set) )
          curr = curr->next;

        if (curr)
          task_set_list_head.curr=curr;
        return (curr);
    };

/* lookup_tp_set_subitem() */
/* lookup tp set sub item, return pointer */
static struct rsbac_pm_tp_set_sublist_item_t *
  lookup_tp_set_subitem(struct rsbac_pm_tp_set_list_item_t * set,
                          rsbac_pm_tp_id_t tp)
    {
      struct rsbac_pm_tp_set_sublist_item_t  * curr;
      
      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != tp) )
        curr = curr->next;
      return (curr);
    };

/* lookup_tp_set() */
/* lookup tp set item */
static struct rsbac_pm_tp_set_list_item_t *
  lookup_tp_set(rsbac_pm_tp_set_id_t tp_set)
    {
      struct rsbac_pm_tp_set_list_item_t  * curr = tp_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == tp_set) )
        return (curr);
      else
        curr = tp_set_list_head.head;
        while (curr && (curr->id != tp_set) )
          curr = curr->next;

        if (curr)
          tp_set_list_head.curr=curr;
        return (curr);
    };

/* lookup_ru_set_subitem() */
/* lookup ru set sub item, return pointer */
static struct rsbac_pm_ru_set_sublist_item_t *
  lookup_ru_set_subitem(struct rsbac_pm_ru_set_list_item_t * set,
                          rsbac_uid_t ru)
    {
      struct rsbac_pm_ru_set_sublist_item_t  * curr;
      
      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != ru) )
        curr = curr->next;
      return (curr);
    };

/* lookup_ru_set() */
/* lookup ru set item */
static struct rsbac_pm_ru_set_list_item_t *
  lookup_ru_set(rsbac_pm_ru_set_id_t ru_set)
    {
      struct rsbac_pm_ru_set_list_item_t  * curr = ru_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == ru_set) )
        return (curr);
      else
        curr = ru_set_list_head.head;
        while (curr && (curr->id != ru_set) )
          curr = curr->next;

        if (curr)
          ru_set_list_head.curr=curr;
        return (curr);
    };

/* lookup_pp_set_subitem() */
/* lookup pp set sub item, return pointer */
static struct rsbac_pm_pp_set_sublist_item_t *
  lookup_pp_set_subitem(struct rsbac_pm_pp_set_list_item_t * set,
                        rsbac_pm_purpose_id_t pp)
    {
      struct rsbac_pm_pp_set_sublist_item_t  * curr;
      
      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != pp) )
        curr = curr->next;
      return (curr);
    };

/* lookup_pp_set() */
/* lookup pp set item */
static struct rsbac_pm_pp_set_list_item_t *
  lookup_pp_set(rsbac_pm_pp_set_id_t pp_set)
    {
      struct rsbac_pm_pp_set_list_item_t  * curr = pp_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == pp_set) )
        return (curr);
      else
        curr = pp_set_list_head.head;
        while (curr && (curr->id != pp_set) )
          curr = curr->next;

        if (curr)
          pp_set_list_head.curr=curr;
        return (curr);
    };

/* lookup_in_pp_set_subitem() */
/* lookup input pp set sub item, return pointer */
static struct rsbac_pm_in_pp_set_sublist_item_t *
  lookup_in_pp_set_subitem(struct rsbac_pm_in_pp_set_list_item_t * set,
                        rsbac_pm_purpose_id_t pp)
    {
      struct rsbac_pm_in_pp_set_sublist_item_t  * curr;
      
      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != pp) )
        curr = curr->next;
      return (curr);
    };

/* lookup_in_pp_set() */
/* lookup input pp set item */
static struct rsbac_pm_in_pp_set_list_item_t *
  lookup_in_pp_set(rsbac_pm_in_pp_set_id_t in_pp_set)
    {
      struct rsbac_pm_in_pp_set_list_item_t  * curr = in_pp_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == in_pp_set) )
        return (curr);
      else
        curr = in_pp_set_list_head.head;
        while (curr && (curr->id != in_pp_set) )
          curr = curr->next;

        if (curr)
          in_pp_set_list_head.curr=curr;
        return (curr);
    };

/* lookup_out_pp_set_subitem() */
/* lookup output pp set sub item, return pointer */
static struct rsbac_pm_out_pp_set_sublist_item_t *
  lookup_out_pp_set_subitem(struct rsbac_pm_out_pp_set_list_item_t * set,
                        rsbac_pm_purpose_id_t pp)
    {
      struct rsbac_pm_out_pp_set_sublist_item_t  * curr;
      
      if(!set)
        return(NULL);      
      curr = set->sublist_head;
      while (curr && (curr->id != pp) )
        curr = curr->next;
      return (curr);
    };

/* lookup_out_pp_set() */
/* lookup output pp set item */
static struct rsbac_pm_out_pp_set_list_item_t *
  lookup_out_pp_set(rsbac_pm_out_pp_set_id_t out_pp_set)
    {
      struct rsbac_pm_out_pp_set_list_item_t  * curr = out_pp_set_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->id == out_pp_set) )
        return (curr);
      else
        curr = out_pp_set_list_head.head;
        while (curr && (curr->id != out_pp_set) )
          curr = curr->next;

        if (curr)
          out_pp_set_list_head.curr=curr;
        return (curr);
    };

/**************/
/* Main lists */
/**************/

/* lookup_task() */
/* lookup task item */
static struct rsbac_pm_task_list_item_t *
  lookup_task(rsbac_pm_task_id_t task)
    {
      struct rsbac_pm_task_list_item_t  * curr = task_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.id == task) )
        return (curr);
      else
        curr = task_list_head.head;
        while (curr && (curr->data.id != task) )
          curr = curr->next;

        if (curr)
          task_list_head.curr=curr;
        return (curr);
    };

/* lookup_class() */
/* lookup class item */
static struct rsbac_pm_class_list_item_t *
  lookup_class(rsbac_pm_object_class_id_t object_class)
    {
      struct rsbac_pm_class_list_item_t  * curr = class_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.id == object_class) )
        return (curr);
      else
        curr = class_list_head.head;
        while (curr && (curr->data.id != object_class) )
          curr = curr->next;

        if (curr)
          class_list_head.curr=curr;
        return (curr);
    };

/* lookup_na() */
/* lookup na item */
static struct rsbac_pm_na_list_item_t *
  lookup_na(struct rsbac_pm_na_id_t na)
    {
      struct rsbac_pm_na_list_item_t  * curr = na_list_head.curr;
      
      if (rsbac_debug_ds_pm)
        printk(KERN_DEBUG "lookup_na(): Looking up (%i,%i,%i)\n",
               na.task,na.object_class,na.tp);
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.task  == na.task)
               && (curr->data.object_class == na.object_class)
               && (curr->data.tp    == na.tp) )
        return (curr);
      else
        curr = na_list_head.head;
        while (curr &&
                   (   (curr->data.task  != na.task)
                    || (curr->data.object_class != na.object_class)
                    || (curr->data.tp    != na.tp)
                   ) )
          curr = curr->next;

        if (curr)
          na_list_head.curr=curr;
        return (curr);
    };

/* lookup_cs() */
/* lookup cs item */
static struct rsbac_pm_cs_list_item_t *
  lookup_cs(struct rsbac_pm_cs_id_t cs)
    {
      struct rsbac_pm_cs_list_item_t  * curr = cs_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.purpose     == cs.purpose)
               && (curr->data.file.device == cs.file.device)
               && (curr->data.file.inode  == cs.file.inode ) )
        return (curr);
      else
        curr = cs_list_head.head;
        while (curr &&
                 (   (curr->data.purpose     != cs.purpose)
                  || (curr->data.file.device != cs.file.device)
                  || (curr->data.file.inode  != cs.file.inode )
                 )
              )
          curr = curr->next;

        if (curr)
          cs_list_head.curr=curr;
        return (curr);
    };

/* lookup_tp() */
/* lookup tp item */
static struct rsbac_pm_tp_list_item_t *
  lookup_tp(rsbac_pm_tp_id_t tp)
    {
      struct rsbac_pm_tp_list_item_t  * curr = tp_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.id == tp) )
        return (curr);
      else
        curr = tp_list_head.head;
        while (curr && (curr->data.id != tp) )
          curr = curr->next;

        if (curr)
          tp_list_head.curr=curr;
        return (curr);
    };

/* lookup_pp() */
/* lookup pp item */
static struct rsbac_pm_pp_list_item_t *
  lookup_pp(rsbac_pm_purpose_id_t pp)
    {
      struct rsbac_pm_pp_list_item_t  * curr = pp_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.id == pp) )
        return (curr);
      else
        curr = pp_list_head.head;
        while (curr && (curr->data.id != pp) )
          curr = curr->next;

        if (curr)
          pp_list_head.curr=curr;
        return (curr);
    };

/* lookup_tkt() */
/* lookup tkt item */
static struct rsbac_pm_tkt_list_item_t *
  lookup_tkt(rsbac_pm_tkt_id_t tkt)
    {
      struct rsbac_pm_tkt_list_item_t  * curr = tkt_list_head.curr;
      
      /* is the current item the one we look for? yes -> return, else search */
      if (curr && (curr->data.id  == tkt))
        return (curr);
      else
        curr = tkt_list_head.head;
        while (curr && (curr->data.id  != tkt) )
          curr = curr->next;

        if (curr)
          tkt_list_head.curr=curr;
        return (curr);
    };

/************************************************************************** */
/* The add_item() functions add an item to the list, set head.curr to it,   */
/* and return a pointer to the item.                                        */
/* These functions will NOT check, if there is already an item under the    */
/* same ID! If this happens, the lookup functions will return the old item! */
/* All list manipulation is protected by rw-spinlocks to prevent inconsistency */
/* and undefined behaviour in other concurrent functions.                   */

/* WARNING: Writing to disk is NOT done in these functions, because it would */
/* not work with read_list(). So write_list() must be called by the caller */
/* of these function afterwards!                                 */

/****************/
/* Helper lists */
/****************/

static struct rsbac_pm_task_set_sublist_item_t * 
         add_task_set_subitem(struct rsbac_pm_task_set_list_item_t * set,
                              rsbac_pm_task_id_t id)
    {
      struct rsbac_pm_task_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_task_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_task_set_list_item_t* 
         add_task_set_item(rsbac_pm_task_set_id_t id)
    {
      struct rsbac_pm_task_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_task_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!task_set_list_head.head)
        {
          task_set_list_head.head=new_item_p;
          task_set_list_head.tail=new_item_p;
          task_set_list_head.curr=new_item_p;
          task_set_list_head.count = 1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=task_set_list_head.tail;
          new_item_p->next=NULL;
          task_set_list_head.tail->next=new_item_p;
          task_set_list_head.tail=new_item_p;
          task_set_list_head.curr=new_item_p;
          task_set_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_tp_set_sublist_item_t * 
         add_tp_set_subitem(struct rsbac_pm_tp_set_list_item_t * set,
                              rsbac_pm_tp_id_t id)
    {
      struct rsbac_pm_tp_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_tp_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
          set->sublist_length=1;
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_tp_set_list_item_t* 
         add_tp_set_item(rsbac_pm_tp_set_id_t id)
    {
      struct rsbac_pm_tp_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_tp_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!tp_set_list_head.head)
        {
          tp_set_list_head.head=new_item_p;
          tp_set_list_head.tail=new_item_p;
          tp_set_list_head.curr=new_item_p;
          tp_set_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=tp_set_list_head.tail;
          new_item_p->next=NULL;
          tp_set_list_head.tail->next=new_item_p;
          tp_set_list_head.tail=new_item_p;
          tp_set_list_head.curr=new_item_p;
          tp_set_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_ru_set_sublist_item_t * 
         add_ru_set_subitem(struct rsbac_pm_ru_set_list_item_t * set,
                            rsbac_uid_t id)
    {
      struct rsbac_pm_ru_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_ru_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
          set->sublist_length=1;
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_ru_set_list_item_t* 
         add_ru_set_item(rsbac_pm_ru_set_id_t id)
    {
      struct rsbac_pm_ru_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_ru_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!ru_set_list_head.head)
        {
          ru_set_list_head.head=new_item_p;
          ru_set_list_head.tail=new_item_p;
          ru_set_list_head.curr=new_item_p;
          ru_set_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=ru_set_list_head.tail;
          new_item_p->next=NULL;
          ru_set_list_head.tail->next=new_item_p;
          ru_set_list_head.tail=new_item_p;
          ru_set_list_head.curr=new_item_p;
          ru_set_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_pp_set_sublist_item_t * 
         add_pp_set_subitem(struct rsbac_pm_pp_set_list_item_t * set,
                              rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_pp_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_pp_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
          set->sublist_length=1;
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_pp_set_list_item_t* 
         add_pp_set_item(rsbac_pm_pp_set_id_t id)
    {
      struct rsbac_pm_pp_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_pp_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!pp_set_list_head.head)
        {
          pp_set_list_head.head=new_item_p;
          pp_set_list_head.tail=new_item_p;
          pp_set_list_head.curr=new_item_p;
          pp_set_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=pp_set_list_head.tail;
          new_item_p->next=NULL;
          pp_set_list_head.tail->next=new_item_p;
          pp_set_list_head.tail=new_item_p;
          pp_set_list_head.curr=new_item_p;
          pp_set_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_in_pp_set_sublist_item_t * 
         add_in_pp_set_subitem(struct rsbac_pm_in_pp_set_list_item_t * set,
                              rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_in_pp_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_in_pp_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
          set->sublist_length=1;
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_in_pp_set_list_item_t* 
         add_in_pp_set_item(rsbac_pm_in_pp_set_id_t id)
    {
      struct rsbac_pm_in_pp_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_in_pp_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!in_pp_set_list_head.head)
        {
          in_pp_set_list_head.head=new_item_p;
          in_pp_set_list_head.tail=new_item_p;
          in_pp_set_list_head.curr=new_item_p;
          in_pp_set_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=in_pp_set_list_head.tail;
          new_item_p->next=NULL;
          in_pp_set_list_head.tail->next=new_item_p;
          in_pp_set_list_head.tail=new_item_p;
          in_pp_set_list_head.curr=new_item_p;
          in_pp_set_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_out_pp_set_sublist_item_t * 
         add_out_pp_set_subitem(struct rsbac_pm_out_pp_set_list_item_t * set,
                              rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_out_pp_set_sublist_item_t * new_item_p = NULL;

      if(!set)
        return(NULL);      
      if ( !(new_item_p = (struct rsbac_pm_out_pp_set_sublist_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      
      if (!set->sublist_head)
        {
          set->sublist_head=new_item_p;
          set->sublist_tail=new_item_p;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
          set->sublist_length=1;
        }  
      else
        {
          new_item_p->prev=set->sublist_tail;
          new_item_p->next=NULL;
          set->sublist_tail->next=new_item_p;
          set->sublist_tail=new_item_p;
          set->sublist_length++;
        };
      return(new_item_p);
    };


static struct rsbac_pm_out_pp_set_list_item_t* 
         add_out_pp_set_item(rsbac_pm_out_pp_set_id_t id)
    {
      struct rsbac_pm_out_pp_set_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_out_pp_set_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->id = id;
      new_item_p->sublist_length = 0;
      new_item_p->sublist_head = NULL;
      new_item_p->sublist_tail = NULL;
      
      if (!out_pp_set_list_head.head)
        {
          out_pp_set_list_head.head=new_item_p;
          out_pp_set_list_head.tail=new_item_p;
          out_pp_set_list_head.curr=new_item_p;
          out_pp_set_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=out_pp_set_list_head.tail;
          new_item_p->next=NULL;
          out_pp_set_list_head.tail->next=new_item_p;
          out_pp_set_list_head.tail=new_item_p;
          out_pp_set_list_head.curr=new_item_p;
          out_pp_set_list_head.count++;
        };
      return(new_item_p);
    };


/**************/
/* Main lists */
/**************/

static struct rsbac_pm_task_list_item_t* 
         add_task_item(struct rsbac_pm_task_data_t data)
    {
      struct rsbac_pm_task_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_task_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!task_list_head.head)
        {
          task_list_head.head=new_item_p;
          task_list_head.tail=new_item_p;
          task_list_head.curr=new_item_p;
          task_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=task_list_head.tail;
          new_item_p->next=NULL;
          task_list_head.tail->next=new_item_p;
          task_list_head.tail=new_item_p;
          task_list_head.curr=new_item_p;
          task_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_class_list_item_t* 
         add_class_item(struct rsbac_pm_class_data_t data)
    {
      struct rsbac_pm_class_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_class_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!class_list_head.head)
        {
          class_list_head.head=new_item_p;
          class_list_head.tail=new_item_p;
          class_list_head.curr=new_item_p;
          class_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=class_list_head.tail;
          new_item_p->next=NULL;
          class_list_head.tail->next=new_item_p;
          class_list_head.tail=new_item_p;
          class_list_head.curr=new_item_p;
          class_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_na_list_item_t* 
         add_na_item(struct rsbac_pm_na_data_t data)
    {
      struct rsbac_pm_na_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_na_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!na_list_head.head)
        {
          na_list_head.head=new_item_p;
          na_list_head.tail=new_item_p;
          na_list_head.curr=new_item_p;
          na_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=na_list_head.tail;
          new_item_p->next=NULL;
          na_list_head.tail->next=new_item_p;
          na_list_head.tail=new_item_p;
          na_list_head.curr=new_item_p;
          na_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_cs_list_item_t* 
         add_cs_item(struct rsbac_pm_cs_data_t data)
    {
      struct rsbac_pm_cs_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_cs_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!cs_list_head.head)
        {
          cs_list_head.head=new_item_p;
          cs_list_head.tail=new_item_p;
          cs_list_head.curr=new_item_p;
          cs_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=cs_list_head.tail;
          new_item_p->next=NULL;
          cs_list_head.tail->next=new_item_p;
          cs_list_head.tail=new_item_p;
          cs_list_head.curr=new_item_p;
          cs_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_tp_list_item_t* 
         add_tp_item(struct rsbac_pm_tp_data_t data)
    {
      struct rsbac_pm_tp_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_tp_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!tp_list_head.head)
        {
          tp_list_head.head=new_item_p;
          tp_list_head.tail=new_item_p;
          tp_list_head.curr=new_item_p;
          tp_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=tp_list_head.tail;
          new_item_p->next=NULL;
          tp_list_head.tail->next=new_item_p;
          tp_list_head.tail=new_item_p;
          tp_list_head.curr=new_item_p;
          tp_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_pp_list_item_t* 
         add_pp_item(struct rsbac_pm_pp_data_t data)
    {
      struct rsbac_pm_pp_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_pp_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!pp_list_head.head)
        {
          pp_list_head.head=new_item_p;
          pp_list_head.tail=new_item_p;
          pp_list_head.curr=new_item_p;
          pp_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=pp_list_head.tail;
          new_item_p->next=NULL;
          pp_list_head.tail->next=new_item_p;
          pp_list_head.tail=new_item_p;
          pp_list_head.curr=new_item_p;
          pp_list_head.count++;
        };
      return(new_item_p);
    };

static struct rsbac_pm_tkt_list_item_t* 
         add_tkt_item(struct rsbac_pm_tkt_data_t data)
    {
      struct rsbac_pm_tkt_list_item_t * new_item_p = NULL;

      if ( !(new_item_p = (struct rsbac_pm_tkt_list_item_t *)
                 kmalloc(sizeof(*new_item_p),GFP_KERNEL)) )
        return(NULL);
      new_item_p->data = data;
      
      if (!tkt_list_head.head)
        {
          tkt_list_head.head=new_item_p;
          tkt_list_head.tail=new_item_p;
          tkt_list_head.curr=new_item_p;
          tkt_list_head.count=1;
          new_item_p->prev=NULL;
          new_item_p->next=NULL;          
        }  
      else
        {
          new_item_p->prev=tkt_list_head.tail;
          new_item_p->next=NULL;
          tkt_list_head.tail->next=new_item_p;
          tkt_list_head.tail=new_item_p;
          tkt_list_head.curr=new_item_p;
          tkt_list_head.count++;
        };
      return(new_item_p);
    };

/************************************************************************** */
/* The remove_item() functions remove an item from the list. If this item   */
/* is head, tail or curr, these pointers are set accordingly.               */
/* To speed up removing several subsequent items, curr is set to the next   */
/* item, if possible.                                                       */
/* If the item is not found, nothing is done.                               */

/****************/
/* Helper lists */
/****************/

static void remove_task_set_subitem(struct rsbac_pm_task_set_list_item_t * set,
                                    rsbac_pm_task_id_t id)
    {
      struct rsbac_pm_task_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_task_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_task_set_subitem() */


static void
  remove_all_task_set_subitems(struct rsbac_pm_task_set_list_item_t * set_p)
    {
      struct rsbac_pm_task_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_task_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_task_set_subitems() */


static void remove_task_set_item(rsbac_pm_task_set_id_t id)
    {
      struct rsbac_pm_task_set_list_item_t * item_p;
      struct rsbac_pm_task_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_task_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_task_set(id)) )
        { /* ok, item was found */
          if ( (task_set_list_head.head == item_p) )
             { /* item is head */
               if ( (task_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   task_set_list_head.head = NULL;
                   task_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   task_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (task_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   task_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          task_set_list_head.curr=NULL;
          /* adjust count */
          task_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_task_set_item() */

/*****************/
 
static void remove_tp_set_subitem(struct rsbac_pm_tp_set_list_item_t * set,
                                    rsbac_pm_tp_id_t id)
    {
      struct rsbac_pm_tp_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_tp_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_tp_set_subitem() */


static void
  remove_all_tp_set_subitems(struct rsbac_pm_tp_set_list_item_t * set_p)
    {
      struct rsbac_pm_tp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_tp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_tp_set_subitems() */


static void remove_tp_set_item(rsbac_pm_tp_set_id_t id)
    {
      struct rsbac_pm_tp_set_list_item_t * item_p;
      struct rsbac_pm_tp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_tp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_tp_set(id)) )
        { /* ok, item was found */
          if ( (tp_set_list_head.head == item_p) )
             { /* item is head */
               if ( (tp_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   tp_set_list_head.head = NULL;
                   tp_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   tp_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (tp_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   tp_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          tp_set_list_head.curr=NULL;
          /* adjust count */
          tp_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_tp_set_item() */
 
/*****************/
 
static void remove_ru_set_subitem(struct rsbac_pm_ru_set_list_item_t * set,
                                  rsbac_uid_t id)
    {
      struct rsbac_pm_ru_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_ru_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_ru_set_subitem() */

static void
  remove_all_ru_set_subitems(struct rsbac_pm_ru_set_list_item_t * set_p)
    {
      struct rsbac_pm_ru_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_ru_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_ru_set_subitems() */


static void remove_ru_set_item(rsbac_pm_ru_set_id_t id)
    {
      struct rsbac_pm_ru_set_list_item_t * item_p;
      struct rsbac_pm_ru_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_ru_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_ru_set(id)) )
        { /* ok, item was found */
          if ( (ru_set_list_head.head == item_p) )
             { /* item is head */
               if ( (ru_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   ru_set_list_head.head = NULL;
                   ru_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   ru_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (ru_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   ru_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          ru_set_list_head.curr=NULL;
          /* adjust count */
          ru_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_ru_set_item() */
 
/*****************/

static void remove_pp_set_subitem(struct rsbac_pm_pp_set_list_item_t * set,
                                  rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_pp_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_pp_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_pp_set_subitem() */

static void
  remove_all_pp_set_subitems(struct rsbac_pm_pp_set_list_item_t * set_p)
    {
      struct rsbac_pm_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_pp_set_subitems() */

static void remove_pp_set_item(rsbac_pm_pp_set_id_t id)
    {
      struct rsbac_pm_pp_set_list_item_t * item_p;
      struct rsbac_pm_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_pp_set(id)) )
        { /* ok, item was found */
          if ( (pp_set_list_head.head == item_p) )
             { /* item is head */
               if ( (pp_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   pp_set_list_head.head = NULL;
                   pp_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   pp_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (pp_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   pp_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          pp_set_list_head.curr=NULL;
          /* adjust count */
          pp_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_pp_set_item() */
 
/*****************/

static void remove_in_pp_set_subitem(struct rsbac_pm_in_pp_set_list_item_t * set,
                                     rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_in_pp_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_in_pp_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_in_pp_set_subitem() */

static void
  remove_all_in_pp_set_subitems(struct rsbac_pm_in_pp_set_list_item_t * set_p)
    {
      struct rsbac_pm_in_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_in_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_in_pp_set_subitems() */

static void remove_in_pp_set_item(rsbac_pm_in_pp_set_id_t id)
    {
      struct rsbac_pm_in_pp_set_list_item_t * item_p;
      struct rsbac_pm_in_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_in_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_in_pp_set(id)) )
        { /* ok, item was found */
          if ( (in_pp_set_list_head.head == item_p) )
             { /* item is head */
               if ( (in_pp_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   in_pp_set_list_head.head = NULL;
                   in_pp_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   in_pp_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (in_pp_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   in_pp_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          in_pp_set_list_head.curr=NULL;
          /* adjust count */
          in_pp_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_in_pp_set_item() */
/*****************/

static void remove_out_pp_set_subitem(struct rsbac_pm_out_pp_set_list_item_t * set,
                                     rsbac_pm_purpose_id_t id)
    {
      struct rsbac_pm_out_pp_set_sublist_item_t * item_p;
    
      /* first we must locate the item. */
      if (set && (item_p = lookup_out_pp_set_subitem(set,id)) )
        { /* ok, item was found */
          if ( (set->sublist_head == item_p) )
             { /* item is head */
               if ( (set->sublist_tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   set->sublist_head = NULL;
                   set->sublist_tail = NULL;
                   set->sublist_length = 0;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   set->sublist_head = item_p->next;
                   set->sublist_length--;
                 };
             }
          else
             { /* item is not head */
               if ( (set->sublist_tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   set->sublist_tail = item_p->prev;
                   set->sublist_length--;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                   set->sublist_length--;
                 };
             };
             
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_out_pp_set_subitem() */

static void
  remove_all_out_pp_set_subitems(struct rsbac_pm_out_pp_set_list_item_t * set_p)
    {
      struct rsbac_pm_out_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_out_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if (set_p)
        { /* ok, valid set pointer */
          /* remove all subitems from memory */
          sub_item_p = set_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          /* adjust start pointers */
          set_p->sublist_head = NULL;
          set_p->sublist_tail = NULL;
          set_p->sublist_length = 0;
        };  /* end of if: item was found */

    }; /* end of remove_all_out_pp_set_subitems() */

static void remove_out_pp_set_item(rsbac_pm_out_pp_set_id_t id)
    {
      struct rsbac_pm_out_pp_set_list_item_t * item_p;
      struct rsbac_pm_out_pp_set_sublist_item_t * sub_item_p;
      struct rsbac_pm_out_pp_set_sublist_item_t * next_sub_item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_out_pp_set(id)) )
        { /* ok, item was found */
          if ( (out_pp_set_list_head.head == item_p) )
             { /* item is head */
               if ( (out_pp_set_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   out_pp_set_list_head.head = NULL;
                   out_pp_set_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   out_pp_set_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (out_pp_set_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   out_pp_set_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          out_pp_set_list_head.curr=NULL;
          /* adjust count */
          out_pp_set_list_head.count--;
          /* now we can remove the item from memory, but first the sub-items */
          sub_item_p = item_p->sublist_head;
          while(sub_item_p)
            {
              next_sub_item_p = sub_item_p->next;
              kfree(sub_item_p);
              sub_item_p = next_sub_item_p;
            }
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_out_pp_set_item() */
 
/**************/
/* Main lists */
/**************/

static void remove_task_item(rsbac_pm_task_id_t task)
    {
      struct rsbac_pm_task_list_item_t * item_p;
      u_long flags;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_task(task)) )
        { /* ok, item was found */
          /* task items can have an attached tp_set -> remove first */
          if(item_p->data.tp_set)
            {
              rsbac_write_lock(&tp_set_list_head.lock, &flags);
              remove_tp_set_item(item_p->data.tp_set);
              rsbac_write_unlock(&tp_set_list_head.lock, &flags);
            }
          /* task items can also have an attached ru_set -> remove first */
          if(item_p->data.ru_set)
            {
              rsbac_write_lock(&ru_set_list_head.lock, &flags);
              remove_ru_set_item(item_p->data.ru_set);
              rsbac_write_unlock(&ru_set_list_head.lock, &flags);
            }
          
          if ( (task_list_head.head == item_p) )
             { /* item is head */
               if ( (task_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   task_list_head.head = NULL;
                   task_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   task_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (task_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   task_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          task_list_head.curr=NULL;
          /* adjust count */
          task_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_task_item() */

static void remove_class_item(rsbac_pm_object_class_id_t object_class)
    {
      struct rsbac_pm_class_list_item_t * item_p;
      u_long flags;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_class(object_class)) )
        { /* ok, item was found */
          /* class items can have an attached pp_set -> remove first */
          if(item_p->data.pp_set)
            {
              rsbac_write_lock(&pp_set_list_head.lock, &flags);
              remove_pp_set_item(item_p->data.pp_set);
              rsbac_write_unlock(&pp_set_list_head.lock, &flags);
            }
          
          if ( (class_list_head.head == item_p) )
             { /* item is head */
               if ( (class_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   class_list_head.head = NULL;
                   class_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   class_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (class_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   class_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          class_list_head.curr=NULL;
          /* adjust count */
          class_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_class_item() */

static void remove_na_item(struct rsbac_pm_na_id_t na)
    {
      struct rsbac_pm_na_list_item_t * item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_na(na)) )
        { /* ok, item was found */
          if ( (na_list_head.head == item_p) )
             { /* item is head */
               if ( (na_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   na_list_head.head = NULL;
                   na_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   na_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (na_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   na_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          na_list_head.curr=NULL;
          /* adjust count */
          na_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
          /* since the list was changed, it must be saved to disk */
          na_list_head.dirty = TRUE;
        };  /* end of if: item was found */

    }; /* end of remove_na_item() */

static void remove_cs_item(struct rsbac_pm_cs_id_t cs)
    {
      struct rsbac_pm_cs_list_item_t * item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_cs(cs)) )
        { /* ok, item was found */
          if ( (cs_list_head.head == item_p) )
             { /* item is head */
               if ( (cs_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   cs_list_head.head = NULL;
                   cs_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   cs_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (cs_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   cs_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          cs_list_head.curr=NULL;
          /* adjust count */
          cs_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_cs_item() */

static void remove_tp_item(rsbac_pm_tp_id_t tp)
    {
      struct rsbac_pm_tp_list_item_t * item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_tp(tp)) )
        { /* ok, item was found */
          if ( (tp_list_head.head == item_p) )
             { /* item is head */
               if ( (tp_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   tp_list_head.head = NULL;
                   tp_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   tp_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (tp_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   tp_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          tp_list_head.curr=NULL;
          /* adjust count */
          tp_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_tp_item() */

static void remove_pp_item(rsbac_pm_purpose_id_t pp)
    {
      struct rsbac_pm_pp_list_item_t * item_p;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_pp(pp)) )
        { /* ok, item was found */
          if ( (pp_list_head.head == item_p) )
             { /* item is head */
               if ( (pp_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   pp_list_head.head = NULL;
                   pp_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   pp_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (pp_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   pp_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          pp_list_head.curr=NULL;
          /* adjust count */
          pp_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_pp_item() */

static void remove_tkt_item(rsbac_pm_tkt_id_t tkt)
    {
      struct rsbac_pm_tkt_list_item_t * item_p;
      u_long flags;
    
      /* first we must locate the item. */
      if ( (item_p = lookup_tkt(tkt)) )
        { /* ok, item was found */
          /* special case: ticket for add_object_class can have an attached */
          /* pp_set -> remove first */
          if(item_p->data.function_type == PTF_add_object_class)
            {
              rsbac_write_lock(&pp_set_list_head.lock, &flags);
              remove_pp_set_item(item_p->data.function_param.tkt_add_object_class.pp_set);
              rsbac_write_unlock(&pp_set_list_head.lock, &flags);
            }
          
          if ( (tkt_list_head.head == item_p) )
             { /* item is head */
               if ( (tkt_list_head.tail == item_p) )
                 { /* item is head and tail = only item -> list will be empty*/
                   tkt_list_head.head = NULL;
                   tkt_list_head.tail = NULL;
                 }
               else
                 { /* item is head, but not tail -> next item becomes head */
                   item_p->next->prev = NULL;
                   tkt_list_head.head = item_p->next;
                 };
             }
          else
             { /* item is not head */
               if ( (tkt_list_head.tail == item_p) )
                 { /*item is not head, but tail -> previous item becomes tail*/
                   item_p->prev->next = NULL;
                   tkt_list_head.tail = item_p->prev;
                 }
               else
                 { /* item is neither head nor tail -> item is cut out */
                   item_p->prev->next = item_p->next;
                   item_p->next->prev = item_p->prev;
                 };
             };
             
          /* curr is no longer valid -> reset */
          tkt_list_head.curr=NULL;
          /* adjust count */
          tkt_list_head.count--;
          /* now we can remove the item from memory */
          kfree(item_p);    
        };  /* end of if: item was found */

    }; /* end of remove_tkt_item() */


/************************************************* */
/*               proc functions                    */
/************************************************* */

#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
static int
stats_pm_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
#else
static int
stats_pm_proc_info(char *buffer, char **start, off_t offset, int length)
#endif
{
    u_int len = 0;
    off_t pos   = 0;
    off_t begin = 0;

    struct rsbac_pm_task_set_list_item_t   * task_set_item_p;
    struct rsbac_pm_tp_set_list_item_t     * tp_set_item_p;
    struct rsbac_pm_ru_set_list_item_t     * ru_set_item_p;
    struct rsbac_pm_pp_set_list_item_t     * pp_set_item_p;
    struct rsbac_pm_in_pp_set_list_item_t     * in_pp_set_item_p;
    struct rsbac_pm_out_pp_set_list_item_t     * out_pp_set_item_p;
    u_int                                    task_set_count = 0;
    u_int                                    tp_set_count = 0;
    u_int                                    ru_set_count = 0;
    u_int                                    pp_set_count = 0;
    u_int                                    in_pp_set_count = 0;
    u_int                                    out_pp_set_count = 0;
    u_long                                   all_set_count = 0;
    u_long                                   all_member_count = 0;
    u_int                                    member_count = 0;

    u_long                               all_count = 0;
    
    u_int                                count = 0;
    u_long flags;
  
    union rsbac_target_id_t       rsbac_target_id;
    union rsbac_attribute_value_t rsbac_attribute_value;

    if (!rsbac_is_initialized)
      {
        printk(KERN_WARNING "stats_pm_proc_info(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (rsbac_debug_aef_pm)
      printk(KERN_DEBUG "stats_pm_proc_info(): calling ADF\n");
    rsbac_target_id.scd = ST_rsbac;
    rsbac_attribute_value.dummy = 0;
    if (!rsbac_adf_request(R_GET_STATUS_DATA,
                           current->pid,
                           T_SCD,
                           rsbac_target_id,
                           A_none,
                           rsbac_attribute_value))
      {
        return -EPERM;
      }

    len += sprintf(buffer, "PM Status\n---------\n");

/****************/
/* Helper lists */
/****************/

    /* protect task set list */
    rsbac_read_lock(&task_set_list_head.lock, &flags);
    if(task_set_list_head.dirty)
      count++;
    task_set_item_p = task_set_list_head.head;
    member_count = 0;
    while (task_set_item_p)
      {
        task_set_count++;
        member_count += task_set_item_p->sublist_length;
        task_set_item_p = task_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&task_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u task-set-items, sum of %u members\n",
                 task_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count = task_set_count;
    all_member_count += member_count;

    /* protect tp set list */
    rsbac_read_lock(&tp_set_list_head.lock, &flags);
    if(tp_set_list_head.dirty)
      count++;
    tp_set_item_p = tp_set_list_head.head;
    member_count = 0;
    while (tp_set_item_p)
      {
        tp_set_count++;
        member_count += tp_set_item_p->sublist_length;
        tp_set_item_p = tp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&tp_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u tp-set-items, sum of %u members\n",
                 tp_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count += tp_set_count;
    all_member_count += member_count;
  
    /* protect ru set list */
    rsbac_read_lock(&ru_set_list_head.lock, &flags);
    if(ru_set_list_head.dirty)
      count++;
    ru_set_item_p = ru_set_list_head.head;
    member_count = 0;
    while (ru_set_item_p)
      {
        ru_set_count++;
        member_count += ru_set_item_p->sublist_length;
        ru_set_item_p = ru_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&ru_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u ru-set-items, sum of %u members\n",
                 ru_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count += ru_set_count;
    all_member_count += member_count;
  
    /* protect pp set list */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    if(pp_set_list_head.dirty)
      count++;
    pp_set_item_p = pp_set_list_head.head;
    member_count = 0;
    while (pp_set_item_p)
      {
        pp_set_count++;
        member_count += pp_set_item_p->sublist_length;
        pp_set_item_p = pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u pp-set-items, sum of %u members\n",
                 pp_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count += pp_set_count;
    all_member_count += member_count;

    /* protect in_pp set list */
    rsbac_read_lock(&in_pp_set_list_head.lock, &flags);
    if(in_pp_set_list_head.dirty)
      count++;
    in_pp_set_item_p = in_pp_set_list_head.head;
    member_count = 0;
    while (in_pp_set_item_p)
      {
        in_pp_set_count++;
        member_count += in_pp_set_item_p->sublist_length;
        in_pp_set_item_p = in_pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u in-pp-set-items, sum of %u members\n",
                 in_pp_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count += in_pp_set_count;
    all_member_count += member_count;

    /* protect out_pp set list */
    rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
    if(out_pp_set_list_head.dirty)
      count++;
    out_pp_set_item_p = out_pp_set_list_head.head;
    member_count = 0;
    while (out_pp_set_item_p)
      {
        out_pp_set_count++;
        member_count += out_pp_set_item_p->sublist_length;
        out_pp_set_item_p = out_pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
    len += sprintf(buffer + len, "%u out-pp-set-items, sum of %u members\n",
                 out_pp_set_count,member_count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_set_count += out_pp_set_count;
    all_member_count += member_count;
    len += sprintf(buffer + len, "Total of %lu registered rsbac-pm-set-items, %lu members, %u lists dirty\n",
                 all_set_count, all_member_count,count);

/**************/
/* Main lists */
/**************/
    count = 0;

    /* task list */
    if(task_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u task-items\n",
                 task_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count = task_list_head.count;
    
    /* class list */
    if(class_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u class-items\n",
                 class_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += class_list_head.count;
    
    /* na list */
    if(na_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u necessary-access-items\n",
                 na_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += na_list_head.count;
    
    /* cs list */
    if(cs_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u consent-items\n",
                 cs_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += cs_list_head.count;
    
    /* tp list */
    if(tp_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u transformation-procedure-items\n",
                 tp_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += tp_list_head.count;
    
    /* pp list */
    if(pp_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u purpose-items\n",
                 pp_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += pp_list_head.count;
    
    /* tkt list */
    if(tkt_list_head.dirty)
      count++;
    len += sprintf(buffer + len, "%u ticket-items\n",
                 tkt_list_head.count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }
    if (pos > offset+length)
      goto out;
    all_count += tkt_list_head.count;
    
    len += sprintf(buffer + len, "Total of %lu registered rsbac-pm-items, %u lists dirty\n",
                 all_count, count);
    pos = begin + len;
    if (pos < offset)
      {
        len = 0;
        begin = pos;
      }

out:
  *start = buffer + (offset - begin);
  len -= (offset - begin);
  
  if (len > length)
    len = length;
  return len;
}
#endif /* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */

/************************************************* */
/*               Init functions                    */
/************************************************* */

/* All functions return 0, if no error occurred, and a negative error code  */
/* otherwise. The error codes are defined in rsbac/error.h.                 */

/************************************************************************** */
/* Initialization of all PM data structures. After this call, all PM data   */
/* is kept in memory for performance reasons, but is written to disk on     */
/* every change.    */

/* Because there can be no access to aci data structures before init,       */
/* rsbac_init_pm() will initialize all rw-spinlocks to unlocked.            */

inline int __init rsbac_init_pm(void)
  {
    int  err = 0;
    int  tmperr = 0;
    u_long flags;
    struct proc_dir_entry * tmp_entry_p;

    if (rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_init_pm(): RSBAC already initialized\n");
        return(-RSBAC_EREINIT);
      }

    /* set rw-spinlocks to unlocked status and init data structures */
    printk(KERN_INFO "rsbac_init_pm(): Initializing RSBAC: PM subsystem\n");

/* Helper lists */
    task_set_list_head.lock=RW_LOCK_UNLOCKED;
    task_set_list_head.head = NULL;
    task_set_list_head.tail = NULL;
    task_set_list_head.curr = NULL;
    task_set_list_head.dirty = FALSE;
    task_set_list_head.count = 0;
    task_set_list_head.no_write = FALSE;
    tp_set_list_head.lock=RW_LOCK_UNLOCKED;
    tp_set_list_head.head = NULL;
    tp_set_list_head.tail = NULL;
    tp_set_list_head.curr = NULL;
    tp_set_list_head.dirty = FALSE;
    tp_set_list_head.count = 0;
    tp_set_list_head.no_write = FALSE;
    ru_set_list_head.lock=RW_LOCK_UNLOCKED;
    ru_set_list_head.head = NULL;
    ru_set_list_head.tail = NULL;
    ru_set_list_head.curr = NULL;
    ru_set_list_head.dirty = FALSE;
    ru_set_list_head.count = 0;
    ru_set_list_head.no_write = FALSE;
    pp_set_list_head.lock=RW_LOCK_UNLOCKED;
    pp_set_list_head.head = NULL;
    pp_set_list_head.tail = NULL;
    pp_set_list_head.curr = NULL;
    pp_set_list_head.dirty = FALSE;
    pp_set_list_head.count = 0;
    pp_set_list_head.no_write = FALSE;
    in_pp_set_list_head.lock=RW_LOCK_UNLOCKED;
    in_pp_set_list_head.head = NULL;
    in_pp_set_list_head.tail = NULL;
    in_pp_set_list_head.curr = NULL;
    in_pp_set_list_head.dirty = FALSE;
    in_pp_set_list_head.count = 0;
    out_pp_set_list_head.lock=RW_LOCK_UNLOCKED;
    out_pp_set_list_head.head = NULL;
    out_pp_set_list_head.tail = NULL;
    out_pp_set_list_head.curr = NULL;
    out_pp_set_list_head.dirty = FALSE;
    out_pp_set_list_head.count = 0;

/* Main lists */
    task_list_head.lock=RW_LOCK_UNLOCKED;
    task_list_head.head = NULL;
    task_list_head.tail = NULL;
    task_list_head.curr = NULL;
    task_list_head.dirty = FALSE;
    task_list_head.count = 0;
    task_list_head.no_write = FALSE;
    class_list_head.lock=RW_LOCK_UNLOCKED;
    class_list_head.head = NULL;
    class_list_head.tail = NULL;
    class_list_head.curr = NULL;
    class_list_head.dirty = FALSE;
    class_list_head.count = 0;
    class_list_head.no_write = FALSE;
    na_list_head.lock=RW_LOCK_UNLOCKED;
    na_list_head.head = NULL;
    na_list_head.tail = NULL;
    na_list_head.curr = NULL;
    na_list_head.dirty = FALSE;
    na_list_head.count = 0;
    na_list_head.no_write = FALSE;
    cs_list_head.lock=RW_LOCK_UNLOCKED;
    cs_list_head.head = NULL;
    cs_list_head.tail = NULL;
    cs_list_head.curr = NULL;
    cs_list_head.dirty = FALSE;
    cs_list_head.count = 0;
    cs_list_head.no_write = FALSE;
    tp_list_head.lock=RW_LOCK_UNLOCKED;
    tp_list_head.head = NULL;
    tp_list_head.tail = NULL;
    tp_list_head.curr = NULL;
    tp_list_head.dirty = FALSE;
    tp_list_head.count = 0;
    tp_list_head.no_write = FALSE;
    pp_list_head.lock=RW_LOCK_UNLOCKED;
    pp_list_head.head = NULL;
    pp_list_head.tail = NULL;
    pp_list_head.curr = NULL;
    pp_list_head.dirty = FALSE;
    pp_list_head.count = 0;
    pp_list_head.no_write = FALSE;
    tkt_list_head.lock=RW_LOCK_UNLOCKED;
    tkt_list_head.head = NULL;
    tkt_list_head.tail = NULL;
    tkt_list_head.curr = NULL;
    tkt_list_head.dirty = FALSE;
    tkt_list_head.count = 0;
    tkt_list_head.no_write = FALSE;

    /* read all data */
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): Reading data\n");

/* Helper lists */
    /* read task set data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading task set list\n");
    rsbac_write_lock(&task_set_list_head.lock, &flags);
    if ((tmperr = read_task_set_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): task set data could not be read!\n");
      };
    rsbac_write_unlock(&task_set_list_head.lock, &flags);
    err |= tmperr;

    /* read tp set data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading tp set list\n");
    rsbac_write_lock(&tp_set_list_head.lock, &flags);
    if ((tmperr = read_tp_set_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): tp set data could not be read!\n");
      };
    rsbac_write_unlock(&tp_set_list_head.lock, &flags);
    err |= tmperr;

    /* read ru set data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading ru set list\n");
    rsbac_write_lock(&ru_set_list_head.lock, &flags);
    if ((tmperr = read_ru_set_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): ru set data could not be read!\n");
      };
    rsbac_write_unlock(&ru_set_list_head.lock, &flags);
    err |= tmperr;

    /* read pp set data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading pp set list\n");
    rsbac_write_lock(&pp_set_list_head.lock, &flags);
    if ((tmperr = read_pp_set_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): pp set data could not be read!\n");
      };
    rsbac_write_unlock(&pp_set_list_head.lock, &flags);
    err |= tmperr;

/* Main lists */
    /* read task data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading task list\n");
    rsbac_write_lock(&task_list_head.lock, &flags);
    if ((tmperr = read_task_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): task data could not be read!\n");
      };
    rsbac_write_unlock(&task_list_head.lock, &flags);
    err |= tmperr;

    /* read class data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading class list\n");
    rsbac_write_lock(&class_list_head.lock, &flags);
    if ((tmperr = read_class_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): class data could not be read!\n");
      };
    rsbac_write_unlock(&class_list_head.lock, &flags);
    err |= tmperr;

    /* read na data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading necessary accesses list\n");
    rsbac_write_lock(&na_list_head.lock, &flags);
    if ((tmperr = read_na_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): necessary accesses data could not be read!\n");
      };
    rsbac_write_unlock(&na_list_head.lock, &flags);
    err |= tmperr;

    /* read cs data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading consent list\n");
    rsbac_write_lock(&cs_list_head.lock, &flags);
    if ((tmperr = read_cs_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): consent data could not be read!\n");
      };
    rsbac_write_unlock(&cs_list_head.lock, &flags);
    err |= tmperr;

    /* read tp data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading tp list\n");
    rsbac_write_lock(&tp_list_head.lock, &flags);
    if ((tmperr = read_tp_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): tp data could not be read!\n");
      };
    rsbac_write_unlock(&tp_list_head.lock, &flags);
    err |= tmperr;

    /* read pp data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading pp list\n");
    rsbac_write_lock(&pp_list_head.lock, &flags);
    if ((tmperr = read_pp_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): purpose data could not be read!\n");
      };
    rsbac_write_unlock(&pp_list_head.lock, &flags);
    err |= tmperr;

    /* read tkt data from root device */      
    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): reading ticket list\n");
    rsbac_write_lock(&tkt_list_head.lock, &flags);
    if ((tmperr = read_tkt_list()))
      {
        printk(KERN_WARNING "rsbac_init_pm(): ticket data could not be read!\n");
      };
    rsbac_write_unlock(&tkt_list_head.lock, &flags);
    err |= tmperr;

    #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
    tmp_entry_p = create_proc_entry("stats_pm",
                                    S_IFREG | S_IRUGO,
                                    proc_rsbac_root_p);
    if(tmp_entry_p)
      {
        tmp_entry_p->get_info = stats_pm_proc_info;
      }
    #endif

    if (rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_init_pm(): Ready.\n");
    return(err);
  };

/***************************************************/
/* We also need some status information...         */

int rsbac_stats_pm(void)
  {
    struct rsbac_pm_task_set_list_item_t   * task_set_item_p;
    struct rsbac_pm_tp_set_list_item_t     * tp_set_item_p;
    struct rsbac_pm_ru_set_list_item_t     * ru_set_item_p;
    struct rsbac_pm_pp_set_list_item_t     * pp_set_item_p;
    struct rsbac_pm_in_pp_set_list_item_t     * in_pp_set_item_p;
    struct rsbac_pm_out_pp_set_list_item_t     * out_pp_set_item_p;
    u_int                                    task_set_count = 0;
    u_int                                    tp_set_count = 0;
    u_int                                    ru_set_count = 0;
    u_int                                    pp_set_count = 0;
    u_int                                    in_pp_set_count = 0;
    u_int                                    out_pp_set_count = 0;
    u_long                                   all_set_count = 0;
    u_long                                   all_member_count = 0;
    u_int                                    member_count = 0;

    u_long                               all_count = 0;
    
    u_int                                count = 0;
    u_long flags;
  
    if (!rsbac_is_initialized)
      {
        printk(KERN_WARNING "rsbac_stats_pm(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }

/****************/
/* Helper lists */
/****************/

    /* protect task set list */
    rsbac_read_lock(&task_set_list_head.lock, &flags);
    if(task_set_list_head.dirty)
      count++;
    task_set_item_p = task_set_list_head.head;
    member_count = 0;
    while (task_set_item_p)
      {
        task_set_count++;
        member_count += task_set_item_p->sublist_length;
        task_set_item_p = task_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&task_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u task-set-items, sum of %u members\n",
                 task_set_count,member_count);
    all_set_count = task_set_count;
    all_member_count += member_count;

    /* protect tp set list */
    rsbac_read_lock(&tp_set_list_head.lock, &flags);
    if(tp_set_list_head.dirty)
      count++;
    tp_set_item_p = tp_set_list_head.head;
    member_count = 0;
    while (tp_set_item_p)
      {
        tp_set_count++;
        member_count += tp_set_item_p->sublist_length;
        tp_set_item_p = tp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&tp_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u tp-set-items, sum of %u members\n",
                 tp_set_count,member_count);
    all_set_count += tp_set_count;
    all_member_count += member_count;
  
    /* protect ru set list */
    rsbac_read_lock(&ru_set_list_head.lock, &flags);
    if(ru_set_list_head.dirty)
      count++;
    ru_set_item_p = ru_set_list_head.head;
    member_count = 0;
    while (ru_set_item_p)
      {
        ru_set_count++;
        member_count += ru_set_item_p->sublist_length;
        ru_set_item_p = ru_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&ru_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u ru-set-items, sum of %u members\n",
                 ru_set_count,member_count);
    all_set_count += ru_set_count;
    all_member_count += member_count;
  
    /* protect pp set list */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    if(pp_set_list_head.dirty)
      count++;
    pp_set_item_p = pp_set_list_head.head;
    member_count = 0;
    while (pp_set_item_p)
      {
        pp_set_count++;
        member_count += pp_set_item_p->sublist_length;
        pp_set_item_p = pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u pp-set-items, sum of %u members\n",
                 pp_set_count,member_count);
    all_set_count += pp_set_count;
    all_member_count += member_count;

    /* protect in_pp set list */
    rsbac_read_lock(&in_pp_set_list_head.lock, &flags);
    if(in_pp_set_list_head.dirty)
      count++;
    in_pp_set_item_p = in_pp_set_list_head.head;
    member_count = 0;
    while (in_pp_set_item_p)
      {
        in_pp_set_count++;
        member_count += in_pp_set_item_p->sublist_length;
        in_pp_set_item_p = in_pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u in-pp-set-items, sum of %u members\n",
                 in_pp_set_count,member_count);
    all_set_count += in_pp_set_count;
    all_member_count += member_count;

    /* protect out_pp set list */
    rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
    if(out_pp_set_list_head.dirty)
      count++;
    out_pp_set_item_p = out_pp_set_list_head.head;
    member_count = 0;
    while (out_pp_set_item_p)
      {
        out_pp_set_count++;
        member_count += out_pp_set_item_p->sublist_length;
        out_pp_set_item_p = out_pp_set_item_p->next;
      };
    /* unprotect the list */
    rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
    printk(KERN_INFO "rsbac_stats_pm(): %u out-pp-set-items, sum of %u members\n",
                 out_pp_set_count,member_count);
    all_set_count += out_pp_set_count;
    all_member_count += member_count;
    printk(KERN_INFO "rsbac_stats_pm(): Total of %lu registered rsbac-pm-set-items, %lu members, %u lists dirty\n",
                 all_set_count, all_member_count,count);

/**************/
/* Main lists */
/**************/
    count = 0;

    /* task list */
    if(task_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u task-items\n",
                 task_list_head.count);
    all_count = task_list_head.count;
    
    /* class list */
    if(class_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u class-items\n",
                 class_list_head.count);
    all_count += class_list_head.count;
    
    /* na list */
    if(na_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u necessary-access-items\n",
                 na_list_head.count);
    all_count += na_list_head.count;
    
    /* cs list */
    if(cs_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u consent-items\n",
                 cs_list_head.count);
    all_count += cs_list_head.count;
    
    /* tp list */
    if(tp_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u transformation-procedure-items\n",
                 tp_list_head.count);
    all_count += tp_list_head.count;
    
    /* pp list */
    if(pp_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u purpose-items\n",
                 pp_list_head.count);
    all_count += pp_list_head.count;
    
    /* tkt list */
    if(tkt_list_head.dirty)
      count++;
    printk(KERN_INFO "rsbac_stats_pm(): %u ticket-items\n",
                 tkt_list_head.count);
    all_count += tkt_list_head.count;
    
    printk(KERN_INFO "rsbac_stats_pm(): Total of %lu registered rsbac-pm-items, %u lists dirty\n",
                 all_count, count);
    return(0);
  };

/***************************************************/
/* rsbac_write_pm() to write all dirty lists to disk  */
/*               returns no. of lists written      */

#ifdef CONFIG_RSBAC_AUTO_WRITE
int rsbac_write_pm(boolean need_lock)
  {
    u_int  count = 0;
  
    if (!rsbac_is_initialized)
      {
        printk(KERN_WARNING "rsbac_write_pm(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }

    if(need_lock)
      lock_kernel();

/****************/
/* Helper lists */
/****************/

    /* task set list */
    if(task_set_list_head.dirty)
      {
        task_set_list_head.dirty = FALSE;
        if(!write_task_set_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): task set list written\n");
          }
        else
          task_set_list_head.dirty = TRUE;
      }

    /* tp set list */
    if(tp_set_list_head.dirty)
      {
        tp_set_list_head.dirty = FALSE;
        if(!write_tp_set_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): tp set list written\n");
          }
        else
          tp_set_list_head.dirty = TRUE;
      }
  
    /* ru set list */
    if(ru_set_list_head.dirty)
      {
        ru_set_list_head.dirty = FALSE;
        if(!write_ru_set_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): ru set list written\n");
          }
        else
          ru_set_list_head.dirty = TRUE;
      }
  
    /* pp set list */
    if(pp_set_list_head.dirty)
      {
        pp_set_list_head.dirty = FALSE;
        if(!write_pp_set_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): pp set list written\n");
          }
        else
          pp_set_list_head.dirty = TRUE;
      }

/**************/
/* Main lists */
/**************/

    /* task list */
    if(task_list_head.dirty)
      {
        task_list_head.dirty = FALSE;
        if(!write_task_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): task list written\n");
          }
        else
          task_list_head.dirty = TRUE;
      }
    
    /* class list */
    if(class_list_head.dirty)
      {
        class_list_head.dirty = FALSE;
        if(!write_class_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): class list written\n");
          }
        else
          class_list_head.dirty = TRUE;
      }
    
    /* na list */
    if(na_list_head.dirty)
      {
        na_list_head.dirty = FALSE;
        if(!write_na_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): necessary accesses list written\n");
          }
        else
          na_list_head.dirty = TRUE;
      }
    
    /* cs list */
    if(cs_list_head.dirty)
      {
        cs_list_head.dirty = FALSE;
        if(!write_cs_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): consent list written\n");
          }
        else
          cs_list_head.dirty = TRUE;
      }
    
    /* tp list */
    if(tp_list_head.dirty)
      {
        tp_list_head.dirty = FALSE;
        if(!write_tp_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): tp list written\n");
          }
        else
          tp_list_head.dirty = TRUE;
      }
    
    /* pp list */
    if(pp_list_head.dirty)
      {
        pp_list_head.dirty = FALSE;
        if(!write_pp_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): purpose list written\n");
          }
        else
          pp_list_head.dirty = TRUE;
      }
    
    /* tkt list */
    if(tkt_list_head.dirty)
      {
        tkt_list_head.dirty = FALSE;
        if(!write_tkt_list())
          {
            count++;
            if(rsbac_debug_ds_pm)
              printk(KERN_DEBUG "rsbac_write_pm(): ticket list written\n");
          }
        else
          tkt_list_head.dirty = TRUE;
      }
    
    if(rsbac_debug_ds_pm)
      printk(KERN_DEBUG "rsbac_write_pm(): %u lists written\n",count);

    if(need_lock)
      unlock_kernel();

    return(count);
  };
#endif /* CONFIG_RSBAC_AUTO_WRITE */

/************************************************* */
/*               Access functions                  */
/************************************************* */

/***********************/
/* Helper lists / sets */
/***********************/

/* All these procedures handle the rw-spinlocks to protect the targets during */
/* access.                                                                  */
/* Trying to access a never created or removed set returns an error!        */


/* rsbac_pm_add_to_set */
/* Add a set member to a set sublist. Set behaviour: also returns success, */
/* if member was already in set! */

int rsbac_pm_add_to_set(enum  rsbac_pm_set_t set,
                        union rsbac_pm_set_id_t id,
                        union rsbac_pm_set_member_t member)
  {
    int                                    err=0;
    struct rsbac_pm_task_set_list_item_t * task_set_p;
    struct rsbac_pm_tp_set_list_item_t   * tp_set_p;
    struct rsbac_pm_ru_set_list_item_t   * ru_set_p;
    struct rsbac_pm_pp_set_list_item_t   * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t   * in_pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t   * out_pp_set_p;
    u_long flags;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_add_to_set(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_add_to_set(): called from interrupt!\n");
      }
    switch(set)
      {
        case PS_TASK:
          /* protect the list */
          rsbac_write_lock(&task_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          task_set_p = lookup_task_set(id.task_set);
          if (!task_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_task_set_subitem(task_set_p,member.task))
                && (!add_task_set_subitem(task_set_p,member.task)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&task_set_list_head.lock, &flags);
          /* since the list was changed, it must be saved to disk */
          if(!err)
            task_set_list_head.dirty = TRUE;
          return(err);
        case PS_TP:
          /* protect the list */
          rsbac_write_lock(&tp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          tp_set_p = lookup_tp_set(id.tp_set);
          if (!tp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_tp_set_subitem(tp_set_p,member.tp))
                && (!add_tp_set_subitem(tp_set_p,member.tp)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&tp_set_list_head.lock, &flags);
          /* since the list was changed, it must be saved to disk */
          if(!err)
            tp_set_list_head.dirty = TRUE;
          return(err);
        case PS_RU:
          /* protect the list */
          rsbac_write_lock(&ru_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          ru_set_p = lookup_ru_set(id.ru_set);
          if (!ru_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_ru_set_subitem(ru_set_p,member.ru))
                && (!add_ru_set_subitem(ru_set_p,member.ru)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&ru_set_list_head.lock, &flags);
          /* since the list was changed, it must be saved to disk */
          if(!err)
            ru_set_list_head.dirty = TRUE;
          return(err);
        case PS_PP:
          /* protect the list */
          rsbac_write_lock(&pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          pp_set_p = lookup_pp_set(id.pp_set);
          if (!pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_pp_set_subitem(pp_set_p,member.pp))
                && (!add_pp_set_subitem(pp_set_p,member.pp)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&pp_set_list_head.lock, &flags);
          /* since the list was changed, it must be saved to disk */
          if(!err)
            pp_set_list_head.dirty = TRUE;
          return(err);
        case PS_IN_PP:
          /* protect the list */
          rsbac_write_lock(&in_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          in_pp_set_p = lookup_in_pp_set(id.in_pp_set);
          if (!in_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_in_pp_set_subitem(in_pp_set_p,member.pp))
                && (!add_in_pp_set_subitem(in_pp_set_p,member.pp)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
          return(err);
        case PS_OUT_PP:
          /* protect the list */
          rsbac_write_lock(&out_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          out_pp_set_p = lookup_out_pp_set(id.out_pp_set);
          if (!out_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and return error, if adding failed */
            if (   (!lookup_out_pp_set_subitem(out_pp_set_p,member.pp))
                && (!add_out_pp_set_subitem(out_pp_set_p,member.pp)))
                err = -RSBAC_ECOULDNOTADDITEM;
          /* unprotect the list */
          rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
          return(err);
        default:
          return(-RSBAC_EINVALIDTARGET);
      }
  }

/* rsbac_pm_remove_from_set */
/* Remove a set member from a sublist. Set behaviour: Returns no error, if */
/* member is not in list.                                                  */
/* Caution: Writing to disk is not done in the remove functions!               */

int rsbac_pm_remove_from_set(enum  rsbac_pm_set_t set,
                             union rsbac_pm_set_id_t id,
                             union rsbac_pm_set_member_t member)
  {
    int                                    err=0;
    struct rsbac_pm_task_set_list_item_t * task_set_p;
    struct rsbac_pm_tp_set_list_item_t   * tp_set_p;
    struct rsbac_pm_ru_set_list_item_t   * ru_set_p;
    struct rsbac_pm_pp_set_list_item_t   * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t   * in_pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t   * out_pp_set_p;
    u_long flags;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_remove_from_set(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_remove_from_set(): called from interrupt!\n");
      }
    switch(set)
      {
        case PS_TASK:
          /* protect the list */
          rsbac_write_lock(&task_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          task_set_p = lookup_task_set(id.task_set);
          if (!task_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_task_set_subitem(task_set_p,member.task);
          /* unprotect the list */
          rsbac_write_unlock(&task_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            task_set_list_head.dirty = TRUE;
          return(0);
        case PS_TP:
          /* protect the list */
          rsbac_write_lock(&tp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          tp_set_p = lookup_tp_set(id.tp_set);
          if (!tp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_tp_set_subitem(tp_set_p,member.tp);
          /* unprotect the list */
          rsbac_write_unlock(&tp_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            tp_set_list_head.dirty = TRUE;
          return(0);
        case PS_RU:
          /* protect the list */
          rsbac_write_lock(&ru_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          ru_set_p = lookup_ru_set(id.ru_set);
          if (!ru_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_ru_set_subitem(ru_set_p,member.ru);
          /* unprotect the list */
          rsbac_write_unlock(&ru_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            ru_set_list_head.dirty = TRUE;
          return(0);
        case PS_PP:
          /* protect the list */
          rsbac_write_lock(&pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          pp_set_p = lookup_pp_set(id.pp_set);
          if (!pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_pp_set_subitem(pp_set_p,member.pp);
          /* unprotect the list */
          rsbac_write_unlock(&pp_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            pp_set_list_head.dirty = TRUE;
          return(0);
        case PS_IN_PP:
          /* protect the list */
          rsbac_write_lock(&in_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          in_pp_set_p = lookup_in_pp_set(id.in_pp_set);
          if (!in_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_in_pp_set_subitem(in_pp_set_p,member.pp);
          /* unprotect the list */
          rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
          return(0);
        case PS_OUT_PP:
          /* protect the list */
          rsbac_write_lock(&out_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          out_pp_set_p = lookup_out_pp_set(id.out_pp_set);
          if (!out_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_out_pp_set_subitem(out_pp_set_p,member.pp);
          /* unprotect the list */
          rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
          return(0);
        default:
          return(-RSBAC_EINVALIDTARGET);
      }
  }

/* rsbac_pm_clear_set */
/* Remove all set members from a sublist. Set behaviour: Returns no error, */
/* if list is empty.                                                       */
/* Caution: Writing to disk is not done in the remove functions!               */

int rsbac_pm_clear_set(enum  rsbac_pm_set_t set,
                       union rsbac_pm_set_id_t id)
  {
    int                                    err=0;
    struct rsbac_pm_task_set_list_item_t * task_set_p;
    struct rsbac_pm_tp_set_list_item_t   * tp_set_p;
    struct rsbac_pm_ru_set_list_item_t   * ru_set_p;
    struct rsbac_pm_pp_set_list_item_t   * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t   * in_pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t   * out_pp_set_p;
    u_long flags;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_clear_set(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_clear_set(): called from interrupt!\n");
      }
    switch(set)
      {
        case PS_TASK:
          /* protect the list */
          rsbac_write_lock(&task_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          task_set_p = lookup_task_set(id.task_set);
          if (!task_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_task_set_subitems(task_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&task_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            task_set_list_head.dirty = TRUE;
          return(err);
        case PS_TP:
          /* protect the list */
          rsbac_write_lock(&tp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          tp_set_p = lookup_tp_set(id.tp_set);
          if (!tp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_tp_set_subitems(tp_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&tp_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            tp_set_list_head.dirty = TRUE;
          return(err);
        case PS_RU:
          /* protect the list */
          rsbac_write_lock(&ru_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          ru_set_p = lookup_ru_set(id.ru_set);
          if (!ru_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_ru_set_subitems(ru_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&ru_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            ru_set_list_head.dirty = TRUE;
          return(err);
        case PS_PP:
          /* protect the list */
          rsbac_write_lock(&pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          pp_set_p = lookup_pp_set(id.pp_set);
          if (!pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_pp_set_subitems(pp_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&pp_set_list_head.lock, &flags);
          /* if the list was changed, it must be saved to disk */
          if(!err)
            pp_set_list_head.dirty = TRUE;
          return(0);
        case PS_IN_PP:
          /* protect the list */
          rsbac_write_lock(&in_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          in_pp_set_p = lookup_in_pp_set(id.in_pp_set);
          if (!in_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_in_pp_set_subitems(in_pp_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
          return(0);
        case PS_OUT_PP:
          /* protect the list */
          rsbac_write_lock(&out_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          out_pp_set_p = lookup_out_pp_set(id.out_pp_set);
          if (!out_pp_set_p)
            err = -RSBAC_EINVALIDTARGET;
          else
            remove_all_out_pp_set_subitems(out_pp_set_p);
          /* unprotect the list */
          rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
          return(0);
        default:
          return(-RSBAC_EINVALIDTARGET);
      }
  }

/* rsbac_pm_set_member */
/* Return truth value, whether member is in set */

boolean  rsbac_pm_set_member(enum  rsbac_pm_set_t set,
                             union rsbac_pm_set_id_t id,
                             union rsbac_pm_set_member_t member)
  {
    boolean                                res;
    struct rsbac_pm_task_set_list_item_t * task_set_p;
    struct rsbac_pm_tp_set_list_item_t * tp_set_p;
    struct rsbac_pm_ru_set_list_item_t * ru_set_p;
    struct rsbac_pm_pp_set_list_item_t * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t * in_pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t * out_pp_set_p;
    u_long flags;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_set_member(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_set_member(): called from interrupt!\n");
      }
    switch(set)
      {
        case PS_TASK:
          /* protect the list */
          rsbac_read_lock(&task_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          task_set_p = lookup_task_set(id.task_set);
          if (!task_set_p)
            res = FALSE;
          else
            if (lookup_task_set_subitem(task_set_p,member.task))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&task_set_list_head.lock, &flags);
          return(res);
        case PS_TP:
          /* protect the list */
          rsbac_read_lock(&tp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          tp_set_p = lookup_tp_set(id.tp_set);
          if (!tp_set_p)
            res = FALSE;
          else
            if (lookup_tp_set_subitem(tp_set_p,member.tp))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&tp_set_list_head.lock, &flags);
          return(res);
        case PS_RU:
          /* protect the list */
          rsbac_read_lock(&ru_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          ru_set_p = lookup_ru_set(id.ru_set);
          if (!ru_set_p)
            res = FALSE;
          else
            if (lookup_ru_set_subitem(ru_set_p,member.ru))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&ru_set_list_head.lock, &flags);
          return(res);
        case PS_PP:
          /* protect the list */
          rsbac_read_lock(&pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          pp_set_p = lookup_pp_set(id.pp_set);
          if (!pp_set_p)
            res = FALSE;
          else
            if (lookup_pp_set_subitem(pp_set_p,member.pp))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&pp_set_list_head.lock, &flags);
          return(res);
        case PS_IN_PP:
          /* protect the list */
          rsbac_read_lock(&in_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          in_pp_set_p = lookup_in_pp_set(id.in_pp_set);
          if (!in_pp_set_p)
            /* set does not exist, so assume every item is member */
            res = TRUE;
          else
            if (lookup_in_pp_set_subitem(in_pp_set_p,member.pp))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
          return(res);
        case PS_OUT_PP:
          /* protect the list */
          rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
          /* check, whether set-id exists */
          out_pp_set_p = lookup_out_pp_set(id.out_pp_set);
          if (!out_pp_set_p)
            /* set does not exist, so assume no item is member */
            res = FALSE;
          else
            if (lookup_out_pp_set_subitem(out_pp_set_p,member.pp))
              res = TRUE;
            else
              res = FALSE;
          /* unprotect the list */
          rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
          return(res);
        default:
          return(FALSE);
      }
  }

/* rsbac_pm_pp_subset */
/* Return truth value, whether pp_set is subset of in_pp_set */

boolean  rsbac_pm_pp_subset (rsbac_pm_pp_set_id_t    pp_set,
                             rsbac_pm_in_pp_set_id_t in_pp_set)
  {
    boolean                                 res = TRUE;
    struct rsbac_pm_pp_set_list_item_t    * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t * in_pp_set_p;
    struct rsbac_pm_pp_set_sublist_item_t * curr;
    u_long flags,flags2;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_pp_subset(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_pp_subset(): called from interrupt!\n");
      }
    if(!in_pp_set)
      return(FALSE);
    /* protect the lists */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    rsbac_read_lock(&in_pp_set_list_head.lock, &flags2);
    /* check, whether set-ids exist */
    pp_set_p = lookup_pp_set(pp_set);
    if (!pp_set_p)
      res = FALSE;
    else
      {      
        in_pp_set_p = lookup_in_pp_set(in_pp_set);
        if (!in_pp_set_p)
          { /* in_pp_set does not exist -> no previous read-open -> OK */
            /* unprotect the lists */
            rsbac_read_unlock(&in_pp_set_list_head.lock, &flags2);
            rsbac_read_unlock(&pp_set_list_head.lock, &flags);
            return(TRUE);
          }
      }
    if(res)
      {
        curr = pp_set_p->sublist_head;
        /* are all items in pp_set also in in_pp_set? */
        while (curr &&
               lookup_in_pp_set_subitem(in_pp_set_p,
                                        curr->id))
          curr = curr->next;
        if(curr)
          res = FALSE;
      }

    /* unprotect the lists */
    rsbac_read_unlock(&in_pp_set_list_head.lock, &flags2);
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    return(res);
  }

/* rsbac_pm_pp_superset */
/* Return truth value, whether pp_set is superset of out_pp_set */

boolean  rsbac_pm_pp_superset (rsbac_pm_pp_set_id_t    pp_set,
                               rsbac_pm_out_pp_set_id_t out_pp_set)
  {
    boolean                                     res = TRUE;
    struct rsbac_pm_pp_set_list_item_t        * pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t    * out_pp_set_p;
    struct rsbac_pm_out_pp_set_sublist_item_t * curr;
    u_long flags,flags2;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_pp_superset(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_pp_superset(): called from interrupt!\n");
      }
    if(!out_pp_set)
      return(TRUE);
    /* protect the lists */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    rsbac_read_lock(&out_pp_set_list_head.lock, &flags2);
    /* check, whether set-ids exist */
    pp_set_p = lookup_pp_set(pp_set);
    if (!pp_set_p)
      res = FALSE;
    else
      {      
        out_pp_set_p = lookup_out_pp_set(out_pp_set);
        if (!out_pp_set_p)
          { /* out_pp_set does not exist -> no previous write-open -> OK */
            /* unprotect the lists */
            rsbac_read_unlock(&out_pp_set_list_head.lock, &flags2);
            rsbac_read_unlock(&pp_set_list_head.lock, &flags);
            return(TRUE);
          }
      }
    if(res)
      {
        curr = out_pp_set_p->sublist_head;
        /* are all items in out_pp_set also in pp_set? */
        while (curr &&
               lookup_pp_set_subitem(pp_set_p,
                                     curr->id))
          curr = curr->next;
        if(curr)
          res = FALSE;
      }

    /* unprotect the lists */
    rsbac_read_unlock(&out_pp_set_list_head.lock, &flags2);
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    return(res);
  }

/* rsbac_pm_pp_only */
/* Return truth value, if there is no other item in out_pp_set than purpose */

boolean  rsbac_pm_pp_only (rsbac_pm_purpose_id_t    purpose,
                           rsbac_pm_out_pp_set_id_t out_pp_set)
  {
    boolean                                     res = TRUE;
    struct rsbac_pm_out_pp_set_list_item_t    * out_pp_set_p;
    struct rsbac_pm_out_pp_set_sublist_item_t * curr;
    u_long flags;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_pp_only(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_pp_only(): called from interrupt!\n");
      }
    if(!out_pp_set)
      return(TRUE);
    /* protect the lists */
    rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
    /* check, whether set-id exists */
    out_pp_set_p = lookup_out_pp_set(out_pp_set);
    if (!out_pp_set_p)
      { /* out_pp_set does not exist -> no other item -> OK */
        /* unprotect the list */
        rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
        return(TRUE);
      }
    curr = out_pp_set_p->sublist_head;
    /* is there any item in out_pp_set that is not purpose? */
    while (curr && (curr->id == purpose))
      curr = curr->next;
    /* There is another item -> purpose is not only one -> FALSE */
    if(curr)
      res = FALSE;
    /* unprotect the list */
    rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
    return(res);
  }

/* rsbac_pm_pp_intersec */
/* Create intersection of pp_set and in_pp_set in in_pp_set */
/* If in_pp_set does not exist, it is created with all members of pp_set */
/* If pp_set does not exist or one of them is invalid, an error is returned */

int rsbac_pm_pp_intersec (rsbac_pm_pp_set_id_t      pp_set,
                          rsbac_pm_in_pp_set_id_t   in_pp_set)
  {
    int                                        err = 0;
    struct rsbac_pm_pp_set_list_item_t       * pp_set_p;
    struct rsbac_pm_in_pp_set_list_item_t    * in_pp_set_p;
    struct rsbac_pm_pp_set_sublist_item_t    * curr;
    struct rsbac_pm_in_pp_set_sublist_item_t * in_curr;
    u_long flags,flags2;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_pp_intersec(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_pp_intersec(): called from interrupt!\n");
      }
    /* protect the lists */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    /* check, whether set-id pp_set exists */
    pp_set_p = lookup_pp_set(pp_set);
    if (!pp_set_p)
      {
        rsbac_read_unlock(&pp_set_list_head.lock, &flags);
        return(-RSBAC_EINVALIDVALUE);
      }
    rsbac_write_lock(&in_pp_set_list_head.lock, &flags2);
    in_pp_set_p = lookup_in_pp_set(in_pp_set);
    if (!in_pp_set_p)
      { /* in_pp_set not found -> try to create and fill with pp_set */
        in_pp_set_p = add_in_pp_set_item(in_pp_set);
        if(in_pp_set_p)
          { /* creation successful -> copy list */
            curr = pp_set_p->sublist_head;
            while (curr &&
                   add_in_pp_set_subitem(in_pp_set_p,
                                         curr->id))
              curr = curr->next;
            err = 0;
          }
        else /* creation failed */
          err = -RSBAC_EWRITEFAILED;
      }
    else
      { /* in_pp_set exists -> remove all members not in pp_set */
        in_curr = in_pp_set_p->sublist_head;
        while (in_curr)
          {
            if(!lookup_pp_set_subitem(pp_set_p,
                                      in_curr->id))
              { /* in_pp_set member not pp_set member -> remove */
                remove_in_pp_set_subitem(in_pp_set_p,
                                         in_curr->id);
                in_curr = in_pp_set_p->sublist_head;
              }
            else
              in_curr = in_curr->next;
          }
      }

    /* unprotect the lists */
    rsbac_write_unlock(&in_pp_set_list_head.lock, &flags2);
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    return(err);
  }

/* rsbac_pm_pp_union */
/* Create union of pp_set and out_pp_set in out_pp_set */
/* If out_pp_set does not exist, it is created with all members of pp_set */
/* If pp_set does not exist or one of them is invalid, an error is returned */

int rsbac_pm_pp_union (rsbac_pm_pp_set_id_t      pp_set,
                       rsbac_pm_out_pp_set_id_t   out_pp_set)
  {
    int                                         err = 0;
    struct rsbac_pm_pp_set_list_item_t        * pp_set_p;
    struct rsbac_pm_out_pp_set_list_item_t    * out_pp_set_p;
    struct rsbac_pm_pp_set_sublist_item_t     * curr;
    u_long flags, flags2;
    
    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_pp_union(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_pp_union(): called from interrupt!\n");
      }
    /* protect the lists */
    rsbac_read_lock(&pp_set_list_head.lock, &flags);
    /* check, whether set-id pp_set exists */
    pp_set_p = lookup_pp_set(pp_set);
    if (!pp_set_p)
      {
        rsbac_read_unlock(&pp_set_list_head.lock, &flags);
        return(-RSBAC_EINVALIDVALUE);
      }
    rsbac_write_lock(&out_pp_set_list_head.lock, &flags2);
    out_pp_set_p = lookup_out_pp_set(out_pp_set);
    if (!out_pp_set_p)
      { /* out_pp_set not found -> try to create and fill with pp_set */
        out_pp_set_p = add_out_pp_set_item(out_pp_set);
        if(out_pp_set_p)
          { /* creation successful -> copy list */
            curr = pp_set_p->sublist_head;
            while (curr &&
                   add_out_pp_set_subitem(out_pp_set_p,
                                          curr->id))
              curr = curr->next;
            err = 0;
          }
        else /* creation failed */
          err = -RSBAC_EWRITEFAILED;
      }
    else
      { /* out_pp_set exists -> add all members in pp_set */
        curr = pp_set_p->sublist_head;
        while (curr)
          {
            /* check for subitem, try to add subitem, if it does not exist, */
            /* and set error, if adding failed */
            if (   (!lookup_out_pp_set_subitem(out_pp_set_p,curr->id))
                && (!add_out_pp_set_subitem(out_pp_set_p,curr->id)))
              err = -RSBAC_ECOULDNOTADDITEM;
            curr = curr->next;
          }
      }

    /* unprotect the lists */
    rsbac_write_unlock(&out_pp_set_list_head.lock, &flags2);
    rsbac_read_unlock(&pp_set_list_head.lock, &flags);
    return(err);
  }

/* rsbac_pm_create_set */
/* Create a new set of given type set, using id id. Using any other set */
/* function for a set id without creating this set returns an error.    */
/* To empty an existing set use rsbac_pm_clear_set.                     */

int rsbac_pm_create_set     (enum  rsbac_pm_set_t set,
                             union rsbac_pm_set_id_t id)
  {
    u_long flags;

    if (!rsbac_is_initialized())
      {
        printk(KERN_WARNING "rsbac_pm_create_set(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }
    if (in_interrupt())
      {
        printk(KERN_WARNING "rsbac_pm_create_set(): called from interrupt!\n");
      }
      switch (set)
        {
          case PS_TASK:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating task set");
            /* protect the list */
            rsbac_write_lock(&task_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_task_set(id.task_set))
              {/* exists -> error */
                rsbac_write_unlock(&task_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call add function */
            if (!add_task_set_item(id.task_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&task_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&task_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            task_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_TP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating tp set");
            /* protect the list */
            rsbac_write_lock(&tp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_tp_set(id.tp_set))
              {/* exists -> error */
                rsbac_write_unlock(&tp_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call the add function */
            if (!add_tp_set_item(id.tp_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&tp_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tp_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            tp_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_RU:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_create_set(): Creating ru set %i\n",
                     id.ru_set);
            /* protect the list */
            rsbac_write_lock(&ru_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_ru_set(id.ru_set))
              {/* exists -> error */
                rsbac_write_unlock(&ru_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call the add function */
            if (!add_ru_set_item(id.ru_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&ru_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&ru_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            ru_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating pp set");
            /* protect the list */
            rsbac_write_lock(&pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_pp_set(id.pp_set))
              {/* exists -> error */
                rsbac_write_unlock(&pp_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call the add function */
            if (!add_pp_set_item(id.pp_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&pp_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&pp_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            pp_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_IN_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating input pp set");
            /* protect the list */
            rsbac_write_lock(&in_pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_in_pp_set(id.in_pp_set))
              {/* exists -> error */
                rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call the add function */
            if (!add_in_pp_set_item(id.in_pp_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
            return(0);
            break;
          case PS_OUT_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating output pp set");
            /* protect the list */
            rsbac_write_lock(&out_pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_out_pp_set(id.out_pp_set))
              {/* exists -> error */
                rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            /* call the add function */
            if (!add_out_pp_set_item(id.out_pp_set))
              {/* adding failed -> error */
                rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
            return(0);
            break;
          default:
            return(-RSBAC_EINVALIDTARGET);          
        }
  }

/* rsbac_pm_set_exist */
/* Return boolean value whether set exists */

boolean rsbac_pm_set_exist (enum  rsbac_pm_set_t set,
                            union rsbac_pm_set_id_t id)
  {
    u_long flags;

      if (!rsbac_is_initialized)
        {
          printk(KERN_WARNING "rsbac_pm_set_exist(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_set_exist(): called from interrupt!\n");
        }
      switch (set)
        {
          case PS_TASK:
            /* protect the list */
            rsbac_read_lock(&task_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_task_set(id.task_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&task_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&task_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          case PS_TP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating tp set");
            /* protect the list */
            rsbac_read_lock(&tp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_tp_set(id.tp_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&tp_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&tp_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          case PS_RU:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_create_set(): Creating ru set %i\n",
                     id.ru_set);
            /* protect the list */
            rsbac_read_lock(&ru_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_ru_set(id.ru_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&ru_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&ru_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          case PS_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating pp set");
            /* protect the list */
            rsbac_read_lock(&pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_pp_set(id.pp_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&pp_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&pp_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          case PS_IN_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating input pp set");
            /* protect the list */
            rsbac_read_lock(&in_pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_in_pp_set(id.in_pp_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          case PS_OUT_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_create_set(): Creating output pp set");
            /* protect the list */
            rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
            /* check, whether set-id exists */
            if(lookup_out_pp_set(id.out_pp_set))
              {/* exists -> TRUE */
                rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
                return(TRUE);
              }
            else
              {/* does not exist -> FALSE */
                rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
                return(FALSE);
              }
            break;
          default:
            return(FALSE);
        }
  }

/* rsbac_pm_remove_set */
/* Remove a full set. After this call the given id can only be used for */
/* creating a new set, anything else returns an error.                  */
/* To empty an existing set use rsbac_pm_clear_set.                     */
/* Caution: Writing to disk is done in the remove_item functions!       */

int rsbac_pm_remove_set     (enum  rsbac_pm_set_t set,
                             union rsbac_pm_set_id_t id)
  {
    u_long flags;

      if (!rsbac_is_initialized)
        {
          printk(KERN_WARNING "rsbac_pm_remove_set(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_remove_set(): called from interrupt!\n");
        }
      switch (set)
        {
          case PS_TASK:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing task set data");
            /* protect the list */
            rsbac_write_lock(&task_set_list_head.lock, &flags);
            /* call the remove function */
            remove_task_set_item(id.task_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&task_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            task_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_TP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing tp set data");
            /* protect the list */
            rsbac_write_lock(&tp_set_list_head.lock, &flags);
            /* call the remove function */
            remove_tp_set_item(id.tp_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tp_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            tp_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_RU:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing ru set data");
            /* protect the list */
            rsbac_write_lock(&ru_set_list_head.lock, &flags);
            /* call the remove function */
            remove_ru_set_item(id.ru_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&ru_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            ru_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing pp set data");
            /* protect the list */
            rsbac_write_lock(&pp_set_list_head.lock, &flags);
            /* call the remove function */
            remove_pp_set_item(id.pp_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&pp_set_list_head.lock, &flags);
            /* since the list was changed, it must be saved to disk */
            pp_set_list_head.dirty = TRUE;
            return(0);
            break;
          case PS_IN_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing input pp set data");
            /* protect the list */
            rsbac_write_lock(&in_pp_set_list_head.lock, &flags);
            /* call the remove function */
            remove_in_pp_set_item(id.in_pp_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&in_pp_set_list_head.lock, &flags);
            return(0);
            break;
          case PS_OUT_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_set(): Removing output pp set data");
            /* protect the list */
            rsbac_write_lock(&out_pp_set_list_head.lock, &flags);
            /* call the remove function */
            remove_out_pp_set_item(id.out_pp_set);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&out_pp_set_list_head.lock, &flags);
            return(0);
            break;
          default:
            return(-RSBAC_EINVALIDTARGET);          
        }
  }

/**************/
/* Main lists */
/**************/

/* rsbac_pm_get_data() and rsbac_pm_set_data() change single data values.   */
/* rsbac_pm_add_target() adds a new list item and sets all data values as   */
/* given. rsbac_pm_remove_target() removes an item.                         */

/* A rsbac_pm_[sg]et_data() call for a non-existing target will return an   */
/* error.*/
/* Invalid parameter combinations return an error.                          */

/* All these procedures handle the rw-spinlocks to protect the targets during */
/* access.                                                                  */

int rsbac_pm_get_data(enum rsbac_pm_target_t target,
                      union rsbac_pm_target_id_t tid,
                      enum rsbac_pm_data_t data,
                      union rsbac_pm_data_value_t * value)
    { 
      int err = 0;
      struct rsbac_pm_task_list_item_t     * task_p;
      struct rsbac_pm_class_list_item_t    * object_class_p;
      struct rsbac_pm_na_list_item_t       * na_p;
      struct rsbac_pm_cs_list_item_t       * cs_p;
      struct rsbac_pm_tp_list_item_t       * tp_p;
      struct rsbac_pm_pp_list_item_t       * pp_p;
      struct rsbac_pm_tkt_list_item_t      * tkt_p;
      u_long flags;
    
      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_get_data(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_get_data(): called from interrupt!\n");
        }
      if (!value)
        return(-RSBAC_EINVALIDVALUE);
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting task data\n");
            /* protect the list */
            rsbac_read_lock(&task_list_head.lock, &flags);
            if (!(task_p = lookup_task(tid.task)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&task_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_purpose:
                  value->purpose = task_p->data.purpose;
                  break;
                case PD_tp_set:
                  value->tp_set = task_p->data.tp_set;
                  break;
                case PD_ru_set:
                  value->ru_set = task_p->data.ru_set;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&task_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting class data\n");
            /* protect the list */
            rsbac_read_lock(&class_list_head.lock, &flags);
            if (!(object_class_p = lookup_class(tid.object_class)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&class_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_pp_set:
                  value->pp_set = object_class_p->data.pp_set;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&class_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting na data\n");
            /* protect the list */
            rsbac_read_lock(&na_list_head.lock, &flags);
            if (!(na_p = lookup_na(tid.na)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&na_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_task:
                   value->task = na_p->data.task;
                  break;
                case PD_class:
                  value->object_class = na_p->data.object_class;
                  break;
                case PD_tp:
                  value->tp = na_p->data.tp;
                  break;
                case PD_accesses:
                  value->accesses = na_p->data.accesses;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&na_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_CS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting cs data\n");
            /* protect the list */
            rsbac_read_lock(&cs_list_head.lock, &flags);
            if (!(cs_p = lookup_cs(tid.cs)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&cs_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_purpose:
                  value->purpose = cs_p->data.purpose;
                  break;
                case PD_file:
                  value->file = cs_p->data.file;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&cs_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_TP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting tp data\n");
            /* protect the list */
            rsbac_read_lock(&tp_list_head.lock, &flags);
            if (!(tp_p = lookup_tp(tid.tp)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&tp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_tp:
                  value->tp = tp_p->data.id;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&tp_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_PP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting pp data\n");
            /* protect the list */
            rsbac_read_lock(&pp_list_head.lock, &flags);
            if (!(pp_p = lookup_pp(tid.pp)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&pp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_purpose:
                  value->purpose = pp_p->data.id;
                  break;
                case PD_def_class:
                  value->def_class = pp_p->data.def_class;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&pp_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          case PMT_TKT:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting tkt data\n");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            if (!(tkt_p = lookup_tkt(tid.tkt)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            /* ticket too old? -> remove it and return error */
            if(tkt_p->data.valid_until < CURRENT_TIME)
              {
                remove_tkt_item(tid.tkt);
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_issuer:
                  value->issuer = tkt_p->data.issuer;
                  break;
                case PD_function_type:
                  value->function_type = tkt_p->data.function_type;
                  break;
                case PD_function_param:
                  value->function_param = tkt_p->data.function_param;
                  break;
                case PD_valid_until:
                  value->valid_until = tkt_p->data.valid_until;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* and return                          */
            return(err);
            break;
            
          /* switch target: no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);
        }
    };      /* end of rsbac_pm_get_data() */

/************************************************************************** */

int rsbac_pm_get_all_data(enum rsbac_pm_target_t target,
                          union rsbac_pm_target_id_t tid,
                          union rsbac_pm_all_data_value_t * value)
    { 
      struct rsbac_pm_task_list_item_t     * task_p;
      struct rsbac_pm_class_list_item_t    * object_class_p;
      struct rsbac_pm_na_list_item_t       * na_p;
      struct rsbac_pm_cs_list_item_t       * cs_p;
      struct rsbac_pm_tp_list_item_t       * tp_p;
      struct rsbac_pm_pp_list_item_t       * pp_p;
      struct rsbac_pm_tkt_list_item_t      * tkt_p;
      u_long flags;
    
      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_get_all_data(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_get_all_data(): called from interrupt!\n");
        }
      if (!value)
        return(-RSBAC_EINVALIDVALUE);
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting task data\n");
            /* protect the list */
            rsbac_read_lock(&task_list_head.lock, &flags);
            if (!(task_p = lookup_task(tid.task)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&task_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->task = task_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&task_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting class data\n");
            /* protect the list */
            rsbac_read_lock(&class_list_head.lock, &flags);
            if (!(object_class_p = lookup_class(tid.object_class)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&class_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->object_class = object_class_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&class_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm) 
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting na data\n");
            /* protect the list */
            rsbac_read_lock(&na_list_head.lock, &flags);
            if (!(na_p = lookup_na(tid.na)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&na_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->na = na_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&na_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_CS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting cs data\n");
            /* protect the list */
            rsbac_read_lock(&cs_list_head.lock, &flags);
            if (!(cs_p = lookup_cs(tid.cs)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&cs_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->cs = cs_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&cs_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_TP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting tp data\n");
            /* protect the list */
            rsbac_read_lock(&tp_list_head.lock, &flags);
            if (!(tp_p = lookup_tp(tid.tp)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&tp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->tp = tp_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&tp_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_PP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting pp data\n");
            /* protect the list */
            rsbac_read_lock(&pp_list_head.lock, &flags);
            if (!(pp_p = lookup_pp(tid.pp)))
              { /* not found -> free list lock and return error */
                rsbac_read_unlock(&pp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->pp = pp_p->data;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&pp_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          case PMT_TKT:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_get_data(): Getting tkt data\n");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            if (!(tkt_p = lookup_tkt(tid.tkt)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            /* ticket too old? -> remove it and return error */
            if(tkt_p->data.valid_until < CURRENT_TIME)
              {
                remove_tkt_item(tid.tkt);
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            value->tkt = tkt_p->data;
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* and return                          */
            return(0);
            break;
            
          /* switch target: no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);
        }
    };      /* end of rsbac_pm_get_all_data() */

/************************************************************************** */

boolean rsbac_pm_exists(enum rsbac_pm_target_t target,
                        union rsbac_pm_target_id_t tid)
    { 
      boolean  res;
      struct rsbac_pm_tkt_list_item_t      * tkt_p;
      u_long flags;
    
      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_exists(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_exists(): called from interrupt!\n");
        }
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for task\n");
            /* protect the list */
            rsbac_read_lock(&task_list_head.lock, &flags);
            /* lookup item */
            if (lookup_task(tid.task))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&task_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for class\n");
            /* IPC and DEV classes always exists */
            if(   (tid.object_class == RSBAC_PM_IPC_OBJECT_CLASS_ID)
               || (tid.object_class == RSBAC_PM_DEV_OBJECT_CLASS_ID))
              return(TRUE);
            /* protect the list */
            rsbac_read_lock(&class_list_head.lock, &flags);
            /* lookup item */
            if (lookup_class(tid.object_class))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&class_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for na\n");
            /* protect the list */
            rsbac_read_lock(&na_list_head.lock, &flags);
            /* lookup item */
            if (lookup_na(tid.na))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&na_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_CS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for cs\n");
            /* protect the list */
            rsbac_read_lock(&cs_list_head.lock, &flags);
            /* lookup item */
            if (lookup_cs(tid.cs))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&cs_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_TP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for tp\n");
            /* protect the list */
            rsbac_read_lock(&tp_list_head.lock, &flags);
            /* lookup item */
            if (lookup_tp(tid.tp))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&tp_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_PP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for pp\n");
            /* protect the list */
            rsbac_read_lock(&pp_list_head.lock, &flags);
            /* lookup item */
            if (lookup_pp(tid.pp))
              res = TRUE;
            else
              res = FALSE;
            /* we are ready, so unprotect the list */
            rsbac_read_unlock(&pp_list_head.lock, &flags);
            /* and return                          */
            return(res);
            break;
            
          case PMT_TKT:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_exists(): Looking for tkt\n");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            if (!(tkt_p = lookup_tkt(tid.tkt)))
              { /* not found -> free list lock and return FALSE */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(FALSE);
              }
            /* ticket too old? -> remove it and return FALSE */
            if(tkt_p->data.valid_until < CURRENT_TIME)
              {
                remove_tkt_item(tid.tkt);
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(FALSE);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* and return                          */
            return(TRUE);
            break;
            
          /* switch target: no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);
        }
    };      /* end of rsbac_pm_exists() */

/************************************************************************** */

int rsbac_pm_set_data(enum rsbac_pm_target_t target,
                      union rsbac_pm_target_id_t tid,
                      enum rsbac_pm_data_t data,
                      union rsbac_pm_data_value_t value)
    { 
      int err = 0;
      struct rsbac_pm_task_list_item_t     * task_p;
      struct rsbac_pm_class_list_item_t    * object_class_p;
      struct rsbac_pm_na_list_item_t       * na_p;
      struct rsbac_pm_cs_list_item_t       * cs_p;
      struct rsbac_pm_tp_list_item_t       * tp_p;
      struct rsbac_pm_pp_list_item_t       * pp_p;
      struct rsbac_pm_tkt_list_item_t      * tkt_p;
      u_long flags;
    
      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_set_data(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_set_data(): called from interrupt!\n");
        }
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting task data\n");
            /* protect the list */
            rsbac_write_lock(&task_list_head.lock, &flags);
            if (!(task_p = lookup_task(tid.task)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&task_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_purpose:
                  task_p->data.purpose = value.purpose;
                  break;
                case PD_tp_set:
                  task_p->data.tp_set = value.tp_set;
                  break;
                case PD_ru_set:
                  task_p->data.ru_set = value.ru_set;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&task_list_head.lock, &flags);
            /* save the list */
            if(!err)
              task_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting class data\n");
            /* protect the list */
            rsbac_write_lock(&class_list_head.lock, &flags);
            if (!(object_class_p = lookup_class(tid.object_class)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&class_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_pp_set:
                  object_class_p->data.pp_set = value.pp_set;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&class_list_head.lock, &flags);
            /* save the list */
            if(!err)
              class_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting na data\n");
            /* protect the list */
            rsbac_write_lock(&na_list_head.lock, &flags);
            if (!(na_p = lookup_na(tid.na)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&na_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_task:
                  na_p->data.task = value.task;
                  break;
                case PD_class:
                  na_p->data.object_class = value.object_class;
                  break;
                case PD_tp:
                  na_p->data.tp = value.tp;
                  break;
                case PD_accesses:
                  na_p->data.accesses = value.accesses;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&na_list_head.lock, &flags);
            /* save the list */
            if(!err)
              na_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_CS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting cs data\n");
            /* protect the list */
            rsbac_write_lock(&cs_list_head.lock, &flags);
            if (!(cs_p = lookup_cs(tid.cs)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&cs_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_purpose:
                  cs_p->data.purpose = value.purpose;
                  break;
                case PD_file:
                  cs_p->data.file = value.file;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&cs_list_head.lock, &flags);
            /* save the list */
            if(!err)
              cs_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_TP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting tp data\n");
            /* protect the list */
            rsbac_write_lock(&tp_list_head.lock, &flags);
            if (!(tp_p = lookup_tp(tid.tp)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&tp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tp_list_head.lock, &flags);
            /* save the list */
            if(!err)
              tp_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_PP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting pp data\n");
            /* protect the list */
            rsbac_write_lock(&pp_list_head.lock, &flags);
            if (!(pp_p = lookup_pp(tid.pp)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&pp_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_def_class:
                  pp_p->data.def_class = value.def_class;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&pp_list_head.lock, &flags);
            /* save the list */
            if(!err)
              pp_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_TKT:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_set_data(): Setting tkt data\n");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            if (!(tkt_p = lookup_tkt(tid.tkt)))
              { /* not found -> free list lock and return error */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EINVALIDTARGET);
              }
            switch (data)
              {
                case PD_issuer:
                  tkt_p->data.issuer = value.issuer;
                  break;
                case PD_function_type:
                  tkt_p->data.function_type = value.function_type;
                  break;
                case PD_function_param:
                  tkt_p->data.function_param = value.function_param;
                  break;
                case PD_valid_until:
                  tkt_p->data.valid_until = value.valid_until;
                  break;
                default:
                  err = -RSBAC_EINVALIDATTR;
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* save the list */
            if(!err)
              tkt_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          /* switch target: no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);
        }
    };      /* end of rsbac_pm_set_data() */

/************************************************************************** */

int rsbac_pm_add_target(enum rsbac_pm_target_t target,
                        union rsbac_pm_all_data_value_t data)
    { 
      int err = 0;
      struct rsbac_pm_task_list_item_t     * task_p;
      struct rsbac_pm_class_list_item_t    * object_class_p;
      struct rsbac_pm_na_list_item_t       * na_p;
      struct rsbac_pm_cs_list_item_t       * cs_p;
      struct rsbac_pm_tp_list_item_t       * tp_p;
      struct rsbac_pm_pp_list_item_t       * pp_p;
      struct rsbac_pm_tkt_list_item_t      * tkt_p;
      struct rsbac_pm_na_id_t                na_id;
      struct rsbac_pm_cs_id_t                cs_id;
      u_long flags;
    
      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_add_target(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_add_target(): called from interrupt!\n");
        }
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding task item\n");
            /* protect the list */
            rsbac_write_lock(&task_list_head.lock, &flags);
            if (lookup_task(data.task.id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&task_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(task_p = add_task_item(data.task)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&task_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&task_list_head.lock, &flags);
            /* save the list */
            task_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding class item\n");
            /* protect the list */
            rsbac_write_lock(&class_list_head.lock, &flags);
            if (lookup_class(data.object_class.id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&class_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(object_class_p = add_class_item(data.object_class)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&class_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&class_list_head.lock, &flags);
            /* save the list */
            class_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding na item\n");
            /* protect the list */
            rsbac_write_lock(&na_list_head.lock, &flags);
            na_id.task  = data.na.task;
            na_id.object_class = data.na.object_class;
            na_id.tp    = data.na.tp;
            if (lookup_na(na_id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&na_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(na_p = add_na_item(data.na)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&na_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&na_list_head.lock, &flags);
            /* save the list */
            na_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_CS:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding cs item\n");
            /* protect the list */
            rsbac_write_lock(&cs_list_head.lock, &flags);
            cs_id.purpose = data.cs.purpose;
            cs_id.file = data.cs.file;
            if (lookup_cs(cs_id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&cs_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(cs_p = add_cs_item(data.cs)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&cs_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&cs_list_head.lock, &flags);
            /* save the list */
            cs_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_TP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding tp item\n");
            /* protect the list */
            rsbac_write_lock(&tp_list_head.lock, &flags);
            if (lookup_tp(data.tp.id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&tp_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(tp_p = add_tp_item(data.tp)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&tp_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tp_list_head.lock, &flags);
            /* save the list */
            tp_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_PP:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding pp item\n");
            /* protect the list */
            rsbac_write_lock(&pp_list_head.lock, &flags);
            if (lookup_pp(data.pp.id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&pp_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(pp_p = add_pp_item(data.pp)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&pp_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&pp_list_head.lock, &flags);
            /* save the list */
            pp_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          case PMT_TKT:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_add_target(): Adding tkt item\n");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            if (lookup_tkt(data.tkt.id))
              { /* item with same id exists -> free list lock and return error */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_EEXISTS);
              }
            if (!(tkt_p = add_tkt_item(data.tkt)))
              { /* could not add item -> free list lock and return error */
                rsbac_write_unlock(&tkt_list_head.lock, &flags);
                return(-RSBAC_ECOULDNOTADDITEM);
              }
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* save the list */
            tkt_list_head.dirty = TRUE;
            /* and return                          */
            return(err);
            break;
            
          /* switch target: no valid target */
          default:  
            return(-RSBAC_EINVALIDTARGET);
        }
    };      /* end of rsbac_pm_add_target() */

/************************************************************************** */

int rsbac_pm_remove_target(enum rsbac_pm_target_t target,
                           union rsbac_pm_target_id_t tid)
    { 
      u_long flags;

      if (!rsbac_is_initialized())
        {
          printk(KERN_WARNING "rsbac_pm_remove_target(): RSBAC not initialized\n");
          return(-RSBAC_ENOTINITIALIZED);
        }
      if (in_interrupt())
        {
          printk(KERN_WARNING "rsbac_pm_remove_target(): called from interrupt!\n");
        }
      switch (target)
        {
          case PMT_TASK:
            if (rsbac_debug_ds_pm)
              printk(KERN_DEBUG
                     "rsbac_pm_remove_target(): Removing task data\n");
            /* protect the list */
            rsbac_write_lock(&task_list_head.lock, &flags);
            /* call the remove function */
            remove_task_item(tid.task);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&task_list_head.lock, &flags);
            /* save the list */
            task_list_head.dirty = TRUE;
            return(0);
            break;
            
          case PMT_CLASS:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing class data");
            /* protect the list */
            rsbac_write_lock(&class_list_head.lock, &flags);
            /* call the remove function */
            remove_class_item(tid.object_class);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&class_list_head.lock, &flags);
            /* save the list */
            class_list_head.dirty = TRUE;
            return(0);
            break;
            
          case PMT_NA:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing tp data");
            /* protect the list */
            rsbac_write_lock(&na_list_head.lock, &flags);
            /* call the remove function */
            remove_na_item(tid.na);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&na_list_head.lock, &flags);
            /* save the list */
            na_list_head.dirty = TRUE;
            return(0);
            break;
          case PMT_CS:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing cs data");
            /* protect the list */
            rsbac_write_lock(&cs_list_head.lock, &flags);
            /* call the remove function */
            remove_cs_item(tid.cs);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&cs_list_head.lock, &flags);
            /* save the list */
            cs_list_head.dirty = TRUE;
            return(0);
            break;
          case PMT_TP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing tp data");
            /* protect the list */
            rsbac_write_lock(&tp_list_head.lock, &flags);
            /* call the remove function */
            remove_tp_item(tid.tp);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tp_list_head.lock, &flags);
            /* save the list */
            tp_list_head.dirty = TRUE;
            return(0);
            break;
          case PMT_PP:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing pp data");
            /* protect the list */
            rsbac_write_lock(&pp_list_head.lock, &flags);
            /* call the remove function */
            remove_pp_item(tid.pp);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&pp_list_head.lock, &flags);
            /* save the list */
            pp_list_head.dirty = TRUE;
            return(0);
            break;
          case PMT_TKT:
            if (rsbac_debug_ds_pm) printk(KERN_DEBUG "%s\n",
                        "rsbac_pm_remove_target(): Removing tkt data");
            /* protect the list */
            rsbac_write_lock(&tkt_list_head.lock, &flags);
            /* call the remove function */
            remove_tkt_item(tid.tkt);
            /* we are ready, so unprotect the list */
            rsbac_write_unlock(&tkt_list_head.lock, &flags);
            /* save the list */
            tkt_list_head.dirty = TRUE;
            return(0);
            break;
          default:
            return(-RSBAC_EINVALIDTARGET);          
        }
    };      /* end of rsbac_remove_target() */


/* rsbac_pm_write_list() */
/* write a list in readable format on user request to user file */
int rsbac_pm_write_list(char * name, enum rsbac_pm_list_t list)
  {
    int             fd;
    int             error;
    char          * k_name;
    char            tmp1[80];
    char            tmp2[10];
    struct rsbac_pm_task_set_sublist_item_t * task_set_sub_item_p;
    struct rsbac_pm_tp_set_sublist_item_t   * tp_set_sub_item_p;
    struct rsbac_pm_ru_set_sublist_item_t   * ru_set_sub_item_p;
    struct rsbac_pm_pp_set_sublist_item_t   * pp_set_sub_item_p;
    struct rsbac_pm_in_pp_set_sublist_item_t   * in_pp_set_sub_item_p;
    struct rsbac_pm_out_pp_set_sublist_item_t   * out_pp_set_sub_item_p;
    struct rsbac_pm_task_set_list_item_t * task_set_item_p;
    struct rsbac_pm_tp_set_list_item_t   * tp_set_item_p;
    struct rsbac_pm_ru_set_list_item_t   * ru_set_item_p;
    struct rsbac_pm_pp_set_list_item_t   * pp_set_item_p;
    struct rsbac_pm_in_pp_set_list_item_t   * in_pp_set_item_p;
    struct rsbac_pm_out_pp_set_list_item_t   * out_pp_set_item_p;
    struct rsbac_pm_task_list_item_t   * task_item_p;
    struct rsbac_pm_class_list_item_t  * class_item_p;
    struct rsbac_pm_na_list_item_t     * na_item_p;
    struct rsbac_pm_cs_list_item_t     * cs_item_p;
    struct rsbac_pm_tp_list_item_t     * tp_item_p;
    struct rsbac_pm_pp_list_item_t     * pp_item_p;
    struct rsbac_pm_tkt_list_item_t    * tkt_item_p;
    u_int                                count = 0;
    struct file                        * file_p;
    mm_segment_t oldfs;
    u_long flags;
  
    if (!rsbac_is_initialized)
      {
        printk(KERN_WARNING "rsbac_pm_write_list(): RSBAC not initialized\n");
        return(-RSBAC_ENOTINITIALIZED);
      }

    k_name = getname(name);
    if((fd = sys_open(name,
                      O_WRONLY & O_CREAT & O_TRUNC,
                      0600)) < 0)
      {
        printk(KERN_DEBUG
               "rsbac_pm_write_list(): Write open failed for %s, error: %i",
               k_name, fd);
        putname(k_name);
        return(fd);
      }
    file_p=fget(fd);
    putname(k_name);

    switch(list)
      {
        case PA_task_set:
          /* protect task set list */
          rsbac_read_lock(&task_set_list_head.lock, &flags);
          task_set_item_p = task_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. task-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&task_set_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (task_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,task_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&task_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              task_set_sub_item_p = task_set_item_p->sublist_head;
              while (task_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,task_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&task_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  task_set_sub_item_p = task_set_sub_item_p->next;
                };
              
              task_set_item_p = task_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&task_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

        case PA_tp_set:
          /* protect tp set list */
          rsbac_read_lock(&tp_set_list_head.lock, &flags);
          tp_set_item_p = tp_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. tp-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&tp_set_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (tp_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,tp_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&tp_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              tp_set_sub_item_p = tp_set_item_p->sublist_head;
              while (tp_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,tp_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&tp_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  tp_set_sub_item_p = tp_set_sub_item_p->next;
                };
              
              tp_set_item_p = tp_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&tp_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

        case PA_ru_set:
          /* protect ru set list */
          rsbac_read_lock(&ru_set_list_head.lock, &flags);
          ru_set_item_p = ru_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. ru-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&ru_set_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (ru_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,ru_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&ru_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              ru_set_sub_item_p = ru_set_item_p->sublist_head;
              while (ru_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,ru_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&ru_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  ru_set_sub_item_p = ru_set_sub_item_p->next;
                };
              
              ru_set_item_p = ru_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&ru_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

        case PA_pp_set:
          /* protect pp set list */
          rsbac_read_lock(&pp_set_list_head.lock, &flags);
          pp_set_item_p = pp_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. pp-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&pp_set_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (pp_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,pp_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&pp_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              pp_set_sub_item_p = pp_set_item_p->sublist_head;
              while (pp_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,pp_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&pp_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  pp_set_sub_item_p = pp_set_sub_item_p->next;
                };
              
              pp_set_item_p = pp_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&pp_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

        case PA_in_pp_set:
          /* protect input pp set list */
          rsbac_read_lock(&in_pp_set_list_head.lock, &flags);
          in_pp_set_item_p = in_pp_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. pp-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (in_pp_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,in_pp_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              in_pp_set_sub_item_p = in_pp_set_item_p->sublist_head;
              while (in_pp_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,in_pp_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  in_pp_set_sub_item_p = in_pp_set_sub_item_p->next;
                };
              
              in_pp_set_item_p = in_pp_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&in_pp_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

        case PA_out_pp_set:
          /* protect output pp set list */
          rsbac_read_lock(&out_pp_set_list_head.lock, &flags);
          out_pp_set_item_p = out_pp_set_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. pp-set-id set-members\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (out_pp_set_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,out_pp_set_item_p->id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              out_pp_set_sub_item_p = out_pp_set_item_p->sublist_head;
              while (out_pp_set_sub_item_p)
                {
                  strcpy(tmp1,"\t\t");
                  inttostr(tmp2,out_pp_set_sub_item_p->id);
                  strcat(tmp1,tmp2);
                  strcat(tmp1,"\n");
                  if( (error = file_p->f_op->write(file_p,
                                                   tmp1,
                                                   strlen(tmp1),
	                                           &file_p->f_pos)) <= 0)
                    {
                      rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
                      set_fs(oldfs);
                      printk(KERN_DEBUG
                             "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                             k_name, error);
                      fput(file_p);
                      sys_close(fd);
                      return(-RSBAC_EWRITEFAILED);
                     }
                  out_pp_set_sub_item_p = out_pp_set_sub_item_p->next;
                };
              
              out_pp_set_item_p = out_pp_set_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&out_pp_set_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);

/***********/
          
        case PA_task:
          /* protect task list */
          rsbac_read_lock(&task_list_head.lock, &flags);
          task_item_p = task_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. task-id\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&task_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (task_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,task_item_p->data.id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&task_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              task_item_p = task_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&task_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_class:
          /* protect class list */
          rsbac_read_lock(&class_list_head.lock, &flags);
          class_item_p = class_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. class-id\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&class_list_head.lock, &flags);
              set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (class_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,class_item_p->data.id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&class_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              class_item_p = class_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&class_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_na:
          /* protect na list */
          rsbac_read_lock(&na_list_head.lock, &flags);
          na_item_p = na_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. task class tp accesses\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&na_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (na_item_p)
            {
              count++;
              inttostr(tmp1,count);
              strcat(tmp1,"\t");
              inttostr(tmp2,na_item_p->data.task);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\t");
              inttostr(tmp2,na_item_p->data.object_class);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\t");
              inttostr(tmp2,na_item_p->data.tp);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\t");
              inttostr(tmp2,na_item_p->data.accesses);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&na_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              na_item_p = na_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&na_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_cs:
          /* protect cs list */
          rsbac_read_lock(&cs_list_head.lock, &flags);
          cs_item_p = cs_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. purpose file-device file-inode\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&cs_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (cs_item_p)
            {
              count++;
              inttostr(tmp1,count);
              strcat(tmp1,"\t");
              inttostr(tmp2,cs_item_p->data.purpose);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\t");
              inttostr(tmp2,cs_item_p->data.file.device);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\t");
              ulongtostr(tmp2,cs_item_p->data.file.inode);
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&cs_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              cs_item_p = cs_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&cs_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_tp:
          /* protect tp list */
          rsbac_read_lock(&tp_list_head.lock, &flags);
          tp_item_p = tp_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. tp-id\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&tp_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (tp_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,tp_item_p->data.id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&tp_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              tp_item_p = tp_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&tp_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_pp:
          /* protect pp list */
          rsbac_read_lock(&pp_list_head.lock, &flags);
          pp_item_p = pp_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. purpose-id def-class\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&pp_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (pp_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,pp_item_p->data.id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              inttostr(tmp2,pp_item_p->data.def_class);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&pp_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              pp_item_p = pp_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&pp_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        case PA_tkt:
          /* protect tkt list */
          rsbac_read_lock(&tkt_list_head.lock, &flags);
          tkt_item_p = tkt_list_head.head;
          oldfs = get_fs();
          set_fs(KERNEL_DS);
          strcpy(tmp1,"line-no. tkt-id valid-for function-type\n");
          if( (error = file_p->f_op->write(file_p,
                                           tmp1,
                                           strlen(tmp1),
	                                   &file_p->f_pos)) <= 0)
            {
              rsbac_read_unlock(&tkt_list_head.lock, &flags);
              set_fs(oldfs);
              printk(KERN_DEBUG
                     "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                     k_name, error);
              fput(file_p);
              sys_close(fd);
              return(-RSBAC_EWRITEFAILED);
            }
          while (tkt_item_p)
            {
              count++;
              inttostr(tmp1,count);
              inttostr(tmp2,tkt_item_p->data.id);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              longtostr(tmp2, (tkt_item_p->data.valid_until - CURRENT_TIME));
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              if(tkt_item_p->data.valid_until < CURRENT_TIME)
                {
                  strcat(tmp1," (removed on cleanup)");
                }
              get_pm_function_type_name(tmp2,tkt_item_p->data.function_type);
              strcat(tmp1,"\t");
              strcat(tmp1,tmp2);
              strcat(tmp1,"\n");
              if( (error = file_p->f_op->write(file_p,
                                               tmp1,
                                               strlen(tmp1),
	                                       &file_p->f_pos)) <= 0)
                {
                  rsbac_read_unlock(&tkt_list_head.lock, &flags);
                  set_fs(oldfs);
                  printk(KERN_DEBUG
                         "rsbac_pm_write_list(): Write failed for %s, error %i\n",
                         k_name, error);
                  fput(file_p);
                  sys_close(fd);
                  return(-RSBAC_EWRITEFAILED);
                }
              tkt_item_p = tkt_item_p->next;
            };
          /* unprotect the list */
          rsbac_read_unlock(&tkt_list_head.lock, &flags);
          set_fs(oldfs);
          fput(file_p);
          sys_close(fd);
          return(0);
          
        default:
          fput(file_p);
          return(-RSBAC_EINVALIDTARGET);
      }
  };        /* end of rsbac_pm_write_list */

/* end of pm_data_structures.c */
