/******************************** */
/* Rule Set Based Access Control  */
/* Author and (c) 1999: Amon Ott  */
/* Helper functions for all parts */
/* Last modified: 16/Aug/99       */
/******************************** */

#include <rsbac/types.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include <rsbac/rc_types.h>
#include <rsbac/getname.h>

#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#endif
#ifndef __KERNEL__
#include <stdio.h>
#include <string.h>
#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);
  };

#ifndef __KERNEL__

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

    if(error)
      {
        if((error > -RSBAC_EPERM) || (error < -RSBAC_EDECISIONMISMATCH))
          fprintf(stderr, "Error: %s\n", strerror(-error));
        else
          {
            get_error_name(tmp1,error);
            fprintf(stderr, "Error: %s\n", tmp1);
          }
        exit(1);
      }
  }

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 = RSBAC_RC_MAX_ROLE;j >= 0;j--)
      {
        if (i & k)
          str[j] = '1';
        else
          str[j] = '0';
        k<<=1;
      };

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

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

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

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

__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);
  };
#endif

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

#ifdef __KERNEL__
/****************************************************************/
/* Access to user data space                                    */


#ifdef __KERNEL__
#ifdef CONFIG_RSBAC_REG
EXPORT_SYMBOL(rsbac_get_user);
#endif
#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);
  };


#ifdef __KERNEL__
#ifdef CONFIG_RSBAC_REG
EXPORT_SYMBOL(rsbac_put_user);
#endif
#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);
  };

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

#endif /* __KERNEL__ */
