#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <rsbac/types.h>
#include <rsbac/getname.h>
#include <rsbac/syscalls.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include <rsbac/aci_data_structures.h>

const char   set_prog[] = "attr_set_file_dir";
enum rsbac_attribute_t attr_list[RSBAC_DEV_NR_ATTRIBUTES] = RSBAC_DEV_ATTR_LIST;
int recurse = 0;
int verbose = 0;
FILE * tfile;

int process(char * name)
  {
    struct rsbac_dev_aci_t default_dev_aci = DEFAULT_DEV_ACI;
    int def_attr[RSBAC_DEV_NR_ATTRIBUTES] = {
      default_dev_aci.sec_level,
      default_dev_aci.object_category,
      default_dev_aci.data_type,
      default_dev_aci.mac_check,
      default_dev_aci.pm_object_type,
      default_dev_aci.pm_object_class
      };
    int res = 0;
    char tmp1[120];
    char tmp2[65];
    int j;
    struct stat buf;
    union rsbac_attribute_value_t value;

    if (lstat(name,&buf))
      {
        fprintf(stderr, "stat for file %s returned error: %s\n",
               name,
               strerror(errno));
        return(1);
      }
      if(   !(S_ISCHR(buf.st_mode))
         && !(S_ISBLK(buf.st_mode)) )
        {
          if(verbose)
            printf("%s is neither block nor char special file, skipped\n",
                   name);
          return(-1);
        }
    if(verbose)
      printf("Processing DEV '%s'\n", name);
    for (j=0;j < RSBAC_DEV_NR_ATTRIBUTES;j++)
      {
        value.dummy = -1;
        res = rsbac_get_attr_n(T_DEV, name, attr_list[j], &value, 0);
        if(res)
          {
            if((res > -RSBAC_EPERM) || (res < -RSBAC_EDECISIONMISMATCH))
              fprintf(stderr, "%s (%s): %s\n",
                      name,
                      get_attribute_name(tmp1,attr_list[j]),
                      strerror(-res));
            else
              {
                get_error_name(tmp1,res);
                fprintf(stderr, "%s (%s): %s\n",
                        name,
                        get_attribute_name(tmp2,attr_list[j]),
                        tmp1);
              }
          }
        else
          switch(attr_list[j])
            {
              case A_log_array_low:
              case A_log_array_high:
                if (value.log_array_low != -1)
                  fprintf(tfile,
                          "%s DEV %s %s %s\n",
                          set_prog,
                          name,
                          get_attribute_name(tmp1,attr_list[j]),
                          u64tostrlog(tmp2,value.log_array_low));
                break;
              default:
                if(value.dummy != def_attr[j])
                  fprintf(tfile,
                          "%s DEV %s %s %i\n",
                          set_prog,
                          name,
                          get_attribute_name(tmp1,attr_list[j]),
                          value.dummy);
            }
      }
    return(res);
  }

int main(int argc, char ** argv)
{
  int res = 0;
  char tmp1[80],tmp2[120];
  int i,j;
  char * progname;

  progname = argv[0];
  if ((argc > 1) && (!strcmp("-v",argv[1])) )
    {
      verbose=1;
      argv++;
      argc--;
    }  
  if (argc > 2)
    {
      if (!(tfile=fopen(argv[1],"w")))
        {
          fprintf(stderr, "opening target file returned error: %s\n", strerror(errno));
        }
      printf("%s: %i targets\n", progname, argc - 2);
      for (i=1;i < (argc-1);i++)
        {
          process(argv[i+1]);
        }
      fclose(tfile);
    }
  else
    {
      printf("%s (RSBAC %s)\n***\n", argv[0], VERSION);
      printf("Use: %s [-v] target-file file/dirname(s)\n", progname);  
      printf("- should be called by root with all rsbac modules switched off,\n");
      printf("- -v = verbose, no symlinks followed,\n");
      printf("- target-file = name of restore script to be created,\n");
      printf("- attributes and values in backup = see following list:\n");
      for (j=0;j<RSBAC_DEV_NR_ATTRIBUTES;j++)
        {
          get_attribute_name(tmp1,attr_list[j]);
          get_attribute_param(tmp2,attr_list[j]);
          printf("%s \t%s\n",tmp1,tmp2);
        }
    }
  return (res);
}

