Browse code

Extract files completed

git-svn: trunk@831

Nigel Horne authored on 2004/09/06 03:58:22
Showing 2 changed files
... ...
@@ -15,10 +15,139 @@
15 15
  *  along with this program; if not, write to the Free Software
16 16
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  *
18
+ * Some of this code is based on minitar.c which is in the public domain.
19
+ * Author: Charles G. Waldman (cgw@pgt.com),  Aug 4 1998
20
+ *
18 21
  * Change History:
19 22
  * $Log: untar.c,v $
23
+ * Revision 1.2  2004/09/05 18:58:21  nigelhorne
24
+ * Extract files completed
25
+ *
20 26
  * Revision 1.1  2004/09/05 15:28:10  nigelhorne
21 27
  * First draft
22 28
  *
23 29
  */
24
-static	char	const	rcsid[] = "$Id: untar.c,v 1.1 2004/09/05 15:28:10 nigelhorne Exp $";
30
+static	char	const	rcsid[] = "$Id: untar.c,v 1.2 2004/09/05 18:58:21 nigelhorne Exp $";
31
+
32
+#include <stdio.h>
33
+#include <errno.h>
34
+#include <string.h>
35
+#include <unistd.h>
36
+#include <sys/stat.h>
37
+
38
+#include "clamav.h"
39
+#include "others.h"
40
+
41
+#define BLOCKSIZE 512
42
+#define MAXNAMELEN 1024
43
+
44
+static
45
+int octal(const char *str)
46
+{
47
+	int ret = -1;
48
+
49
+	sscanf(str, "%o", &ret);
50
+	return ret;
51
+}
52
+
53
+int
54
+cli_untar(const char *dir, int desc)
55
+{
56
+	int size = 0;
57
+	int in_block = 0;
58
+	int directory = 0;
59
+	FILE *outfile = (FILE*)0;
60
+
61
+	cli_dbgmsg("In untar(%s, %d)\n", dir ? dir : "", desc);
62
+
63
+	for(;;) {
64
+		char fullname[MAXNAMELEN];
65
+		char block[BLOCKSIZE];
66
+		const int nread = read(desc, block, sizeof(block));
67
+
68
+		if(!in_block && nread == 0)
69
+			break;
70
+
71
+		if(nread != BLOCKSIZE) {
72
+			cli_errmsg("cli_untar: incomplete block read\n");
73
+			return CL_EIO;
74
+		}
75
+
76
+		if(!in_block) {
77
+			char magic[7];
78
+			char name[101];
79
+			char type;
80
+
81
+			if(block[0] == '\0')  /* We're done */
82
+				break;
83
+
84
+			strncpy(magic, block+257, 6);
85
+			magic[6] = '\0';
86
+			if(strcmp(magic, "ustar ") != 0) {
87
+				cli_errmsg("Incorrect magic number in tar header\n");
88
+				return CL_EDSIG;
89
+			}
90
+
91
+			strncpy(name, block, 100);
92
+			name[100] = '\0';
93
+			sprintf(fullname, "%s/%s", dir, name);
94
+			cli_dbgmsg("cli_untar: extracting %s\n", fullname);
95
+			type = block[156];
96
+
97
+			switch(type) {
98
+				case '0':
99
+				case '\0':
100
+					directory = 0;
101
+					break;
102
+				case '5':
103
+					directory = 1;
104
+					break;
105
+				default:
106
+					cli_errmsg("cli_untar: unknown type flag %c\n", type);
107
+					break;
108
+			}
109
+
110
+			if(directory)
111
+				continue;
112
+			else { /*file */
113
+				char osize[13];
114
+
115
+				in_block = 1;
116
+				if(outfile) {
117
+					if(fclose(outfile)) {
118
+						cli_errmsg("cli_untar: cannot close file %s\n",
119
+						    fullname);
120
+						return CL_EIO;
121
+					}
122
+					outfile = (FILE*)0;
123
+				}
124
+
125
+				if(!(outfile = fopen(fullname,"wb"))) {
126
+					cli_errmsg("cli_untar: cannot create file %s\n",
127
+					    fullname);
128
+					return CL_ETMPFILE;
129
+				}
130
+
131
+				strncpy(osize, block+124, 12);
132
+				osize[12] = '\0';
133
+				size = octal(osize);
134
+				if(size < 0){
135
+					cli_errmsg("Invalid size in tar header\n");
136
+					return CL_EDSIG;
137
+				}
138
+			}
139
+		} else { /* write or continue writing file contents */
140
+			const int nbytes = size>512? 512:size;
141
+			const int nwritten = fwrite(block, 1, nbytes, outfile);
142
+
143
+			if(nwritten != nbytes) {
144
+				cli_errmsg("cli_untar: only wrote %d bytes to file %s\n",
145
+					nwritten, fullname);
146
+			}
147
+			size -= nbytes;
148
+			if (size == 0)
149
+				in_block = 0;
150
+		}
151
+	}
152
+	return CL_CLEAN;
153
+}
... ...
@@ -17,7 +17,11 @@
17 17
  *
18 18
  * Change History:
19 19
  * $Log: untar.h,v $
20
+ * Revision 1.2  2004/09/05 18:58:22  nigelhorne
21
+ * Extract files completed
22
+ *
20 23
  * Revision 1.1  2004/09/05 15:28:10  nigelhorne
21 24
  * First draft
22 25
  *
23 26
  */
27
+int	cli_untar(const char *dir, int desc);