Bug Summary

File:/home/joel/rtems-4.11-work/build/rtems/c/src/../../cpukit/libmisc/untar/untar.c
Location:line 284, column 12
Description:Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'

Annotated Source Code

1/* FIXME:
2 * 1. Symbolic links are not created.
3 * 2. Untar_FromMemory uses FILE *fp.
4 * 3. How to determine end of archive?
5 *
6 * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
7 *
8 * The license and distribution terms for this file may be
9 * found in the file LICENSE in this distribution or at
10 * http://www.rtems.com/license/LICENSE.
11 *
12 * $Id: untar.c,v 1.14 2010/08/24 13:06:24 ralf Exp $
13 */
14
15#ifdef HAVE_CONFIG_H1
16#include "config.h"
17#endif
18
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <rtems/untar.h>
26#include <rtems/bspIo.h>
27
28
29/**************************************************************************
30 * TAR file format:
31 *
32 * Offset Length Contents
33 * 0 100 bytes File name ('\0' terminated, 99 maxmum length)
34 * 100 8 bytes File mode (in octal ascii)
35 * 108 8 bytes User ID (in octal ascii)
36 * 116 8 bytes Group ID (in octal ascii)
37 * 124 12 bytes File size (s) (in octal ascii)
38 * 136 12 bytes Modify time (in octal ascii)
39 * 148 8 bytes Header checksum (in octal ascii)
40 * 156 1 bytes Link flag
41 * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
42 * 257 8 bytes Magic PAX ("ustar\0" + 2 bytes padding)
43 * 257 8 bytes Magic GNU tar ("ustar \0")
44 * 265 32 bytes User name ('\0' terminated, 31 maxmum length)
45 * 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
46 * 329 8 bytes Major device ID (in octal ascii)
47 * 337 8 bytes Minor device ID (in octal ascii)
48 * 345 155 bytes Prefix
49 * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
50 * round up to 512 bytes
51 *
52 * Checksum:
53 * int i, sum;
54 * char* header = tar_header_pointer;
55 * sum = 0;
56 * for(i = 0; i < 512; i++)
57 * sum += 0xFF & header[i];
58 *************************************************************************/
59
60#define MAX_NAME_FIELD_SIZE99 99
61
62#define MIN(a,b)((a)>(b)?(b):(a)) ((a)>(b)?(b):(a))
63
64
65/**************************************************************************
66 * This converts octal ASCII number representations into an
67 * unsigned long. Only support 32-bit numbers for now.
68 *************************************************************************/
69unsigned long
70_rtems_octal2ulong(
71 const char *octascii,
72 size_t len
73)
74{
75 size_t i;
76 unsigned long num;
77
78 num = 0;
79 for (i=0; i < len; i++)
80 {
81 if ((octascii[i] < '0') || (octascii[i] > '9'))
82 {
83 continue;
84 }
85 num = num * 8 + ((unsigned long)(octascii[i] - '0'));
86 }
87 return(num);
88}
89
90
91/**************************************************************************
92 * Function: Untar_FromMemory *
93 **************************************************************************
94 * Description: *
95 * *
96 * This is a simple subroutine used to rip links, directories, and *
97 * files out of a block of memory. *
98 * *
99 * *
100 * Inputs: *
101 * *
102 * void * tar_buf - Pointer to TAR buffer. *
103 * size_t size - Length of TAR buffer. *
104 * *
105 * *
106 * Output: *
107 * *
108 * int - UNTAR_SUCCESSFUL (0) on successful completion. *
109 * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
110 * UNTAR_INVALID_HEADER for an invalid header. *
111 * *
112 **************************************************************************/
113int
114Untar_FromMemory(
115 void *tar_buf,
116 size_t size
117)
118{
119 FILE *fp;
120 const char *tar_ptr = (const char *)tar_buf;
121 const char *bufr;
122 size_t n;
123 char fname[100];
124 char linkname[100];
125 int sum;
126 int hdr_chksum;
127 int retval;
128 unsigned long ptr;
129 unsigned long i;
130 unsigned long nblocks;
131 unsigned long file_size;
132 unsigned char linkflag;
133
134
135 ptr = 0;
136 while (1)
137 {
138 if (ptr + 512 > size)
139 {
140 retval = UNTAR_SUCCESSFUL0;
141 break;
142 }
143
144 /* Read the header */
145 bufr = &tar_ptr[ptr];
146 ptr += 512;
147 if (strncmp(&bufr[257], "ustar", 5))
148 {
149 retval = UNTAR_SUCCESSFUL0;
150 break;
151 }
152
153 strncpy(fname, bufr, MAX_NAME_FIELD_SIZE99);
154 fname[MAX_NAME_FIELD_SIZE99] = '\0';
155
156 linkflag = bufr[156];
157 file_size = _rtems_octal2ulong(&bufr[124], 12);
158
159 /******************************************************************
160 * Compute the TAR checksum and check with the value in
161 * the archive. The checksum is computed over the entire
162 * header, but the checksum field is substituted with blanks.
163 ******************************************************************/
164 hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
165 sum = _rtems_tar_header_checksum(bufr);
166
167 if (sum != hdr_chksum)
168 {
169 retval = UNTAR_INVALID_CHECKSUM2;
170 break;
171 }
172
173
174 /******************************************************************
175 * We've decoded the header, now figure out what it contains and
176 * do something with it.
177 *****************************************************************/
178 if (linkflag == SYMTYPE'2')
179 {
180 strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE99);
181 linkname[MAX_NAME_FIELD_SIZE99] = '\0';
182 symlink(linkname, fname);
183 }
184 else if (linkflag == REGTYPE'0')
185 {
186 nblocks = (((file_size) + 511) & ~511) / 512;
187 if ((fp = fopen(fname, "w")) == NULL((void*)0))
188 {
189 printk("Untar: failed to create file %s\n", fname);
190 ptr += 512 * nblocks;
191 }
192 else
193 {
194 unsigned long sizeToGo = file_size;
195 size_t len;
196
197 /***************************************************************
198 * Read out the data. There are nblocks of data where nblocks
199 * is the file_size rounded to the nearest 512-byte boundary.
200 **************************************************************/
201 for (i=0; i<nblocks; i++)
202 {
203 len = ((sizeToGo < 512L)?(sizeToGo):(512L));
204 n = fwrite(&tar_ptr[ptr], 1, len, fp);
205 if (n != len)
206 {
207 printk("untar: Error during write\n");
208 break;
209 }
210 ptr += 512;
211 sizeToGo -= n;
212 }
213 fclose(fp);
214 }
215 }
216 else if (linkflag == DIRTYPE'5')
217 {
218 mkdir(fname, S_IRWXU(0400|0200|0100) | S_IRWXG((0400|0200|0100) >> 3) | S_IRWXO(((0400|0200|0100) >> 3) >> 3));
219 }
220 }
221
222 return(retval);
223}
224
225
226/**************************************************************************
227 * Function: Untar_FromFile *
228 **************************************************************************
229 * Description: *
230 * *
231 * This is a simple subroutine used to rip links, directories, and *
232 * files out of a TAR file. *
233 * *
234 * *
235 * Inputs: *
236 * *
237 * const char *tar_name - TAR filename. *
238 * *
239 * *
240 * Output: *
241 * *
242 * int - UNTAR_SUCCESSFUL (0) on successful completion. *
243 * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
244 * UNTAR_INVALID_HEADER for an invalid header. *
245 * *
246 **************************************************************************
247 * Change History: *
248 * 12/30/1998 - Creation (JWJ) *
249 *************************************************************************/
250int
251Untar_FromFile(
252 const char *tar_name
253)
254{
255 int fd;
256 char *bufr;
257 ssize_t n;
258 char fname[100];
259 char linkname[100];
260 int sum;
261 int hdr_chksum;
262 int retval;
263 unsigned long i;
264 unsigned long nblocks;
265 unsigned long size;
266 unsigned char linkflag;
267
268 retval = UNTAR_SUCCESSFUL0;
269
270 if ((fd = open(tar_name, O_RDONLY00)) < 0) {
271 return UNTAR_FAIL1;
272 }
273
274 bufr = (char *)malloc(512);
275 if (bufr == NULL((void*)0)) {
276 return(UNTAR_FAIL1);
277 }
278
279 while (1)
280 {
281 /* Read the header */
282 /* If the header read fails, we just consider it the end
283 of the tarfile. */
284 if ((n = read(fd, bufr, 512)) != 512)
Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
285 {
286 break;
287 }
288
289 if (strncmp(&bufr[257], "ustar", 5))
290 {
291 break;
292 }
293
294 strncpy(fname, bufr, MAX_NAME_FIELD_SIZE99);
295 fname[MAX_NAME_FIELD_SIZE99] = '\0';
296
297 linkflag = bufr[156];
298 size = _rtems_octal2ulong(&bufr[124], 12);
299
300 /******************************************************************
301 * Compute the TAR checksum and check with the value in
302 * the archive. The checksum is computed over the entire
303 * header, but the checksum field is substituted with blanks.
304 ******************************************************************/
305 hdr_chksum = _rtems_octal2ulong(&bufr[148], 8);
306 sum = _rtems_tar_header_checksum(bufr);
307
308 if (sum != hdr_chksum)
309 {
310 retval = UNTAR_INVALID_CHECKSUM2;
311 break;
312 }
313
314 /******************************************************************
315 * We've decoded the header, now figure out what it contains and
316 * do something with it.
317 *****************************************************************/
318 if (linkflag == SYMTYPE'2')
319 {
320 strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE99);
321 linkname[MAX_NAME_FIELD_SIZE99] = '\0';
322 symlink(linkname,fname);
323 }
324 else if (linkflag == REGTYPE'0')
325 {
326 int out_fd;
327
328 /******************************************************************
329 * Read out the data. There are nblocks of data where nblocks
330 * is the size rounded to the nearest 512-byte boundary.
331 *****************************************************************/
332 nblocks = (((size) + 511) & ~511) / 512;
333
334 if ((out_fd = creat(fname, 0644)) == -1)
335 {
336 for (i=0; i<nblocks; i++)
337 {
338 n = read(fd, bufr, 512);
339 }
340 }
341 else
342 {
343 for (i=0; i<nblocks; i++)
344 {
345 n = read(fd, bufr, 512);
346 n = MIN(n, size - i*512)((n)>(size - i*512)?(size - i*512):(n));
347 write(out_fd, bufr, n);
348 }
349 close(out_fd);
350 }
351 }
352 else if (linkflag == DIRTYPE'5')
353 {
354 mkdir(fname, S_IRWXU(0400|0200|0100) | S_IRWXG((0400|0200|0100) >> 3) | S_IRWXO(((0400|0200|0100) >> 3) >> 3));
355 }
356 }
357 free(bufr);
358 close(fd);
359
360 return(retval);
361}
362
363/************************************************************************
364 * Compute the TAR checksum and check with the value in
365 * the archive. The checksum is computed over the entire
366 * header, but the checksum field is substituted with blanks.
367 ************************************************************************/
368int
369_rtems_tar_header_checksum(
370 const char *bufr
371)
372{
373 int i, sum;
374
375 sum = 0;
376 for (i=0; i<512; i++)
377 {
378 if ((i >= 148) && (i < 156))
379 sum += 0xff & ' ';
380 else
381 sum += 0xff & bufr[i];
382 }
383 return(sum);
384}