/************************************* */
/* Rule Set Based Access Control       */
/* Author and (c) 1999-2021:           */
/*   Amon Ott <ao@rsbac.org>           */
/* Helper functions for all parts      */
/* Last modified: 24/Mar/2021          */
/************************************* */

#ifndef __KERNEL__
#include <stdlib.h>
#endif
#include <rsbac/types.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#ifndef __KERNEL__
#include <rsbac/syscalls.h>
#endif
#include <rsbac/rc_types.h>
#include <rsbac/getname.h>
#include <rsbac/cap_getname.h>

#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <rsbac/aci.h>
#include <rsbac/rkmem.h>
#include <rsbac/debug.h>
#ifdef CONFIG_RSBAC_RC
#include <rsbac/rc_getname.h>
#endif
#endif
#ifndef __KERNEL__
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#endif

#define CAP_TO_INDEX(x)     ((x) >> 5)        /* 1 << 5 == bits in __u32 */

int rsbac_get_vset_num(char * sourcename, rsbac_um_set_t * vset_p)
  {
    if (!sourcename || !vset_p)
      return -RSBAC_EINVALIDPOINTER;
    if (!strcmp(sourcename,"all")) {
      *vset_p = RSBAC_UM_VIRTUAL_ALL;
      return 0;
    }
    if (!strcmp(sourcename,"auto") || !strcmp(sourcename,"keep")) {
      *vset_p = RSBAC_UM_VIRTUAL_KEEP;
      return 0;
    }
#ifdef __KERNEL__
    *vset_p = simple_strtoul(sourcename, NULL, 0);
#else
    *vset_p = strtoul(sourcename, NULL, 0);
#endif
    if(!*vset_p && strcmp(sourcename,"0"))
      return -RSBAC_EINVALIDVALUE;
    if (*vset_p > RSBAC_UM_VIRTUAL_MAX)
      return -RSBAC_EINVALIDVALUE;
    return 0;
  }

#ifndef __KERNEL__
int rsbac_u32_compare(__u32 * a, __u32 * b)
  {
    if(*a < *b)
     return -1;
    if(*a > *b)
      return 1;
    return 0;
  }

int rsbac_u16_compare(__u16 * a, __u16 * b)
  {
    if(*a < *b)
     return -1;
    if(*a > *b)
      return 1;
    return 0;
  }

int rsbac_u32_void_compare(const void *a, const void *b)
{
	return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
}

int rsbac_user_compare(const void * a, const void * b)
  {
    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
  }

int rsbac_group_compare(const void * a, const void * b)
  {
    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
  }

int rsbac_nettemp_id_compare(const void * a, const void * b)
  {
    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
  }

int rsbac_dev_compare(const void * desc1,
                      const void * desc2)
  {
    const struct rsbac_dev_desc_t * i_desc1 = desc1;
    const struct rsbac_dev_desc_t * i_desc2 = desc2;
    int result;
    
    result = memcmp(&i_desc1->type,
                    &i_desc2->type,
                    sizeof(i_desc1->type));
    if(result)
      return result;
    result = memcmp(&i_desc1->major,
                    &i_desc2->major,
                    sizeof(i_desc1->major));
    if(result)
      return result;
    return memcmp(&i_desc1->minor,
                  &i_desc2->minor,
                  sizeof(i_desc1->minor));
  }
#endif

char * inttostr(char * str, int i)
  {
    int j = 0;
    
    if(!str)
      return(NULL);
      
    if (i<0)
      {
        str[j] = '-';
        j++;
        i = -i;
      }
    if (i>=10000)
      {
        str[j] = '0' + (i / 10000);
        j++;
      }
    if (i>=1000)
      {
        str[j] = '0' + ((i % 10000) / 1000);
        j++;
      }
    if (i>=100)
      {
        str[j] = '0' + ((i % 1000) / 100);
        j++;
      }
    if (i>=10)
      {
        str[j] = '0' + ((i % 100) / 10);
        j++;
      }
    str[j] = '0' + (i % 10);
    j++;
    str[j] = 0;
    return (str);
  };

