comparison nt/minitar.c @ 327:03446687b7cc r21-0-61

Import from CVS: tag r21-0-61
author cvs
date Mon, 13 Aug 2007 10:48:16 +0200
parents
children 8e84bee8ddd0 74fd4e045ea6 9d177e8d4150
comparison
equal deleted inserted replaced
326:e2671bc7f66a 327:03446687b7cc
1
2 /* Minitar: extract .tar.gz files on Win32 platforms.
3 Uses zlib for decompression.
4
5 This is very simple-minded, it ignores checksums, and any type of file
6 that is not a plain file or a directory. Nonetheless it is useful.
7
8 Author: Charles G. Waldman (cgw@pgt.com), Aug 4 1998
9
10 This file is placed in the public domain; you can
11 do whatever you like with it. There is NO WARRANTY.
12 If it breaks, you get to keep both pieces */
13
14
15 #include <stdio.h>
16 #include <Errno.h>
17
18 #include <zlib.h>
19
20 Usage(char *name)
21 {
22 fprintf(stderr,"Usage: %s file.tar.gz [base-dir]\n",name);
23 fprintf(stderr,"\tExtracts the contents compressed tar file to base-dir\n");
24 exit(-1);
25 }
26
27
28 #define BLOCKSIZE 512
29 #define MAXNAMELEN 1024
30
31 int octal(char *str)
32 {
33 int ret = -1;
34 sscanf(str,"%o",&ret);
35 return ret;
36 }
37
38 /* this is like mkdir -p, except if there is no trailing slash,
39 the final component is assumed to be a file, rather than a
40 path component, so it is not created as a directory */
41
42 int makepath(char *path)
43 {
44 char tmp[MAXNAMELEN];
45 char *cp;
46 extern int errno;
47
48 for (cp=path; cp; cp = (char*)strchr(cp+1,'/')){
49 if (!*cp)
50 break;
51 if (*cp != '/')
52 continue;
53 strncpy(tmp, path, cp-path);
54 tmp[cp-path] = '\0';
55 if (strlen(tmp) == 0)
56 continue;
57 if (mkdir(tmp,0777)){
58 if (errno == EEXIST)
59 continue;
60 else
61 return -1;
62 }
63 }
64 return 0;
65 }
66
67
68
69
70 main(int argc, char **argv)
71 {
72 char fullname[MAXNAMELEN];
73 char *basedir = ".";
74 char *tarfile;
75 char *cp;
76 int size;
77 char osize[13];
78 char name[101];
79 char magic[7];
80 char type;
81
82 gzFile *infile = (gzFile*)0;
83 FILE *outfile = (FILE*)0;
84
85 char block[BLOCKSIZE];
86 int nbytes, nread, nwritten;
87
88 int in_block = 0;
89 int directory = 0;
90
91 if (argc < 2 || argc > 3)
92 Usage(argv[0]);
93
94 tarfile = argv[1];
95 if (argc==3)
96 basedir = argv[2];
97
98 if (! (infile = gzopen(tarfile,"rb"))){
99 fprintf(stderr,"Cannot open %s\n", tarfile);
100 exit(-2);
101 }
102
103 while (1){
104
105
106 nread = gzread(infile,block,512);
107
108 if (!in_block && nread == 0)
109 break;
110
111 if (nread != BLOCKSIZE){
112 fprintf(stderr,"Error: incomplete block read. Exiting.\n");
113 exit(-2);
114 }
115
116 if (!in_block){
117 if (block[0]=='\0') /* We're done */
118 break;
119
120 strncpy(magic,block+257,6);
121 magic[6] = '\0';
122 if (strcmp(magic,"ustar ")){
123 fprintf(stderr,
124 "Error: incorrect magic number in tar header. Exiting\n");
125 }
126
127 strncpy(name,block,100);
128 name[100] = '\0';
129 sprintf(fullname,"%s/%s",basedir,name);
130 printf("%s\n",fullname);
131 type = block[156];
132
133 switch(type){
134 case '0':
135 case '\0':
136 directory = 0;
137 break;
138 case '5':
139 directory = 1;
140 break;
141 default:
142 fprintf(stderr,"Error: unknown type flag %c. Exiting.\n",type);
143 break;
144 }
145
146 if (directory){
147 in_block = 0;
148
149 /* makepath will ignore the final path component, so make sure
150 dirnames have a trailing slash */
151
152 if (fullname[strlen(fullname)-1] != '/')
153 strcat(fullname,"/");
154 if (makepath(fullname)){
155 fprintf(stderr, "Error: cannot create directory %s. Exiting.\n",
156 fullname);
157 exit(-2);
158 }
159 continue;
160 } else { /*file */
161 in_block = 1;
162 if (outfile){
163 if (fclose(outfile)){
164 fprintf(stderr,"Error: cannot close file %s. Exiting.\n",
165 fullname);
166 exit(-2);
167 }
168 outfile = (FILE*)0;
169 }
170
171 if ( !(outfile = fopen(fullname,"wb"))){
172 /*try creating the directory, maybe it's not there */
173 if (makepath(fullname)){
174 fprintf(stderr,"Error: cannot create file %s. Exiting.\n",
175 fullname);
176 exit(-2);
177 }
178 /* now try again to open the file */
179 if (!(outfile = fopen(fullname,"wb"))){
180 fprintf(stderr,"Error: cannot create file %s. Exiting.\n",
181 fullname);
182 exit(-2);
183 }
184 }
185
186 strncpy(osize,block+124,12);
187 osize[12] = '\0';
188 size = octal(osize);
189 if (size<0){
190 fprintf(stderr,"Error: invalid size in tar header. Exiting.\n");
191 exit(-2);
192 }
193 }
194 } else { /* write or continue writing file contents */
195 nbytes = size>512? 512:size;
196
197 nwritten = fwrite(block, 1, nbytes, outfile);
198 if (nwritten != nbytes){
199 fprintf(stderr, "Error: only wrote %d bytes to file %s. Exiting.\n",
200 nwritten, fullname);
201 }
202 size -= nbytes;
203 if (size==0)
204 in_block = 0;
205 }
206 }
207 }
208
209
210
211