/*
 * pcrobj.c
 *
 * Create object on NASD partition
 *
 * Author: Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#include <nasd/nasd_options.h>
#include <nasd/nasd_getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <nasd/nasd_pdrive.h>

#include <nasd/nasd_pdrive_client.h>
#include <nasd/nasd_pdrive_client_kpdev.h>
#include <nasd/nasd_security.h>




void
usage()
{
  int i;
  fprintf(stderr, "USAGE: pcrobj [options] servername master_password\n");
  fprintf(stderr, "Options:\n");
  fprintf(stderr, "  -k use kernel device\n");
  fprintf(stderr, "  -M use message queues\n");
  fprintf(stderr, "  -n number of objects to create [default 1]\n");
  fprintf(stderr, "  -p partition number\n");
  fprintf(stderr, "  -s security level\n");
  fprintf(stderr, "  where security levels are:\n" );
  for(i = 0; i <= NASD_MAX_SECURITY_LEVEL; i++) {
    fprintf(stderr, "     %d %s\n", i, nasd_sec_level_string(i));
  }
#if NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE
  fprintf(stderr, "  -T use DCE-TCP\n");
#endif /* NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE */
  fflush(stderr);
  exit(1);
}

int
main(argc, argv)
  int     argc;
  char  **argv;
{
  int binding_type;
  int binding_args_len;
  void *binding_args;
  char *binding_port = NASD_PDRIVE_PORT;
  nasd_drive_param_kpdev_t kpdev_args;
  int nondefault_binding = 0;
  int nobjs;
  char *server_name, *master_password;
  nasd_p_create_dr_args_t args;
  nasd_error_string_t err_str;
  nasd_p_create_dr_res_t res;
  nasd_rpc_status_t status;
  nasd_drive_handle_t h;
  nasd_status_t rc;
  int partnum, i;
  char c;
  int sec_level = 0;
  nasd_uint16 protection;
  nasd_security_param_t sec_param;
  nasd_sec_keyring_t keys;
  nasd_key_t op_key;

  nobjs = 1;
  partnum = 1;
  binding_type = NASD_BIND_DEFAULT;
  binding_args = NULL;
  binding_args_len = 0;

  while (nasd_getopt(argc, argv, "kMn:p:s:T", &c)) {
    switch(c) {
      case 'k':
        if (nondefault_binding)
          usage();
        nondefault_binding = 1;
        binding_type = NASD_BIND_KPDEV_DEFAULT;
        binding_args = &kpdev_args;
        binding_args_len = sizeof(kpdev_args);
        strcpy(kpdev_args.devname, "/dev/nasdkp0");
        break;
      case 'p':
        if (sscanf(nasd_optarg, "%d", &partnum) != 1)
          usage();
        break;
      case 'n':
        if (sscanf(nasd_optarg, "%d", &nobjs) != 1)
          usage();
        if (nobjs <= 0)
          usage();
        break;
      case 'M':
        if (nondefault_binding)
          usage();
        nondefault_binding = 1;
        binding_type = NASD_BIND_MSGQ;
        break;
      case 's':
        sec_level = atoi(nasd_optarg);
        break;
#if NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE
      case 'T':
        if (nondefault_binding)
          usage();
        nondefault_binding = 1;
        binding_type = NASD_BIND_DCE_DIRECT_TCP;
        break;
#endif /* NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE */
      default:
        fprintf(stderr, "Unknown option '%c'\n", nasd_optopt);
        usage();
    }
  }
  if (nasd_optind >= argc)
    usage();
  server_name = argv[nasd_optind];
  nasd_optind++;

  if (nasd_optind >= argc)
    usage();
  master_password = argv[nasd_optind];
  nasd_optind++;

  if (nasd_optind < argc)
    usage();

  if (partnum < 0)
    usage();

  rc = nasd_cl_p_init();
  if (rc) {
    printf("ERROR (%s:%d): cannot init client library, rc=%ld\n",
      __FILE__, __LINE__, (long)rc);
    return(rc);
  }

  rc = nasd_sec_seclevel_to_protection(sec_level, &protection);
  if(rc) {
    fprintf(stderr, "ERROR: invalid security level %d\n", sec_level);
    usage();
  }

  rc = nasd_bind_to_drive(server_name, binding_port,
    binding_type, binding_args, binding_args_len, &h);
  if (rc) {
    fprintf(stderr, "ERROR: cannot bind to server %s\n", server_name);
    fflush(stderr);
    exit(1);
  }

  bzero(&args, sizeof(nasd_p_create_dr_args_t));
  bzero(&sec_param, sizeof(nasd_security_param_t));

  if(sec_level > 0) {
    /* ordinarily, it is the FM's job to perform the CREATE op, so we
       would have the appropriate daily key.  since we're not the FM, we
       use a cheesy "password" facility to generate the appropriate
       key. */
    nasd_sec_password_to_keys(master_password, partnum, &keys);
    /* This can be any key, though in a real application the FM would
       not have the drive key or the master key.  We arbitratily
       choose the black daily key. */
    sec_param.type = NASD_BLACK_KEY;
    sec_param.partnum = partnum;
    bcopy(keys.black_key, op_key, sizeof(nasd_key_t));
  } else {
    bzero(op_key, sizeof(nasd_key_t));
  }
  sec_param.partnum = partnum;
  sec_param.actual_protection = protection;

  /* Testing standard AV */ 
  args.in_fieldmask=NASD_ATTR_AV;
  args.in_attribute.av=7;
  args.in_partnum = partnum;

  for(i=0;i<nobjs;i++) {
    nasd_cl_p_create_dr(h, op_key, &sec_param, NULL,
                        &args, &res, &status);

    if (status) {
      fprintf(stderr, "ERROR: status=0x%x (%s) nasd_status=0x%x (%s)\n",
        status, nasd_cl_error_string(h, status, err_str),
        res.nasd_status, nasd_error_string(res.nasd_status));
      fflush(stderr);
      exit(2);
    }

    if (res.nasd_status) {
      fprintf(stderr, "ERROR: nasd_status=0x%x (%s) i=%d\n",
        res.nasd_status, nasd_error_string(res.nasd_status), i);
      fflush(stderr);
      exit(2);
    }

    if (nobjs > 1) {
      printf("Succeeded, id=0x%" NASD_ID_FMT " obj #%d\n",
        res.out_identifier, i+1);
    }
    else {
      printf("Succeeded, id=0x%" NASD_ID_FMT "\n", res.out_identifier);
    }
    fflush(stdout);
  }

  rc = nasd_unbind_drive(&h);
  if (rc) {
    fprintf(stderr, "ERROR: got 0x%x (%s) from nasd_unbind_drive()\n",
      rc, nasd_error_string(rc));
    fflush(stderr);
    exit(2);
  }

  nasd_cl_p_shutdown();

  exit(0);
}

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