char * ulongtostr(char * str, u_long i)
  {
    int    j = 0;
    u_long k = 1000000000;
    
    if(!str)
      return(NULL);

    if (i>=k)
      {
        str[j] = '0' + ((i / k) % 100);
        j++;
      }
    k /= 10;

    while (k>1)
      {
        if (i>=k)
          {
            str[j] = '0' + ((i % (k*10)) / k);
            j++;
          }
        k /= 10;
      };

    str[j] = '0' + (i % 10);
    j++;
    str[j] = 0;
    return (str);
  };

char * longtostr(char * str, long i)
  {
    int    j = 0;
    u_long k = 1000000000;
    
    if(!str)
      return(NULL);

    if (i<0)
      {
        str[0] = '-';
        j = 1;
        i = -i;
      }
    if (i>=k)
      {
        str[j] = '0' + ((i / k) % 100);
        j++;
      }
    k /= 10;

    while (k>1)
      {
        if (i>=k)
          {
            str[j] = '0' + ((i % (k*10)) / k);
            j++;
          }
        k /= 10;
      };

    str[j] = '0' + (i % 10);
    j++;
    str[j] = 0;
    return (str);
  };

char * u64tostrmac(char * str, __u64 i)
  {
    int    j = 0;
    __u64  k;

    if(!str)
      return(NULL);

    k = 1;
    for(j = RSBAC_MAC_MAX_CAT;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[RSBAC_MAC_NR_CATS] = 0;
    return (str);
  };

#ifndef __KERNEL__

int rsbac_lib_version(void)
  {
    return RSBAC_VERSION_NR;
  }

int rsbac_api_version(void)
  {
    return RSBAC_API_VERSION_NR;
  }

void error_exit(int error)
  {
    char tmp1[80];

    if(error<0)
      {
        get_error_name(tmp1,error);
        fprintf(stderr, "Error: %s\n", tmp1);
        exit(1);
      }
  }

void show_error(int error)
  {
    char tmp1[80];

    if(error<0)
      {
        get_error_name(tmp1,error);
        fprintf(stderr, "Error: %s\n", tmp1);
      }
  }

int rsbac_get_uid_name(rsbac_list_ta_number_t ta_number,
    rsbac_uid_t * uid, char * name, char * sourcename, int nonumeric)
  {
    struct passwd * user_info_p;
    rsbac_uid_t uid_i = RSBAC_NO_USER;
    char * p = sourcename;

    if(!sourcename)
      return -RSBAC_EINVALIDPOINTER;
    
    while (*p && (*p != '/'))
      p++;
    if (*p) {
              rsbac_um_set_t tmp_vset = 0;

              uid_i = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
              if(rsbac_um_get_uid(ta_number, sourcename, &uid_i))
                {
                  int err;

                  if (nonumeric)
                    return -RSBAC_EINVALIDVALUE;
                  *p = 0;
                  err = rsbac_get_vset_num(sourcename, &tmp_vset);
		  if (err)
			return err;
                  *p = '/';
                  p++;
                  if (!strcmp(p, "ALL"))
                    uid_i = RSBAC_ALL_USERS;
                  else
                    {
                      char * q;

                      for (q = p; *q; q++)
                        {
                          if ((*q < '0') || (*q > '9'))
                            {
                              return -RSBAC_EINVALIDVALUE;
                            }
                        }
                      uid_i = strtoul(p, NULL, 0);
                    }
                  uid_i = RSBAC_GEN_UID(tmp_vset, uid_i);
                  if(name) {
                    union rsbac_um_mod_data_t data;

                    if(!rsbac_um_get_user_item(ta_number, uid_i, UM_name, &data))
                      sprintf(name,"%u/%s", RSBAC_UID_SET(uid_i), data.string);
                    else
                      sprintf(name, "%u/%s",
                            RSBAC_UID_SET(uid_i),
                            p);
                  }
                }
              else
                {
                  p++;
                  if(name) {
                    sprintf(name, "%u/%s",
                            RSBAC_UID_SET(uid_i),
                            p);
                  }
                }
              if(uid)
                *uid = uid_i;
              return 0;
    }
    
    if(!(user_info_p = getpwnam(sourcename)))
      {
        char * q;

        if (nonumeric)
          return -RSBAC_EINVALIDVALUE;
        for (q = sourcename; *q; q++)
          {
            if ((*q < '0') || (*q > '9'))
              return -RSBAC_EINVALIDVALUE;
          }
        uid_i = strtoul(sourcename,0,10);
        if(name)
          {
            if((user_info_p = getpwuid(RSBAC_UID_NUM(uid_i))))
              strcpy(name, user_info_p->pw_name);
            else
              sprintf(name, "%u", RSBAC_UID_NUM(uid_i));
          }
      }
    else
      {
        uid_i = user_info_p->pw_uid;
        if(name)
          strcpy(name, user_info_p->pw_name);
      }
    if(uid)
      *uid = uid_i;
    return 0;
  }

int rsbac_get_fullname(rsbac_list_ta_number_t ta_number, char * fullname, rsbac_uid_t uid)
  {
    if(!fullname)
      return -RSBAC_EINVALIDPOINTER;
    if(!RSBAC_UID_SET(uid))
      {
        struct passwd * user_info_p;

        if(!(user_info_p = getpwuid(RSBAC_UID_NUM(uid))))
          {
            sprintf(fullname, "%u", RSBAC_UID_NUM(uid));
          }
        else
          {
            strcpy(fullname, user_info_p->pw_gecos);
          }
      }
    else
      {
        union rsbac_um_mod_data_t data;

        if(!rsbac_um_get_user_item(ta_number, uid, UM_fullname, &data))
          strcpy(fullname, data.string);
        else
          sprintf(fullname, "%u", RSBAC_UID_NUM(uid));
      }
    return 0;
  }

char * get_user_name(rsbac_list_ta_number_t ta_number, rsbac_uid_t user, char * name)
  {
    if(!name)
      return NULL;
    if(!RSBAC_UID_SET(user))
      {
        struct passwd * user_info_p;

        if(!(user_info_p = getpwuid(RSBAC_UID_NUM(user))))
          {
            sprintf(name, "%u", RSBAC_UID_NUM(user));
          }
        else
          {
            strcpy(name, user_info_p->pw_name);
          }
      }
    else
      {
        union rsbac_um_mod_data_t data;

        if(!rsbac_um_get_user_item(ta_number, user, UM_name, &data))
          sprintf(name, "%u/%s", RSBAC_UID_SET(user), data.string);
        else
          sprintf(name, "%u/%u", RSBAC_UID_SET(user), RSBAC_UID_NUM(user));
      }
    return name;
  }

char * get_group_name(rsbac_list_ta_number_t ta_number, rsbac_gid_t group, char * name)
  {
    if(!name)
      return NULL;
    if(!RSBAC_GID_SET(group))
      {
        struct group * group_info_p;

        if(!(group_info_p = getgrgid(RSBAC_GID_NUM(group))))
          {
            sprintf(name, "%u", RSBAC_GID_NUM(group));
          }
        else
          {
            strcpy(name, group_info_p->gr_name);
          }
      }
    else
      {
        union rsbac_um_mod_data_t data;

        if(!rsbac_um_get_group_item(ta_number, group, UM_name, &data))
          sprintf(name, "%u/%s", RSBAC_GID_SET(group), data.string);
        else
          sprintf(name, "%u/%u", RSBAC_GID_SET(group), RSBAC_GID_NUM(group));
      }
    return name;
  }

int rsbac_get_gid_name(rsbac_list_ta_number_t ta_number,
    rsbac_gid_t * gid, char * name, char * sourcename)
  {
    struct group * group_info_p;
    rsbac_gid_t gid_i = RSBAC_NO_GROUP;
    char * p = sourcename;

    if(!sourcename)
      return -RSBAC_EINVALIDPOINTER;
    
    while (*p && (*p != '/'))
      p++;
    if (*p) {
              rsbac_um_set_t tmp_vset = 0;

              gid_i = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_GROUP);
              if(rsbac_um_get_gid(ta_number, sourcename, &gid_i))
                {
                  int err;

                  *p = 0;
                  err = rsbac_get_vset_num(sourcename, &tmp_vset);
		  if (err)
			return err;
                  *p = '/';
                  p++;
                  if (!strcmp(p, "ALL"))
                    gid_i = RSBAC_ALL_GROUPS;
                  else
                    {
                      gid_i = strtoul(p, NULL, 0);
                      if(!gid_i && strcmp(p,"0"))
                        {
                          return -RSBAC_EINVALIDVALUE;
                        }
                    }
                  gid_i = RSBAC_GEN_GID(tmp_vset, gid_i);
                }
              p++;
              if(name) {
                sprintf(name, "%u/%s",
                        RSBAC_GID_SET(gid_i),
                        p);
              }
              if(gid)
                *gid = gid_i;
              return 0;
    }

    if(!(group_info_p = getgrnam(sourcename)))
      {
        gid_i = strtoul(sourcename,0,10);
        if(   !gid_i
           && strcmp("0", sourcename)
          )
          {
            return -RSBAC_EINVALIDVALUE;
          }
        if(name)
          {
            if((group_info_p = getgrgid(RSBAC_GID_NUM(gid_i))))
              strcpy(name, group_info_p->gr_name);
            else
              sprintf(name, "%u", RSBAC_GID_NUM(gid_i));
          }
      }
    else
      {
        gid_i = group_info_p->gr_gid;
        if(name)
          strcpy(name, group_info_p->gr_name);
      }
    if(gid)
      *gid = gid_i;
    return 0;
  }


