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