OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [libmisc/] [untar/] [untar.c] - Blame information for rev 1779

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.