/*
 * nasd_edrfs_remove.c
 *
 * Remove a file from an EDRFS server
 *
 * Author: Marc Unangst
 */
/*
 * Copyright (c) of Carnegie Mellon University, 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 <nasd/nasd_types.h>
#include <nasd/nasd_general.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_edrfs_client.h>
#include <stdio.h>

char *progname;

#define ARBITRARY_MAX_PATH_LEN 8192

void
usage()
{
  fprintf(stderr, "USAGE: %s [options] servername pathname\n", progname);
  fprintf(stderr, "  -v     be verbose\n");
  fflush(stderr);
  exit(1);
}

int
main(
  int     argc,
  char  **argv)
{
  nasd_edrfscli_error_string_t edrfserr_str;
  nasd_rpc_status_t status;
  nasd_edrfs_handle_t h;
  char *server_name;
  char pathname[ARBITRARY_MAX_PATH_LEN];
  char *in_pathname;
  char *last_path;
  char *p;
  nasd_status_t rc;
  char c;
  int verbose;
  nasd_cookie_t cookie;
  nasd_cookie_t last_cookie;
  nasd_edrfs_identifier_t dir_nid;
  nasd_edrfs_identifier_t last_dir;
  nasd_edrfs_credential_t cred;
  nasd_edrfs_mount_args_t mount_args;
  nasd_edrfs_mount_res_t mount_res;
  nasd_edrfs_lookup_args_t lookup_args;
  nasd_edrfs_lookup_res_t lookup_res;
  nasd_edrfs_remove_args_t remove_args;
  nasd_edrfs_remove_res_t remove_res;

  progname = argv[0];
  verbose = 0;

  while (nasd_getopt(argc, argv, "v", &c)) {
    switch(c) {
    case 'v':
      verbose = 1;
      break;
    default:
      fprintf(stderr, "Unknown option '%c'\n", c);
      usage();
    }
  }

  if (nasd_optind >= argc)
    usage();
  server_name = argv[nasd_optind];
  nasd_optind++;
  if(nasd_optind >= argc)
    usage();
  in_pathname = argv[nasd_optind];
  if (strlen(in_pathname) >= ARBITRARY_MAX_PATH_LEN) {
    fprintf(stderr, "\"%s\": name too long\n", in_pathname);
    fflush(stderr);
    exit(1);
  }
  strcpy(pathname, in_pathname);
  nasd_optind++;
  if (nasd_optind < argc) {
    fprintf(stderr, "Extra arguments detected on command line\n");
    usage();
  }

  cred.uid = 0;
  cred.gid = 0;

  rc = nasd_cl_p_init();
  if (rc) {
    fprintf(stderr, "ERROR: failed nasd_cl_p_init(), rc=0x%x (%s)\n",
            rc, nasd_error_string(rc));
    exit(1);
  }

  rc = nasd_edrfscli_init();
  if (rc) {
    fprintf(stderr, "ERROR: failed nasd_edrfscli_init() rc=0x%x (%s)\n",
      rc, nasd_error_string(rc));
    exit(1);
  }

  rc = nasd_bind_to_edrfs_server(server_name, NASD_EDRFS_SERVER_PORT,
			       NASD_BIND_DEFAULT, NULL, 0, &h);
  if (rc) {
    fprintf(stderr, "ERROR: unable to bind to server %s, rc=0x%x (%s)\n",
      server_name, rc, nasd_error_string(rc));
    exit(1);
  }

  p = pathname;
  if(*p != '/') {
    printf("ERROR: relative paths are not supported\n");
    goto done;
  }
  p = strtok(p+1, "/");
  if(!p) {
    printf("ERROR: must specify filesystem\n");
    goto done;
  }
  p--;
  mount_args.in_credential = cred;
  strcpy(mount_args.in_dirpath, p);
  nasd_edrfscli_mount(h, &mount_args, &mount_res, &status);
  rc = mount_res.nasd_status;
  if(status || rc) {
    printf("ERROR: mount %s:%s: status=0x%x (%s) nasd_status=0x%x (%s)\n",
	   server_name, p, status, nasd_edrfscli_error_string(h, status, edrfserr_str),
	   rc, nasd_error_string(rc));
    goto done;
  }
  cookie = mount_res.out_cookie;
  dir_nid = mount_res.out_identifier;

  if(verbose)
    printf("mount %s:%s successful\n", server_name, p);

  last_path = NULL;
  while((p = strtok(NULL, "/"))) {
    lookup_args.in_cookie = cookie;
    lookup_args.in_identifier = dir_nid;
    lookup_args.in_credential = cred;
    strcpy(lookup_args.in_dirpath, p);
    nasd_edrfscli_lookup(h, &lookup_args, &lookup_res, &status);
    rc = lookup_res.nasd_status;

    if(status || rc) {
      printf("ERROR: lookup %s in dir 0x%" NASD_ID_FMT
         ": status=0x%x (%s) nasd_status=0x%x (%s)\n",
	     p, dir_nid.nasd_identifier,
	     status, nasd_edrfscli_error_string(h, status, edrfserr_str),
	     rc, nasd_error_string(rc));
      goto done;
    }
    if(verbose) {
      printf("lookup %s in dir 0x%" NASD_ID_FMT " successful\n", p,
        dir_nid.nasd_identifier);
    }
    last_path = p;
    last_dir = dir_nid;
    last_cookie = cookie;
    cookie = lookup_res.out_cookie;
    dir_nid = lookup_res.out_identifier;
  }
  if (last_path == NULL) {
    fprintf(stderr, "ERROR: unable to parse path \"%s\" for last element\n",
      in_pathname);
    fflush(stderr);
    exit(1);
  }
  remove_args.in_credential = cred;
  remove_args.in_directory = last_dir;
  remove_args.in_cookie = last_cookie;
  strcpy(remove_args.in_dirpath, last_path);
  nasd_edrfscli_remove(h, &remove_args, &remove_res, &status);
  rc = remove_res.nasd_status;
  if(status || rc) {
    printf("ERROR: remove %s in dir 0x%" NASD_ID_FMT ": status=0x%x (%s) nasd_status=0x%x (%s)\n",
	   last_path, last_dir.nasd_identifier, status,
	   nasd_edrfscli_error_string(h, status, edrfserr_str), rc,
	   nasd_error_string(rc));
    goto done;
  }
  if(verbose)
    printf("remove %s from dir 0x%" NASD_ID_FMT " successful\n", last_path,
	   last_dir.nasd_identifier);

 done:
  rc = nasd_unbind_edrfs_server(&h);
  if (rc) {
    fprintf(stderr, "ERROR: got 0x%x (%s) unbinding EDRFS server\n",
      rc, nasd_error_string(rc));
    exit(1);
  }

  nasd_edrfscli_shutdown();
  nasd_cl_p_shutdown();

  exit(0);
}