char * u64tostrlog(char * str, __u64 i)
  {
    int    j = 0;
    __u64  k;

    if(!str)
      return(NULL);

    k = 1;
    for(j = R_NONE - 1;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[R_NONE] = 0;
    return (str);
  };

__u64 strtou64log(char * str, __u64 * i_p)
  {
    int    j;
    __u64  k = 1, res=0;
    
    if(!str)
      return(0);

    if (strlen(str) < R_NONE)
      return(-1);
    for(j=R_NONE-1;j>=0;j--)
      {
        if(str[j] != '0')
          {
            res |= k;
          }
        k <<= 1;
      }
    for(j=R_NONE;j<64;j++)
      {
        res |= k;
        k <<= 1;
      }
    *i_p = res;
    return(res);
  };

char * u64tostrrc(char * str, __u64 i)
  {
    int    j = 0;
    __u64  k;

    if(!str)
      return(NULL);

    k = 1;
    for(j = 63;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[64] = 0;
    return (str);
  };

__u64 strtou64rc(char * str, __u64 * i_p)
  {
    int    j;
    __u64  k = 1, res=0;
    
    if(!str)
      return(0);

    if (strlen(str) < 64)
      return(-1);
    for(j=63;j>=0;j--)
      {
        if(str[j] != '0')
          {
            res |= k;
          }
        k <<= 1;
      }
    *i_p = res;
    return(res);
  };

char * u64tostrrcr(char * str, __u64 i)
  {
    int    j = 0;
    __u64  k;

    if(!str)
      return(NULL);

    k = 1;
    for(j = RCR_NONE - 1;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[RCR_NONE] = 0;
    return (str);
  };

__u64 strtou64rcr(char * str, __u64 * i_p)
  {
    int    j;
    __u64  k = 1, res=0;
    
    if(!str)
      return(0);

    if (strlen(str) < RCR_NONE)
      return(-1);
    for(j=RCR_NONE-1;j>=0;j--)
      {
        if(str[j] != '0')
          {
            res |= k;
          }
        k <<= 1;
      }
    for(j=RCR_NONE;j<64;j++)
      {
        res |= k;
        k <<= 1;
      }
    *i_p = res;
    return(res);
  };

__u64 strtou64mac(char * str, __u64 * i_p)
  {
    int    j;
    __u64  k = 1, res=0;
    
    if(!str)
      return(0);

    if (strlen(str) < RSBAC_MAC_NR_CATS)
      return(-1);
    for(j=RSBAC_MAC_MAX_CAT;j>=0;j--)
      {
        if(str[j] != '0')
          {
            res |= k;
          }
        k <<= 1;
      }
    for(j=RSBAC_MAC_NR_CATS;j<64;j++)
      {
        res |= k;
        k <<= 1;
      }
    *i_p = res;
    return(res);
  };

__u64 strtou64acl(char * str, __u64 * i_p)
  {
    int    j;
    __u64  k = 1, res=0;
    
    if(!str)
      return(0);

    if (strlen(str) < (ACLR_NONE - 1))
      return(-1);
    for(j=ACLR_NONE-1;j>=0;j--)
      {
        if(str[j] != '0')
          {
            res |= k;
          }
        k <<= 1;
      }
    for(j=ACLR_NONE-1;j<64;j++)
      {
        res |= k;
        k <<= 1;
      }
    *i_p = res;
    return(res);
  }

int strtodevdesc(char * str, struct rsbac_dev_desc_t * dev_p)
  {
    char * p;
    char * c;

    if(!str)
      return -RSBAC_EINVALIDVALUE;
    if(!strcmp(str, ":DEFAULT:"))
      {
        *dev_p = RSBAC_ZERO_DEV_DESC;
        return 0;
      }
    p = str;
    c = strchr(p,':');
    switch(*p)
      {
        case 'b':
        case 'B':
          if(c)
            dev_p->type = D_block;
          else
            dev_p->type = D_block_major;
          break;
        case 'c':
        case 'C':
          if(c)
            dev_p->type = D_char;
          else
            dev_p->type = D_char_major;
          break;
        default:
          return -RSBAC_EINVALIDTARGET;
      }
    p++;
    dev_p->major = strtoul(p,0,0);
    if(c)
      {
        c++;
        dev_p->minor = strtoul(c,0,0);
      }
    else
      dev_p->minor = 0;
    return 0;
  }

char * devdesctostr(char * str, struct rsbac_dev_desc_t dev)
  {
    if(RSBAC_IS_ZERO_DEV_DESC(dev))
      {
        sprintf(str, ":DEFAULT:");
        return str;
      }
    switch(dev.type)
      {
        case D_block:
        case D_char:
          sprintf(str, "%c%u:%u", 'b' + dev.type, dev.major, dev.minor);
          break;
        case D_block_major:
        case D_char_major:
          sprintf(str, "%c%u",
                  'b' + dev.type - (D_block_major - D_block),
                  dev.major);
          break;
        default:
          sprintf(str, "invalid!");
      }
    return str;
  }
#endif /* ifndef __KERNEL__ */

char * u64tostracl(char * str, __u64 i)
  {
    int    j = 0;
    __u64  k;

    if(!str)
      return(NULL);

    k = 1;
    for(j = ACLR_NONE - 1;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[ACLR_NONE] = 0;
    return (str);
  };

char * kcaptostrcap(char * str, rsbac_cap_vector_t i)
  {
    int    j = 0;
    int off;
    __u32  k;

    if(!str)
      return NULL;

    k = 1;
    for(j = CAP_NONE - 1;j >= 32;j--)
      {
        if (i.cap[1] & k)
          str[j-32] = '1';
        else
          str[j-32] = '0';
        k<<=1;
      };
    k = 1;
    off = CAP_NONE-32;
    for(j = 31+off;j >= off;j--)
      {
        if (i.cap[0] & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

    str[CAP_NONE] = 0;

    return str;
  }

int strcaptokcap(char * str, rsbac_cap_vector_t * i)
  {
    int    j;
    int    off;
    __u32  k = 1;
    int bitlen;
    
    if(!str)
      return -1;
    bitlen = strlen(str);
    if(bitlen != CAP_NONE && bitlen != CAP_NONE_OLD && bitlen != CAP_NONE_OLD_OLD)
      return -1;

    i->cap[0] = 0;
    i->cap[1] = 0;
    if (bitlen > 32)
      {
        for(j = bitlen-1; j >= 32; j--)
          {
            if(str[j-32] == '1')
              {
                i->cap[1] |= k;
              }
            k <<= 1;
          }
      }
    k = 1;
    off = bitlen-32;
	for(j = 31+off; j >= off; j--) {
		if(str[j] == '1') {
			i->cap[0] |= k;
		}
		k <<= 1;
	}
    return 0;
  }

int strtokmgu32(char * string, __u32 * value_p)
  {
    __u32 number;
    char * endptr;

    if (!string)
      return 0;
    number = strtoul(string, &endptr, 10);
    switch (*endptr)
      {
        case '\0':
          *value_p = number;
          return 0;
        case 'k':
        case 'K':
          *value_p = number * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'm':
        case 'M':
          *value_p = number * 1024 * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'g':
        case 'G':
          *value_p = number * 1024 * 1024 * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'h':
        case 'H':
          *value_p = number * 3600;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'd':
        case 'D':
          *value_p = number * 86400;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        default:
          /* trailing chars? */
          return -RSBAC_EINVALIDVALUE;
      }
  }

int strtokmgu64(char * string, __u64 * value_p)
  {
    __u64 number;
    char * endptr;

    if (!string)
      return 0;
    number = strtoull(string, &endptr, 10);
    switch (*endptr)
      {
        case '\0':
          *value_p = number;
          return 0;
        case 'k':
        case 'K':
          *value_p = number * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'm':
        case 'M':
          *value_p = number * 1024 * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'g':
        case 'G':
          *value_p = number * 1024 * 1024 * 1024;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'h':
        case 'H':
          *value_p = number * 3600;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        case 'd':
        case 'D':
          *value_p = number * 86400;
          /* trailing chars or overrun? */
          if (*(endptr + 1) != '\0' || number > *value_p)
            return -RSBAC_EINVALIDVALUE;
          return 0;
        default:
          /* trailing chars? */
          return -RSBAC_EINVALIDVALUE;
      }
  }

#ifdef __KERNEL__

/* find the current owner of this process */
int rsbac_get_owner(rsbac_uid_t * user_p)
  {
    *user_p = current->uid;
    return(0);
  }

void rsbac_ds_get_error(char * function, enum rsbac_attribute_t attr)
  {
    if(!function)
      return;
    if(attr != A_none)
      {
        char tmp[80];

        get_attribute_name(tmp, attr);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_get_attr() for %s returned error!\n",
                     function, tmp);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_get_attr() returned error!\n",
                     function);
      }
  }

void rsbac_ds_get_error_num(char * function, enum rsbac_attribute_t attr, int err)
  {
    if(!function)
      return;
    if(attr != A_none)
      {
        char tmp[80];
        char tmp2[80];

        get_attribute_name(tmp, attr);
        get_error_name(tmp2, err);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_get_attr() for %s returned error %s!\n",
                     function, tmp, tmp2);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_get_attr() returned error!\n",
                     function);
      }
  }

void rsbac_ds_set_error(char * function, enum rsbac_attribute_t attr)
  {
    if(!function)
      return;
    if(attr != A_none)
      {
        char tmp[80];

        get_attribute_name(tmp, attr);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_set_attr() for %s returned error!\n",
                     function, tmp);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_set_attr() returned error!\n",
                     function);
      }
  }

