db_line* db_char2line(char** ss, database* db){

  db_line* line=(db_line*)checked_malloc(sizeof(db_line)*1);

  line->perm=0;
  line->uid=0;
  line->gid=0;
  line->atime=0;
  line->ctime=0;
  line->mtime=0;
  line->inode=0;
  line->nlink=0;
  line->bcount=0;
  line->size=0;
  line->filename=NULL;
  line->fullpath=NULL;
  line->linkname=NULL;
  line->acl=NULL;
  line->xattrs=NULL;
  line->e2fsattrs=0;
  line->cntx=NULL;
  line->capabilities=NULL;

  for (int i = 0 ; i < num_hashes ; ++i) {
      line->hashsums[i]=NULL;
  }

  
  line->attr=conf->attr; /* attributes from @@dbspec */

  for(int i=0;i<db->num_fields;i++){

    log_msg(LOG_LEVEL_TRACE, "db_char2line(): %d[%d]: '%s' (%p)", db->lineno, i, ss[i], ss[i]);

    switch (db->fields[i]) {
    case attr_filename : {
      if(ss[db->fields[i]]!=NULL){
	decode_string(ss[db->fields[i]]);
	line->fullpath=checked_strdup(ss[db->fields[i]]);
	line->filename=line->fullpath;
      } else {
        log_msg(LOG_LEVEL_ERROR, "db_char2line(): error while reading database");
	exit(EXIT_FAILURE);
      }
      break;
    }
    case attr_linkname : {
      line->linkname = db_readchar(ss[db->fields[i]]);
      break;
    }
    case attr_mtime : {
      line->mtime=base64totime_t(ss[db->fields[i]], db, "mtime");
      break;
    }
    case attr_bcount : {
      line->bcount=readlonglong(ss[db->fields[i]], db, "bcount");
      break;
    }
    case attr_atime : {
      line->atime=base64totime_t(ss[db->fields[i]], db, "atime");
      break;
    }
    case attr_ctime : {
      line->ctime=base64totime_t(ss[db->fields[i]], db, "ctime");
      break;
    }
    case attr_inode : {
      line->inode=readlong(ss[db->fields[i]], db, "inode");
      break;
    }

    case attr_uid : {
      line->uid=readlong(ss[db->fields[i]], db, "uid");
      break;
    }
    case attr_gid : {
      line->gid=readlong(ss[db->fields[i]], db, "gid");
      break;
    }
    case attr_size : {
      line->size=readlonglong(ss[db->fields[i]], db, "size");
      break;
    }
    CHAR2HASH(md5)
    CHAR2HASH(sha256)
    CHAR2HASH(sha512)
    CHAR2HASH(sha1)
    CHAR2HASH(rmd160)
    CHAR2HASH(tiger)
    CHAR2HASH(crc32)
    CHAR2HASH(crc32b)
    CHAR2HASH(haval)
    CHAR2HASH(whirlpool)
    CHAR2HASH(gostr3411_94)
    CHAR2HASH(stribog256)
    CHAR2HASH(stribog512)
    case attr_acl : {
#ifdef WITH_POSIX_ACL
      char *tval = NULL;
      
      tval = strtok(ss[db->fields[i]], ",");

      line->acl = NULL;

      if (tval[0] == '0')
        line->acl = NULL;
      else if (!strcmp(tval, "POSIX"))
      {
        line->acl = checked_malloc(sizeof(acl_type));
        line->acl->acl_a = NULL;
        line->acl->acl_d = NULL;
        
        tval = strtok(NULL, ",");
        line->acl->acl_a = (char *)base64tobyte(tval, strlen(tval), NULL);
        tval = strtok(NULL, ",");
        line->acl->acl_d = (char *)base64tobyte(tval, strlen(tval), NULL);
      }
      /* else, it's broken... */
#endif
      break;
    }
      case attr_xattrs : {
        size_t num = 0;
        char *tval = NULL;
        
        tval = strtok(ss[db->fields[i]], ",");
        num = readlong(tval,  db, "xattrs");
        if (num)
        {
          line->xattrs = checked_malloc(sizeof(xattrs_type));
          line->xattrs->ents = checked_calloc(sizeof(xattr_node), num);
          line->xattrs->sz  = num;
          line->xattrs->num = num;
          num = 0;
          while (num < line->xattrs->num)
          {
            byte  *val = NULL;
            size_t vsz = 0;
            
            tval = strtok(NULL, ",");
            line->xattrs->ents[num].key = db_readchar(checked_strdup(tval));
            tval = strtok(NULL, ",");
            val = base64tobyte(tval, strlen(tval), &vsz);
            line->xattrs->ents[num].val = val;
            line->xattrs->ents[num].vsz = vsz;

            ++num;
          }
        }
        break;
      }

      case attr_selinux : {
        byte  *val = NULL;
        
        val = base64tobyte(ss[db->fields[i]], strlen(ss[db->fields[i]]),NULL);
        line->cntx = (char *)val;
        break;
      }
      
    case attr_perm : {
      line->perm=readoct(ss[db->fields[i]], db, "permissions");
      break;
    }
    
    case attr_linkcount : {
      line->nlink=readlong(ss[db->fields[i]], db, "nlink");
      break;
    }

    case attr_attr : {
      line->attr=readlonglong(ss[db->fields[i]], db, "attr");
      break;
    }
    
    case attr_e2fsattrs : {
      line->e2fsattrs=readlong(ss[db->fields[i]], db, "e2fsattrs");
      break;
    }

    case attr_capabilities : {
      byte  *val = NULL;

      val = base64tobyte(ss[db->fields[i]], strlen(ss[db->fields[i]]),NULL);
      line->capabilities = (char *)val;
      break;
    }
    case attr_bsize :
    case attr_sizeg :
    case attr_rdev :
    case attr_dev :
    case attr_ftype :
    case attr_checkinode :
    case attr_allhashsums :
    case attr_allownewfile :
    case attr_allowrmfile : {
      /*  no db field */
      break;
    }
    case attr_unknown : {
      /* Unknown fields are ignored. */
      break;
    }
    
    }
    
  }

  return line;
}
db_line* db_char2line(char** ss, database* db){

  db_line* line=(db_line*)checked_malloc(sizeof(db_line)*1);

  line->perm=0;
  line->uid=0;
  line->gid=0;
  line->atime=0;
  line->ctime=0;
  line->mtime=0;
  line->inode=0;
  line->nlink=0;
  line->bcount=0;
  line->size=0;
  line->filename=NULL;
  line->fullpath=NULL;
  line->linkname=NULL;
  line->acl=NULL;
  line->xattrs=NULL;
  line->e2fsattrs=0;
  line->cntx=NULL;
  line->capabilities=NULL;

  for (int i = 0 ; i < num_hashes ; ++i) {
      line->hashsums[i]=NULL;
  }

  
  line->attr=conf->attr;  

  for(int i=0;i<db->num_fields;i++){

    log_msg(LOG_LEVEL_TRACE, "db_char2line(): %d[%d]: '%s' (%p)", db->lineno, i, ss[i], ss[i]);

    switch (db->fields[i]) {
    case attr_filename : {
      if(ss[db->fields[i]]!=NULL){
	decode_string(ss[db->fields[i]]);
	line->fullpath=checked_strdup(ss[db->fields[i]]);
	line->filename=line->fullpath;
      } else {
        log_msg(LOG_LEVEL_ERROR, "db_char2line(): error while reading database");
	exit(EXIT_FAILURE);
      }
      break;
    }
    case attr_linkname : {
      line->linkname = db_readchar(ss[db->fields[i]]);
      break;
    }
    case attr_mtime : {
      line->mtime=base64totime_t(ss[db->fields[i]], db, "mtime");
      break;
    }
    case attr_bcount : {
      line->bcount=readlonglong(ss[db->fields[i]], db, "bcount");
      break;
    }
    case attr_atime : {
      line->atime=base64totime_t(ss[db->fields[i]], db, "atime");
      break;
    }
    case attr_ctime : {
      line->ctime=base64totime_t(ss[db->fields[i]], db, "ctime");
      break;
    }
    case attr_inode : {
      line->inode=readlong(ss[db->fields[i]], db, "inode");
      break;
    }

    case attr_uid : {
      line->uid=readlong(ss[db->fields[i]], db, "uid");
      break;
    }
    case attr_gid : {
      line->gid=readlong(ss[db->fields[i]], db, "gid");
      break;
    }
    case attr_size : {
      line->size=readlonglong(ss[db->fields[i]], db, "size");
      break;
    }
    CHAR2HASH(md5)
    CHAR2HASH(sha256)
    CHAR2HASH(sha512)
    CHAR2HASH(sha1)
    CHAR2HASH(rmd160)
    CHAR2HASH(tiger)
    CHAR2HASH(crc32)
    CHAR2HASH(crc32b)
    CHAR2HASH(haval)
    CHAR2HASH(whirlpool)
    CHAR2HASH(gostr3411_94)
    CHAR2HASH(stribog256)
    CHAR2HASH(stribog512)
    case attr_acl : {
#ifdef WITH_POSIX_ACL
      char *tval = NULL;
      
      tval = strtok(ss[db->fields[i]], ",");

      line->acl = NULL;

      if (tval[0] == '0')
        line->acl = NULL;
      else if (!strcmp(tval, "POSIX"))
      {
        line->acl = checked_malloc(sizeof(acl_type));
        line->acl->acl_a = NULL;
        line->acl->acl_d = NULL;
        
        tval = strtok(NULL, ",");
        line->acl->acl_a = (char *)base64tobyte(tval, strlen(tval), NULL);
        tval = strtok(NULL, ",");
        line->acl->acl_d = (char *)base64tobyte(tval, strlen(tval), NULL);
      }
       
#endif
      break;
    }
      case attr_xattrs : {
        size_t num = 0;
        char *tval = NULL;
        
        tval = strtok(ss[db->fields[i]], ",");
        num = readlong(tval,  db, "xattrs");
        if (num)
        {
          line->xattrs = checked_malloc(sizeof(xattrs_type));
          line->xattrs->ents = checked_calloc(sizeof(xattr_node), num);
          line->xattrs->sz  = num;
          line->xattrs->num = num;
          num = 0;
          while (num < line->xattrs->num)
          {
            byte  *val = NULL;
            size_t vsz = 0;
            
            tval = strtok(NULL, ",");
            line->xattrs->ents[num].key = db_readchar(checked_strdup(tval));
            tval = strtok(NULL, ",");
            val = base64tobyte(tval, strlen(tval), &vsz);
            line->xattrs->ents[num].val = val;
            line->xattrs->ents[num].vsz = vsz;

            ++num;
          }
        }
        break;
      }

      case attr_selinux : {
        byte  *val = NULL;
        
        val = base64tobyte(ss[db->fields[i]], strlen(ss[db->fields[i]]),NULL);
        line->cntx = (char *)val;
        break;
      }
      
    case attr_perm : {
      line->perm=readoct(ss[db->fields[i]], db, "permissions");
      break;
    }
    
    case attr_linkcount : {
      line->nlink=readlong(ss[db->fields[i]], db, "nlink");
      break;
    }

    case attr_attr : {
      line->attr=readlonglong(ss[db->fields[i]], db, "attr");
      break;
    }
    
    case attr_e2fsattrs : {
      line->e2fsattrs=readlong(ss[db->fields[i]], db, "e2fsattrs");
      break;
    }

    case attr_capabilities : {
      byte  *val = NULL;

      val = base64tobyte(ss[db->fields[i]], strlen(ss[db->fields[i]]),NULL);
      line->capabilities = (char *)val;
      break;
    }
    case attr_bsize :
    case attr_sizeg :
    case attr_rdev :
    case attr_dev :
    case attr_ftype :
    case attr_checkinode :
    case attr_allhashsums :
    case attr_allownewfile :
    case attr_allowrmfile : {
       
      break;
    }
    case attr_unknown : {
       
      break;
    }
    
    }
    
  }

  return line;
}