git-svn: trunk@831
Nigel Horne authored on 2004/09/06 03:58:22... | ... |
@@ -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); |