#include <stdio.h>
#include <osbind.h>
#include "ndir.h"
#include "ftw.h"
#include "detar.h"

extern FILE *ftar;
extern int qblk, blocks;
extern char *tbuf;
extern char *tounix(); /* char * */
extern void tooct(),calc_chksum();
extern int tfile, type, verbos;
static union record tar_rec;
static struct stat *stbuf;

/* calculate number of blocks that are left in the buffer for a file read */
/* operation.  Limit the block count to under 128 (64K) though */

char *getblks(rbytes) long *rbytes;
{
    int btd;

    if(tfile)
    {
	*rbytes = 512L;
	return(&tbuf[0]);
    }
    btd = blocks - qblk;
    *rbytes = (long)(btd) * 512L; 
    return(&tbuf[(long)(qblk) * 512L]);
}

static void dump_header(name,x) char *name;int x;
{
    long dummy;
    extern char *getblks();

    lzero(tar_rec.charptr,(RECORDSIZE >> 2));
    strncpy(tar_rec.header.name,tounix(name),NAMSIZ);
    tooct(0644L,8,tar_rec.header.mode);
    tooct(0L,8,tar_rec.header.uid);
    tooct(0L,8,tar_rec.header.gid);
    tooct(stbuf->st_size,12,tar_rec.header.size);
    tooct(stbuf->st_mtime,12,tar_rec.header.mtime);
    strncpy(tar_rec.header.magic,TMAGIC,8);
    strncpy(tar_rec.header.chksum,CHKBLANKS,8);
    tar_rec.header.linkflag=x+'0';
    calc_chksum(&tar_rec);
    if(tfile)
    {
        fwrite(tar_rec.charptr, 1, RECORDSIZE, ftar);
	qblk = 0;
    }
    else
    {
	lcopy(tar_rec.charptr, getblks(&dummy), RECORDSIZE >> 2);
	qblk += 1;
	if(qblk >= blocks) twritef(qblk);
    }
}

static void dump_file(name) char *name;
{
    FILE *fin;
    long rbytes, n, blks;
    char *bptr;
    extern char *getblks();

    fin=fopen(name,"rb");

    if(type || verbos)
    {
        printf("a %s", tar_rec.header.name);
        if(verbos)
        {
            printf(" %8ld", stbuf->st_size);
            blks = stbuf->st_size >> 9;
            if(stbuf->st_size % 512L) blks += 1L;
            printf(" %8ld blocks", blks);
        }
        printf("\n");
    }

    if(!tfile)
    {
	do {
	    bptr = getblks(&rbytes);
	    n = Fread((int)(fin->_fd), rbytes, bptr);
	    qblk += hmbr(n);
            if(qblk >= blocks) twritef(qblk);
        } while(n==rbytes);
    }
    else
    {
	do {
            n=fread(tar_rec.charptr,1,RECORDSIZE,fin);
	    if(n < RECORDSIZE) bzero(tar_rec.charptr+(long)(n), RECORDSIZE-n);
            fwrite(tar_rec.charptr,1,RECORDSIZE,ftar);
    	}while(n==RECORDSIZE);
    }
    fclose(fin);
}

int create_tar(name,sbuf,flag) char *name; struct stat *sbuf; int flag;
{
    stbuf=sbuf;
    switch(flag)
    {
    case FTW_NS:
        fprintf(stderr,"tar:can't stat %s\n",name);
        return -1;
    case FTW_DNR:
        fprintf(stderr,"tar:can't open directory %s\n");
        return -2;
    case FTW_F:
        dump_header(name,0);
        dump_file(name);
        return 0;
    case FTW_D:
        strcat(name,"\\");
        dump_header(name,5);
        return 0;
    }
}


/* get the acutal number of bytes read and convert to block count */

int hmbr(bread) long bread;
{
    int btb;

    if(!bread) return(0);
    btb = bread >> 9;
    if(bread % 512L) btb += 1;
    return(btb);
}
