144 lines
2.7 KiB
C
144 lines
2.7 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <auth.h>
|
|
#include <fcall.h>
|
|
#include "tapefs.h"
|
|
|
|
/*
|
|
* File system for tar tapes (read-only)
|
|
*/
|
|
|
|
#define TBLOCK 512
|
|
#define NBLOCK 40 /* maximum blocksize */
|
|
#define DBLOCK 20 /* default blocksize */
|
|
#define TNAMSIZ 100
|
|
|
|
union hblock {
|
|
char dummy[TBLOCK];
|
|
char tbuf[Maxbuf];
|
|
struct header {
|
|
char name[TNAMSIZ];
|
|
char mode[8];
|
|
char uid[8];
|
|
char gid[8];
|
|
char size[12];
|
|
char mtime[12];
|
|
char chksum[8];
|
|
char linkflag;
|
|
char linkname[TNAMSIZ];
|
|
} dbuf;
|
|
} dblock;
|
|
|
|
int tapefile;
|
|
int checksum(void);
|
|
|
|
void
|
|
populate(char *name)
|
|
{
|
|
long blkno, isabs, chksum, linkflg;
|
|
Fileinf f;
|
|
|
|
tapefile = open(name, OREAD);
|
|
if (tapefile<0)
|
|
error("Can't open argument file");
|
|
replete = 1;
|
|
for (blkno = 0;;) {
|
|
seek(tapefile, TBLOCK*blkno, 0);
|
|
if (read(tapefile, dblock.dummy, sizeof(dblock.dummy))<sizeof(dblock.dummy))
|
|
break;
|
|
if (dblock.dbuf.name[0]=='\0')
|
|
break;
|
|
f.addr = blkno+1;
|
|
f.mode = strtoul(dblock.dbuf.mode, 0, 8);
|
|
f.uid = strtoul(dblock.dbuf.uid, 0, 8);
|
|
f.gid = strtoul(dblock.dbuf.gid, 0, 8);
|
|
if((uchar)dblock.dbuf.size[0] == 0x80)
|
|
f.size = g8byte(dblock.dbuf.size+3);
|
|
else
|
|
f.size = strtoull(dblock.dbuf.size, 0, 8);
|
|
f.mdate = strtoul(dblock.dbuf.mtime, 0, 8);
|
|
chksum = strtoul(dblock.dbuf.chksum, 0, 8);
|
|
/* the mode test is ugly but sometimes necessary */
|
|
if (dblock.dbuf.linkflag == '5'
|
|
|| (f.mode&0170000) == 040000
|
|
|| strrchr(dblock.dbuf.name, '\0')[-1] == '/'){
|
|
f.mode |= DMDIR;
|
|
f.size = 0;
|
|
}
|
|
f.mode &= DMDIR|0777;
|
|
linkflg = dblock.dbuf.linkflag=='s' || dblock.dbuf.linkflag=='1';
|
|
isabs = dblock.dbuf.name[0]=='/';
|
|
if (chksum != checksum()){
|
|
fprint(1, "bad checksum on %.28s\n", dblock.dbuf.name);
|
|
exits("checksum");
|
|
}
|
|
if (linkflg) {
|
|
/*fprint(2, "link %s->%s skipped\n", dblock.dbuf.name,
|
|
dblock.dbuf.linkname);*/
|
|
f.size = 0;
|
|
blkno += 1;
|
|
continue;
|
|
}
|
|
f.name = dblock.dbuf.name+isabs;
|
|
if (f.name[0]=='\0')
|
|
fprint(1, "null name skipped\n");
|
|
else
|
|
poppath(f, 1);
|
|
blkno += 1 + (f.size+TBLOCK-1)/TBLOCK;
|
|
}
|
|
}
|
|
|
|
void
|
|
dotrunc(Ram *r)
|
|
{
|
|
USED(r);
|
|
}
|
|
|
|
void
|
|
docreate(Ram *r)
|
|
{
|
|
USED(r);
|
|
}
|
|
|
|
char *
|
|
doread(Ram *r, vlong off, long cnt)
|
|
{
|
|
seek(tapefile, TBLOCK*r->addr+off, 0);
|
|
if (cnt>sizeof(dblock.tbuf))
|
|
error("read too big");
|
|
read(tapefile, dblock.tbuf, cnt);
|
|
return dblock.tbuf;
|
|
}
|
|
|
|
void
|
|
popdir(Ram *r)
|
|
{
|
|
USED(r);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int
|
|
checksum()
|
|
{
|
|
int i;
|
|
char *cp;
|
|
|
|
for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
|
|
*cp = ' ';
|
|
i = 0;
|
|
for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
|
|
i += *cp&0xff;
|
|
return(i);
|
|
}
|