annotate nt/minitar.c @ 461:120ed4009e51

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