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>
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
11 bc7cb1a1 2003-11-23 devnull char dummy[TBLOCK];
12 bc7cb1a1 2003-11-23 devnull struct header
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];
24 bc7cb1a1 2003-11-23 devnull } dblock, tbuf[NBLOCK];
26 bc7cb1a1 2003-11-23 devnull Dir *stbuf;
27 bc7cb1a1 2003-11-23 devnull Biobuf bout;
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;
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);
56 bc7cb1a1 2003-11-23 devnull main(int argc, char **argv)
58 bc7cb1a1 2003-11-23 devnull char *usefile;
59 bc7cb1a1 2003-11-23 devnull char *cp, *ap;
61 bc7cb1a1 2003-11-23 devnull if (argc < 2)
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;
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)
76 bc7cb1a1 2003-11-23 devnull case 'u':
77 bc7cb1a1 2003-11-23 devnull ap = *argv++;
80 bc7cb1a1 2003-11-23 devnull uflag = strtoul(ap, 0, 0);
82 bc7cb1a1 2003-11-23 devnull case 'g':
83 bc7cb1a1 2003-11-23 devnull ap = *argv++;
86 bc7cb1a1 2003-11-23 devnull gflag = strtoul(ap, 0, 0);
88 bc7cb1a1 2003-11-23 devnull case 'c':
92 bc7cb1a1 2003-11-23 devnull case 'r':
95 bc7cb1a1 2003-11-23 devnull case 'v':
98 bc7cb1a1 2003-11-23 devnull case 'x':
101 bc7cb1a1 2003-11-23 devnull case 'T':
102 bc7cb1a1 2003-11-23 devnull Tflag++;
104 bc7cb1a1 2003-11-23 devnull case 't':
105 bc7cb1a1 2003-11-23 devnull tflag++;
107 bc7cb1a1 2003-11-23 devnull case 'R':
108 bc7cb1a1 2003-11-23 devnull Rflag++;
110 bc7cb1a1 2003-11-23 devnull case '-':
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();
117 bc7cb1a1 2003-11-23 devnull fmtinstall('M', dirmodefmt);
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");
125 bc7cb1a1 2003-11-23 devnull mt = dup(1, -1);
126 bc7cb1a1 2003-11-23 devnull nblock = 1;
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");
134 bc7cb1a1 2003-11-23 devnull dorep(argv);
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;
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");
145 bc7cb1a1 2003-11-23 devnull doxtract(argv);
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;
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");
156 bc7cb1a1 2003-11-23 devnull dotable();
159 bc7cb1a1 2003-11-23 devnull usage();
160 bc7cb1a1 2003-11-23 devnull exits(0);
164 bc7cb1a1 2003-11-23 devnull usage(void)
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");
171 bc7cb1a1 2003-11-23 devnull dorep(char **argv)
173 bc7cb1a1 2003-11-23 devnull char cwdbuf[2048], *cwd, thisdir[2048];
174 bc7cb1a1 2003-11-23 devnull char *cp, *cp2;
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");
181 bc7cb1a1 2003-11-23 devnull cwd = cwdbuf;
183 bc7cb1a1 2003-11-23 devnull if (!cflag) {
184 bc7cb1a1 2003-11-23 devnull getdir();
186 bc7cb1a1 2003-11-23 devnull passtar();
187 bc7cb1a1 2003-11-23 devnull getdir();
188 bc7cb1a1 2003-11-23 devnull } while (!endtar());
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]) {
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;
199 bc7cb1a1 2003-11-23 devnull continue;
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));
211 bc7cb1a1 2003-11-23 devnull snprint(thisdir, sizeof(thisdir), "%s/%s", cwd, *argv);
212 bc7cb1a1 2003-11-23 devnull *cp2 = '/';
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");
223 bc7cb1a1 2003-11-23 devnull putempty();
224 bc7cb1a1 2003-11-23 devnull putempty();
225 bc7cb1a1 2003-11-23 devnull flushtar();
229 bc7cb1a1 2003-11-23 devnull endtar(void)
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);
236 bc7cb1a1 2003-11-23 devnull return(0);
240 bc7cb1a1 2003-11-23 devnull getdir(void)
242 bc7cb1a1 2003-11-23 devnull Dir *sp;
244 bc7cb1a1 2003-11-23 devnull readtar((char*)&dblock);
245 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.name[0] == '\0')
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");
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");
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;
274 bc7cb1a1 2003-11-23 devnull passtar(void)
276 bc7cb1a1 2003-11-23 devnull long blocks;
277 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK];
279 bc7cb1a1 2003-11-23 devnull if (dblock.dbuf.linkflag == '1' || dblock.dbuf.linkflag == 's')
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;
285 bc7cb1a1 2003-11-23 devnull while (blocks-- > 0)
286 bc7cb1a1 2003-11-23 devnull readtar(buf);
290 bc7cb1a1 2003-11-23 devnull putfile(char *dir, char *longname, char *sname)
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;
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);
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);
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);
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);
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);
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);
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);
355 bc7cb1a1 2003-11-23 devnull tomodes(stbuf);
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);
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);
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);
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--;
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();
387 bc7cb1a1 2003-11-23 devnull doxtract(char **argv)
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;
395 bc7cb1a1 2003-11-23 devnull for (;;) {
396 bc7cb1a1 2003-11-23 devnull getdir();
397 bc7cb1a1 2003-11-23 devnull if (endtar())
400 bc7cb1a1 2003-11-23 devnull if (*argv == 0)
401 bc7cb1a1 2003-11-23 devnull goto gotit;
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;
410 bc7cb1a1 2003-11-23 devnull if(checkdir(dblock.dbuf.name, stbuf->mode, &(stbuf->qid)))
411 bc7cb1a1 2003-11-23 devnull continue;
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;
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;
423 bc7cb1a1 2003-11-23 devnull if(dblock.dbuf.name[0] != '/' || Rflag)
424 bc7cb1a1 2003-11-23 devnull sprint(outname, "./%s", dblock.dbuf.name);
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;
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");
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");
449 bc7cb1a1 2003-11-23 devnull bytes -= TBLOCK;
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);
456 bc7cb1a1 2003-11-23 devnull close(ofile);
461 bc7cb1a1 2003-11-23 devnull dotable(void)
463 bc7cb1a1 2003-11-23 devnull for (;;) {
464 bc7cb1a1 2003-11-23 devnull getdir();
465 bc7cb1a1 2003-11-23 devnull if (endtar())
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();
480 bc7cb1a1 2003-11-23 devnull putempty(void)
482 bc7cb1a1 2003-11-23 devnull char buf[TBLOCK];
484 bc7cb1a1 2003-11-23 devnull memset(buf, 0, TBLOCK);
485 bc7cb1a1 2003-11-23 devnull writetar(buf);
489 bc7cb1a1 2003-11-23 devnull longt(Dir *st)
491 bc7cb1a1 2003-11-23 devnull char *cp;
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);
500 bc7cb1a1 2003-11-23 devnull checkdir(char *name, int mode, Qid *qid)
502 bc7cb1a1 2003-11-23 devnull char *cp;
504 bc7cb1a1 2003-11-23 devnull Dir *d, null;
506 bc7cb1a1 2003-11-23 devnull if(Rflag && *name == '/')
508 bc7cb1a1 2003-11-23 devnull cp = name;
509 bc7cb1a1 2003-11-23 devnull if(*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);
520 bc7cb1a1 2003-11-23 devnull *cp = '/';
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);
532 bc7cb1a1 2003-11-23 devnull return 1;
534 bc7cb1a1 2003-11-23 devnull return 0;
538 bc7cb1a1 2003-11-23 devnull tomodes(Dir *sp)
540 bc7cb1a1 2003-11-23 devnull char *cp;
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);
552 bc7cb1a1 2003-11-23 devnull checksum(void)
555 bc7cb1a1 2003-11-23 devnull char *cp;
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 = ' ';
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);
566 bc7cb1a1 2003-11-23 devnull prefix(char *s1, char *s2)
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);
577 bc7cb1a1 2003-11-23 devnull readtar(char *buffer)
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");
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");
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;
597 bc7cb1a1 2003-11-23 devnull recno = 0;
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);
605 bc7cb1a1 2003-11-23 devnull writetar(char *buffer)
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");
613 bc7cb1a1 2003-11-23 devnull recno = 0;
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");
621 bc7cb1a1 2003-11-23 devnull recno = 0;
623 bc7cb1a1 2003-11-23 devnull return(TBLOCK);
627 bc7cb1a1 2003-11-23 devnull * backup over last tar block
630 bc7cb1a1 2003-11-23 devnull backtar(void)
632 bc7cb1a1 2003-11-23 devnull seek(mt, -TBLOCK*nblock, 1);
633 bc7cb1a1 2003-11-23 devnull recno--;
637 bc7cb1a1 2003-11-23 devnull flushtar(void)
639 bc7cb1a1 2003-11-23 devnull write(mt, tbuf, TBLOCK*nblock);