plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

tarfs.c (2759B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <auth.h>
      4 #include <fcall.h>
      5 #include "tapefs.h"
      6 
      7 /*
      8  * File system for tar tapes (read-only)
      9  */
     10 
     11 #define TBLOCK	512
     12 #define NBLOCK	40	/* maximum blocksize */
     13 #define DBLOCK	20	/* default blocksize */
     14 #define TNAMSIZ	100
     15 
     16 union hblock {
     17 	char dummy[TBLOCK];
     18 	char tbuf[Maxbuf];
     19 	struct header {
     20 		char name[TNAMSIZ];
     21 		char mode[8];
     22 		char uid[8];
     23 		char gid[8];
     24 		char size[12];
     25 		char mtime[12];
     26 		char chksum[8];
     27 		char linkflag;
     28 		char linkname[TNAMSIZ];
     29 	} dbuf;
     30 } dblock;
     31 
     32 int	tapefile;
     33 int	checksum(void);
     34 
     35 void
     36 populate(char *name)
     37 {
     38 	long blkno, isabs, chksum, linkflg;
     39 	Fileinf f;
     40 
     41 	tapefile = open(name, OREAD);
     42 	if (tapefile<0)
     43 		error("Can't open argument file");
     44 	replete = 1;
     45 	for (blkno = 0;;) {
     46 		seek(tapefile, TBLOCK*blkno, 0);
     47 		if (read(tapefile, dblock.dummy, sizeof(dblock.dummy))<sizeof(dblock.dummy))
     48 			break;
     49 		if (dblock.dbuf.name[0]=='\0')
     50 			break;
     51 		f.addr = blkno+1;
     52 		f.mode = strtoul(dblock.dbuf.mode, 0, 8);
     53 		f.uid = strtoul(dblock.dbuf.uid, 0, 8);
     54 		f.gid = strtoul(dblock.dbuf.gid, 0, 8);
     55 		if((uchar)dblock.dbuf.size[0] == 0x80)
     56 			f.size = b8byte(dblock.dbuf.size+3);
     57 		else
     58 			f.size = strtoull(dblock.dbuf.size, 0, 8);
     59 		f.mdate = strtoul(dblock.dbuf.mtime, 0, 8);
     60 		chksum = strtoul(dblock.dbuf.chksum, 0, 8);
     61 		/* the mode test is ugly but sometimes necessary */
     62 		if (dblock.dbuf.linkflag == '5'
     63 		|| (f.mode&0170000) == 040000
     64 		||  strrchr(dblock.dbuf.name, '\0')[-1] == '/'){
     65 			f.mode |= DMDIR;
     66 			f.size = 0;
     67 		}
     68 		f.mode &= DMDIR|0777;
     69 		linkflg = dblock.dbuf.linkflag=='s' || dblock.dbuf.linkflag=='1';
     70 		isabs = dblock.dbuf.name[0]=='/';
     71 		if (chksum != checksum()){
     72 			fprint(1, "bad checksum on %.28s\n", dblock.dbuf.name);
     73 			exits("checksum");
     74 		}
     75 		if (linkflg) {
     76 			/*fprint(2, "link %s->%s skipped\n", dblock.dbuf.name,
     77 			   dblock.dbuf.linkname);*/
     78 			f.size = 0;
     79 			blkno += 1;
     80 			continue;
     81 		}
     82 		f.name = dblock.dbuf.name+isabs;
     83 		if (f.name[0]=='\0')
     84 			fprint(1, "null name skipped\n");
     85 		else
     86 			poppath(f, 1);
     87 		blkno += 1 + (f.size+TBLOCK-1)/TBLOCK;
     88 	}
     89 }
     90 
     91 void
     92 dotrunc(Ram *r)
     93 {
     94 	USED(r);
     95 }
     96 
     97 void
     98 docreate(Ram *r)
     99 {
    100 	USED(r);
    101 }
    102 
    103 char *
    104 doread(Ram *r, vlong off, long cnt)
    105 {
    106 	seek(tapefile, TBLOCK*r->addr+off, 0);
    107 	if (cnt>sizeof(dblock.tbuf))
    108 		error("read too big");
    109 	read(tapefile, dblock.tbuf, cnt);
    110 	return dblock.tbuf;
    111 }
    112 
    113 void
    114 popdir(Ram *r)
    115 {
    116 	USED(r);
    117 }
    118 
    119 void
    120 dowrite(Ram *r, char *buf, long off, long cnt)
    121 {
    122 	USED(r); USED(buf); USED(off); USED(cnt);
    123 }
    124 
    125 int
    126 dopermw(Ram *r)
    127 {
    128 	USED(r);
    129 	return 0;
    130 }
    131 
    132 int
    133 checksum()
    134 {
    135 	int i;
    136 	char *cp;
    137 
    138 	for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
    139 		*cp = ' ';
    140 	i = 0;
    141 	for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
    142 		i += *cp&0xff;
    143 	return(i);
    144 }