xref: /plan9-contrib/sys/src/cmd/tapefs/tarfs.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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 = (void*)(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 		f.size = strtoul(dblock.dbuf.size, 0, 8);
56 		f.mdate = strtoul(dblock.dbuf.mtime, 0, 8);
57 		chksum = strtoul(dblock.dbuf.chksum, 0, 8);
58 		/* the mode test is ugly but sometimes necessary */
59 		if (dblock.dbuf.linkflag == '5' || (f.mode&0170000) == 040000)
60 			f.mode |= DMDIR;
61 		linkflg = dblock.dbuf.linkflag=='s' || dblock.dbuf.linkflag=='1';
62 		isabs = dblock.dbuf.name[0]=='/';
63 		if (chksum != checksum()){
64 			fprint(1, "bad checksum on %.28s\n", dblock.dbuf.name);
65 			abort();
66 		}
67 		if (linkflg) {
68 			/*fprint(2, "link %s->%s skipped\n", dblock.dbuf.name,
69 			   dblock.dbuf.linkname);*/
70 			f.size = 0;
71 			blkno += 1;
72 			continue;
73 		}
74 		f.name = dblock.dbuf.name+isabs;
75 		if (f.name[0]=='\0')
76 			fprint(1, "null name skipped\n");
77 		else
78 			poppath(f, 1);
79 		blkno += 1 + (f.size+TBLOCK-1)/TBLOCK;
80 	}
81 }
82 
83 void
84 dotrunc(Ram *r)
85 {
86 	USED(r);
87 }
88 
89 void
90 docreate(Ram *r)
91 {
92 	USED(r);
93 }
94 
95 char *
96 doread(Ram *r, long off, long cnt)
97 {
98 
99 	seek(tapefile, (TBLOCK * (long)r->data)+off, 0);
100 	if (cnt>sizeof(dblock.tbuf))
101 		error("read too big");
102 	read(tapefile, dblock.tbuf, cnt);
103 	return dblock.tbuf;
104 }
105 
106 void
107 popdir(Ram *r)
108 {
109 	USED(r);
110 }
111 
112 void
113 dowrite(Ram *r, char *buf, long off, long cnt)
114 {
115 	USED(r); USED(buf); USED(off); USED(cnt);
116 }
117 
118 int
119 dopermw(Ram *r)
120 {
121 	USED(r);
122 	return 0;
123 }
124 
125 int
126 checksum()
127 {
128 	register i;
129 	register char *cp;
130 
131 	for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
132 		*cp = ' ';
133 	i = 0;
134 	for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
135 		i += *cp&0xff;
136 	return(i);
137 }
138