/* Blocks
 *
 * by Thies Wellpott
 *
 * Usage: Blocks <file>|<bytes>
 * calculates number of blocks used by file or bytes including file header
 * and file list blocks
 *
 * compile (SAS C V5.10a):
 *   LC -cisu -rr -v -O Blocks
 * link:
 *   BLink FROM LIB:c.o,Blocks.o TO Blocks SC SD ND LIB LIB:lcr.lib
 *
 *
 * HISTORY
 *
 * V1.00  28.6.92
 *   first version
 * V1.10  29.6.92
 *   feature added: you may give a number (of bytes) as argument
 *
 *
 * TODO
 *
 * - accept device name and calculated number of blocks for that device
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <exec/memory.h>
#include <dos/dos.h>

#define VERSION "1.10"
#define DATE "29.06.92"


/* for DOS-command Version (OS 2.0) */
char version[] = "$VER: Blocks V"VERSION" ("DATE")";
BPTR lock = NULL;
struct FileInfoBlock *fib = NULL;   /* must be longword-aligned!! */


void close_all(char *s, int err)
/* close/free all and exit */
{
   if (lock) UnLock(lock);
   if (fib) FreeMem(fib, sizeof(struct FileInfoBlock));

   if (s) printf("%s!\n", s);
   exit(err);
}


void usage(void)
/* print usage and exit */
{
   printf("\2334m%s\2330m by Thies Wellpott\n\n", &version[6]);
   printf("Usage: Blocks <file>|<bytes>\n");

   exit(5);
}


int get_blocks(long size, int bpb)
/* returns number of blocks used by size bytes with bpb bytes per block */
{
   int data_blk, list_blk;

   data_blk = (size + bpb - 1) / bpb;  /* number of data blocks */
   list_blk = (data_blk - 1) / 72;     /* number of file list blocks */

   return(1 + list_blk + data_blk);    /* file header + list + data blocks */
}


void main(int argc, char *argv[])
{
   int i, flag=1;
   long size;

   if ((argc != 2) || (*argv[1] == '?'))
      usage();

   size = strlen(argv[1]);
   for (i = 0; i < size; i++)
      if ((argv[1][i] < '0') || (argv[1][i] > '9'))
      {
	 flag = 0;
	 break;
      }

   if (flag)
   {
      size = atoi(argv[1]);
      printf("%d byte(s) need\n", size);
   }
   else
   {
      if (!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
	 close_all("Out of memory", 20);
      if (!(lock = Lock(argv[1], ACCESS_READ)))
	 close_all("Can`t find file", 20);
      if (!(Examine(lock, fib)))
	 close_all("Can`t examine file", 20);
      size = fib->fib_Size;
      printf("%s has %d byte(s) and needs\n", argv[1], size);
   }

   printf("NFS (488 bytes per block): %d block(s)\n", get_blocks(size, 488));
   printf("FFS (512 bytes per block): %d block(s)\n", get_blocks(size, 512));

   close_all(NULL, 0);
}

