source: rtems/cpukit/libfs/src/imfs/imfs_load_tar.c @ 32f415d

4.104.114.84.95
Last change on this file since 32f415d was 0ef748fb, checked in by Joel Sherrill <joel.sherrill@…>, on 12/13/00 at 17:53:55

2000-12-12 Jake Janovetz <janovetz@…>

  • src/imfs/linearfile.c, src/imfs/imfs_load_tar.c: New files.
  • src/imfs/Makefile.am, src/imfs/imfs.h, src/imfs/imfs_creat.c, src/imfs/imfs_debug.c, src/imfs/imfs_eval.c, src/imfs/imfs_handlers_memfile.c, src/imfs/imfs_init.c, src/imfs/imfs_initsupp.c, src/imfs/imfs_stat.c, src/imfs/miniimfs_init.c: Added "tarfs". This is not really a tar filesystem. It is a way to load a tar image into the IMFS but actually leave bulky file contents in the original tar image. It essentially adds the linear file type and associated support and a loader routine.
  • Property mode set to 100644
File size: 6.9 KB
Line 
1/**************************************************************************
2 * This file implements the "mount" procedure for tar-based IMFS
3 * extensions.  The TAR is not actually mounted under the IMFS.
4 * Directories from the TAR file are created as usual in the IMFS.
5 * File entries are created as IMFS_LINEAR_FILE nodes with their nods
6 * pointing to addresses in the TAR image.
7 *
8 *  $Id$
9 *
10 *************************************************************************/
11
12#include <rtems.h>
13#include <rtems/libio.h>
14#include <string.h>
15#include <chain.h>
16#include <imfs.h>
17
18
19/**************************************************************************
20 * TAR file format:
21 *
22 *   Offset   Length   Contents
23 *     0    100 bytes  File name ('\0' terminated, 99 maxmum length)
24 *   100      8 bytes  File mode (in octal ascii)
25 *   108      8 bytes  User ID (in octal ascii)
26 *   116      8 bytes  Group ID (in octal ascii)
27 *   124     12 bytes  File size (s) (in octal ascii)
28 *   136     12 bytes  Modify time (in octal ascii)
29 *   148      8 bytes  Header checksum (in octal ascii)
30 *   156      1 bytes  Link flag
31 *   157    100 bytes  Linkname ('\0' terminated, 99 maxmum length)
32 *   257      8 bytes  Magic ("ustar  \0")
33 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
34 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
35 *   329      8 bytes  Major device ID (in octal ascii)
36 *   337      8 bytes  Minor device ID (in octal ascii)
37 *   345    167 bytes  Padding
38 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
39 *                     round up to 512 bytes
40 *
41 *   Checksum:
42 *   int i, sum;
43 *   char* header = tar_header_pointer;
44 *   sum = 0;
45 *   for(i = 0; i < 512; i++)
46 *       sum += 0xFF & header[i];
47 *************************************************************************/
48
49#define LF_OLDNORMAL  '\0'     /* Normal disk file, Unix compatible */
50#define LF_NORMAL     '0'      /* Normal disk file                  */
51#define LF_LINK       '1'      /* Link to previously dumped file    */
52#define LF_SYMLINK    '2'      /* Symbolic link                     */
53#define LF_CHR        '3'      /* Character special file            */
54#define LF_BLK        '4'      /* Block special file                */
55#define LF_DIR        '5'      /* Directory                         */
56#define LF_FIFO       '6'      /* FIFO special file                 */
57#define LF_CONFIG     '7'      /* Contiguous file                   */
58
59#define MAX_NAME_FIELD_SIZE      99
60
61#define MIN(a,b)   ((a)>(b)?(b):(a))
62
63
64/**************************************************************************
65 * This converts octal ASCII number representations into an
66 * unsigned long.  Only support 32-bit numbers for now.
67 *************************************************************************/
68static unsigned long
69octal2ulong(char *octascii, int len)
70{
71   int           i;
72   unsigned long num;
73   unsigned long mult;
74
75   num = 0;
76   mult = 1;
77   for (i=len-1; i>=0; i--)
78   {
79      if ((octascii[i] < '0') || (octascii[i] > '9'))
80         continue;
81
82      num  += mult*((unsigned long)(octascii[i] - '0'));
83      mult *= 8;
84   }
85   return(num);
86}
87
88
89/************************************************************************
90 * Compute the TAR checksum and check with the value in
91 * the archive.  The checksum is computed over the entire
92 * header, but the checksum field is substituted with blanks.
93 ************************************************************************/
94static int
95compute_tar_header_checksum(char *bufr)
96{
97   int  i, sum;
98
99
100   sum = 0;
101   for (i=0; i<512; i++)
102   {
103      if ((i >= 148) && (i < 156))
104         sum += 0xff & ' ';
105      else
106         sum += 0xff & bufr[i];
107   }
108   return(sum);
109}
110
111
112/**************************************************************************
113 * rtems_tarfs_mount
114 *
115 * Here we create the mountpoint directory and mount the tarfs at
116 * that node.  Once the IMFS has been mounted, we work through the
117 * tar image and perform as follows:
118 *  - For directories, simply call mkdir().  The IMFS creates nodes as
119 *    needed.
120 *  - For files, we make our own calls to IMFS eval_for_make and
121 *    create_node.
122 *************************************************************************/
123int
124rtems_tarfs_mount(char *mountpoint,
125                  unsigned char *tar_image,
126                  unsigned long tar_size)
127{
128   rtems_filesystem_location_info_t root_loc;
129   rtems_filesystem_location_info_t loc;
130   char            *hdr_ptr;
131   char            filename[100];
132   char            full_filename[256];
133   int             hdr_chksum;
134   unsigned char   linkflag;
135   unsigned long   file_size;
136   int             offset;
137   unsigned long   nblocks;
138   IMFS_jnode_t    *node;
139   int             status;
140
141
142   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
143   if (status != 0)
144      return(-1);
145
146   /***********************************************************************
147    * Create an IMFS node structure pointing to tar image memory.
148    **********************************************************************/
149   offset = 0;
150   while (1)
151   {
152      if (offset + 512 > tar_size)
153         break;
154
155      /******************************************************************
156       * Read a header.
157       ******************************************************************/
158      hdr_ptr = &tar_image[offset];
159      offset += 512;
160      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
161         break;
162
163      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
164      filename[MAX_NAME_FIELD_SIZE] = '\0';
165
166      linkflag   = hdr_ptr[156];
167      file_size  = octal2ulong(&hdr_ptr[124], 12);
168
169      hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8);
170      if (compute_tar_header_checksum(hdr_ptr) != hdr_chksum)
171         break;
172
173      /******************************************************************
174       * Generate an IMFS node depending on the file type.
175       * - For directories, just create directories as usual.  IMFS
176       *   will take care of the rest.
177       * - For files, create a file node with special tarfs properties.
178       *****************************************************************/
179      if (linkflag == LF_DIR)
180      {
181         strcpy(full_filename, mountpoint);
182         strcat(full_filename, "/");
183         strcat(full_filename, filename);
184         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
185      }
186      else if (linkflag == LF_NORMAL)
187      {
188         const char  *name;
189
190
191         loc = root_loc;
192         if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
193         {
194            node = IMFS_create_node(&loc,
195                                    IMFS_LINEAR_FILE, (char *)name,
196                                    (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
197                                    NULL);
198            node->info.linearfile.size   = file_size;
199            node->info.linearfile.direct = &tar_image[offset];
200         }
201
202         nblocks = (((file_size) + 511) & ~511) / 512;
203         offset += 512 * nblocks;
204      }
205   }
206
207   return(status);
208}
209
Note: See TracBrowser for help on using the repository browser.