#ifdef DOCUMENTATION

Title     nftupd    Updates file from remote computer to local computer
Index     nftupd    Updates file from remote computer to local computer

Usage
	.s.nf
	nup node::[uic]infile outfile.spec

Description

	nftupd will open a file remotely, a file locally and copy from
	the remote file to the local file.  Both files must have been
	created.

        To use nftupd, you must supply arguments in the form of:

	   Node::[XX,XX]input.ext output.ext 

           (e.g. DEVSYS::[40,40]options.dat new.dat)

       The example above would open a file remotely on the devsys computer
       called options.dat and copy that file to a file called new.dat on 
       whatever computer you are using.		

Implementation Details

	nftupd does remote file access on computer requested (node name).
	It opens remote file requested in read mode.  If then opens local file
	requested in append mode.

        It uses rgetb to get one block of data from remote file and put it into
       	a buffer.  If then used fputb to put this same data into a buffer for
	the local file (thus copying the data to the local output file). 

        The block number for the input (rgetb) and output (fputb) is increased
	each time by the number of blocks being read in (BLKSIZ).

        The input and output continues until the physical end of file is
	reached (-10), at which time both files are closed and the program
	exits.

	If any errors are encountered, a message is sent out through tmsg.
#endif	

#include <stdio.h>
#include <cap.h>
#include <cx.h>
#include <stdnet.h>

#define BUFSIZ 15		/* maximum xfr across net is 8k */

char buf[BUFSIZ*512];		/* read-write buffer         */

NIOV     *fd1;			/* Input file channel        */
FILE	*fd2;			/* Output file channel       */

extern OPNSTS $rstat;		/* statistics for remote file */
extern unsigned $$stbk[];	/* statistics block for local file */

extern int $$ferr;		/* file error		     */
extern int $$nerr;		/* network error 	     */	

main(argc,argv)
char *argv[];
{
  int blknum;
  FATRB *ap;		/* attributes pointer */
  int rmtsiz;		/* remote file size */
  int lclsiz;		/* local file size */
  int xfrsiz;		/* size of current  transfer */

  if(argc != 3) {			/* check for valid argument input */
     tmsg('F',"usage: nup <infile> <outfile> \n");
     exit(1);
     }

  if((fd1 = fopnxn(argv[1], "rn", 0, 0)) == NULL){ /* remote file open */
     tmsg('F', "can't open input file %s ferr %o nerr %o\n", argv[1], $$ferr, 
	 $$nerr);
     exits(4);			/* exit with error */
	    }

  ap = &$rstat.att;	/* point remote file attributes */
  rmtsiz = ap->f_efbk[1] - 1;	/* end of file on remote */

#ifdef DEBUG
  tmsg('M', "typ %3.3o att %3.3o rsiz %d hibk|%d|%d| efbk|%d|%d| ffby %d\n",
	ap->f_rtyp, ap->f_ratt, ap->f_rsiz, ap->f_hibk[0], ap->f_hibk[1], 
    	ap->f_efbk[0], ap->f_efbk[1], ap->f_ffby);
#endif

  if((fd2 =fopenx(argv[2],"m", 0, 0)) == NULL){	/* local file open */
     tmsg('F',"can't open file %s\n", argv[2]);
     exit(4);			/* exit with error */
     }

  lclsiz = $$stbk[3];	/* local file allocation */

  if (lclsiz < rmtsiz) {
    tmsg('W', "local file smaller than remote, update will be incomplete\n");
    rmtsiz = lclsiz;	/* rmtsiz is the amount to copy */
  }
  blknum=1;			/* input & output start at block 1 */

  for (;;) {

    if (rmtsiz >= BUFSIZ) xfrsiz = BUFSIZ;
    else xfrsiz = rmtsiz;

    rmtsiz -= xfrsiz;

    if (rgetb(&buf, 512*xfrsiz, blknum, fd1) <= 0) { /* remote get */
       if ($$ferr != -10) break;	/* physical end of file indicator */
       else {
	  tmsg('F',"geterr %o nerr %o\n", $$ferr, $$nerr);
	  exits(4);		/* exit with error */
	}
     }
    
     if (fputb(&buf, 512*xfrsiz, blknum, fd2) ==0) { /* local put */
	 tmsg('F', "file write error ferr %o\n", $$ferr & 0377); 
	 exits(4);			/* exit with error */
      }

      blknum = blknum + xfrsiz;   /* increment by num of blocks read */

  } /* end for(;;) */

  rclose(fd1);		/* close input file when done */
  fclose(fd2);		/* close output file when done */ 
  exits(1);
}