void rsbac_ds_set_error_num(char * function, enum rsbac_attribute_t attr, int err)
  {
    if(!function)
      return;
    if(attr != A_none)
      {
        char tmp[80];
        char tmp2[80];

        get_attribute_name(tmp, attr);
        get_error_name(tmp2, err);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_set_attr() for %s returned error %s!\n",
                     function, tmp, tmp2);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_set_attr() returned error!\n",
                     function);
      }
  }

#ifdef CONFIG_RSBAC_RC
void rsbac_rc_ds_get_error(char * function, enum rsbac_rc_item_t item)
  {
    if(!function)
      return;
    if(item != RI_none)
      {
        char tmp[80];

        get_rc_item_name(tmp, item);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_rc_get_item() for %s returned error!\n",
                     function, tmp);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_rc_get_item() returned error!\n",
                     function);
      }
  }

void rsbac_rc_ds_set_error(char * function, enum rsbac_rc_item_t item)
  {
    if(!function)
      return;
    if(item != RI_none)
      {
        char tmp[80];

        get_rc_item_name(tmp, item);
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_rc_set_item() for %s returned error!\n",
                     function, tmp);
      }
    else
      {
        rsbac_printk(KERN_WARNING
                     "%s: rsbac_rc_set_item() returned error!\n",
                     function);
      }
  }
#endif


/****************************************************************/
/* Access to user data space                                    */


#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
EXPORT_SYMBOL(rsbac_get_user);
#endif
int rsbac_get_user(unsigned char * kern_p, unsigned char * user_p, int size)
  {
    if(kern_p && user_p && (size > 0))
      {
        return copy_from_user(kern_p, user_p, size);
      }
    return(0);
  }


#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
EXPORT_SYMBOL(rsbac_put_user);
#endif
int rsbac_put_user(unsigned char * kern_p, unsigned char * user_p, int size)
  {
    if(kern_p && user_p && (size > 0))
      {
        return copy_to_user(user_p,kern_p,size);
      }
    return(0);
  };

#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
EXPORT_SYMBOL(rsbac_getname);
#endif
char * rsbac_getname(const char * name)
  {
    return getname(name);
  };

#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
EXPORT_SYMBOL(rsbac_putname);
#endif
void rsbac_putname(const char * name)
  {
    putname(name);
  }

inline int clear_user_buf(char * ubuf, int len)
  {
    return clear_user(ubuf,len);
  }

#endif /* __KERNEL__ */
