source: rtems/c/src/libfs/src/imfs/imfs_load_tar.c @ 74e0ba5

4.104.114.84.95
Last change on this file since 74e0ba5 was 74e0ba5, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 8, 2002 at 12:05:36 PM

2002-01-07 Ralf Corsepius <corsepiu@…>

  • src/imfs/imfs_load_tar.c: Add include <sys/types.h>. Add include <sys/stat.h>. Add include <fcntl.h>.
  • src/imfs/imfs_rmnod.c: Add include <stdlib.h>.
  • Property mode set to 100644
File size: 8.6 KB
Line 
1/*
2 * $Id$
3 */
4
5#if HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9/**************************************************************************
10 * This file implements the "mount" procedure for tar-based IMFS
11 * extensions.  The TAR is not actually mounted under the IMFS.
12 * Directories from the TAR file are created as usual in the IMFS.
13 * File entries are created as IMFS_LINEAR_FILE nodes with their nods
14 * pointing to addresses in the TAR image.
15 *************************************************************************/
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20
21#include <string.h>
22
23#include <rtems.h>
24#include <rtems/libio_.h>
25#include <chain.h>
26#include <imfs.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 ("ustar  \0")
43 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
44 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
45 *   329      8 bytes  Major device ID (in octal ascii)
46 *   337      8 bytes  Minor device ID (in octal ascii)
47 *   345    167 bytes  Padding
48 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
49 *                     round up to 512 bytes
50 *
51 *   Checksum:
52 *   int i, sum;
53 *   char* header = tar_header_pointer;
54 *   sum = 0;
55 *   for(i = 0; i < 512; i++)
56 *       sum += 0xFF & header[i];
57 *************************************************************************/
58
59#define LF_OLDNORMAL  '\0'     /* Normal disk file, Unix compatible */
60#define LF_NORMAL     '0'      /* Normal disk file                  */
61#define LF_LINK       '1'      /* Link to previously dumped file    */
62#define LF_SYMLINK    '2'      /* Symbolic link                     */
63#define LF_CHR        '3'      /* Character special file            */
64#define LF_BLK        '4'      /* Block special file                */
65#define LF_DIR        '5'      /* Directory                         */
66#define LF_FIFO       '6'      /* FIFO special file                 */
67#define LF_CONFIG     '7'      /* Contiguous file                   */
68
69#define MAX_NAME_FIELD_SIZE      99
70
71#define MIN(a,b)   ((a)>(b)?(b):(a))
72
73static unsigned long octal2ulong(char *octascii, int len);
74static int compute_tar_header_checksum(char *bufr);
75
76/**************************************************************************
77 * rtems_tarfs_load
78 *
79 * Here we create the mountpoint directory and load the tarfs at
80 * that node.  Once the IMFS has been mounted, we work through the
81 * tar image and perform as follows:
82 *  - For directories, simply call mkdir().  The IMFS creates nodes as
83 *    needed.
84 *  - For files, we make our own calls to IMFS eval_for_make and
85 *    create_node.
86 *************************************************************************/
87int
88rtems_tarfs_load(char *mountpoint,
89                 unsigned char *tar_image,
90                 unsigned long tar_size)
91{
92   rtems_filesystem_location_info_t root_loc;
93   rtems_filesystem_location_info_t loc;
94   char            *hdr_ptr;
95   char            filename[100];
96   char            full_filename[256];
97   int             hdr_chksum;
98   unsigned char   linkflag;
99   unsigned long   file_size;
100   unsigned long   file_mode;
101   int             offset;
102   unsigned long   nblocks;
103   IMFS_jnode_t    *node;
104   int             status;
105
106
107   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
108   if (status != 0)
109      return(-1);
110
111   if (root_loc.ops != &IMFS_ops)
112      return(-1);
113
114   /***********************************************************************
115    * Create an IMFS node structure pointing to tar image memory.
116    **********************************************************************/
117   offset = 0;
118   while (1)
119   {
120      if (offset + 512 > tar_size)
121         break;
122
123      /******************************************************************
124       * Read a header.
125       ******************************************************************/
126      hdr_ptr = &tar_image[offset];
127      offset += 512;
128      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
129         break;
130
131      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
132      filename[MAX_NAME_FIELD_SIZE] = '\0';
133
134      linkflag   = hdr_ptr[156];
135      file_mode  = octal2ulong(&hdr_ptr[100], 8);
136      file_size  = octal2ulong(&hdr_ptr[124], 12);
137      hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8);
138
139      if (compute_tar_header_checksum(hdr_ptr) != hdr_chksum)
140         break;
141
142      /******************************************************************
143       * Generate an IMFS node depending on the file type.
144       * - For directories, just create directories as usual.  IMFS
145       *   will take care of the rest.
146       * - For files, create a file node with special tarfs properties.
147       *****************************************************************/
148      if (linkflag == LF_DIR)
149      {
150         strcpy(full_filename, mountpoint);
151         if (full_filename[strlen(full_filename)-1] != '/')
152            strcat(full_filename, "/");
153         strcat(full_filename, filename);
154         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
155      }
156      /******************************************************************
157       * Create a LINEAR_FILE node if no user write permission.
158       *****************************************************************/
159      else if ((linkflag == LF_NORMAL) &&
160               ((file_mode & 0200) == 0000))
161      {
162         const char  *name;
163
164         loc = root_loc;
165         if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
166         {
167            node = IMFS_create_node(&loc,
168                                    IMFS_LINEAR_FILE, (char *)name,
169                                    (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
170                                    NULL);
171            node->info.linearfile.size   = file_size;
172            node->info.linearfile.direct = &tar_image[offset];
173         }
174
175         nblocks = (((file_size) + 511) & ~511) / 512;
176         offset += 512 * nblocks;
177      }
178      /******************************************************************
179       * Create a regular MEMORY_FILE if write permission exists.
180       *****************************************************************/
181      else if ((linkflag == LF_NORMAL) &&
182               ((file_mode & 0200) == 0200))
183      {
184         int fd;
185         int n, left, ptr;
186
187         strcpy(full_filename, mountpoint);
188         if (full_filename[strlen(full_filename)-1] != '/')
189            strcat(full_filename, "/");
190         strcat(full_filename, filename);
191
192         fd = creat(full_filename, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP);
193         if (fd != -1)
194         {
195            left = file_size;
196            ptr  = offset;
197            while ((n = write(fd, &tar_image[ptr], left)) > 0)
198            {
199               left -= n;
200               ptr += n;
201            }
202            close(fd);
203         }
204
205         nblocks = (((file_size) + 511) & ~511) / 512;
206         offset += 512 * nblocks;
207      }
208   }
209
210   return(status);
211}
212
213/**************************************************************************
214 * This converts octal ASCII number representations into an
215 * unsigned long.  Only support 32-bit numbers for now.
216 *************************************************************************/
217static unsigned long
218octal2ulong(char *octascii, int len)
219{
220   int           i;
221   unsigned long num;
222   unsigned long mult;
223
224   num = 0;
225   mult = 1;
226   for (i=len-1; i>=0; i--)
227   {
228      if (octascii[i] < '0') 
229         continue;
230      if (octascii[i] > '9')
231         continue;
232
233      num  += mult*((unsigned long)(octascii[i] - '0'));
234      mult *= 8;
235   }
236   return(num);
237}
238
239
240/************************************************************************
241 * Compute the TAR checksum and check with the value in
242 * the archive.  The checksum is computed over the entire
243 * header, but the checksum field is substituted with blanks.
244 ************************************************************************/
245static int
246compute_tar_header_checksum(char *bufr)
247{
248   int  i, sum;
249
250
251   sum = 0;
252   for (i=0; i<512; i++)
253   {
254      if ((i >= 148) && (i < 156))
255         sum += 0xff & ' ';
256      else
257         sum += 0xff & bufr[i];
258   }
259   return(sum);
260}
Note: See TracBrowser for help on using the repository browser.