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 }