Blame


1 bc7cb1a1 2003-11-23 devnull #include <u.h>
2 bc7cb1a1 2003-11-23 devnull #include <libc.h>
3 bc7cb1a1 2003-11-23 devnull #include <bio.h>
4 bc7cb1a1 2003-11-23 devnull
5 bc7cb1a1 2003-11-23 devnull #define TBLOCK 512
6 bc7cb1a1 2003-11-23 devnull #define NBLOCK 40 /* maximum blocksize */
7 bc7cb1a1 2003-11-23 devnull #define DBLOCK 20 /* default blocksize */
8 bc7cb1a1 2003-11-23 devnull #define NAMSIZ 100
9 bc7cb1a1 2003-11-23 devnull union hblock
10 bc7cb1a1 2003-11-23 devnull {
11 bc7cb1a1 2003-11-23 devnull char dummy[TBLOCK];
12 bc7cb1a1 2003-11-23 devnull struct header
13 bc7cb1a1 2003-11-23 devnull {
14 bc7cb1a1 2003-11-23 devnull char name[NAMSIZ];
15 bc7cb1a1 2003-11-23 devnull char mode[8];
16 bc7cb1a1 2003-11-23 devnull char uid[8];
17 bc7cb1a1 2003-11-23 devnull char gid[8];
18 bc7cb1a1 2003-11-23 devnull char size[12];
19 bc7cb1a1 2003-11-23 devnull char mtime[12];
20 bc7cb1a1 2003-11-23 devnull char chksum[8];
21 bc7cb1a1 2003-11-23 devnull char linkflag;
22 bc7cb1a1 2003-11-23 devnull char linkname[NAMSIZ];
23 bc7cb1a1 2003-11-23 devnull } dbuf;
24 bc7cb1a1 2003-11-23 devnull } dblock, tbuf[NBLOCK];
25 bc7cb1a1 2003-11-23 devnull
26 bc7cb1a1 2003-11-23 devnull Dir *stbuf;
27 bc7cb1a1 2003-11-23 devnull Biobuf bout;
28 bc7cb1a1 2003-11-23 devnull
29 bc7cb1a1 2003-11-23 devnull int rflag, xflag, vflag, tflag, mt, cflag, fflag, Tflag, Rflag;
30 bc7cb1a1 2003-11-23 devnull int uflag, gflag;
31 bc7cb1a1 2003-11-23 devnull int chksum, recno, first;
32 bc7cb1a1 2003-11-23 devnull int nblock = DBLOCK;
33 bc7cb1a1 2003-11-23 devnull
34 bc7cb1a1 2003-11-23 devnull void usage(void);
35 bc7cb1a1 2003-11-23 devnull void dorep(char **);
36 bc7cb1a1 2003-11-23 devnull int endtar(void);
37 bc7cb1a1 2003-11-23 devnull void getdir(void);
38 bc7cb1a1 2003-11-23 devnull void passtar(void);
39 bc7cb1a1 2003-11-23 devnull void putfile(char*, char *, char *);
40 bc7cb1a1 2003-11-23 devnull void doxtract(char **);
41 bc7cb1a1 2003-11-23 devnull void dotable(void);
42 bc7cb1a1 2003-11-23 devnull void putempty(void);
43 bc7cb1a1 2003-11-23 devnull void longt(Dir *);
44 bc7cb1a1 2003-11-23 devnull int checkdir(char *, int, Qid*);
45 bc7cb1a1 2003-11-23 devnull void tomodes(Dir *);
46 bc7cb1a1 2003-11-23 devnull int checksum(void);
47 bc7cb1a1 2003-11-23 devnull int checkupdate(char *);
48 bc7cb1a1 2003-11-23 devnull int prefix(char *, char *);
49 bc7cb1a1 2003-11-23 devnull int readtar(char *);
50 bc7cb1a1 2003-11-23 devnull int writetar(char *);
51 bc7cb1a1 2003-11-23 devnull void backtar(void);
52 bc7cb1a1 2003-11-23 devnull void flushtar(void);
53 bc7cb1a1 2003-11-23 devnull void affix(int, char *);
54 bc7cb1a1 2003-11-23 devnull int volprompt(void);
55 bc7cb1a1 2003-11-23 devnull void
56 bc7cb1a1 2003-11-23 devnull main(int argc, char **argv)
57 bc7cb1a1 2003-11-23 devnull {
58 bc7cb1a1 2003-11-23 devnull char *usefile;
59 bc7cb1a1 2003-11-23 devnull char *cp, *ap;
60 bc7cb1a1 2003-11-23 devnull
61 bc7cb1a1 2003-11-23 devnull if (argc < 2)
62 bc7cb1a1 2003-11-23 devnull usage();
63 bc7cb1a1 2003-11-23 devnull
64 bc7cb1a1 2003-11-23 devnull Binit(&bout, 1, OWRITE);
65 bc7cb1a1 2003-11-23 devnull usefile = 0;
66 bc7cb1a1 2003-11-23 devnull argv[argc] = 0;
67 bc7cb1a1 2003-11-23 devnull argv++;
68 bc7cb1a1 2003-11-23 devnull for (cp = *argv++; *cp; cp++)
69 bc7cb1a1 2003-11-23 devnull switch(*cp) {
70 bc7cb1a1 2003-11-23 devnull case 'f':
71 bc7cb1a1 2003-11-23 devnull usefile = *argv++;
72 bc7cb1a1 2003-11-23 devnull if(!usefile)
73 bc7cb1a1 2003-11-23 devnull usage();
74 bc7cb1a1 2003-11-23 devnull fflag++;
75 bc7cb1a1 2003-11-23 devnull break;
76 bc7cb1a1 2003-11-23 devnull case 'u':
77 bc7cb1a1 2003-11-23 devnull ap = *argv++;
78 bc7cb1a1 2003-11-23 devnull if(!ap)
79 bc7cb1a1 2003-11-23 devnull usage();
80 bc7cb1a1 2003-11-23 devnull uflag = strtoul(ap, 0, 0);
81 bc7cb1a1 2003-11-23 devnull break;
82 bc7cb1a1 2003-11-23 devnull case 'g':
83 bc7cb1a1 2003-11-23 devnull ap = *argv++;
84 bc7cb1a1 2003-11-23 devnull if(!ap)
85 bc7cb1a1 2003-11-23 devnull usage();
86 bc7cb1a1 2003-11-23 devnull gflag = strtoul(ap, 0, 0);
87 bc7cb1a1 2003-11-23 devnull break;
88 bc7cb1a1 2003-11-23 devnull case 'c':
89 bc7cb1a1 2003-11-23 devnull cflag++;
90 bc7cb1a1 2003-11-23 devnull rflag++;
91 bc7cb1a1 2003-11-23 devnull break;
92 bc7cb1a1 2003-11-23 devnull case 'r':
93 bc7cb1a1 2003-11-23 devnull rflag++;
94 bc7cb1a1 2003-11-23 devnull break;
95 bc7cb1a1 2003-11-23 devnull case 'v':
96 bc7cb1a1 2003-11-23 devnull vflag++;
97 bc7cb1a1 2003-11-23 devnull break;
98 bc7cb1a1 2003-11-23 devnull case 'x':
99 bc7cb1a1 2003-11-23 devnull xflag++;
100 bc7cb1a1 2003-11-23 devnull break;
101 bc7cb1a1 2003-11-23 devnull case 'T':
102 bc7cb1a1 2003-11-23 devnull Tflag++;
103 bc7cb1a1 2003-11-23 devnull break;
104 bc7cb1a1 2003-11-23 devnull case 't':
105 bc7cb1a1 2003-11-23 devnull tflag++;
106 bc7cb1a1 2003-11-23 devnull break;
107 bc7cb1a1 2003-11-23 devnull case 'R':
108 bc7cb1a1 2003-11-23 devnull Rflag++;
109 bc7cb1a1 2003-11-23 devnull break;
110 bc7cb1a1 2003-11-23 devnull case '-':
111 bc7cb1a1 2003-11-23 devnull break;
112 bc7cb1a1 2003-11-23 devnull default:
113 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %c: unknown option\n", *cp);
114 bc7cb1a1 2003-11-23 devnull usage();
115 bc7cb1a1 2003-11-23 devnull }
116 bc7cb1a1 2003-11-23 devnull
117 bc7cb1a1 2003-11-23 devnull fmtinstall('M', dirmodefmt);
118 bc7cb1a1 2003-11-23 devnull
119 bc7cb1a1 2003-11-23 devnull if (rflag) {
120 bc7cb1a1 2003-11-23 devnull if (!usefile) {
121 bc7cb1a1 2003-11-23 devnull if (cflag == 0) {
122 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can only create standard output archives\n");
123 bc7cb1a1 2003-11-23 devnull exits("arg error");
124 bc7cb1a1 2003-11-23 devnull }
125 bc7cb1a1 2003-11-23 devnull mt = dup(1, -1);
126 bc7cb1a1 2003-11-23 devnull nblock = 1;
127 bc7cb1a1 2003-11-23 devnull }
128 bc7cb1a1 2003-11-23 devnull else if ((mt = open(usefile, ORDWR)) < 0) {
129 bc7cb1a1 2003-11-23 devnull if (cflag == 0 || (mt = create(usefile, OWRITE, 0666)) < 0) {
130 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: cannot open %s: %r\n", usefile);
131 bc7cb1a1 2003-11-23 devnull exits("open");
132 bc7cb1a1 2003-11-23 devnull }
133 bc7cb1a1 2003-11-23 devnull }
134 bc7cb1a1 2003-11-23 devnull dorep(argv);
135 bc7cb1a1 2003-11-23 devnull }
136 bc7cb1a1 2003-11-23 devnull else if (xflag) {
137 bc7cb1a1 2003-11-23 devnull if (!usefile) {
138 bc7cb1a1 2003-11-23 devnull mt = dup(0, -1);
139 bc7cb1a1 2003-11-23 devnull nblock = 1;
140 bc7cb1a1 2003-11-23 devnull }
141 bc7cb1a1 2003-11-23 devnull else if ((mt = open(usefile, OREAD)) < 0) {
142 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: cannot open %s: %r\n", usefile);
143 bc7cb1a1 2003-11-23 devnull exits("open");
144 bc7cb1a1 2003-11-23 devnull }
145 bc7cb1a1 2003-11-23 devnull doxtract(argv);
146 bc7cb1a1 2003-11-23 devnull }
147 bc7cb1a1 2003-11-23 devnull else if (tflag) {
148 bc7cb1a1 2003-11-23 devnull if (!usefile) {
149 bc7cb1a1 2003-11-23 devnull mt = dup(0, -1);
150 bc7cb1a1 2003-11-23 devnull nblock = 1;
151 bc7cb1a1 2003-11-23 devnull }
152 bc7cb1a1 2003-11-23 devnull else if ((mt = open(usefile, OREAD)) < 0) {
153 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: cannot open %s: %r\n", usefile);
154 bc7cb1a1 2003-11-23 devnull exits("open");
155 bc7cb1a1 2003-11-23 devnull }
156 bc7cb1a1 2003-11-23 devnull dotable();
157 bc7cb1a1 2003-11-23 devnull }
158 bc7cb1a1 2003-11-23 devnull else
159 bc7cb1a1 2003-11-23 devnull usage();
160 bc7cb1a1 2003-11-23 devnull exits(0);
161 bc7cb1a1 2003-11-23 devnull }
162 bc7cb1a1 2003-11-23 devnull
163 bc7cb1a1 2003-11-23 devnull void
164 bc7cb1a1 2003-11-23 devnull usage(void)
165 bc7cb1a1 2003-11-23 devnull {
166 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: usage tar {txrc}[Rvf] [tarfile] file1 file2...\n");
167 bc7cb1a1 2003-11-23 devnull exits("usage");
168 bc7cb1a1 2003-11-23 devnull }
169 bc7cb1a1 2003-11-23 devnull
170 bc7cb1a1 2003-11-23 devnull void
171 bc7cb1a1 2003-11-23 devnull dorep(char **argv)
172 bc7cb1a1 2003-11-23 devnull {
173 bc7cb1a1 2003-11-23 devnull char cwdbuf[2048], *cwd, thisdir[2048];
174 bc7cb1a1 2003-11-23 devnull char *cp, *cp2;
175 bc7cb1a1 2003-11-23 devnull int cd;
176 bc7cb1a1 2003-11-23 devnull
177 bc7cb1a1 2003-11-23 devnull if (getwd(cwdbuf, sizeof(cwdbuf)) == 0) {
178 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't find current directory: %r\n");
179 bc7cb1a1 2003-11-23 devnull exits("cwd");
180 bc7cb1a1 2003-11-23 devnull }
181 bc7cb1a1 2003-11-23 devnull cwd = cwdbuf;
182 bc7cb1a1 2003-11-23 devnull
183 bc7cb1a1 2003-11-23 devnull if (!cflag) {
184 bc7cb1a1 2003-11-23 devnull getdir();
185 bc7cb1a1 2003-11-23 devnull do {
186 bc7cb1a1 2003-11-23 devnull passtar();
187 bc7cb1a1 2003-11-23 devnull getdir();
188 bc7cb1a1 2003-11-23 devnull } while (!endtar());
189 bc7cb1a1 2003-11-23 devnull }
190 bc7cb1a1 2003-11-23 devnull
191 bc7cb1a1 2003-11-23 devnull while (*argv) {
192 bc7cb1a1 2003-11-23 devnull cp2 = *argv;
193 bc7cb1a1 2003-11-23 devnull if (!strcmp(cp2, "-C") && argv[1]) {
194 bc7cb1a1 2003-11-23 devnull argv++;
195 bc7cb1a1 2003-11-23 devnull if (chdir(*argv) < 0)
196 bc7cb1a1 2003-11-23 devnull perror(*argv);
197 bc7cb1a1 2003-11-23 devnull cwd = *argv;
198 bc7cb1a1 2003-11-23 devnull argv++;
199 bc7cb1a1 2003-11-23 devnull continue;
200 bc7cb1a1 2003-11-23 devnull }
201 bc7cb1a1 2003-11-23 devnull cd = 0;
202 bc7cb1a1 2003-11-23 devnull for (cp = *argv; *cp; cp++)
203 bc7cb1a1 2003-11-23 devnull if (*cp == '/')
204 bc7cb1a1 2003-11-23 devnull cp2 = cp;
205 bc7cb1a1 2003-11-23 devnull if (cp2 != *argv) {
206 bc7cb1a1 2003-11-23 devnull *cp2 = '\0';
207 bc7cb1a1 2003-11-23 devnull chdir(*argv);
208 bc7cb1a1 2003-11-23 devnull if(**argv == '/')
209 bc7cb1a1 2003-11-23 devnull strncpy(thisdir, *argv, sizeof(thisdir));
210 bc7cb1a1 2003-11-23 devnull else
211 bc7cb1a1 2003-11-23 devnull snprint(thisdir, sizeof(thisdir), "%s/%s", cwd, *argv);
212 bc7cb1a1 2003-11-23 devnull *cp2 = '/';
213 bc7cb1a1 2003-11-23 devnull cp2++;
214 bc7cb1a1 2003-11-23 devnull cd = 1;
215 bc7cb1a1 2003-11-23 devnull } else
216 bc7cb1a1 2003-11-23 devnull strncpy(thisdir, cwd, sizeof(thisdir));
217 bc7cb1a1 2003-11-23 devnull putfile(thisdir, *argv++, cp2);
218 bc7cb1a1 2003-11-23 devnull if(cd && chdir(cwd) < 0) {
219 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't cd back to %s: %r\n", cwd);
220 bc7cb1a1 2003-11-23 devnull exits("cwd");
221 bc7cb1a1 2003-11-23 devnull }
222 bc7cb1a1 2003-11-23 devnull }
223 bc7cb1a1 2003-11-23 devnull putempty();
224 bc7cb1a1 2003-11-23 devnull putempty();
225 bc7cb1a1 2003-11-23 devnull flushtar();
226 bc7cb1a1 2003-11-23 devnull }
227 bc7cb1a1 2003-11-23 devnull
228 bc7cb1a1 2003-11-23 devnull int
229 bc7cb1a1 2003-11-23 devnull endtar(void)
230 bc7cb1a1 2003-11-23 devnull {
231 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.name[0] == '\0') {
232 bc7cb1a1 2003-11-23 devnull backtar();
233 bc7cb1a1 2003-11-23 devnull return(1);
234 bc7cb1a1 2003-11-23 devnull }
235 bc7cb1a1 2003-11-23 devnull else
236 bc7cb1a1 2003-11-23 devnull return(0);
237 bc7cb1a1 2003-11-23 devnull }
238 bc7cb1a1 2003-11-23 devnull
239 bc7cb1a1 2003-11-23 devnull void
240 bc7cb1a1 2003-11-23 devnull getdir(void)
241 bc7cb1a1 2003-11-23 devnull {
242 bc7cb1a1 2003-11-23 devnull Dir *sp;
243 bc7cb1a1 2003-11-23 devnull
244 bc7cb1a1 2003-11-23 devnull readtar((char*)&dblock);
245 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.name[0] == '\0')
246 bc7cb1a1 2003-11-23 devnull return;
247 bc7cb1a1 2003-11-23 devnull if(stbuf == nil){
248 bc7cb1a1 2003-11-23 devnull stbuf = malloc(sizeof(Dir));
249 bc7cb1a1 2003-11-23 devnull if(stbuf == nil) {
250 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't malloc: %r\n");
251 bc7cb1a1 2003-11-23 devnull exits("malloc");
252 bc7cb1a1 2003-11-23 devnull }
253 bc7cb1a1 2003-11-23 devnull }
254 bc7cb1a1 2003-11-23 devnull sp = stbuf;
255 bc7cb1a1 2003-11-23 devnull sp->mode = strtol(dblock.dbuf.mode, 0, 8);
256 bc7cb1a1 2003-11-23 devnull sp->uid = "adm";
257 bc7cb1a1 2003-11-23 devnull sp->gid = "adm";
258 bc7cb1a1 2003-11-23 devnull sp->length = strtol(dblock.dbuf.size, 0, 8);
259 bc7cb1a1 2003-11-23 devnull sp->mtime = strtol(dblock.dbuf.mtime, 0, 8);
260 bc7cb1a1 2003-11-23 devnull chksum = strtol(dblock.dbuf.chksum, 0, 8);
261 bc7cb1a1 2003-11-23 devnull if (chksum != checksum()) {
262 bc7cb1a1 2003-11-23 devnull fprint(2, "directory checksum error\n");
263 bc7cb1a1 2003-11-23 devnull exits("checksum error");
264 bc7cb1a1 2003-11-23 devnull }
265 bc7cb1a1 2003-11-23 devnull sp->qid.type = 0;
266 bc7cb1a1 2003-11-23 devnull /* the mode test is ugly but sometimes necessary */
267 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == '5' || (sp->mode&0170000) == 040000) {
268 bc7cb1a1 2003-11-23 devnull sp->qid.type |= QTDIR;
269 bc7cb1a1 2003-11-23 devnull sp->mode |= DMDIR;
270 bc7cb1a1 2003-11-23 devnull }
271 bc7cb1a1 2003-11-23 devnull }
272 bc7cb1a1 2003-11-23 devnull
273 bc7cb1a1 2003-11-23 devnull void
274 bc7cb1a1 2003-11-23 devnull passtar(void)
275 bc7cb1a1 2003-11-23 devnull {
276 bc7cb1a1 2003-11-23 devnull long blocks;
277 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK];
278 bc7cb1a1 2003-11-23 devnull
279 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == '1' || dblock.dbuf.linkflag == 's')
280 bc7cb1a1 2003-11-23 devnull return;
281 bc7cb1a1 2003-11-23 devnull blocks = stbuf->length;
282 bc7cb1a1 2003-11-23 devnull blocks += TBLOCK-1;
283 bc7cb1a1 2003-11-23 devnull blocks /= TBLOCK;
284 bc7cb1a1 2003-11-23 devnull
285 bc7cb1a1 2003-11-23 devnull while (blocks-- > 0)
286 bc7cb1a1 2003-11-23 devnull readtar(buf);
287 bc7cb1a1 2003-11-23 devnull }
288 bc7cb1a1 2003-11-23 devnull
289 bc7cb1a1 2003-11-23 devnull void
290 bc7cb1a1 2003-11-23 devnull putfile(char *dir, char *longname, char *sname)
291 bc7cb1a1 2003-11-23 devnull {
292 bc7cb1a1 2003-11-23 devnull int infile;
293 bc7cb1a1 2003-11-23 devnull long blocks;
294 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK];
295 bc7cb1a1 2003-11-23 devnull char curdir[4096];
296 bc7cb1a1 2003-11-23 devnull char shortname[4096];
297 bc7cb1a1 2003-11-23 devnull char *cp, *cp2;
298 bc7cb1a1 2003-11-23 devnull Dir *db;
299 bc7cb1a1 2003-11-23 devnull int i, n;
300 bc7cb1a1 2003-11-23 devnull
301 bc7cb1a1 2003-11-23 devnull if(strlen(sname) > sizeof shortname - 3){
302 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: name too long (max %d)\n", sname, sizeof shortname - 3);
303 bc7cb1a1 2003-11-23 devnull return;
304 bc7cb1a1 2003-11-23 devnull }
305 bc7cb1a1 2003-11-23 devnull
306 bc7cb1a1 2003-11-23 devnull snprint(shortname, sizeof shortname, "./%s", sname);
307 bc7cb1a1 2003-11-23 devnull infile = open(shortname, OREAD);
308 bc7cb1a1 2003-11-23 devnull if (infile < 0) {
309 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: cannot open file - %r\n", longname);
310 bc7cb1a1 2003-11-23 devnull return;
311 bc7cb1a1 2003-11-23 devnull }
312 bc7cb1a1 2003-11-23 devnull
313 bc7cb1a1 2003-11-23 devnull if(stbuf != nil)
314 bc7cb1a1 2003-11-23 devnull free(stbuf);
315 bc7cb1a1 2003-11-23 devnull stbuf = dirfstat(infile);
316 bc7cb1a1 2003-11-23 devnull
317 bc7cb1a1 2003-11-23 devnull if (stbuf->qid.type & QTDIR) {
318 bc7cb1a1 2003-11-23 devnull /* Directory */
319 bc7cb1a1 2003-11-23 devnull for (i = 0, cp = buf; *cp++ = longname[i++];);
320 bc7cb1a1 2003-11-23 devnull *--cp = '/';
321 bc7cb1a1 2003-11-23 devnull *++cp = 0;
322 bc7cb1a1 2003-11-23 devnull if( (cp - buf) >= NAMSIZ) {
323 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: file name too long\n", longname);
324 bc7cb1a1 2003-11-23 devnull close(infile);
325 bc7cb1a1 2003-11-23 devnull return;
326 bc7cb1a1 2003-11-23 devnull }
327 bc7cb1a1 2003-11-23 devnull stbuf->length = 0;
328 bc7cb1a1 2003-11-23 devnull tomodes(stbuf);
329 bc7cb1a1 2003-11-23 devnull strcpy(dblock.dbuf.name,buf);
330 bc7cb1a1 2003-11-23 devnull dblock.dbuf.linkflag = '5'; /* Directory */
331 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.chksum, "%6o", checksum());
332 bc7cb1a1 2003-11-23 devnull writetar( (char *) &dblock);
333 bc7cb1a1 2003-11-23 devnull if (chdir(shortname) < 0) {
334 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't cd to %s: %r\n", shortname);
335 bc7cb1a1 2003-11-23 devnull snprint(curdir, sizeof(curdir), "cd %s", shortname);
336 bc7cb1a1 2003-11-23 devnull exits(curdir);
337 bc7cb1a1 2003-11-23 devnull }
338 bc7cb1a1 2003-11-23 devnull sprint(curdir, "%s/%s", dir, sname);
339 bc7cb1a1 2003-11-23 devnull while ((n = dirread(infile, &db)) > 0) {
340 bc7cb1a1 2003-11-23 devnull for(i = 0; i < n; i++){
341 bc7cb1a1 2003-11-23 devnull strncpy(cp, db[i].name, sizeof buf - (cp-buf));
342 bc7cb1a1 2003-11-23 devnull putfile(curdir, buf, db[i].name);
343 bc7cb1a1 2003-11-23 devnull }free(db);
344 bc7cb1a1 2003-11-23 devnull }
345 bc7cb1a1 2003-11-23 devnull close(infile);
346 bc7cb1a1 2003-11-23 devnull if (chdir(dir) < 0 && chdir("..") < 0) {
347 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't cd to ..(%s): %r\n", dir);
348 bc7cb1a1 2003-11-23 devnull snprint(curdir, sizeof(curdir), "cd ..(%s)", dir);
349 bc7cb1a1 2003-11-23 devnull exits(curdir);
350 bc7cb1a1 2003-11-23 devnull }
351 bc7cb1a1 2003-11-23 devnull return;
352 bc7cb1a1 2003-11-23 devnull }
353 bc7cb1a1 2003-11-23 devnull
354 bc7cb1a1 2003-11-23 devnull
355 bc7cb1a1 2003-11-23 devnull tomodes(stbuf);
356 bc7cb1a1 2003-11-23 devnull
357 bc7cb1a1 2003-11-23 devnull cp2 = longname;
358 bc7cb1a1 2003-11-23 devnull for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
359 bc7cb1a1 2003-11-23 devnull if (i >= NAMSIZ) {
360 bc7cb1a1 2003-11-23 devnull fprint(2, "%s: file name too long\n", longname);
361 bc7cb1a1 2003-11-23 devnull close(infile);
362 bc7cb1a1 2003-11-23 devnull return;
363 bc7cb1a1 2003-11-23 devnull }
364 bc7cb1a1 2003-11-23 devnull
365 bc7cb1a1 2003-11-23 devnull blocks = (stbuf->length + (TBLOCK-1)) / TBLOCK;
366 bc7cb1a1 2003-11-23 devnull if (vflag) {
367 bc7cb1a1 2003-11-23 devnull fprint(2, "a %s ", longname);
368 bc7cb1a1 2003-11-23 devnull fprint(2, "%ld blocks\n", blocks);
369 bc7cb1a1 2003-11-23 devnull }
370 bc7cb1a1 2003-11-23 devnull dblock.dbuf.linkflag = 0; /* Regular file */
371 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.chksum, "%6o", checksum());
372 bc7cb1a1 2003-11-23 devnull writetar( (char *) &dblock);
373 bc7cb1a1 2003-11-23 devnull
374 bc7cb1a1 2003-11-23 devnull while ((i = readn(infile, buf, TBLOCK)) > 0 && blocks > 0) {
375 bc7cb1a1 2003-11-23 devnull writetar(buf);
376 bc7cb1a1 2003-11-23 devnull blocks--;
377 bc7cb1a1 2003-11-23 devnull }
378 bc7cb1a1 2003-11-23 devnull close(infile);
379 bc7cb1a1 2003-11-23 devnull if (blocks != 0 || i != 0)
380 bc7cb1a1 2003-11-23 devnull fprint(2, "%s: file changed size\n", longname);
381 bc7cb1a1 2003-11-23 devnull while (blocks-- > 0)
382 bc7cb1a1 2003-11-23 devnull putempty();
383 bc7cb1a1 2003-11-23 devnull }
384 bc7cb1a1 2003-11-23 devnull
385 bc7cb1a1 2003-11-23 devnull
386 bc7cb1a1 2003-11-23 devnull void
387 bc7cb1a1 2003-11-23 devnull doxtract(char **argv)
388 bc7cb1a1 2003-11-23 devnull {
389 bc7cb1a1 2003-11-23 devnull Dir null;
390 bc7cb1a1 2003-11-23 devnull long blocks, bytes;
391 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK], outname[NAMSIZ+4];
392 bc7cb1a1 2003-11-23 devnull char **cp;
393 bc7cb1a1 2003-11-23 devnull int ofile;
394 bc7cb1a1 2003-11-23 devnull
395 bc7cb1a1 2003-11-23 devnull for (;;) {
396 bc7cb1a1 2003-11-23 devnull getdir();
397 bc7cb1a1 2003-11-23 devnull if (endtar())
398 bc7cb1a1 2003-11-23 devnull break;
399 bc7cb1a1 2003-11-23 devnull
400 bc7cb1a1 2003-11-23 devnull if (*argv == 0)
401 bc7cb1a1 2003-11-23 devnull goto gotit;
402 bc7cb1a1 2003-11-23 devnull
403 bc7cb1a1 2003-11-23 devnull for (cp = argv; *cp; cp++)
404 bc7cb1a1 2003-11-23 devnull if (prefix(*cp, dblock.dbuf.name))
405 bc7cb1a1 2003-11-23 devnull goto gotit;
406 bc7cb1a1 2003-11-23 devnull passtar();
407 bc7cb1a1 2003-11-23 devnull continue;
408 bc7cb1a1 2003-11-23 devnull
409 bc7cb1a1 2003-11-23 devnull gotit:
410 bc7cb1a1 2003-11-23 devnull if(checkdir(dblock.dbuf.name, stbuf->mode, &(stbuf->qid)))
411 bc7cb1a1 2003-11-23 devnull continue;
412 bc7cb1a1 2003-11-23 devnull
413 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == '1') {
414 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: can't link %s %s\n",
415 bc7cb1a1 2003-11-23 devnull dblock.dbuf.linkname, dblock.dbuf.name);
416 bc7cb1a1 2003-11-23 devnull remove(dblock.dbuf.name);
417 bc7cb1a1 2003-11-23 devnull continue;
418 bc7cb1a1 2003-11-23 devnull }
419 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == 's') {
420 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: cannot symlink\n", dblock.dbuf.name);
421 bc7cb1a1 2003-11-23 devnull continue;
422 bc7cb1a1 2003-11-23 devnull }
423 bc7cb1a1 2003-11-23 devnull if(dblock.dbuf.name[0] != '/' || Rflag)
424 bc7cb1a1 2003-11-23 devnull sprint(outname, "./%s", dblock.dbuf.name);
425 bc7cb1a1 2003-11-23 devnull else
426 bc7cb1a1 2003-11-23 devnull strcpy(outname, dblock.dbuf.name);
427 bc7cb1a1 2003-11-23 devnull if ((ofile = create(outname, OWRITE, stbuf->mode & 0777)) < 0) {
428 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s - cannot create: %r\n", outname);
429 bc7cb1a1 2003-11-23 devnull passtar();
430 bc7cb1a1 2003-11-23 devnull continue;
431 bc7cb1a1 2003-11-23 devnull }
432 bc7cb1a1 2003-11-23 devnull
433 bc7cb1a1 2003-11-23 devnull blocks = ((bytes = stbuf->length) + TBLOCK-1)/TBLOCK;
434 bc7cb1a1 2003-11-23 devnull if (vflag)
435 bc7cb1a1 2003-11-23 devnull fprint(2, "x %s, %ld bytes\n",
436 bc7cb1a1 2003-11-23 devnull dblock.dbuf.name, bytes);
437 bc7cb1a1 2003-11-23 devnull while (blocks-- > 0) {
438 bc7cb1a1 2003-11-23 devnull readtar(buf);
439 bc7cb1a1 2003-11-23 devnull if (bytes > TBLOCK) {
440 bc7cb1a1 2003-11-23 devnull if (write(ofile, buf, TBLOCK) < 0) {
441 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
442 bc7cb1a1 2003-11-23 devnull exits("extract write");
443 bc7cb1a1 2003-11-23 devnull }
444 bc7cb1a1 2003-11-23 devnull } else
445 bc7cb1a1 2003-11-23 devnull if (write(ofile, buf, bytes) < 0) {
446 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
447 bc7cb1a1 2003-11-23 devnull exits("extract write");
448 bc7cb1a1 2003-11-23 devnull }
449 bc7cb1a1 2003-11-23 devnull bytes -= TBLOCK;
450 bc7cb1a1 2003-11-23 devnull }
451 bc7cb1a1 2003-11-23 devnull if(Tflag){
452 bc7cb1a1 2003-11-23 devnull nulldir(&null);
453 bc7cb1a1 2003-11-23 devnull null.mtime = stbuf->mtime;
454 bc7cb1a1 2003-11-23 devnull dirfwstat(ofile, &null);
455 bc7cb1a1 2003-11-23 devnull }
456 bc7cb1a1 2003-11-23 devnull close(ofile);
457 bc7cb1a1 2003-11-23 devnull }
458 bc7cb1a1 2003-11-23 devnull }
459 bc7cb1a1 2003-11-23 devnull
460 bc7cb1a1 2003-11-23 devnull void
461 bc7cb1a1 2003-11-23 devnull dotable(void)
462 bc7cb1a1 2003-11-23 devnull {
463 bc7cb1a1 2003-11-23 devnull for (;;) {
464 bc7cb1a1 2003-11-23 devnull getdir();
465 bc7cb1a1 2003-11-23 devnull if (endtar())
466 bc7cb1a1 2003-11-23 devnull break;
467 bc7cb1a1 2003-11-23 devnull if (vflag)
468 bc7cb1a1 2003-11-23 devnull longt(stbuf);
469 bc7cb1a1 2003-11-23 devnull Bprint(&bout, "%s", dblock.dbuf.name);
470 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == '1')
471 bc7cb1a1 2003-11-23 devnull Bprint(&bout, " linked to %s", dblock.dbuf.linkname);
472 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == 's')
473 bc7cb1a1 2003-11-23 devnull Bprint(&bout, " -> %s", dblock.dbuf.linkname);
474 bc7cb1a1 2003-11-23 devnull Bprint(&bout, "\n");
475 bc7cb1a1 2003-11-23 devnull passtar();
476 bc7cb1a1 2003-11-23 devnull }
477 bc7cb1a1 2003-11-23 devnull }
478 bc7cb1a1 2003-11-23 devnull
479 bc7cb1a1 2003-11-23 devnull void
480 bc7cb1a1 2003-11-23 devnull putempty(void)
481 bc7cb1a1 2003-11-23 devnull {
482 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK];
483 bc7cb1a1 2003-11-23 devnull
484 bc7cb1a1 2003-11-23 devnull memset(buf, 0, TBLOCK);
485 bc7cb1a1 2003-11-23 devnull writetar(buf);
486 bc7cb1a1 2003-11-23 devnull }
487 bc7cb1a1 2003-11-23 devnull
488 bc7cb1a1 2003-11-23 devnull void
489 bc7cb1a1 2003-11-23 devnull longt(Dir *st)
490 bc7cb1a1 2003-11-23 devnull {
491 bc7cb1a1 2003-11-23 devnull char *cp;
492 bc7cb1a1 2003-11-23 devnull
493 bc7cb1a1 2003-11-23 devnull Bprint(&bout, "%M %4d/%1d ", st->mode, 0, 0); /* 0/0 uid/gid */
494 bc7cb1a1 2003-11-23 devnull Bprint(&bout, "%8lld", st->length);
495 bc7cb1a1 2003-11-23 devnull cp = ctime(st->mtime);
496 bc7cb1a1 2003-11-23 devnull Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
497 bc7cb1a1 2003-11-23 devnull }
498 bc7cb1a1 2003-11-23 devnull
499 bc7cb1a1 2003-11-23 devnull int
500 bc7cb1a1 2003-11-23 devnull checkdir(char *name, int mode, Qid *qid)
501 bc7cb1a1 2003-11-23 devnull {
502 bc7cb1a1 2003-11-23 devnull char *cp;
503 bc7cb1a1 2003-11-23 devnull int f;
504 bc7cb1a1 2003-11-23 devnull Dir *d, null;
505 bc7cb1a1 2003-11-23 devnull
506 bc7cb1a1 2003-11-23 devnull if(Rflag && *name == '/')
507 bc7cb1a1 2003-11-23 devnull name++;
508 bc7cb1a1 2003-11-23 devnull cp = name;
509 bc7cb1a1 2003-11-23 devnull if(*cp == '/')
510 bc7cb1a1 2003-11-23 devnull cp++;
511 bc7cb1a1 2003-11-23 devnull for (; *cp; cp++) {
512 bc7cb1a1 2003-11-23 devnull if (*cp == '/') {
513 bc7cb1a1 2003-11-23 devnull *cp = '\0';
514 bc7cb1a1 2003-11-23 devnull if (access(name, 0) < 0) {
515 bc7cb1a1 2003-11-23 devnull f = create(name, OREAD, DMDIR + 0775L);
516 bc7cb1a1 2003-11-23 devnull if(f < 0)
517 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: mkdir %s failed: %r\n", name);
518 bc7cb1a1 2003-11-23 devnull close(f);
519 bc7cb1a1 2003-11-23 devnull }
520 bc7cb1a1 2003-11-23 devnull *cp = '/';
521 bc7cb1a1 2003-11-23 devnull }
522 bc7cb1a1 2003-11-23 devnull }
523 bc7cb1a1 2003-11-23 devnull
524 bc7cb1a1 2003-11-23 devnull /* if this is a directory, chmod it to the mode in the tar plus 700 */
525 bc7cb1a1 2003-11-23 devnull if(cp[-1] == '/' || (qid->type&QTDIR)){
526 bc7cb1a1 2003-11-23 devnull if((d=dirstat(name)) != 0){
527 bc7cb1a1 2003-11-23 devnull nulldir(&null);
528 bc7cb1a1 2003-11-23 devnull null.mode = DMDIR | (mode & 0777) | 0700;
529 bc7cb1a1 2003-11-23 devnull dirwstat(name, &null);
530 bc7cb1a1 2003-11-23 devnull free(d);
531 bc7cb1a1 2003-11-23 devnull }
532 bc7cb1a1 2003-11-23 devnull return 1;
533 bc7cb1a1 2003-11-23 devnull } else
534 bc7cb1a1 2003-11-23 devnull return 0;
535 bc7cb1a1 2003-11-23 devnull }
536 bc7cb1a1 2003-11-23 devnull
537 bc7cb1a1 2003-11-23 devnull void
538 bc7cb1a1 2003-11-23 devnull tomodes(Dir *sp)
539 bc7cb1a1 2003-11-23 devnull {
540 bc7cb1a1 2003-11-23 devnull char *cp;
541 bc7cb1a1 2003-11-23 devnull
542 bc7cb1a1 2003-11-23 devnull for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
543 bc7cb1a1 2003-11-23 devnull *cp = '\0';
544 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.mode, "%6lo ", sp->mode & 0777);
545 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.uid, "%6o ", uflag);
546 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.gid, "%6o ", gflag);
547 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.size, "%11llo ", sp->length);
548 bc7cb1a1 2003-11-23 devnull sprint(dblock.dbuf.mtime, "%11lo ", sp->mtime);
549 bc7cb1a1 2003-11-23 devnull }
550 bc7cb1a1 2003-11-23 devnull
551 bc7cb1a1 2003-11-23 devnull int
552 bc7cb1a1 2003-11-23 devnull checksum(void)
553 bc7cb1a1 2003-11-23 devnull {
554 bc7cb1a1 2003-11-23 devnull int i;
555 bc7cb1a1 2003-11-23 devnull char *cp;
556 bc7cb1a1 2003-11-23 devnull
557 bc7cb1a1 2003-11-23 devnull for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
558 bc7cb1a1 2003-11-23 devnull *cp = ' ';
559 bc7cb1a1 2003-11-23 devnull i = 0;
560 bc7cb1a1 2003-11-23 devnull for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
561 bc7cb1a1 2003-11-23 devnull i += *cp & 0xff;
562 bc7cb1a1 2003-11-23 devnull return(i);
563 bc7cb1a1 2003-11-23 devnull }
564 bc7cb1a1 2003-11-23 devnull
565 bc7cb1a1 2003-11-23 devnull int
566 bc7cb1a1 2003-11-23 devnull prefix(char *s1, char *s2)
567 bc7cb1a1 2003-11-23 devnull {
568 bc7cb1a1 2003-11-23 devnull while (*s1)
569 bc7cb1a1 2003-11-23 devnull if (*s1++ != *s2++)
570 bc7cb1a1 2003-11-23 devnull return(0);
571 bc7cb1a1 2003-11-23 devnull if (*s2)
572 bc7cb1a1 2003-11-23 devnull return(*s2 == '/');
573 bc7cb1a1 2003-11-23 devnull return(1);
574 bc7cb1a1 2003-11-23 devnull }
575 bc7cb1a1 2003-11-23 devnull
576 bc7cb1a1 2003-11-23 devnull int
577 bc7cb1a1 2003-11-23 devnull readtar(char *buffer)
578 bc7cb1a1 2003-11-23 devnull {
579 bc7cb1a1 2003-11-23 devnull int i;
580 bc7cb1a1 2003-11-23 devnull
581 bc7cb1a1 2003-11-23 devnull if (recno >= nblock || first == 0) {
582 bc7cb1a1 2003-11-23 devnull if ((i = readn(mt, tbuf, TBLOCK*nblock)) <= 0) {
583 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: archive read error: %r\n");
584 bc7cb1a1 2003-11-23 devnull exits("archive read");
585 bc7cb1a1 2003-11-23 devnull }
586 bc7cb1a1 2003-11-23 devnull if (first == 0) {
587 bc7cb1a1 2003-11-23 devnull if ((i % TBLOCK) != 0) {
588 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: archive blocksize error: %r\n");
589 bc7cb1a1 2003-11-23 devnull exits("blocksize");
590 bc7cb1a1 2003-11-23 devnull }
591 bc7cb1a1 2003-11-23 devnull i /= TBLOCK;
592 bc7cb1a1 2003-11-23 devnull if (i != nblock) {
593 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: blocksize = %d\n", i);
594 bc7cb1a1 2003-11-23 devnull nblock = i;
595 bc7cb1a1 2003-11-23 devnull }
596 bc7cb1a1 2003-11-23 devnull }
597 bc7cb1a1 2003-11-23 devnull recno = 0;
598 bc7cb1a1 2003-11-23 devnull }
599 bc7cb1a1 2003-11-23 devnull first = 1;
600 bc7cb1a1 2003-11-23 devnull memmove(buffer, &tbuf[recno++], TBLOCK);
601 bc7cb1a1 2003-11-23 devnull return(TBLOCK);
602 bc7cb1a1 2003-11-23 devnull }
603 bc7cb1a1 2003-11-23 devnull
604 bc7cb1a1 2003-11-23 devnull int
605 bc7cb1a1 2003-11-23 devnull writetar(char *buffer)
606 bc7cb1a1 2003-11-23 devnull {
607 bc7cb1a1 2003-11-23 devnull first = 1;
608 bc7cb1a1 2003-11-23 devnull if (recno >= nblock) {
609 bc7cb1a1 2003-11-23 devnull if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
610 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: archive write error: %r\n");
611 bc7cb1a1 2003-11-23 devnull exits("write");
612 bc7cb1a1 2003-11-23 devnull }
613 bc7cb1a1 2003-11-23 devnull recno = 0;
614 bc7cb1a1 2003-11-23 devnull }
615 bc7cb1a1 2003-11-23 devnull memmove(&tbuf[recno++], buffer, TBLOCK);
616 bc7cb1a1 2003-11-23 devnull if (recno >= nblock) {
617 bc7cb1a1 2003-11-23 devnull if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
618 bc7cb1a1 2003-11-23 devnull fprint(2, "tar: archive write error: %r\n");
619 bc7cb1a1 2003-11-23 devnull exits("write");
620 bc7cb1a1 2003-11-23 devnull }
621 bc7cb1a1 2003-11-23 devnull recno = 0;
622 bc7cb1a1 2003-11-23 devnull }
623 bc7cb1a1 2003-11-23 devnull return(TBLOCK);
624 bc7cb1a1 2003-11-23 devnull }
625 bc7cb1a1 2003-11-23 devnull
626 bc7cb1a1 2003-11-23 devnull /*
627 bc7cb1a1 2003-11-23 devnull * backup over last tar block
628 bc7cb1a1 2003-11-23 devnull */
629 bc7cb1a1 2003-11-23 devnull void
630 bc7cb1a1 2003-11-23 devnull backtar(void)
631 bc7cb1a1 2003-11-23 devnull {
632 bc7cb1a1 2003-11-23 devnull seek(mt, -TBLOCK*nblock, 1);
633 bc7cb1a1 2003-11-23 devnull recno--;
634 bc7cb1a1 2003-11-23 devnull }
635 bc7cb1a1 2003-11-23 devnull
636 bc7cb1a1 2003-11-23 devnull void
637 bc7cb1a1 2003-11-23 devnull flushtar(void)
638 bc7cb1a1 2003-11-23 devnull {
639 bc7cb1a1 2003-11-23 devnull write(mt, tbuf, TBLOCK*nblock);
640 bc7cb1a1 2003-11-23 devnull }