#include <u.h>
#include <libc.h>
#include "tapefs.h"

/*
* File system for tp tapes.  dectape versions have 192
* entries, magtape have 496.  This treats the same
* by ignoring entries with bad header checksums
*/

struct tp {
       unsigned char   name[32];
       unsigned char   mode[2];
       unsigned char   uid[1];
       unsigned char   gid[1];
       unsigned char   unused[1];
       unsigned char   size[3];
       unsigned char   tmod[4];
       unsigned char   taddress[2];
       unsigned char   unused2[16];
       unsigned char   checksum[2];
} dir[496+8];

char    buffer[8192];
int     tapefile;

void
populate(char *name)
{
       int i, isabs, badcksum, goodcksum;
       struct tp *tpp;
       Fileinf f;

       replete = 1;
       tapefile = open(name, OREAD);
       if (tapefile<0)
               error("Can't open argument file");
       read(tapefile, dir, sizeof dir);
       badcksum = goodcksum = 0;
       for (i=0, tpp=&dir[8]; i<496; i++, tpp++) {
               unsigned char *sp = (unsigned char *)tpp;
               int j, cksum = 0;
               for (j=0; j<32; j++, sp+=2)
                       cksum += sp[0] + (sp[1]<<8);
               cksum &= 0xFFFF;
               if (cksum!=0) {
                       badcksum++;
                       continue;
               }
               goodcksum++;
               if (tpp->name[0]=='\0')
                       continue;
               f.addr = tpp->taddress[0] + (tpp->taddress[1]<<8);
               if (f.addr==0)
                       continue;
               f.size = (tpp->size[0]<<16) + (tpp->size[1]<<0) + (tpp->size[2]<<8);
               f.mdate = (tpp->tmod[2]<<0) + (tpp->tmod[3]<<8)
                    +(tpp->tmod[0]<<16) + (tpp->tmod[1]<<24);
               f.mode = tpp->mode[0]&0777;
               f.uid = tpp->uid[0];
               f.gid = tpp->gid[0];
               isabs = tpp->name[0]=='/';
               f.name = (char *)tpp->name+isabs;
               poppath(f, 1);
       }
       fprint(2, "%d bad checksums, %d good\n", badcksum, goodcksum);
}

void
popdir(Ram *r)
{
       USED(r);
}

void
dotrunc(Ram *r)
{
       USED(r);
}

void
docreate(Ram *r)
{
       USED(r);
}

char *
doread(Ram *r, vlong off, long cnt)
{
       if (cnt>sizeof(buffer))
               print("count too big\n");
       seek(tapefile, 512*r->addr+off, 0);
       read(tapefile, buffer, cnt);
       return buffer;
}

void
dowrite(Ram *r, char *buf, long off, long cnt)
{
       USED(r); USED(buf); USED(off); USED(cnt);
}

int
dopermw(Ram *r)
{
       USED(r);
       return 0;
}