/* Hey Emacs, this is -*-C-*- 
 *
 * cwls.c -- List dynamic partitions.
 * 
 * Author          : Peter Bosch
 * Created On      : Fri Mar 26 11:00:28 1999
 * Last Modified By: Peter Bosch
 * Last Modified On: Fri Sep 24 15:51:37 1999
 * Status          : Unknown, Use with caution!
 * 
 * Unless other notices are present in any part of this file
 * explicitly claiming copyrights for other people and/or 
 * organizations, the contents of this file is fully copyright 
 * (C) 1999 Peter Bosch, all rights reserved.
 */

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sched.h>
#include <string.h>
#include <sys/sysmacros.h>

#include "cwif.h"

static char *clockwise = CLOCKWISE;
static int  longlist;
static char *progname;
static int entrynum = -1;

extern int optind;
extern char *optarg;

static void
usage()
{
  fprintf(stderr, "Usage: %s [-c clockwise] [-l] [-e entry]\n", progname);
  exit(1);
}

int
main(int argc, char **argv)
{
  int opt, fd, entry;

  progname = argv[0];
  while ((opt = getopt(argc, argv, "e:lc:?")) != EOF) {
    switch (opt) {
    case 'e':
      entrynum = (int)strtol(optarg, (char **)NULL, 0);
      break;
    case 'c':
      clockwise = optarg;
      break;
    case 'l':
      longlist = 1;
      break;
    case '?':
      usage();
    }
  }
  if (optind != argc) usage();

  fd = open(clockwise, O_RDONLY);
  if (fd < 0) {
    fprintf(stderr, "%s: Cannot open %s: %s\n",
	    progname, clockwise, strerror(errno));
    exit(1);
  }

  printf("dpnum            fsize  id   iaddr  isz dpname\n");
  printf("=============================================\n");
  entry = 0;
  while (1) {
    cwftabentry_t ft;
    int rv;
    
    if ((rv = read(fd, (void *)&ft, sizeof(cwftabentry_t))) < 0) {
      fprintf(stderr, "%s: Cannot read ftab entry from %s: %s\n",
	      progname, clockwise, strerror(errno));
      exit(1);
    }

    if (rv == 0) break;

    if (rv != sizeof(cwftabentry_t)) {
      fprintf(stderr, "%s: Partially read ftab entry from %s: requested %d, got %d\n",
	      progname, clockwise, sizeof(cwftabentry_t), rv);
      exit(1);
    }
    
    if (ft.ft_magic != CW_FTMAGIC) {
      entry++;
      continue;
    }

    if (entrynum != -1 && entry != entrynum) {
      entry++;
      continue;
    }

    printf("[%03d] %016qd %03d %07d %04d %s\n",
	   entry, ft.ft_fsize, ft.ft_idisk, ft.ft_iaddr, ft.ft_isize,
	   ft.ft_name);

    if (longlist) {
      cwdinode_t *inode;
      int n;

      inode = (cwdinode_t *)malloc(ft.ft_isize);
      if (inode == NULL) {
	fprintf(stderr, "%s: Cannot allocate %d bytes for inode\n",
		progname, ft.ft_isize);
	goto ignore;
      }

      if ((rv = ioctl(fd, CW_INODE(entry), inode)) < 0) {
	fprintf(stderr, "%s: Cannot get inode from %s: %s\n",
		progname, clockwise, strerror(errno));
	free(inode);
	goto ignore;
      }

      for (n = 0; n != ft.ft_isize / sizeof(cwdinode_t); n++)
	printf("     [%05d] %03d %06d\n",
	       n, inode[n].i_ldisk, inode[n].i_daddr);
      free(inode);
    }

  ignore:
    entry++;
  }

  (void)close(fd);
  exit(0);
}
