xref: /plan9/sys/src/cmd/tapefs/tarfs.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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 }
145