131535Sminshall /* tarread.c */
231535Sminshall /* Copyright (c) 1985, by Carnegie-Mellon University */
331535Sminshall 
431535Sminshall #include <stdio.h>
531535Sminshall #include <v2tov3.h>
631535Sminshall #include <sys\types.h>
731535Sminshall #include <sys\stat.h>
831535Sminshall #include "tar.h"
931535Sminshall 
1031535Sminshall char usage[] = "tarread: usage: tarread tx[vwz] tarfile\n";
1131535Sminshall union hblock hbuf;
1231535Sminshall 
1331535Sminshall int verbose = 0;
1431535Sminshall int confirm = 0;
1531535Sminshall int binary = 0;
1631535Sminshall char cmd;
1731535Sminshall 
main(argc,argv)1831535Sminshall main(argc, argv)
1931535Sminshall int argc;
2031535Sminshall char *argv[];
2131535Sminshall {
2231535Sminshall 	FILE *fp;
2331535Sminshall 	char *cp;
2431535Sminshall 
2531535Sminshall 	if (argc != 3) {
2631535Sminshall 		fprintf(stderr, usage);
2731535Sminshall 		exit(1);
2831535Sminshall 	}
2931535Sminshall 
3031535Sminshall 	for (cp = argv[1]; *cp; cp++)
3131535Sminshall 		switch (*cp) {
3231535Sminshall 			case 't':
3331535Sminshall 			case 'x':
3431535Sminshall 				cmd = *cp;
3531535Sminshall 				break;
3631535Sminshall 
3731535Sminshall 			case 'v':
3831535Sminshall 				verbose++;
3931535Sminshall 				break;
4031535Sminshall 			case 'z':
4131535Sminshall 				binary++;
4231535Sminshall 				break;
4331535Sminshall 			case 'w':
4431535Sminshall 				confirm++;
4531535Sminshall 				break;
4631535Sminshall 			default:
4731535Sminshall 				fprintf(stderr, "tarread: unknown switch %c\n", *cp);
4831535Sminshall 				fprintf(stderr, usage);
4931535Sminshall 				exit(1);
5031535Sminshall 		}
5131535Sminshall 
5231535Sminshall 	if ((fp = fopen(argv[2], "rb")) == NULL) {
5331535Sminshall 		fprintf(stderr, "tarrread: cannot open %s\n", argv[2]);
5431535Sminshall 		exit(1);
5531535Sminshall 	}
5631535Sminshall 
5731535Sminshall 	for (;;) {
5831535Sminshall 		if (fread(&hbuf, sizeof(hbuf), 1, fp) != 1) {
5931535Sminshall 			perror("fread");
6031535Sminshall 			exit(1);
6131535Sminshall 		}
6231535Sminshall 		if (!proc_file(fp))
6331535Sminshall 			break;
6431535Sminshall 	}
6531535Sminshall }
6631535Sminshall 
6731535Sminshall 
proc_file(fp)6831535Sminshall int proc_file(fp)
6931535Sminshall FILE *fp;
7031535Sminshall {
7131535Sminshall 	char name[NAMSIZ];
7231535Sminshall 	unsigned short mode;
7331535Sminshall 	short uid, gid;
7431535Sminshall 	long size, mtime;
7531535Sminshall 	char c;
7631535Sminshall 	int confrmd;
7731535Sminshall 	long skip;
7831535Sminshall 
7931535Sminshall 	if (hbuf.dbuf.name[0] == '\0')
8031535Sminshall 		return (NULL);
8131535Sminshall 
8231535Sminshall 	strcpy(name, hbuf.dbuf.name);
8331535Sminshall 	if (sscanf(hbuf.dbuf.mode, "%o", &mode) != 1)
8431535Sminshall 		fprintf("Couldn't read mode\n");
8531535Sminshall 	if (sscanf(hbuf.dbuf.uid, "%o", &uid) != 1)
8631535Sminshall 		fprintf("Couldn't read uid\n");
8731535Sminshall 	if (sscanf(hbuf.dbuf.gid, "%o", &gid) != 1)
8831535Sminshall 		fprintf("Couldn't read gid\n");
8931535Sminshall 	if (sscanf(hbuf.dbuf.size, "%12lo %12lo", &size, &mtime) != 2)
9031535Sminshall 		fprintf("Couldn't read size or mtime\n");
9131535Sminshall 
9231535Sminshall 	skip = (size + TBLOCK - 1) / TBLOCK * TBLOCK;
9331535Sminshall 
9431535Sminshall 	switch (cmd) {
9531535Sminshall 		case 't':
9631535Sminshall 			if (verbose)
9731535Sminshall 				printf("%8o %d/%d\t %6ld %.24s %s\n", mode,
9831535Sminshall 					uid, gid, size, ctime(&mtime), name);
9931535Sminshall 			else
10031535Sminshall 				printf("%s\n", name);
10131535Sminshall 
10231535Sminshall 			break;
10331535Sminshall 
10431535Sminshall 		case 'x':
10531535Sminshall 			if (verbose)
10631535Sminshall 				printf("x %s: ", name);
10731535Sminshall 			confrmd = 1;
10831535Sminshall 
10931535Sminshall 			if (confirm) {
11031535Sminshall 				confrmd = 0;
11131535Sminshall 				if ((c = getchar()) == 'y')
11231535Sminshall 					confrmd++;
11331535Sminshall 				while (c != '\n')
11431535Sminshall 					c = getchar();
11531535Sminshall 				if(!confrmd)
11631535Sminshall 					break;
11731535Sminshall 			}
11831535Sminshall 
11931535Sminshall 			if(extract(name, size, mode, mtime, fp))
12031535Sminshall 				skip = 0;
12131535Sminshall 
12231535Sminshall 			if (verbose)
12331535Sminshall 				printf("\n");
12431535Sminshall 			break;
12531535Sminshall 	}
12631535Sminshall 	if (fseek(fp, skip, 1)) {
12731535Sminshall 		perror("fseek");
12831535Sminshall 		exit(1);
12931535Sminshall 	}
13031535Sminshall 	return (1);
13131535Sminshall }
13231535Sminshall 
13331535Sminshall 
extract(fname,size,mode,mtime,ifp)13431535Sminshall int extract(fname, size, mode, mtime, ifp)
13531535Sminshall char *fname;
13631535Sminshall long size;
13731535Sminshall unsigned short mode;
13831535Sminshall long mtime;
13931535Sminshall FILE *ifp;
14031535Sminshall {
14131535Sminshall 	FILE *ofp;
14231535Sminshall 	char fbuf[TBLOCK];
14331535Sminshall 	long copied, left;
14431535Sminshall 	char *s, *np, *strchr();
14531535Sminshall 	struct stat sbuf;
14631535Sminshall 
14731535Sminshall 	for(np = fname; s = strchr(np, '/'); np = s+1) {
14831535Sminshall 		*s = '\0';
14931535Sminshall 		if(stat(fname, &sbuf)) {
15031535Sminshall 			if(mkdir(fname))
15131535Sminshall 				perror("mkdir");
15231535Sminshall 		} else if(!(sbuf.st_mode & S_IFDIR)) {
15331535Sminshall 			fprintf(stderr, "\n%s: Not a directory", fname);
15431535Sminshall 			*s = '/';
15531535Sminshall 			fprintf(stderr, "\ntar: %s - cannot create", fname);
15631535Sminshall 			return (0);
15731535Sminshall 		}
15831535Sminshall 		*s = '/';
15931535Sminshall 	}
16031535Sminshall 	if(!*np)
16131535Sminshall 		return (0);
16231535Sminshall 
16331535Sminshall 	if (binary) {
16431535Sminshall 		if ((ofp = fopen(fname, "wb")) == NULL) {
16531535Sminshall 			perror("extract:");
16631535Sminshall 			return (0);
16731535Sminshall 		}
16831535Sminshall 	} else {
16931535Sminshall 		if ((ofp = fopen(fname, "w")) == NULL) {
17031535Sminshall 			perror("extract:");
17131535Sminshall 			return (0);
17231535Sminshall 		}
17331535Sminshall 	}
17431535Sminshall 
17531535Sminshall 	for(copied = 0; copied < size; copied += TBLOCK) {
17631535Sminshall 		if(fread(fbuf, TBLOCK, 1, ifp) != 1) {
17731535Sminshall 			perror("fread");
17831535Sminshall 			exit(1);
17931535Sminshall 		}
18031535Sminshall 		left = size - copied;
18131535Sminshall 		if(fwrite(fbuf, (int)min(left, TBLOCK), 1, ofp) != 1) {
18231535Sminshall 			perror("fwrite");
18331535Sminshall 			exit(1);
18431535Sminshall 		}
18531535Sminshall 	}
18631535Sminshall 
18731535Sminshall 	if(fclose(ofp)) {
18831535Sminshall 		perror("fclose");
18931535Sminshall 		exit(1);
19031535Sminshall 	}
191*31536Sminshall 
192*31536Sminshall 	/*
193*31536Sminshall 	 * Now, set modification time.
194*31536Sminshall 	 */
195*31536Sminshall 	{
196*31536Sminshall #include <sys\utime.h>
197*31536Sminshall 	    struct utimbuf utim;
198*31536Sminshall 
199*31536Sminshall 	    utim.modtime = mtime;
200*31536Sminshall 
201*31536Sminshall 	    if (utime(fname, &utim) == -1) {
202*31536Sminshall 		perror("utime");
203*31536Sminshall 		exit(1);
204*31536Sminshall 	    }
205*31536Sminshall 	}
206*31536Sminshall 
20731535Sminshall 	return (1);
20831535Sminshall }
209