Browse code

Added support for various GNU extensions

git-svn: trunk@1713

Nigel Horne authored on 2005/09/02 06:06:09
Showing 2 changed files
... ...
@@ -1,3 +1,10 @@
1
+Thu Sep  1 22:04:00 BST 2005 (njh)
2
+----------------------------------
3
+  * libclamav/untar.c:	Added support for various GNU extensions: volume
4
+				  headers, long file names and long names for
5
+				  symbolic links. Code by Daniel Fahlgren
6
+				  fahlgren <AT> ardendo.se
7
+
1 8
 Mon Aug 29 17:00:36 CEST 2005 (tk)
2 9
 ----------------------------------
3 10
   * libclamav: activate ELF code
... ...
@@ -21,6 +21,9 @@
21 21
  *
22 22
  * Change History:
23 23
  * $Log: untar.c,v $
24
+ * Revision 1.27  2005/09/01 21:03:46  nigelhorne
25
+ * Added support for various GNU extensions
26
+ *
24 27
  * Revision 1.26  2005/08/01 11:30:59  nigelhorne
25 28
  * Spelling fix
26 29
  *
... ...
@@ -100,7 +103,7 @@
100 100
  * First draft
101 101
  *
102 102
  */
103
-static	char	const	rcsid[] = "$Id: untar.c,v 1.26 2005/08/01 11:30:59 nigelhorne Exp $";
103
+static	char	const	rcsid[] = "$Id: untar.c,v 1.27 2005/09/01 21:03:46 nigelhorne Exp $";
104 104
 
105 105
 #include <stdio.h>
106 106
 #include <errno.h>
... ...
@@ -159,7 +162,7 @@ cli_untar(const char *dir, int desc, unsigned int posix)
159 159
 			char type;
160 160
 			const char *suffix;
161 161
 			size_t suffixLen = 0;
162
-			int fd, directory;
162
+			int fd, directory, skipEntry = 0;
163 163
 			char magic[7], name[101], osize[13];
164 164
 
165 165
 			if(outfile) {
... ...
@@ -201,11 +204,18 @@ cli_untar(const char *dir, int desc, unsigned int posix)
201 201
 				case '3':	/* char device */
202 202
 				case '4':	/* block device */
203 203
 				case '6':	/* fifo special */
204
+				case 'V':	/* Volume header */
204 205
 					directory = 1;
205 206
 					break;
206
-				case 'L':	/* GNU extension - ././@LongLink */
207
-					cli_errmsg("cli_untar: only standard TAR files are currently supported\n", type);
208
-					return CL_EFORMAT;
207
+				case 'K':
208
+				case 'L':
209
+					/* GNU extension - ././@LongLink
210
+					 * Discard the blocks with the extended filename,
211
+					 * the last header will contain parts of it anyway
212
+					 */
213
+					directory = 0;
214
+					skipEntry = 1;
215
+					break;
209 216
 				default:
210 217
 					/*cli_errmsg("cli_untar: unknown type flag %c\n", type);
211 218
 					return CL_EFORMAT;*/
... ...
@@ -227,6 +237,23 @@ cli_untar(const char *dir, int desc, unsigned int posix)
227 227
 				continue;
228 228
 			}
229 229
 
230
+			strncpy(osize, block+124, 12);
231
+			osize[12] = '\0';
232
+			size = octal(osize);
233
+			if(size < 0) {
234
+				cli_errmsg("Invalid size in tar header\n");
235
+				fclose(outfile);
236
+				return CL_EFORMAT;
237
+			}
238
+			cli_dbgmsg("cli_untar: size = %d\n", size);
239
+
240
+			if(skipEntry) {
241
+				const int nskip = (size % BLOCKSIZE || !size) ? size + BLOCKSIZE - (size % BLOCKSIZE) : size;
242
+				cli_dbgmsg("cli_untar: GNU extension, skipping entry\n");
243
+				lseek(desc, nskip, SEEK_CUR);
244
+				continue;
245
+			}
246
+
230 247
 			strncpy(name, block, 100);
231 248
 			name[100] = '\0';
232 249
 
... ...
@@ -270,16 +297,6 @@ cli_untar(const char *dir, int desc, unsigned int posix)
270 270
 				close(fd);
271 271
 				return CL_ETMPFILE;
272 272
 			}
273
-
274
-			strncpy(osize, block+124, 12);
275
-			osize[12] = '\0';
276
-			size = octal(osize);
277
-			if(size < 0) {
278
-				cli_errmsg("Invalid size in tar header\n");
279
-				fclose(outfile);
280
-				return CL_EFORMAT;
281
-			}
282
-			cli_dbgmsg("cli_untar: size = %d\n", size);
283 273
 		} else { /* write or continue writing file contents */
284 274
 			const int nbytes = size>512? 512:size;
285 275
 			const int nwritten = fwrite(block, 1, (size_t)nbytes, outfile);